mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
videoencoder: Add min-force-key-unit-interval property
This allows configuring the minimum interval between subsequent force-key-unit requests and prevents a big bitrate increase if a lot of key-units are requested. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/684>
This commit is contained in:
parent
931b5ad996
commit
c5b081edc2
2 changed files with 109 additions and 4 deletions
|
@ -113,11 +113,13 @@ GST_DEBUG_CATEGORY (videoencoder_debug);
|
|||
/* properties */
|
||||
|
||||
#define DEFAULT_QOS FALSE
|
||||
#define DEFAULT_MIN_FORCE_KEY_UNIT_INTERVAL 0
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_QOS,
|
||||
PROP_MIN_FORCE_KEY_UNIT_INTERVAL,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
|
@ -139,6 +141,8 @@ struct _GstVideoEncoderPrivate
|
|||
gboolean new_headers; /* Whether new headers were just set */
|
||||
|
||||
GQueue force_key_unit; /* List of pending forced keyunits */
|
||||
GstClockTime min_force_key_unit_interval;
|
||||
GstClockTime last_force_key_unit_request;
|
||||
|
||||
guint32 system_frame_number;
|
||||
|
||||
|
@ -323,6 +327,10 @@ gst_video_encoder_set_property (GObject * object, guint prop_id,
|
|||
case PROP_QOS:
|
||||
gst_video_encoder_set_qos_enabled (sink, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_MIN_FORCE_KEY_UNIT_INTERVAL:
|
||||
gst_video_encoder_set_min_force_key_unit_interval (sink,
|
||||
g_value_get_uint64 (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -339,6 +347,10 @@ gst_video_encoder_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_QOS:
|
||||
g_value_set_boolean (value, gst_video_encoder_is_qos_enabled (sink));
|
||||
break;
|
||||
case PROP_MIN_FORCE_KEY_UNIT_INTERVAL:
|
||||
g_value_set_uint64 (value,
|
||||
gst_video_encoder_get_min_force_key_unit_interval (sink));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -382,6 +394,22 @@ gst_video_encoder_class_init (GstVideoEncoderClass * klass)
|
|||
g_param_spec_boolean ("qos", "Qos",
|
||||
"Handle Quality-of-Service events from downstream", DEFAULT_QOS,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstVideoEncoder:min-force-key-unit-interval:
|
||||
*
|
||||
* Minimum interval between force-keyunit requests in nanoseconds. See
|
||||
* gst_video_encoder_set_min_force_key_unit_interval() for more details.
|
||||
*
|
||||
* Since: 1.18
|
||||
**/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_MIN_FORCE_KEY_UNIT_INTERVAL,
|
||||
g_param_spec_uint64 ("min-force-key-unit-interval",
|
||||
"Minimum Force Keyunit Interval",
|
||||
"Minimum interval between force-keyunit requests in nanoseconds", 0,
|
||||
G_MAXUINT64, DEFAULT_MIN_FORCE_KEY_UNIT_INTERVAL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
static GList *
|
||||
|
@ -427,6 +455,7 @@ gst_video_encoder_reset (GstVideoEncoder * encoder, gboolean hard)
|
|||
|
||||
g_queue_clear_full (&priv->force_key_unit,
|
||||
(GDestroyNotify) forced_key_unit_event_free);
|
||||
priv->last_force_key_unit_request = GST_CLOCK_TIME_NONE;
|
||||
|
||||
priv->drained = TRUE;
|
||||
|
||||
|
@ -1527,15 +1556,23 @@ gst_video_encoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
|||
|
||||
GST_OBJECT_LOCK (encoder);
|
||||
if (priv->force_key_unit.head) {
|
||||
GstClockTime running_time;
|
||||
GList *l;
|
||||
GstClockTime running_time;
|
||||
gboolean throttled = FALSE, have_fevt = FALSE;
|
||||
GQueue matching_fevt = G_QUEUE_INIT;
|
||||
|
||||
running_time =
|
||||
gst_segment_to_running_time (&encoder->output_segment, GST_FORMAT_TIME,
|
||||
cstart);
|
||||
|
||||
for (l = priv->force_key_unit.head; l; l = l->next) {
|
||||
throttled = (priv->min_force_key_unit_interval != 0 &&
|
||||
priv->min_force_key_unit_interval != GST_CLOCK_TIME_NONE &&
|
||||
priv->last_force_key_unit_request != GST_CLOCK_TIME_NONE &&
|
||||
priv->last_force_key_unit_request + priv->min_force_key_unit_interval >
|
||||
running_time);
|
||||
|
||||
for (l = priv->force_key_unit.head; l && (!throttled || !have_fevt);
|
||||
l = l->next) {
|
||||
ForcedKeyUnitEvent *fevt = l->data;
|
||||
|
||||
/* Skip pending keyunits */
|
||||
|
@ -1544,12 +1581,16 @@ gst_video_encoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
|||
|
||||
/* Simple case, keyunit ASAP */
|
||||
if (fevt->running_time == GST_CLOCK_TIME_NONE) {
|
||||
have_fevt = TRUE;
|
||||
if (!throttled)
|
||||
g_queue_push_tail (&matching_fevt, fevt);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Event for before this frame */
|
||||
if (fevt->running_time <= running_time) {
|
||||
have_fevt = TRUE;
|
||||
if (!throttled)
|
||||
g_queue_push_tail (&matching_fevt, fevt);
|
||||
continue;
|
||||
}
|
||||
|
@ -1558,6 +1599,16 @@ gst_video_encoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
|||
break;
|
||||
}
|
||||
|
||||
if (throttled && have_fevt) {
|
||||
GST_DEBUG_OBJECT (encoder,
|
||||
"Not requesting a new key unit yet due to throttling (%"
|
||||
GST_TIME_FORMAT " + %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (priv->last_force_key_unit_request),
|
||||
GST_TIME_ARGS (priv->min_force_key_unit_interval),
|
||||
GST_TIME_ARGS (running_time));
|
||||
g_queue_clear (&matching_fevt);
|
||||
}
|
||||
|
||||
if (matching_fevt.length > 0) {
|
||||
ForcedKeyUnitEvent *fevt;
|
||||
gboolean all_headers = FALSE;
|
||||
|
@ -1576,6 +1627,7 @@ gst_video_encoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
|||
GST_VIDEO_CODEC_FRAME_SET_FORCE_KEYFRAME (frame);
|
||||
if (all_headers)
|
||||
GST_VIDEO_CODEC_FRAME_SET_FORCE_KEYFRAME_HEADERS (frame);
|
||||
priv->last_force_key_unit_request = running_time;
|
||||
}
|
||||
}
|
||||
GST_OBJECT_UNLOCK (encoder);
|
||||
|
@ -3004,3 +3056,50 @@ gst_video_encoder_is_qos_enabled (GstVideoEncoder * encoder)
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_video_encoder_set_min_force_key_unit_interval:
|
||||
* @encoder: the encoder
|
||||
* @interval: minimum interval
|
||||
*
|
||||
* Sets the minimum interval for requesting keyframes based on force-keyunit
|
||||
* events. Setting this to 0 will allow to handle every event, setting this to
|
||||
* %GST_CLOCK_TIME_NONE causes force-keyunit events to be ignored.
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
void
|
||||
gst_video_encoder_set_min_force_key_unit_interval (GstVideoEncoder * encoder,
|
||||
GstClockTime interval)
|
||||
{
|
||||
g_return_if_fail (GST_IS_VIDEO_ENCODER (encoder));
|
||||
|
||||
GST_OBJECT_LOCK (encoder);
|
||||
encoder->priv->min_force_key_unit_interval = interval;
|
||||
GST_OBJECT_UNLOCK (encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_video_encoder_get_min_force_key_unit_interval:
|
||||
* @encoder: the encoder
|
||||
*
|
||||
* Returns the minimum force-keyunit interval, see gst_video_encoder_set_min_force_key_unit_interval()
|
||||
* for more details.
|
||||
*
|
||||
* Returns: the minimum force-keyunit interval
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
GstClockTime
|
||||
gst_video_encoder_get_min_force_key_unit_interval (GstVideoEncoder * encoder)
|
||||
{
|
||||
GstClockTime interval;
|
||||
|
||||
g_return_val_if_fail (GST_IS_VIDEO_ENCODER (encoder), GST_CLOCK_TIME_NONE);
|
||||
|
||||
GST_OBJECT_LOCK (encoder);
|
||||
interval = encoder->priv->min_force_key_unit_interval;
|
||||
GST_OBJECT_UNLOCK (encoder);
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
|
|
@ -381,6 +381,12 @@ gboolean gst_video_encoder_is_qos_enabled (GstVideoEncoder * encoder
|
|||
GST_VIDEO_API
|
||||
GstClockTimeDiff gst_video_encoder_get_max_encode_time (GstVideoEncoder *encoder, GstVideoCodecFrame * frame);
|
||||
|
||||
GST_VIDEO_API
|
||||
void gst_video_encoder_set_min_force_key_unit_interval (GstVideoEncoder * encoder,
|
||||
GstClockTime interval);
|
||||
GST_VIDEO_API
|
||||
GstClockTime gst_video_encoder_get_min_force_key_unit_interval (GstVideoEncoder * encoder);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVideoEncoder, gst_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
|
Loading…
Reference in a new issue