ccextractor: Include framerate in the closedcaption caps
authorSebastian Dröge <sebastian@centricular.com>
Wed, 5 Dec 2018 16:46:52 +0000 (18:46 +0200)
committerSebastian Dröge <slomo@coaxion.net>
Thu, 6 Dec 2018 16:06:05 +0000 (16:06 +0000)
It depends on the framerate how many cc_data byte pairs are allowed per
frame, and the framerate is also needed for converting into the CDP or
MCC format as the framerate is part of the header metadata.

ext/closedcaption/gstccextractor.c
ext/closedcaption/gstccextractor.h
tests/check/elements/ccextractor.c

index b6bd22b..eb5ebe3 100644 (file)
@@ -70,6 +70,8 @@ static void gst_cc_extractor_get_property (GObject * object, guint prop_id,
 
 static gboolean gst_cc_extractor_sink_event (GstPad * pad, GstObject * parent,
     GstEvent * event);
+static gboolean gst_cc_extractor_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 static GstFlowReturn gst_cc_extractor_chain (GstPad * pad, GstObject * parent,
     GstBuffer * buf);
 static GstStateChangeReturn gst_cc_extractor_change_state (GstElement *
@@ -145,6 +147,8 @@ gst_cc_extractor_reset (GstCCExtractor * filter)
     gst_element_remove_pad ((GstElement *) filter, filter->captionpad);
     filter->captionpad = NULL;
   }
+
+  memset (&filter->video_info, 0, sizeof (filter->video_info));
 }
 
 static void
@@ -153,6 +157,8 @@ gst_cc_extractor_init (GstCCExtractor * filter)
   filter->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
   gst_pad_set_event_function (filter->sinkpad,
       GST_DEBUG_FUNCPTR (gst_cc_extractor_sink_event));
+  gst_pad_set_query_function (filter->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_cc_extractor_sink_query));
   gst_pad_set_chain_function (filter->sinkpad,
       GST_DEBUG_FUNCPTR (gst_cc_extractor_chain));
   gst_pad_set_iterate_internal_links_function (filter->sinkpad,
@@ -210,6 +216,17 @@ gst_cc_extractor_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
   GST_LOG_OBJECT (pad, "received %s event: %" GST_PTR_FORMAT,
       GST_EVENT_TYPE_NAME (event), event);
   switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_CAPS:{
+      GstCaps *caps;
+
+      gst_event_parse_caps (event, &caps);
+      if (!gst_video_info_from_caps (&filter->video_info, caps)) {
+        /* We require any kind of video caps here */
+        gst_event_unref (event);
+        return FALSE;
+      }
+      break;
+    }
     case GST_EVENT_EOS:
     case GST_EVENT_FLUSH_START:
     case GST_EVENT_FLUSH_STOP:
@@ -224,8 +241,41 @@ gst_cc_extractor_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
   return gst_pad_event_default (pad, parent, event);
 }
 
+static gboolean
+gst_cc_extractor_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+  GST_LOG_OBJECT (pad, "received %s query: %" GST_PTR_FORMAT,
+      GST_QUERY_TYPE_NAME (query), query);
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_ACCEPT_CAPS:{
+      GstCaps *caps;
+      const GstStructure *s;
+
+      gst_query_parse_accept_caps (query, &caps);
+
+      /* FIXME: Ideally we would declare this in our caps but there's no way
+       * to declare caps of type "video/" and "image/" that would match all
+       * such caps
+       */
+      s = gst_caps_get_structure (caps, 0);
+      if (s && (g_str_has_prefix (gst_structure_get_name (s), "video/")
+              || g_str_has_prefix (gst_structure_get_name (s), "image/")))
+        gst_query_set_accept_caps_result (query, TRUE);
+      else
+        gst_query_set_accept_caps_result (query, FALSE);
+
+      return TRUE;
+    }
+    default:
+      break;
+  }
+
+  return gst_pad_query_default (pad, parent, query);
+}
+
 static GstCaps *
-create_caps_from_caption_type (GstVideoCaptionType caption_type)
+create_caps_from_caption_type (GstVideoCaptionType caption_type,
+    const GstVideoInfo * video_info)
 {
   GstCaps *caption_caps = NULL;
 
@@ -249,6 +299,9 @@ create_caps_from_caption_type (GstVideoCaptionType caption_type)
       break;
   }
 
