From bd3838064aebb0e19a157317f9b5cee9512fbc44 Mon Sep 17 00:00:00 2001
From: philippegorley <philippe.gorley@savoirfairelinux.com>
Date: Thu, 7 Jun 2018 10:18:29 -0400
Subject: [PATCH] encoder: fix segfault if key isn't in dictionary

Change-Id: If32273538b24853b7aba236efd8db730faa5b954
---
 src/media/libav_utils.cpp   | 10 ++++++++++
 src/media/libav_utils.h     |  3 +++
 src/media/media_encoder.cpp | 12 ++++++------
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/media/libav_utils.cpp b/src/media/libav_utils.cpp
index 7bb5588537..8d76e4548f 100644
--- a/src/media/libav_utils.cpp
+++ b/src/media/libav_utils.cpp
@@ -216,4 +216,14 @@ getError(int err)
     return ret;
 }
 
+const char*
+getDictValue(const AVDictionary* d, const std::string& key, int flags)
+{
+    auto kv = av_dict_get(d, key.c_str(), nullptr, flags);
+    if (kv)
+        return kv->value;
+    else
+        return "";
+}
+
 }} // namespace ring::libav_utils
diff --git a/src/media/libav_utils.h b/src/media/libav_utils.h
index c8f97d32f5..67efca9d67 100644
--- a/src/media/libav_utils.h
+++ b/src/media/libav_utils.h
@@ -24,6 +24,7 @@
 #include <map>
 #include <string>
 
+struct AVDictionary;
 struct AVPixFmtDescriptor;
 
 namespace ring { namespace libav_utils {
@@ -44,4 +45,6 @@ namespace ring { namespace libav_utils {
 
     std::string getError(int err);
 
+    const char* getDictValue(const AVDictionary* d, const std::string& key, int flags=0);
+
 }} // namespace ring::libav_utils
diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp
index eab867310c..b4ea60b312 100644
--- a/src/media/media_encoder.cpp
+++ b/src/media/media_encoder.cpp
@@ -203,9 +203,9 @@ MediaEncoder::addStream(const SystemCodecInfo& systemCodecInfo, std::string para
 
     encoderCtx = prepareEncoderContext(outputCodec, systemCodecInfo.mediaType == MEDIA_VIDEO);
     encoders_.push_back(encoderCtx);
-    auto maxBitrate = 1000 * atoi(av_dict_get(options_, "max_rate", nullptr, 0)->value);
+    auto maxBitrate = 1000 * std::atoi(libav_utils::getDictValue(options_, "max_rate"));
     auto bufSize = 2 * maxBitrate; // as recommended (TODO: make it customizable)
-    auto crf = atoi(av_dict_get(options_, "crf", nullptr, 0)->value);
+    auto crf = std::atoi(libav_utils::getDictValue(options_, "crf"));
 
     /* let x264 preset override our encoder settings */
     if (systemCodecInfo.avcodecId == AV_CODEC_ID_H264) {
@@ -217,7 +217,7 @@ MediaEncoder::addStream(const SystemCodecInfo& systemCodecInfo, std::string para
             crf = 30; // good value for H264-720p@30
         RING_DBG("H264 encoder setup: crf=%u, maxrate=%u, bufsize=%u", crf, maxBitrate, bufSize);
 
-        av_opt_set(encoderCtx->priv_data, "crf", av_dict_get(options_, "crf", nullptr, 0)->value, 0);
+        av_opt_set_int(encoderCtx->priv_data, "crf", crf, 0);
         encoderCtx->rc_buffer_size = bufSize;
         encoderCtx->rc_max_rate = maxBitrate;
     } else if (systemCodecInfo.avcodecId == AV_CODEC_ID_VP8) {
@@ -242,7 +242,7 @@ MediaEncoder::addStream(const SystemCodecInfo& systemCodecInfo, std::string para
         encoderCtx->rc_buffer_size = maxBitrate;
         encoderCtx->bit_rate = maxBitrate;
         if (crf != SystemCodecInfo::DEFAULT_NO_QUALITY) {
-            av_opt_set(encoderCtx->priv_data, "crf", av_dict_get(options_, "crf", nullptr, 0)->value, 0);
+            av_opt_set_int(encoderCtx->priv_data, "crf", crf, 0);
             RING_DBG("Using quality factor %d", crf);
         } else {
             RING_DBG("Using Max bitrate %d", maxBitrate);
@@ -554,8 +554,8 @@ AVCodecContext* MediaEncoder::prepareEncoderContext(AVCodec* outputCodec, bool i
             encoderCtx->width = device_.width;
             encoderCtx->height = device_.height;
         } else {
-            encoderCtx->width = atoi(av_dict_get(options_, "width", nullptr, 0)->value);
-            encoderCtx->height = atoi(av_dict_get(options_, "height", nullptr, 0)->value);
+            encoderCtx->width = std::atoi(libav_utils::getDictValue(options_, "width"));
+            encoderCtx->height = std::atoi(libav_utils::getDictValue(options_, "height"));
         }
 
         // satisfy ffmpeg: denominator must be 16bit or less value
-- 
GitLab