diff --git a/ext/closedcaption/gstccextractor.c b/ext/closedcaption/gstccextractor.c index b6bd22bff7..eb5ebe3b7a 100644 --- a/ext/closedcaption/gstccextractor.c +++ b/ext/closedcaption/gstccextractor.c @@ -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); diff --git a/ext/closedcaption/gstccextractor.h b/ext/closedcaption/gstccextractor.h index 2ad8bd3944..4ff41db7bf 100644 --- a/ext/closedcaption/gstccextractor.h +++ b/ext/closedcaption/gstccextractor.h @@ -23,7 +23,7 @@ #include #include -#include +#include 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; }; diff --git a/tests/check/elements/ccextractor.c b/tests/check/elements/ccextractor.c index 4dd21a7c61..953e9b03ee 100644 --- a/tests/check/elements/ccextractor.c +++ b/tests/check/elements/ccextractor.c @@ -28,11 +28,19 @@ #include -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);