+  gst_caps_set_simple (caption_caps, "framerate", GST_TYPE_FRACTION,
+      video_info->fps_n, video_info->fps_d, NULL);
+
   return caption_caps;
 }
 
@@ -265,7 +318,8 @@ gst_cc_extractor_handle_meta (GstCCExtractor * filter, GstBuffer * buf,
 
   /* Check if the meta type matches the configured one */
   if (filter->captionpad == NULL) {
-    GstCaps *caption_caps = create_caps_from_caption_type (meta->caption_type);
+    GstCaps *caption_caps =
+        create_caps_from_caption_type (meta->caption_type, &filter->video_info);
     GstEvent *stream_event;
 
     GST_DEBUG_OBJECT (filter, "Creating new caption pad");
@@ -311,7 +365,8 @@ gst_cc_extractor_handle_meta (GstCCExtractor * filter, GstBuffer * buf,
 
     filter->caption_type = meta->caption_type;
   } else if (meta->caption_type != filter->caption_type) {
-    GstCaps *caption_caps = create_caps_from_caption_type (meta->caption_type);
+    GstCaps *caption_caps =
+        create_caps_from_caption_type (meta->caption_type, &filter->video_info);
 
     GST_DEBUG_OBJECT (filter, "Caption type changed from %d to %d",
         filter->caption_type, meta->caption_type);
index 2ad8bd3..4ff41db 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <gst/gst.h>
 #include <gst/base/gstflowcombiner.h>
-#include <gst/video/video-anc.h>
+#include <gst/video/video.h>
 
 G_BEGIN_DECLS
 #define GST_TYPE_CCEXTRACTOR \
@@ -47,6 +47,8 @@ struct _GstCCExtractor
   GstPad *sinkpad, *srcpad, *captionpad;
   GstVideoCaptionType caption_type;
 
+  GstVideoInfo video_info;
+
   GstFlowCombiner *combiner;
 };
 
index 4dd21a7..953e9b0 100644 (file)
 
 #include <string.h>
 
-static GstStaticCaps foo_bar_caps = GST_STATIC_CAPS ("foo/bar");
+#define VIDEO_CAPS_STR "video/x-raw, " \
+  "format = (string) UYVY, " \
+  "width = (int) 1920, " \
+  "height = (int) 1080, " \
+  "framerate = (fraction) 30/1"
+
+static GstStaticCaps video_caps = GST_STATIC_CAPS (VIDEO_CAPS_STR);
 static GstStaticCaps cea708_cc_data_caps =
-GST_STATIC_CAPS ("closedcaption/x-cea-708,format=(string) cc_data");
+    GST_STATIC_CAPS
+    ("closedcaption/x-cea-708,format=(string) cc_data, framerate = (fraction) 30/1");
 static GstStaticCaps cea708_cdp_caps =
-GST_STATIC_CAPS ("closedcaption/x-cea-708,format=(string) cdp");
+    GST_STATIC_CAPS
+    ("closedcaption/x-cea-708,format=(string) cdp, framerate = (fraction) 30/1");
 
 GST_START_TEST (no_captions)
 {
@@ -42,7 +50,7 @@ GST_START_TEST (no_captions)
 
   h = gst_harness_new ("ccextractor");
 
-  gst_harness_set_src_caps_str (h, "foo/bar");
+  gst_harness_set_src_caps_str (h, VIDEO_CAPS_STR);
 
   buf = gst_buffer_new_and_alloc (128);
   outbuf = gst_harness_push_and_pull (h, gst_buffer_ref (buf));
@@ -54,7 +62,7 @@ GST_START_TEST (no_captions)
   caps = gst_pad_get_current_caps (h->sinkpad);
   fail_unless (caps != NULL);
   fail_unless (gst_caps_can_intersect (caps,
-          gst_static_caps_get (&foo_bar_caps)));
+          gst_static_caps_get (&video_caps)));
   gst_caps_unref (caps);
 
   gst_buffer_unref (buf);
@@ -85,7 +93,7 @@ GST_START_TEST (captions)
   g_signal_connect (h->element, "pad-added", G_CALLBACK (on_caption_pad_added),
       h2);
 
-  gst_harness_set_src_caps_str (h, "foo/bar");
+  gst_harness_set_src_caps_str (h, VIDEO_CAPS_STR);
 
   buf = gst_buffer_new_and_alloc (128);
   gst_buffer_add_video_caption_meta (buf, GST_VIDEO_CAPTION_TYPE_CEA708_RAW,
@@ -108,7 +116,7 @@ GST_START_TEST (captions)
   caps = gst_pad_get_current_caps (h->sinkpad);
   fail_unless (caps != NULL);
   fail_unless (gst_caps_can_intersect (caps,
-          gst_static_caps_get (&foo_bar_caps)));
+          gst_static_caps_get (&video_caps)));
   gst_caps_unref (caps);
 
   caps = gst_pad_get_current_caps (h2->sinkpad);
