From 36d2a21aa3d6da5f6537aef762c13ae05ae79524 Mon Sep 17 00:00:00 2001 From: Jonas Larsson Date: Fri, 25 Nov 2011 11:48:08 +0100 Subject: [PATCH] basevideoencoder: Add initial support for the all-headers field of the force-keyframe event See bug #607742. --- omx/gstbasevideoencoder.c | 49 ++++++++++++++++++++++++++++++++++++++- omx/gstbasevideoencoder.h | 5 +++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/omx/gstbasevideoencoder.c b/omx/gstbasevideoencoder.c index ca201f3bd1..6b7438c215 100644 --- a/omx/gstbasevideoencoder.c +++ b/omx/gstbasevideoencoder.c @@ -188,6 +188,7 @@ gst_base_video_encoder_reset (GstBaseVideoEncoder * base_video_encoder) gst_event_unref (base_video_encoder->force_keyunit_event); base_video_encoder->force_keyunit_event = NULL; } + gst_buffer_replace (&base_video_encoder->headers, NULL); g_list_foreach (base_video_encoder->current_frame_events, (GFunc) gst_event_unref, NULL); @@ -226,11 +227,20 @@ gst_base_video_encoder_init (GstBaseVideoEncoder * base_video_encoder, GST_DEBUG_FUNCPTR (gst_base_video_encoder_src_event)); base_video_encoder->a.at_eos = FALSE; + base_video_encoder->headers = NULL; /* encoder is expected to do so */ base_video_encoder->sink_clipping = TRUE; } +void +gst_base_video_encoder_set_headers (GstBaseVideoEncoder * base_video_encoder, + GstBuffer * headers) +{ + GST_DEBUG_OBJECT (base_video_encoder, "new headers %p", headers); + gst_buffer_replace (&base_video_encoder->headers, headers); +} + static gboolean gst_base_video_encoder_drain (GstBaseVideoEncoder * enc) { @@ -439,8 +449,13 @@ done: static void gst_base_video_encoder_finalize (GObject * object) { + GstBaseVideoEncoder *base_video_encoder; + GST_DEBUG_OBJECT (object, "finalize"); + base_video_encoder = GST_BASE_VIDEO_ENCODER (object); + gst_buffer_replace (&base_video_encoder->headers, NULL); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -515,9 +530,15 @@ gst_base_video_encoder_sink_eventfunc (GstBaseVideoEncoder * base_video_encoder, if (gst_structure_has_name (s, "GstForceKeyUnit")) { GST_OBJECT_LOCK (base_video_encoder); base_video_encoder->force_keyframe = TRUE; + if (!gst_structure_get_boolean (s, "all-headers", + &base_video_encoder->force_keyframe_headers)) + base_video_encoder->force_keyframe_headers = FALSE; + if (base_video_encoder->force_keyunit_event) gst_event_unref (base_video_encoder->force_keyunit_event); base_video_encoder->force_keyunit_event = gst_event_copy (event); + GST_DEBUG_OBJECT (base_video_encoder, "GstForceKeyUnit, all-headers %d", + base_video_encoder->force_keyframe_headers); GST_OBJECT_UNLOCK (base_video_encoder); gst_event_unref (event); ret = TRUE; @@ -602,9 +623,14 @@ gst_base_video_encoder_src_event (GstPad * pad, GstEvent * event) if (gst_structure_has_name (s, "GstForceKeyUnit")) { GST_OBJECT_LOCK (base_video_encoder); base_video_encoder->force_keyframe = TRUE; + if (!gst_structure_get_boolean (s, "all-headers", + &base_video_encoder->force_keyframe_headers)) + base_video_encoder->force_keyframe_headers = FALSE; GST_OBJECT_UNLOCK (base_video_encoder); gst_event_unref (event); + GST_DEBUG_OBJECT (base_video_encoder, "GstForceKeyUnit, all-headers %d", + base_video_encoder->force_keyframe_headers); ret = TRUE; } else { ret = @@ -841,6 +867,7 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder, GstFlowReturn ret = GST_FLOW_OK; GstBaseVideoEncoderClass *base_video_encoder_class; GList *l; + GstBuffer *headers = NULL; base_video_encoder_class = GST_BASE_VIDEO_ENCODER_GET_CLASS (base_video_encoder); @@ -910,7 +937,15 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder, } if (frame->is_sync_point) { - GST_LOG_OBJECT (base_video_encoder, "key frame"); + if (base_video_encoder->force_keyframe_headers) { + GST_DEBUG_OBJECT (base_video_encoder, "force_keyframe_headers"); + if (base_video_encoder->headers) { + gst_buffer_ref (base_video_encoder->headers); + headers = base_video_encoder->headers; + } + base_video_encoder->force_keyframe_headers = FALSE; + } + GST_LOG_OBJECT (base_video_encoder, "key frame, headers %p", headers); base_video_encoder->distance_from_sync = 0; GST_BUFFER_FLAG_UNSET (frame->src_buffer, GST_BUFFER_FLAG_DELTA_UNIT); } else { @@ -933,6 +968,12 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder, GST_BUFFER_DURATION (frame->src_buffer) = frame->presentation_duration; GST_BUFFER_OFFSET (frame->src_buffer) = frame->decode_timestamp; + if (G_UNLIKELY (headers)) { + GST_BUFFER_TIMESTAMP (headers) = frame->presentation_timestamp; + GST_BUFFER_DURATION (headers) = 0; + GST_BUFFER_OFFSET (headers) = frame->decode_timestamp; + } + /* update rate estimate */ GST_BASE_VIDEO_CODEC (base_video_encoder)->bytes += GST_BUFFER_SIZE (frame->src_buffer); @@ -953,6 +994,12 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder, gst_buffer_set_caps (GST_BUFFER (frame->src_buffer), GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder))); + if (G_UNLIKELY (headers)) { + gst_buffer_set_caps (headers, + GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder))); + gst_pad_push (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), headers); + } + if (base_video_encoder_class->shape_output) { ret = base_video_encoder_class->shape_output (base_video_encoder, frame); } else { diff --git a/omx/gstbasevideoencoder.h b/omx/gstbasevideoencoder.h index 1cb38056f4..c896ded390 100644 --- a/omx/gstbasevideoencoder.h +++ b/omx/gstbasevideoencoder.h @@ -85,6 +85,7 @@ struct _GstBaseVideoEncoder int distance_from_sync; gboolean force_keyframe; + gboolean force_keyframe_headers; /*< private >*/ /* FIXME move to real private part ? @@ -96,6 +97,7 @@ struct _GstBaseVideoEncoder GstEvent *force_keyunit_event; GList *current_frame_events; + GstBuffer *headers; union { void *padding; @@ -178,7 +180,8 @@ void gst_base_video_encoder_set_latency (GstBaseVideoEncoder * GstClockTime min_latency, GstClockTime max_latency); void gst_base_video_encoder_set_latency_fields (GstBaseVideoEncoder *base_video_encoder, int n_fields); - +void gst_base_video_encoder_set_headers (GstBaseVideoEncoder *base_video_encoder, + GstBuffer *headers); G_END_DECLS #endif