From 11e8cf92f27188cdda2c6690f7130106e90f21d8 Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Tue, 18 Jul 2017 00:49:12 +0200 Subject: [PATCH] openh264enc: allow to dynamically change bitrate https://bugzilla.gnome.org/show_bug.cgi?id=784988 --- ext/openh264/gstopenh264enc.cpp | 54 +++++++++++++++++++++++++++++++-- ext/openh264/gstopenh264enc.h | 2 ++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/ext/openh264/gstopenh264enc.cpp b/ext/openh264/gstopenh264enc.cpp index 120c6edcab..51f038d1b8 100644 --- a/ext/openh264/gstopenh264enc.cpp +++ b/ext/openh264/gstopenh264enc.cpp @@ -392,6 +392,8 @@ gst_openh264enc_init (GstOpenh264Enc * openh264enc) openh264enc->num_slices = DEFAULT_NUM_SLICES; openh264enc->encoder = NULL; openh264enc->complexity = DEFAULT_COMPLEXITY; + openh264enc->bitrate_changed = FALSE; + openh264enc->max_bitrate_changed = FALSE; gst_openh264enc_set_usage_type (openh264enc, CAMERA_VIDEO_REAL_TIME); gst_openh264enc_set_rate_control (openh264enc, RC_QUALITY_MODE); } @@ -442,11 +444,21 @@ gst_openh264enc_set_property (GObject * object, guint property_id, switch (property_id) { case PROP_BITRATE: - openh264enc->bitrate = g_value_get_uint (value); + GST_OBJECT_LOCK (openh264enc); + if (openh264enc->bitrate != g_value_get_uint (value)) { + openh264enc->bitrate = g_value_get_uint (value); + openh264enc->bitrate_changed = TRUE; + } + GST_OBJECT_UNLOCK (openh264enc); break; case PROP_MAX_BITRATE: - openh264enc->max_bitrate = g_value_get_uint (value); + GST_OBJECT_LOCK (openh264enc); + if (openh264enc->max_bitrate != g_value_get_uint (value)) { + openh264enc->max_bitrate = g_value_get_uint (value); + openh264enc->max_bitrate_changed = TRUE; + } + GST_OBJECT_UNLOCK (openh264enc); break; case PROP_QP_MIN: @@ -701,6 +713,8 @@ gst_openh264enc_set_format (GstVideoEncoder * encoder, unsigned int uiTraceLevel = WELS_LOG_ERROR; openh264enc->encoder->SetOption (ENCODER_OPTION_TRACE_LEVEL, &uiTraceLevel); + GST_OBJECT_LOCK (openh264enc); + openh264enc->encoder->GetDefaultParams (&enc_params); enc_params.iUsageType = openh264enc->usage_type; @@ -769,6 +783,11 @@ gst_openh264enc_set_format (GstVideoEncoder * encoder, ret = openh264enc->encoder->InitializeExt (&enc_params); + openh264enc->bitrate_changed = FALSE; + openh264enc->max_bitrate_changed = FALSE; + + GST_OBJECT_UNLOCK (openh264enc); + if (ret != cmResultSuccess) { GST_ERROR_OBJECT (openh264enc, "failed to initialize encoder"); return FALSE; @@ -811,6 +830,37 @@ gst_openh264enc_handle_frame (GstVideoEncoder * encoder, gint i, j; gsize buf_length = 0; + GST_OBJECT_LOCK (openh264enc); + + if (openh264enc->bitrate_changed || openh264enc->max_bitrate_changed) { + SEncParamExt enc_params; + if (openh264enc->encoder->GetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, + &enc_params) == cmResultSuccess) { + if (openh264enc->bitrate_changed) { + enc_params.iTargetBitrate = openh264enc->bitrate; + enc_params.sSpatialLayers[0].iSpatialBitrate = + enc_params.iTargetBitrate; + } + if (openh264enc->max_bitrate_changed) { + enc_params.iMaxBitrate = openh264enc->max_bitrate; + enc_params.sSpatialLayers[0].iMaxSpatialBitrate = + enc_params.iMaxBitrate; + } + if (openh264enc->encoder->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, + &enc_params) != cmResultSuccess) { + GST_WARNING_OBJECT (openh264enc, + "Error changing bitrate/max bitrate, unable to set new enc_params"); + } + } else { + GST_WARNING_OBJECT (openh264enc, + "Error changing bitrate/max bitrate, unable to get enc_params"); + } + openh264enc->bitrate_changed = FALSE; + openh264enc->max_bitrate_changed = FALSE; + } + + GST_OBJECT_UNLOCK (openh264enc); + if (frame) { src_pic = new SSourcePicture; diff --git a/ext/openh264/gstopenh264enc.h b/ext/openh264/gstopenh264enc.h index 60bdba30f8..334b302501 100644 --- a/ext/openh264/gstopenh264enc.h +++ b/ext/openh264/gstopenh264enc.h @@ -91,6 +91,8 @@ struct _GstOpenh264Enc GstOpenh264EncSliceMode slice_mode; guint num_slices; ECOMPLEXITY_MODE complexity; + gboolean bitrate_changed; + gboolean max_bitrate_changed; }; struct _GstOpenh264EncClass