mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-22 14:06:23 +00:00
ccconverter: implement support for CDP framerate conversions
- Any format involving CDP is supported. - Time codes (if present) are scaled as well. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1116>
This commit is contained in:
parent
ddc7563ac9
commit
7d028af675
3 changed files with 969 additions and 237 deletions
File diff suppressed because it is too large
Load diff
|
@ -54,6 +54,18 @@ struct _GstCCConverter
|
|||
|
||||
gint in_fps_n, in_fps_d;
|
||||
gint out_fps_n, out_fps_d;
|
||||
|
||||
/* for framerate differences, we need to keep previous/next frames in order
|
||||
* to split/merge data across multiple input or output buffers. The data is
|
||||
* stored as cc_data */
|
||||
guint8 scratch[MAX_CDP_PACKET_LEN];
|
||||
guint scratch_len;
|
||||
|
||||
guint input_frames;
|
||||
guint output_frames;
|
||||
GstVideoTimeCode current_output_timecode;
|
||||
/* previous buffer for copying metas onto */
|
||||
GstBuffer *previous_buffer;
|
||||
};
|
||||
|
||||
struct _GstCCConverterClass
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
enum CheckConversionFlags
|
||||
{
|
||||
FLAG_NONE,
|
||||
FLAG_SEND_EOS = 1,
|
||||
};
|
||||
|
||||
GST_START_TEST (cdp_requires_framerate)
|
||||
{
|
||||
GstHarness *h;
|
||||
|
@ -54,7 +60,7 @@ GST_START_TEST (cdp_requires_framerate)
|
|||
GST_FLOW_NOT_NEGOTIATED);
|
||||
|
||||
/* Now set a framerate only on the sink caps, this should still fail:
|
||||
* We can't do framerate conversion!
|
||||
* We can't come up with a framerate
|
||||
*/
|
||||
gst_harness_set_sink_caps_str (h,
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1");
|
||||
|
@ -62,7 +68,7 @@ GST_START_TEST (cdp_requires_framerate)
|
|||
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
||||
GST_FLOW_NOT_NEGOTIATED);
|
||||
|
||||
/* Then try with a framerate, this should work now */
|
||||
/* Then try with a change of framerate, this should work */
|
||||
gst_harness_set_sink_caps_str (h,
|
||||
"closedcaption/x-cea-708,format=(string)cdp");
|
||||
gst_harness_set_src_caps_str (h,
|
||||
|
@ -144,40 +150,96 @@ GST_START_TEST (framerate_passthrough)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (framerate_changes)
|
||||
{
|
||||
GstHarness *h;
|
||||
GstBuffer *buffer;
|
||||
GstMapInfo map;
|
||||
|
||||
h = gst_harness_new ("ccconverter");
|
||||
|
||||
buffer = gst_buffer_new_and_alloc (3);
|
||||
gst_buffer_map (buffer, &map, GST_MAP_WRITE);
|
||||
map.data[0] = 0x00;
|
||||
map.data[1] = 0x80;
|
||||
map.data[2] = 0x80;
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
|
||||
/* success case */
|
||||
gst_harness_set_src_caps_str (h,
|
||||
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
|
||||
gst_harness_set_sink_caps_str (h,
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1");
|
||||
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
||||
GST_FLOW_OK);
|
||||
|
||||
/* test an invalid cdp framerate */
|
||||
gst_harness_set_sink_caps_str (h,
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)1111/1");
|
||||
fail_unless_equals_int (gst_harness_push (h, buffer),
|
||||
GST_FLOW_NOT_NEGOTIATED);
|
||||
|
||||
gst_harness_teardown (h);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static void
|
||||
check_conversion (const guint8 * in, guint in_len, const guint8 * out,
|
||||
guint out_len, const gchar * in_caps, const gchar * out_caps,
|
||||
const GstVideoTimeCode * in_tc, const GstVideoTimeCode * out_tc)
|
||||
check_conversion_multiple (guint n_in, const guint8 ** in, guint * in_len,
|
||||
guint n_out, const guint8 ** out, guint * out_len, const gchar * in_caps,
|
||||
const gchar * out_caps, const GstVideoTimeCode ** in_tc,
|
||||
const GstVideoTimeCode ** out_tc, enum CheckConversionFlags flags)
|
||||
{
|
||||
GstHarness *h;
|
||||
GstBuffer *buffer;
|
||||
GstVideoTimeCodeMeta *out_tc_meta;
|
||||
int i = 0;
|
||||
|
||||
h = gst_harness_new ("ccconverter");
|
||||
|
||||
gst_harness_set_src_caps_str (h, in_caps);
|
||||
gst_harness_set_sink_caps_str (h, out_caps);
|
||||
|
||||
buffer =
|
||||
gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, (gpointer) in,
|
||||
in_len, 0, in_len, NULL, NULL);
|
||||
if (in_tc)
|
||||
gst_buffer_add_video_time_code_meta (buffer, in_tc);
|
||||
for (i = 0; i < n_in; i++) {
|
||||
buffer =
|
||||
gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, (gpointer) in[i],
|
||||
in_len[i], 0, in_len[i], NULL, NULL);
|
||||
GST_INFO ("pushing buffer %u %" GST_PTR_FORMAT, i, buffer);
|
||||
if (in_tc && in_tc[i])
|
||||
gst_buffer_add_video_time_code_meta (buffer, in_tc[i]);
|
||||
fail_unless_equals_int (gst_harness_push (h, buffer), GST_FLOW_OK);
|
||||
}
|
||||
|
||||
buffer = gst_harness_push_and_pull (h, buffer);
|
||||
if (flags & FLAG_SEND_EOS)
|
||||
fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
|
||||
|
||||
fail_unless (buffer != NULL);
|
||||
gst_check_buffer_data (buffer, out, out_len);
|
||||
out_tc_meta = gst_buffer_get_video_time_code_meta (buffer);
|
||||
fail_if (out_tc_meta == NULL && out_tc != NULL);
|
||||
if (out_tc_meta)
|
||||
fail_unless (gst_video_time_code_compare (&out_tc_meta->tc, out_tc) == 0);
|
||||
for (i = 0; i < n_out; i++) {
|
||||
buffer = gst_harness_pull (h);
|
||||
|
||||
gst_buffer_unref (buffer);
|
||||
GST_INFO ("pulled buffer %u %" GST_PTR_FORMAT, i, buffer);
|
||||
fail_unless (buffer != NULL);
|
||||
gst_check_buffer_data (buffer, out[i], out_len[i]);
|
||||
out_tc_meta = gst_buffer_get_video_time_code_meta (buffer);
|
||||
fail_if (out_tc_meta == NULL && out_tc != NULL && out_tc[i] != NULL);
|
||||
if (out_tc_meta && out_tc && out_tc[i])
|
||||
fail_unless (gst_video_time_code_compare (&out_tc_meta->tc,
|
||||
out_tc[i]) == 0);
|
||||
|
||||
gst_buffer_unref (buffer);
|
||||
}
|
||||
|
||||
gst_harness_teardown (h);
|
||||
}
|
||||
|
||||
static void
|
||||
check_conversion (const guint8 * in, guint in_len, const guint8 * out,
|
||||
guint out_len, const gchar * in_caps, const gchar * out_caps,
|
||||
const GstVideoTimeCode * in_tc, const GstVideoTimeCode * out_tc)
|
||||
{
|
||||
check_conversion_multiple (1, &in, &in_len, 1, &out, &out_len, in_caps,
|
||||
out_caps, &in_tc, &out_tc, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
check_conversion_tc_passthrough (const guint8 * in, guint in_len,
|
||||
const guint8 * out, guint out_len, const gchar * in_caps,
|
||||
|
@ -362,6 +424,7 @@ GST_END_TEST;
|
|||
|
||||
GST_START_TEST (convert_cea708_cdp_cea708_cc_data_too_big)
|
||||
{
|
||||
/* tests that too large input is truncated */
|
||||
const guint8 in[] =
|
||||
{ 0x96, 0x69, 0x2e, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xeb, 0xfc, 0x80, 0x80,
|
||||
0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
||||
|
@ -379,6 +442,316 @@ GST_START_TEST (convert_cea708_cdp_cea708_cc_data_too_big)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (convert_cea708_cdp_cea708_cdp_double_framerate)
|
||||
{
|
||||
/* tests that packets are split exactly in half when doubling the framerate */
|
||||
const guint8 in1[] =
|
||||
{ 0x96, 0x69, 0x49, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xf4, 0xfc, 0x80, 0x80,
|
||||
0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00,
|
||||
0xfc, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x00, 0xd2
|
||||
};
|
||||
const guint8 *in[] = { in1 };
|
||||
guint in_len[] = { sizeof (in1) };
|
||||
GstVideoTimeCode in_tc1;
|
||||
const GstVideoTimeCode *in_tc[] = { &in_tc1 };
|
||||
|
||||
const guint8 out1[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x00, 0x71, 0xd0,
|
||||
0xa0, 0x30, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74,
|
||||
0x00, 0x00, 0xe4
|
||||
};
|
||||
const guint8 out2[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x01, 0x71, 0xd0,
|
||||
0xa0, 0x30, 0x10, 0x72, 0xea, 0xfe, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc,
|
||||
0x00, 0x00, 0xfc, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74,
|
||||
0x00, 0x01, 0xca
|
||||
};
|
||||
const guint8 *out[] = { out1, out2 };
|
||||
guint out_len[] = { sizeof (out1), sizeof (out2) };
|
||||
GstVideoTimeCode out_tc1, out_tc2;
|
||||
const GstVideoTimeCode *out_tc[] = { &out_tc1, &out_tc2 };
|
||||
|
||||
gst_video_time_code_init (&in_tc1, 30, 1, NULL,
|
||||
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 4, 0);
|
||||
fail_unless (gst_video_time_code_is_valid (&in_tc1));
|
||||
|
||||
gst_video_time_code_init (&out_tc1, 60, 1, NULL,
|
||||
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
|
||||
fail_unless (gst_video_time_code_is_valid (&out_tc1));
|
||||
gst_video_time_code_init (&out_tc2, 60, 1, NULL,
|
||||
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 9, 0);
|
||||
fail_unless (gst_video_time_code_is_valid (&out_tc2));
|
||||
|
||||
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
||||
G_N_ELEMENTS (out_len), out, out_len,
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
||||
in_tc, out_tc, 0);
|
||||
|
||||
gst_video_time_code_clear (&in_tc1);
|
||||
gst_video_time_code_clear (&out_tc1);
|
||||
gst_video_time_code_clear (&out_tc2);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (convert_cea708_cdp_cea708_cdp_half_framerate)
|
||||
{
|
||||
/* tests that two input packets are merged together when halving the
|
||||
* framerate */
|
||||
const guint8 in1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
|
||||
0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x00, 0x7a
|
||||
};
|
||||
const guint8 in2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
|
||||
0xfe, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x01, 0x70
|
||||
};
|
||||
const guint8 *in[] = { in1, in2 };
|
||||
guint in_len[] = { sizeof (in1), sizeof (in2) };
|
||||
GstVideoTimeCode in_tc1, in_tc2;
|
||||
const GstVideoTimeCode *in_tc[] = { &in_tc1, &in_tc2 };
|
||||
|
||||
const guint8 out1[] =
|
||||
{ 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x00, 0x71, 0xd0, 0xa0, 0x30, 0x00,
|
||||
0x72, 0xf4, 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfc,
|
||||
0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8,
|
||||
0x00, 0x00, 0x74, 0x00, 0x00, 0x2a
|
||||
};
|
||||
const guint8 *out[] = { out1 };
|
||||
guint out_len[] = { sizeof (out1) };
|
||||
GstVideoTimeCode out_tc1;
|
||||
const GstVideoTimeCode *out_tc[] = { &out_tc1 };
|
||||
|
||||
gst_video_time_code_init (&in_tc1, 60, 1, NULL,
|
||||
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
|
||||
fail_unless (gst_video_time_code_is_valid (&in_tc1));
|
||||
gst_video_time_code_init (&in_tc2, 60, 1, NULL,
|
||||
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
|
||||
fail_unless (gst_video_time_code_is_valid (&in_tc2));
|
||||
|
||||
gst_video_time_code_init (&out_tc1, 30, 1, NULL,
|
||||
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 4, 0);
|
||||
fail_unless (gst_video_time_code_is_valid (&out_tc1));
|
||||
|
||||
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
||||
G_N_ELEMENTS (out_len), out, out_len,
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
|
||||
in_tc, out_tc, 0);
|
||||
|
||||
gst_video_time_code_clear (&in_tc1);
|
||||
gst_video_time_code_clear (&in_tc2);
|
||||
gst_video_time_code_clear (&out_tc1);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_merge)
|
||||
{
|
||||
/* check that a low framerate packet can be split into 3 high framerate
|
||||
* packets with the extra data on the third input packet being placed at the
|
||||
* beginning of the second output packet */
|
||||
const guint8 in1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
|
||||
0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x00, 0x7a
|
||||
};
|
||||
/* enough input to fully cover two output packets. Extra is discarded */
|
||||
const guint8 *in[] = { in1, in1, in1, in1, in1, in1, in1 };
|
||||
guint in_len[] =
|
||||
{ sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1),
|
||||
sizeof (in1)
|
||||
};
|
||||
|
||||
const guint8 out1[] =
|
||||
{ 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x80, 0x80,
|
||||
0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x80, 0x80,
|
||||
0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0x74, 0x00, 0x00, 0x12
|
||||
};
|
||||
const guint8 out2[] =
|
||||
{ 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x01, 0x72, 0xf9, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0x74, 0x00, 0x01, 0x1a
|
||||
};
|
||||
const guint8 *out[] = { out1, out2 };
|
||||
guint out_len[] = { sizeof (out1), sizeof (out2) };
|
||||
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
||||
G_N_ELEMENTS (out_len), out, out_len,
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
|
||||
NULL, NULL, 0);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split)
|
||||
{
|
||||
/* test that a low framerate stream produces multiple output packets for a
|
||||
* high framerate */
|
||||
const guint8 in1[] =
|
||||
{ 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x80, 0x80,
|
||||
0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x80, 0x80,
|
||||
0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0x74, 0x00, 0x00, 0x12
|
||||
};
|
||||
const guint8 *in[] = { in1, in1 };
|
||||
guint in_len[] = { sizeof (in1), sizeof (in1) };
|
||||
|
||||
const guint8 out1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
|
||||
0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x00, 0x7a
|
||||
};
|
||||
const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
|
||||
0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x01, 0x78
|
||||
};
|
||||
const guint8 out3[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea,
|
||||
0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x02, 0x6c
|
||||
};
|
||||
const guint8 out4[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x03, 0x74
|
||||
};
|
||||
const guint8 *out[] = { out1, out2, out3, out4 };
|
||||
guint out_len[] =
|
||||
{ sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4) };
|
||||
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
||||
G_N_ELEMENTS (out_len), out, out_len,
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
||||
NULL, NULL, 0);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split_eos)
|
||||
{
|
||||
/* test that a low framerate stream produces multiple output packets for a
|
||||
* high framerate and that an EOS will push the pending data */
|
||||
const guint8 in1[] =
|
||||
{ 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x80, 0x80,
|
||||
0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x80, 0x80,
|
||||
0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf9, 0x00, 0x00,
|
||||
0x74, 0x00, 0x00, 0x12
|
||||
};
|
||||
const guint8 *in[] = { in1 };
|
||||
guint in_len[] = { sizeof (in1) };
|
||||
|
||||
const guint8 out1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
|
||||
0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x00, 0x7a
|
||||
};
|
||||
const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
|
||||
0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x01, 0x78
|
||||
};
|
||||
const guint8 out3[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea,
|
||||
0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf9, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x02, 0x75
|
||||
};
|
||||
const guint8 *out[] = { out1, out2, out3 };
|
||||
guint out_len[] = { sizeof (out1), sizeof (out2), sizeof (out3) };
|
||||
|
||||
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
||||
G_N_ELEMENTS (out_len), out, out_len,
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
||||
NULL, NULL, FLAG_SEND_EOS);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling)
|
||||
{
|
||||
const guint8 in1[] = { 0x96, 0x69, 0x10, 0x7f, 0x43, 0x00, 0x00, 0x72, 0xe1,
|
||||
0xfc, 0x80, 0x80, 0x74, 0x00, 0x00, 0x7a
|
||||
};
|
||||
const guint8 *in[] = { in1, in1 };
|
||||
guint in_len[] = { sizeof (in1), sizeof (in1) };
|
||||
GstVideoTimeCode in_tc1, in_tc2;
|
||||
const GstVideoTimeCode *in_tc[] = { &in_tc1, &in_tc2 };
|
||||
|
||||
const guint8 out1[] =
|
||||
{ 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x00, 0x71, 0xc0, 0x90, 0x12, 0x12,
|
||||
0x72, 0xea, 0xfc, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x00, 0x16
|
||||
};
|
||||
const guint8 out2[] =
|
||||
{ 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x01, 0x71, 0xc0, 0xa0, 0x00, 0x00,
|
||||
0x72, 0xea, 0xfc, 0x80, 0x80, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8,
|
||||
0x00, 0x00, 0xf8, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x74, 0x00, 0x01, 0x28
|
||||
};
|
||||
const guint8 *out[] = { out1, out2 };
|
||||
guint out_len[] = { sizeof (out1), sizeof (out2) };
|
||||
GstVideoTimeCode out_tc1, out_tc2;
|
||||
const GstVideoTimeCode *out_tc[] = { &out_tc1, &out_tc2 };
|
||||
|
||||
gst_video_time_code_init (&in_tc1, 60000, 1001, NULL,
|
||||
GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME, 0, 1, 59, 59, 0);
|
||||
fail_unless (gst_video_time_code_is_valid (&in_tc1));
|
||||
|
||||
gst_video_time_code_init (&in_tc2, 60000, 1001, NULL,
|
||||
GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME, 0, 2, 0, 4, 0);
|
||||
fail_unless (gst_video_time_code_is_valid (&in_tc2));
|
||||
|
||||
gst_video_time_code_init (&out_tc1, 60, 1, NULL,
|
||||
GST_VIDEO_TIME_CODE_FLAGS_NONE, 0, 1, 59, 59, 0);
|
||||
fail_unless (gst_video_time_code_is_valid (&out_tc1));
|
||||
|
||||
gst_video_time_code_init (&out_tc2, 60, 1, NULL,
|
||||
GST_VIDEO_TIME_CODE_FLAGS_NONE, 0, 2, 0, 0, 0);
|
||||
fail_unless (gst_video_time_code_is_valid (&out_tc2));
|
||||
|
||||
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
||||
G_N_ELEMENTS (out_len), out, out_len,
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60000/1001",
|
||||
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
||||
in_tc, out_tc, FLAG_SEND_EOS);
|
||||
|
||||
gst_video_time_code_clear (&in_tc1);
|
||||
gst_video_time_code_clear (&out_tc1);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
ccextractor_suite (void)
|
||||
{
|
||||
|
@ -389,6 +762,7 @@ ccextractor_suite (void)
|
|||
|
||||
tcase_add_test (tc, cdp_requires_framerate);
|
||||
tcase_add_test (tc, framerate_passthrough);
|
||||
tcase_add_test (tc, framerate_changes);
|
||||
tcase_add_test (tc, convert_cea608_raw_cea608_s334_1a);
|
||||
tcase_add_test (tc, convert_cea608_raw_cea708_cc_data);
|
||||
tcase_add_test (tc, convert_cea608_raw_cea708_cdp);
|
||||
|
@ -403,6 +777,12 @@ ccextractor_suite (void)
|
|||
tcase_add_test (tc, convert_cea708_cdp_cea608_s334_1a);
|
||||
tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data);
|
||||
tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data_too_big);
|
||||
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_half_framerate);
|
||||
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_double_framerate);
|
||||
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_merge);
|
||||
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_split);
|
||||
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_split_eos);
|
||||
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue