Skip to content
Snippets Groups Projects
Commit abb09e1e authored by Philippe Gorley's avatar Philippe Gorley Committed by Sébastien Blin
Browse files

libav_utils: add shortcut to set dictionary values


Change-Id: Iab880ac674e15dc2f0baba260632ead4cb6e4870
Reviewed-by: default avatarSébastien Blin <sebastien.blin@savoirfairelinux.com>
parent d0390c98
No related branches found
No related tags found
No related merge requests found
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
* Author: Luca Barbato <lu_zero@gentoo.org> * Author: Luca Barbato <lu_zero@gentoo.org>
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com> * Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
* Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -205,6 +206,12 @@ getDictValue(const AVDictionary* d, const std::string& key, int flags) ...@@ -205,6 +206,12 @@ getDictValue(const AVDictionary* d, const std::string& key, int flags)
return ""; return "";
} }
void
setDictValue(AVDictionary** d, const std::string& key, const std::string& value, int flags)
{
av_dict_set(d, key.c_str(), value.c_str(), flags);
}
void void
fillWithBlack(AVFrame* frame) fillWithBlack(AVFrame* frame)
{ {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Copyright (C) 2004-2019 Savoir-faire Linux Inc. * Copyright (C) 2004-2019 Savoir-faire Linux Inc.
* *
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com> * Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
* Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -45,6 +46,8 @@ namespace ring { namespace libav_utils { ...@@ -45,6 +46,8 @@ namespace ring { namespace libav_utils {
const char* getDictValue(const AVDictionary* d, const std::string& key, int flags=0); const char* getDictValue(const AVDictionary* d, const std::string& key, int flags=0);
void setDictValue(AVDictionary** d, const std::string& key, const std::string& value, int flags=0);
void fillWithBlack(AVFrame* frame); void fillWithBlack(AVFrame* frame);
void fillWithSilence(AVFrame* frame); void fillWithSilence(AVFrame* frame);
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com> * Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
* Author: Eloi Bail <Eloi.Bail@savoirfairelinux.com> * Author: Eloi Bail <Eloi.Bail@savoirfairelinux.com>
* Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -76,39 +77,39 @@ void MediaEncoder::setDeviceOptions(const DeviceParams& args) ...@@ -76,39 +77,39 @@ void MediaEncoder::setDeviceOptions(const DeviceParams& args)
device_.width -= device_.width % 2; device_.width -= device_.width % 2;
device_.height -= device_.height % 2; device_.height -= device_.height % 2;
if (device_.width) if (device_.width)
av_dict_set(&options_, "width", ring::to_string(device_.width).c_str(), 0); libav_utils::setDictValue(&options_, "width", ring::to_string(device_.width));
if (device_.height) if (device_.height)
av_dict_set(&options_, "height", ring::to_string(device_.height).c_str(), 0); libav_utils::setDictValue(&options_, "height", ring::to_string(device_.height));
if (not device_.framerate) if (not device_.framerate)
device_.framerate = 30; device_.framerate = 30;
av_dict_set(&options_, "framerate", ring::to_string(device_.framerate.real()).c_str(), 0); libav_utils::setDictValue(&options_, "framerate", ring::to_string(device_.framerate.real()));
} }
void MediaEncoder::setOptions(const MediaDescription& args) void MediaEncoder::setOptions(const MediaDescription& args)
{ {
codec_ = args.codec; codec_ = args.codec;
av_dict_set(&options_, "payload_type", ring::to_string(args.payload_type).c_str(), 0); libav_utils::setDictValue(&options_, "payload_type", ring::to_string(args.payload_type));
av_dict_set(&options_, "max_rate", ring::to_string(args.codec->bitrate).c_str(), 0); libav_utils::setDictValue(&options_, "max_rate", ring::to_string(args.codec->bitrate));
av_dict_set(&options_, "crf", ring::to_string(args.codec->quality).c_str(), 0); libav_utils::setDictValue(&options_, "crf", ring::to_string(args.codec->quality));
if (args.codec->systemCodecInfo.mediaType == MEDIA_AUDIO) { if (args.codec->systemCodecInfo.mediaType == MEDIA_AUDIO) {
auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(args.codec); auto accountAudioCodec = std::static_pointer_cast<AccountAudioCodecInfo>(args.codec);
if (accountAudioCodec->audioformat.sample_rate) if (accountAudioCodec->audioformat.sample_rate)
av_dict_set(&options_, "sample_rate", libav_utils::setDictValue(&options_, "sample_rate",
ring::to_string(accountAudioCodec->audioformat.sample_rate).c_str(), 0); ring::to_string(accountAudioCodec->audioformat.sample_rate));
if (accountAudioCodec->audioformat.nb_channels) if (accountAudioCodec->audioformat.nb_channels)
av_dict_set(&options_, "channels", libav_utils::setDictValue(&options_, "channels",
ring::to_string(accountAudioCodec->audioformat.nb_channels).c_str(), 0); ring::to_string(accountAudioCodec->audioformat.nb_channels));
if (accountAudioCodec->audioformat.sample_rate && accountAudioCodec->audioformat.nb_channels) if (accountAudioCodec->audioformat.sample_rate && accountAudioCodec->audioformat.nb_channels)
av_dict_set(&options_, "frame_size", libav_utils::setDictValue(&options_, "frame_size",
ring::to_string(static_cast<unsigned>(0.02 * accountAudioCodec->audioformat.sample_rate)).c_str(), 0); ring::to_string(static_cast<unsigned>(0.02 * accountAudioCodec->audioformat.sample_rate)));
} }
if (not args.parameters.empty()) if (not args.parameters.empty())
av_dict_set(&options_, "parameters", args.parameters.c_str(), 0); libav_utils::setDictValue(&options_, "parameters", args.parameters);
} }
void void
...@@ -116,7 +117,7 @@ MediaEncoder::setInitSeqVal(uint16_t seqVal) ...@@ -116,7 +117,7 @@ MediaEncoder::setInitSeqVal(uint16_t seqVal)
{ {
//only set not default value (!=0) //only set not default value (!=0)
if (seqVal != 0) if (seqVal != 0)
av_dict_set(&options_, "seq", ring::to_string(seqVal).c_str(), 0); libav_utils::setDictValue(&options_, "seq", ring::to_string(seqVal));
} }
uint16_t uint16_t
...@@ -168,9 +169,9 @@ MediaEncoder::openFileOutput(const std::string& filename, std::map<std::string, ...@@ -168,9 +169,9 @@ MediaEncoder::openFileOutput(const std::string& filename, std::map<std::string,
avformat_alloc_output_context2(&outputCtx_, nullptr, nullptr, filename.c_str()); avformat_alloc_output_context2(&outputCtx_, nullptr, nullptr, filename.c_str());
if (!options["title"].empty()) if (!options["title"].empty())
av_dict_set(&outputCtx_->metadata, "title", options["title"].c_str(), 0); libav_utils::setDictValue(&outputCtx_->metadata, "title", options["title"]);
if (!options["description"].empty()) if (!options["description"].empty())
av_dict_set(&outputCtx_->metadata, "description", options["description"].c_str(), 0); libav_utils::setDictValue(&outputCtx_->metadata, "description", options["description"]);
auto bitrate = SystemCodecInfo::DEFAULT_MAX_BITRATE; auto bitrate = SystemCodecInfo::DEFAULT_MAX_BITRATE;
auto quality = SystemCodecInfo::DEFAULT_CODEC_QUALITY; auto quality = SystemCodecInfo::DEFAULT_CODEC_QUALITY;
...@@ -185,7 +186,7 @@ MediaEncoder::openFileOutput(const std::string& filename, std::map<std::string, ...@@ -185,7 +186,7 @@ MediaEncoder::openFileOutput(const std::string& filename, std::map<std::string,
options.insert({"height", "240"}); options.insert({"height", "240"});
options.insert({"framerate", "30.00"}); options.insert({"framerate", "30.00"});
for (const auto& it : options) for (const auto& it : options)
av_dict_set(&options_, it.first.c_str(), it.second.c_str(), 0); libav_utils::setDictValue(&options_, it.first, it.second);
// for a file output, addStream is done by the caller, as there may be multiple streams // for a file output, addStream is done by the caller, as there may be multiple streams
} }
...@@ -498,17 +499,16 @@ AVCodecContext* MediaEncoder::prepareEncoderContext(AVCodec* outputCodec, bool i ...@@ -498,17 +499,16 @@ AVCodecContext* MediaEncoder::prepareEncoderContext(AVCodec* outputCodec, bool i
// satisfy ffmpeg: denominator must be 16bit or less value // satisfy ffmpeg: denominator must be 16bit or less value
// time base = 1/FPS // time base = 1/FPS
if (device_.framerate) { if (device_.framerate) {
av_dict_set(&options_, "width", ring::to_string(device_.width).c_str(), 0);
av_reduce(&encoderCtx->framerate.num, &encoderCtx->framerate.den, av_reduce(&encoderCtx->framerate.num, &encoderCtx->framerate.den,
device_.framerate.numerator(), device_.framerate.denominator(), device_.framerate.numerator(), device_.framerate.denominator(),
(1U << 16) - 1); (1U << 16) - 1);
encoderCtx->time_base = av_inv_q(encoderCtx->framerate); encoderCtx->time_base = av_inv_q(encoderCtx->framerate);
} else { } else {
// get from options_, else default to 30 fps // get from options_, else default to 30 fps
auto v = av_dict_get(options_, "framerate", nullptr, 0); auto v = libav_utils::getDictValue(options_, "framerate");
AVRational framerate = AVRational{30, 1}; AVRational framerate = AVRational{30, 1};
if (v) if (v)
av_parse_ratio_quiet(&framerate, v->value, 120); av_parse_ratio_quiet(&framerate, v, 120);
if (framerate.den == 0) if (framerate.den == 0)
framerate.den = 1; framerate.den = 1;
av_reduce(&encoderCtx->framerate.num, &encoderCtx->framerate.den, av_reduce(&encoderCtx->framerate.num, &encoderCtx->framerate.den,
...@@ -528,18 +528,18 @@ AVCodecContext* MediaEncoder::prepareEncoderContext(AVCodec* outputCodec, bool i ...@@ -528,18 +528,18 @@ AVCodecContext* MediaEncoder::prepareEncoderContext(AVCodec* outputCodec, bool i
// encoderCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // encoderCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
} else { } else {
encoderCtx->sample_fmt = AV_SAMPLE_FMT_S16; encoderCtx->sample_fmt = AV_SAMPLE_FMT_S16;
auto v = av_dict_get(options_, "sample_rate", nullptr, 0); auto v = libav_utils::getDictValue(options_, "sample_rate");
if (v) { if (v) {
encoderCtx->sample_rate = atoi(v->value); encoderCtx->sample_rate = atoi(v);
encoderCtx->time_base = AVRational{1, encoderCtx->sample_rate}; encoderCtx->time_base = AVRational{1, encoderCtx->sample_rate};
} else { } else {
RING_WARN("[%s] No sample rate set", encoderName); RING_WARN("[%s] No sample rate set", encoderName);
encoderCtx->sample_rate = 8000; encoderCtx->sample_rate = 8000;
} }
v = av_dict_get(options_, "channels", nullptr, 0); v = libav_utils::getDictValue(options_, "channels");
if (v) { if (v) {
auto c = std::atoi(v->value); auto c = std::atoi(v);
if (c > 2 or c < 1) { if (c > 2 or c < 1) {
RING_WARN("[%s] Clamping invalid channel value %d", encoderName, c); RING_WARN("[%s] Clamping invalid channel value %d", encoderName, c);
c = 1; c = 1;
...@@ -552,9 +552,9 @@ AVCodecContext* MediaEncoder::prepareEncoderContext(AVCodec* outputCodec, bool i ...@@ -552,9 +552,9 @@ AVCodecContext* MediaEncoder::prepareEncoderContext(AVCodec* outputCodec, bool i
encoderCtx->channel_layout = encoderCtx->channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; encoderCtx->channel_layout = encoderCtx->channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
v = av_dict_get(options_, "frame_size", nullptr, 0); v = libav_utils::getDictValue(options_, "frame_size");
if (v) { if (v) {
encoderCtx->frame_size = atoi(v->value); encoderCtx->frame_size = atoi(v);
RING_DBG("[%s] Frame size %d", encoderName, encoderCtx->frame_size); RING_DBG("[%s] Frame size %d", encoderName, encoderCtx->frame_size);
} else { } else {
RING_WARN("[%s] Frame size not set", encoderName); RING_WARN("[%s] Frame size not set", encoderName);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Copyright (C) 2013-2019 Savoir-faire Linux Inc. * Copyright (C) 2013-2019 Savoir-faire Linux Inc.
* *
* Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com> * Author: Guillaume Roguez <Guillaume.Roguez@savoirfairelinux.com>
* Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment