Commit f0571a94 authored by Sebastian Dröge's avatar Sebastian Dröge 🍵 Committed by Sebastian Dröge
Browse files

ccextractor: Include framerate in the closedcaption caps

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.
parent e0adbee4
......@@ -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);
......
......@@ -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;
};
......
......@@ -28,11 +28,19 @@
#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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment