From 26c598dd1b6cb7064f570eadefa1831ed77a6375 Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Tue, 19 Nov 2024 17:38:43 +0100 Subject: [PATCH] tests: cccombiner: Test rescheduling 50fps to 25fps w/o overflow Part-of: --- .../tests/check/elements/cccombiner.c | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/subprojects/gst-plugins-bad/tests/check/elements/cccombiner.c b/subprojects/gst-plugins-bad/tests/check/elements/cccombiner.c index 236e45b295..93d9da8bea 100644 --- a/subprojects/gst-plugins-bad/tests/check/elements/cccombiner.c +++ b/subprojects/gst-plugins-bad/tests/check/elements/cccombiner.c @@ -29,6 +29,8 @@ #include static GstStaticCaps foo_bar_caps = GST_STATIC_CAPS ("foo/bar"); +static GstStaticCaps foo_bar_caps_25fps = +GST_STATIC_CAPS ("foo/bar,framerate=25/1"); static GstStaticCaps foo_bar_caps_60fps = GST_STATIC_CAPS ("foo/bar,framerate=60/1"); static GstStaticCaps cea708_cc_data_caps = @@ -301,6 +303,126 @@ GST_START_TEST (captions_no_output_padding_60fps_608_field1_only) GST_END_TEST; +GST_START_TEST (captions_50fps_to_25fps) +{ + GstHarness *h, *h2; + GstBuffer *outbuf; + GstPad *caption_pad; + GstCaps *caps; + GstVideoCaptionMeta *meta; + const guint8 cc_data_both[72] = { + 0xfc, 0x20, 0x20, 0xfd, 0x20, 0x20, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + }; + const guint8 cc_data_field1[36] = { + 0xfc, 0x20, 0x20, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + }; + const guint8 cc_data_field2[36] = { + 0xfd, 0x20, 0x20, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, + }; + int i = 0; + + h = gst_harness_new_with_padnames ("cccombiner", "sink", "src"); + h2 = gst_harness_new_with_element (h->element, NULL, NULL); + caption_pad = gst_element_request_pad_simple (h->element, "caption"); + gst_harness_add_element_sink_pad (h2, caption_pad); + gst_object_unref (caption_pad); + + g_object_set (h->element, "emit-signals", TRUE, NULL); + g_signal_connect (h->element, "samples-selected", + G_CALLBACK (samples_selected_cb), NULL); + + gst_element_set_state (h->element, GST_STATE_NULL); + gst_element_set_state (h->element, GST_STATE_PLAYING); + + gst_harness_set_src_caps_str (h, foo_bar_caps_25fps.string); + gst_harness_set_src_caps_str (h2, cea708_cc_data_caps.string); + + /* We're rescheduling a 50 fps stream (1 tuple per frame) + * to 25 fps (2 tuples per frame) */ + + /* Push a video buffer and two caption buffers */ + for (i = 0; i < 300; i++) { + GstBuffer *video_buf, *caption_buf = NULL; + + video_buf = gst_buffer_new_and_alloc (128); + GST_BUFFER_PTS (video_buf) = i * 40 * GST_MSECOND; + GST_BUFFER_DURATION (video_buf) = 40 * GST_MSECOND; + gst_harness_push (h, video_buf); + + caption_buf = gst_buffer_new_and_alloc (36); + gst_buffer_fill (caption_buf, 0, cc_data_field1, 36); + GST_BUFFER_PTS (caption_buf) = (2 * i) * 20 * GST_MSECOND; + GST_BUFFER_DURATION (caption_buf) = 20 * GST_MSECOND; + gst_harness_push (h2, caption_buf); + + caption_buf = gst_buffer_new_and_alloc (36); + gst_buffer_fill (caption_buf, 0, cc_data_field2, 36); + GST_BUFFER_PTS (caption_buf) = (2 * i + 1) * 20 * GST_MSECOND; + GST_BUFFER_DURATION (caption_buf) = 20 * GST_MSECOND; + gst_harness_push (h2, caption_buf); + + /* Pull the previous output buffer */ + if (i > 0) { + int j; + outbuf = gst_harness_pull (h); + fail_unless (outbuf != NULL); + + meta = gst_buffer_get_video_caption_meta (outbuf); + fail_unless (meta != NULL); + fail_unless_equals_int (meta->caption_type, + GST_VIDEO_CAPTION_TYPE_CEA708_RAW); + fail_unless_equals_int (meta->size, 72); + GST_MEMDUMP ("caption data", meta->data, meta->size); + + for (j = 0; j < meta->size; j++) { + fail_unless_equals_int (meta->data[j], cc_data_both[j]); + } + + gst_buffer_unref (outbuf); + } + expected_video_buffer = video_buf; + if (caption_buf) + expected_caption_buffer = caption_buf; + } + + /* Push EOS on both pads get the second output buffer, we otherwise wait + * in case there are further captions for the current video buffer */ + gst_harness_push_event (h, gst_event_new_eos ()); + gst_harness_push_event (h2, gst_event_new_eos ()); + + outbuf = gst_harness_pull (h); + fail_unless (outbuf != NULL); + + meta = gst_buffer_get_video_caption_meta (outbuf); + fail_unless (meta != NULL); + fail_unless_equals_int (meta->caption_type, + GST_VIDEO_CAPTION_TYPE_CEA708_RAW); + fail_unless_equals_int (meta->size, 72); + + gst_buffer_unref (outbuf); + + /* Caps should be equal to input caps */ + 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_caps_unref (caps); + + gst_harness_teardown (h); + gst_harness_teardown (h2); +} + +GST_END_TEST; + static Suite * cccombiner_suite (void) { @@ -312,6 +434,7 @@ cccombiner_suite (void) tcase_add_test (tc, no_captions); tcase_add_test (tc, captions_and_eos); tcase_add_test (tc, captions_no_output_padding_60fps_608_field1_only); + tcase_add_test (tc, captions_50fps_to_25fps); return s; }