From cf4acb3f74c638bda31ea4c132882f1f0ab35a7c Mon Sep 17 00:00:00 2001 From: philippegorley <philippe.gorley@savoirfairelinux.com> Date: Tue, 25 Jun 2019 11:12:34 -0400 Subject: [PATCH] encoder: use avoption api FFmpeg's AVOption API is more flexible and better suited than AVDictionary for codec and format options. This also allows to use strings in encoder.json, such as setting profile to high (instead of 100). Change-Id: I2039b2d039a87f8b3ed8ecb197dfa7b734c27950 --- src/media/media_encoder.cpp | 41 +++++++++++++------------------------ src/media/media_encoder.h | 2 +- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp index b1fbb3c6ff..f4e6220b3a 100644 --- a/src/media/media_encoder.cpp +++ b/src/media/media_encoder.cpp @@ -107,7 +107,12 @@ MediaEncoder::setOptions(const MediaStream& opts) void MediaEncoder::setOptions(const MediaDescription& args) { - libav_utils::setDictValue(&options_, "payload_type", std::to_string(args.payload_type)); + int ret; + if ((ret = av_opt_set_int(reinterpret_cast<void*>(outputCtx_), + "payload_type", args.payload_type, AV_OPT_SEARCH_CHILDREN)) < 0) + JAMI_ERR() << "Failed to set payload type: " << libav_utils::getError(ret); + + // NOTE none of these are format options, and we don't have a codec context yet libav_utils::setDictValue(&options_, "max_rate", std::to_string(args.codec->bitrate)); libav_utils::setDictValue(&options_, "crf", std::to_string(args.codec->quality)); @@ -203,7 +208,7 @@ MediaEncoder::initStream(const SystemCodecInfo& systemCodecInfo, AVBufferRef* fr currentStreamIdx_ = stream->index; - readConfig(&options_, encoderCtx); + readConfig(encoderCtx); if (avcodec_open2(encoderCtx, outputCodec_, &options_) < 0) throw MediaEncoderException("Could not open encoder"); @@ -846,7 +851,7 @@ MediaEncoder::stopEncoder() } void -MediaEncoder::readConfig(AVDictionary** dict, AVCodecContext* encoderCtx) +MediaEncoder::readConfig(AVCodecContext* encoderCtx) { std::string path = fileutils::get_config_dir() + DIR_SEPARATOR_STR + "encoder.json"; std::string name = encoderCtx->codec->name; @@ -868,7 +873,6 @@ MediaEncoder::readConfig(AVDictionary** dict, AVCodecContext* encoderCtx) JAMI_ERR() << "Invalid encoder configuration: '" << name << "' is not an object"; return; } - // If users want to change these, they should use the settings page. for (Json::Value::const_iterator it = config.begin(); it != config.end(); ++it) { Json::Value v = *it; if (!it.key().isConvertibleTo(Json::ValueType::stringValue) @@ -878,29 +882,12 @@ MediaEncoder::readConfig(AVDictionary** dict, AVCodecContext* encoderCtx) } const auto& key = it.key().asString(); const auto& value = v.asString(); - // provides a way to override all AVCodecContext fields MediaEncoder sets - if (key == "parameters") // Used by MediaEncoder for profile-level-id, ignore - continue; - else if (value.empty()) - libav_utils::setDictValue(dict, key, nullptr); - else if (key == "profile") - encoderCtx->profile = v.asInt(); - else if (key == "level") - encoderCtx->level = v.asInt(); - else if (key == "bit_rate") - encoderCtx->bit_rate = v.asInt(); - else if (key == "rc_buffer_size") - encoderCtx->rc_buffer_size = v.asInt(); - else if (key == "rc_min_rate") - encoderCtx->rc_min_rate = v.asInt(); - else if (key == "rc_max_rate") - encoderCtx->rc_max_rate = v.asInt(); - else if (key == "qmin") - encoderCtx->qmin = v.asInt(); - else if (key == "qmax") - encoderCtx->qmax = v.asInt(); - else - libav_utils::setDictValue(dict, key, value); + int ret = av_opt_set(reinterpret_cast<void*>(encoderCtx), + key.c_str(), value.c_str(), AV_OPT_SEARCH_CHILDREN); + if (ret < 0) { + JAMI_ERR() << "Failed to set option " << key << " in encoder context: " + << libav_utils::getError(ret) << "\n"; + } } } catch (const Json::Exception& e) { JAMI_ERR() << "Failed to load encoder configuration file: " << e.what(); diff --git a/src/media/media_encoder.h b/src/media/media_encoder.h index 5dc9d5df10..800ec4bc95 100644 --- a/src/media/media_encoder.h +++ b/src/media/media_encoder.h @@ -152,7 +152,7 @@ private: #endif protected: - void readConfig(AVDictionary** dict, AVCodecContext* encoderCtx); + void readConfig(AVCodecContext* encoderCtx); AVDictionary* options_ = nullptr; MediaStream videoOpts_; MediaStream audioOpts_; -- GitLab