basevideoencoder: Add initial support for the all-headers field of the force-keyframe...
authorJonas Larsson <jonas@hallerud.se>
Fri, 25 Nov 2011 10:48:08 +0000 (11:48 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 29 Nov 2011 11:20:09 +0000 (12:20 +0100)
See bug #607742.

omx/gstbasevideoencoder.c
omx/gstbasevideoencoder.h

index ca201f3..6b7438c 100644 (file)
@@ -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 {
index 1cb3805..c896ded 100644 (file)
@@ -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