@@ -138,7 +146,7 @@ GST_START_TEST (captions)
   caps = gst_pad_get_current_caps (h->sinkpad);
   fail_unless (caps != NULL);
   fail_unless (gst_caps_can_intersect (caps,
-          gst_static_caps_get (&foo_bar_caps)));
+          gst_static_caps_get (&video_caps)));
   gst_caps_unref (caps);
 
   caps = gst_pad_get_current_caps (h2->sinkpad);
@@ -166,7 +174,7 @@ GST_START_TEST (no_captions_at_beginning_and_end)
   g_signal_connect (h->element, "pad-added", G_CALLBACK (on_caption_pad_added),
       h2);
 
-  gst_harness_set_src_caps_str (h, "foo/bar");
+  gst_harness_set_src_caps_str (h, VIDEO_CAPS_STR);
 
   buf = gst_buffer_new_and_alloc (128);
 
@@ -191,7 +199,7 @@ GST_START_TEST (no_captions_at_beginning_and_end)
   caps = gst_pad_get_current_caps (h->sinkpad);
   fail_unless (caps != NULL);
   fail_unless (gst_caps_can_intersect (caps,
-          gst_static_caps_get (&foo_bar_caps)));
+          gst_static_caps_get (&video_caps)));
   gst_caps_unref (caps);
 
   fail_unless (h2->sinkpad != NULL);
@@ -204,7 +212,7 @@ GST_START_TEST (no_captions_at_beginning_and_end)
   caps = gst_pad_get_current_caps (h->sinkpad);
   fail_unless (caps != NULL);
   fail_unless (gst_caps_can_intersect (caps,
-          gst_static_caps_get (&foo_bar_caps)));
+          gst_static_caps_get (&video_caps)));
   gst_caps_unref (caps);
 
   caps = gst_pad_get_current_caps (h2->sinkpad);
@@ -227,7 +235,7 @@ GST_START_TEST (no_captions_at_beginning_and_end)
   caps = gst_pad_get_current_caps (h->sinkpad);
   fail_unless (caps != NULL);
   fail_unless (gst_caps_can_intersect (caps,
-          gst_static_caps_get (&foo_bar_caps)));
+          gst_static_caps_get (&video_caps)));
   gst_caps_unref (caps);
 
   caps = gst_pad_get_current_caps (h2->sinkpad);
@@ -255,7 +263,7 @@ GST_START_TEST (captions_format_change)
   g_signal_connect (h->element, "pad-added", G_CALLBACK (on_caption_pad_added),
       h2);
 
-  gst_harness_set_src_caps_str (h, "foo/bar");
+  gst_harness_set_src_caps_str (h, VIDEO_CAPS_STR);
 
   buf = gst_buffer_new_and_alloc (128);
   gst_buffer_add_video_caption_meta (buf, GST_VIDEO_CAPTION_TYPE_CEA708_RAW,
@@ -278,7 +286,7 @@ GST_START_TEST (captions_format_change)
   caps = gst_pad_get_current_caps (h->sinkpad);
   fail_unless (caps != NULL);
   fail_unless (gst_caps_can_intersect (caps,
-          gst_static_caps_get (&foo_bar_caps)));
+          gst_static_caps_get (&video_caps)));
   gst_caps_unref (caps);
 
   caps = gst_pad_get_current_caps (h2->sinkpad);
@@ -308,7 +316,7 @@ GST_START_TEST (captions_format_change)
   caps = gst_pad_get_current_caps (h->sinkpad);
   fail_unless (caps != NULL);
   fail_unless (gst_caps_can_intersect (caps,
-          gst_static_caps_get (&foo_bar_caps)));
+          gst_static_caps_get (&video_caps)));
   gst_caps_unref (caps);
 
   caps = gst_pad_get_current_caps (h2->sinkpad);