3 * Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
25 #include <gst/video/video.h>
26 #include <gst/check/gstcheck.h>
27 #include <gst/check/gstharness.h>
31 enum CheckConversionFlags
37 GST_START_TEST (cdp_requires_valid_framerate)
43 h = gst_harness_new ("ccconverter");
45 /* Enforce conversion to CDP */
46 gst_harness_set_sink_caps_str (h,
47 "closedcaption/x-cea-708,format=(string)cdp");
49 /* Try without a framerate first, this has to fail */
50 gst_harness_set_src_caps_str (h,
51 "closedcaption/x-cea-708,format=(string)cc_data");
53 buffer = gst_buffer_new_and_alloc (3);
54 gst_buffer_map (buffer, &map, GST_MAP_WRITE);
58 gst_buffer_unmap (buffer, &map);
59 fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
60 GST_FLOW_NOT_NEGOTIATED);
62 /* Now set a framerate only on the sink caps, this should still fail:
63 * We can't come up with a framerate
65 gst_harness_set_sink_caps_str (h,
66 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1");
68 fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
69 GST_FLOW_NOT_NEGOTIATED);
71 /* Then try with a change of framerate, this should work */
72 gst_harness_set_sink_caps_str (h,
73 "closedcaption/x-cea-708,format=(string)cdp");
74 gst_harness_set_src_caps_str (h,
75 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
77 fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
80 /* Then try with an invalid CDP framerate, this should fail */
81 gst_harness_set_sink_caps_str (h,
82 "closedcaption/x-cea-708,format=(string)cdp");
83 gst_harness_set_src_caps_str (h,
84 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)29/1");
86 fail_unless_equals_int (gst_harness_push (h, buffer),
87 GST_FLOW_NOT_NEGOTIATED);
89 gst_harness_teardown (h);
94 GST_START_TEST (framerate_passthrough)
99 GstCaps *caps, *expected_caps;
101 h = gst_harness_new ("ccconverter");
103 gst_harness_set_src_caps_str (h,
104 "closedcaption/x-cea-608,format=(string)s334-1a,framerate=(fraction)30/1");
106 gst_harness_set_sink_caps_str (h,
107 "closedcaption/x-cea-708,format=(string)cc_data");
109 buffer = gst_buffer_new_and_alloc (3);
110 gst_buffer_map (buffer, &map, GST_MAP_WRITE);
114 gst_buffer_unmap (buffer, &map);
116 fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
119 caps = gst_pad_get_current_caps (h->sinkpad);
123 ("closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
124 gst_check_caps_equal (caps, expected_caps);
125 gst_caps_unref (caps);
126 gst_caps_unref (expected_caps);
128 /* Now try between the same formats, should still pass through */
129 gst_harness_set_src_caps_str (h,
130 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
132 gst_harness_set_sink_caps_str (h,
133 "closedcaption/x-cea-708,format=(string)cc_data");
135 fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
138 caps = gst_pad_get_current_caps (h->sinkpad);
142 ("closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
143 gst_check_caps_equal (caps, expected_caps);
144 gst_caps_unref (caps);
145 gst_caps_unref (expected_caps);
147 /* And another time with the same format but only framerate on the output
148 * side. This should fail as we can't just come up with a framerate! */
149 gst_harness_set_src_caps_str (h,
150 "closedcaption/x-cea-708,format=(string)cc_data");
152 gst_harness_set_sink_caps_str (h,
153 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
155 fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
156 GST_FLOW_NOT_NEGOTIATED);
158 /* Now try cdp -> cc_data with framerate passthrough */
159 gst_harness_set_src_caps_str (h,
160 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1");
162 gst_harness_set_sink_caps_str (h,
163 "closedcaption/x-cea-708,format=(string)cc_data");
165 fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
168 gst_buffer_unref (buffer);
169 gst_harness_teardown (h);
174 GST_START_TEST (framerate_changes)
180 h = gst_harness_new ("ccconverter");
182 buffer = gst_buffer_new_and_alloc (3);
183 gst_buffer_map (buffer, &map, GST_MAP_WRITE);
187 gst_buffer_unmap (buffer, &map);
190 gst_harness_set_src_caps_str (h,
191 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
192 gst_harness_set_sink_caps_str (h,
193 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1");
194 fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
197 /* test an invalid cdp framerate */
198 gst_harness_set_sink_caps_str (h,
199 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)1111/1");
200 fail_unless_equals_int (gst_harness_push (h, buffer),
201 GST_FLOW_NOT_NEGOTIATED);
203 gst_harness_teardown (h);
208 GST_START_TEST (framerate_invalid_format)
215 const gchar *failure_caps[] = {
216 /* all of these combinations should fail with different framerates */
217 "closedcaption/x-cea-608,format=(string)raw",
218 "closedcaption/x-cea-608,format=(string)s334-1a",
219 "closedcaption/x-cea-708,format=(string)cc_data",
222 h = gst_harness_new ("ccconverter");
224 buffer = gst_buffer_new_and_alloc (3);
225 gst_buffer_map (buffer, &map, GST_MAP_WRITE);
229 gst_buffer_unmap (buffer, &map);
231 /* framerate conversion failure cases */
232 for (i = 0; i < G_N_ELEMENTS (failure_caps); i++) {
233 for (j = 0; j < G_N_ELEMENTS (failure_caps); j++) {
234 gchar *srccaps, *sinkcaps;
237 g_strdup_printf ("%s%s", failure_caps[i],
238 ",framerate=(fraction)30/1");
240 g_strdup_printf ("%s%s", failure_caps[i],
241 ",framerate=(fraction)60/1");
243 GST_INFO ("attempting conversion from %s", srccaps);
244 GST_INFO (" to %s", sinkcaps);
246 gst_harness_set_src_caps_str (h, srccaps);
247 gst_harness_set_sink_caps_str (h, sinkcaps);
248 fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
249 GST_FLOW_NOT_NEGOTIATED);
256 gst_buffer_unref (buffer);
257 gst_harness_teardown (h);
263 check_conversion_multiple (guint n_in, const guint8 ** in, guint * in_len,
264 guint n_out, const guint8 ** out, guint * out_len, const gchar * in_caps,
265 const gchar * out_caps, const GstVideoTimeCode ** in_tc,
266 const GstVideoTimeCode ** out_tc, enum CheckConversionFlags flags)
270 GstVideoTimeCodeMeta *out_tc_meta;
273 h = gst_harness_new ("ccconverter");
275 gst_harness_set_src_caps_str (h, in_caps);
276 gst_harness_set_sink_caps_str (h, out_caps);
278 for (i = 0; i < n_in; i++) {
280 gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, (gpointer) in[i],
281 in_len[i], 0, in_len[i], NULL, NULL);
282 GST_INFO ("pushing buffer %u %" GST_PTR_FORMAT, i, buffer);
283 if (in_tc && in_tc[i])
284 gst_buffer_add_video_time_code_meta (buffer, in_tc[i]);
285 fail_unless_equals_int (gst_harness_push (h, buffer), GST_FLOW_OK);
288 if (flags & FLAG_SEND_EOS)
289 fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
291 for (i = 0; i < n_out; i++) {
292 buffer = gst_harness_pull (h);
294 GST_INFO ("pulled buffer %u %" GST_PTR_FORMAT, i, buffer);
295 fail_unless (buffer != NULL);
296 gst_check_buffer_data (buffer, out[i], out_len[i]);
297 out_tc_meta = gst_buffer_get_video_time_code_meta (buffer);
298 fail_if (out_tc_meta == NULL && out_tc != NULL && out_tc[i] != NULL);
299 if (out_tc_meta && out_tc && out_tc[i])
300 fail_unless (gst_video_time_code_compare (&out_tc_meta->tc,
303 gst_buffer_unref (buffer);
306 gst_harness_teardown (h);
310 check_conversion (const guint8 * in, guint in_len, const guint8 * out,
311 guint out_len, const gchar * in_caps, const gchar * out_caps,
312 const GstVideoTimeCode * in_tc, const GstVideoTimeCode * out_tc)
314 check_conversion_multiple (1, &in, &in_len, 1, &out, &out_len, in_caps,
315 out_caps, &in_tc, &out_tc, 0);
319 check_conversion_tc_passthrough (const guint8 * in, guint in_len,
320 const guint8 * out, guint out_len, const gchar * in_caps,
321 const gchar * out_caps)
324 gst_video_time_code_init (&tc, 30, 1, NULL, GST_VIDEO_TIME_CODE_FLAGS_NONE,
326 check_conversion (in, in_len, out, out_len, in_caps, out_caps, &tc, &tc);
327 gst_video_time_code_clear (&tc);
330 GST_START_TEST (convert_cea608_raw_cea608_s334_1a)
332 const guint8 in[] = { 0x80, 0x80 };
333 const guint8 out[] = { 0x80, 0x80, 0x80 };
334 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
335 "closedcaption/x-cea-608,format=(string)raw",
336 "closedcaption/x-cea-608,format=(string)s334-1a");
341 GST_START_TEST (convert_cea608_raw_cea708_cc_data)
343 const guint8 in[] = { 0x80, 0x80 };
344 const guint8 out[] = { 0xfc, 0x80, 0x80 };
345 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
346 "closedcaption/x-cea-608,format=(string)raw",
347 "closedcaption/x-cea-708,format=(string)cc_data");
352 GST_START_TEST (convert_cea608_raw_cea708_cdp)
354 const guint8 in1[] = { 0x81, 0x82 };
355 const guint8 in2[] = { 0x80, 0x80 };
356 const guint8 out1[] =
357 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x81, 0x82,
358 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
359 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
360 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6b
362 const guint8 out2[] =
363 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x80, 0x80,
364 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
365 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
366 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x6f
368 const guint8 *in[] = { in1, in2 };
369 guint in_len[] = { sizeof (in1), sizeof (in2) };
370 const guint8 *out[] = { out1, out2 };
371 guint out_len[] = { sizeof (out1), sizeof (out2) };
372 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
373 G_N_ELEMENTS (out_len), out, out_len,
374 "closedcaption/x-cea-608,format=(string)raw,framerate=(fraction)60/1",
375 "closedcaption/x-cea-708,format=(string)cdp", NULL, NULL, 0);
380 GST_START_TEST (convert_cea608_s334_1a_cea608_raw)
382 const guint8 in[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
383 const guint8 out[] = { 0x80, 0x80 };
384 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
385 "closedcaption/x-cea-608,format=(string)s334-1a",
386 "closedcaption/x-cea-608,format=(string)raw");
391 GST_START_TEST (convert_cea608_s334_1a_cea608_raw_too_big)
394 { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80,
397 const guint8 out[] = { 0x80, 0x80, 0x80, 0x80 };
398 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
399 "closedcaption/x-cea-608,format=(string)s334-1a",
400 "closedcaption/x-cea-608,format=(string)raw");
405 GST_START_TEST (convert_cea608_s334_1a_cea708_cc_data)
407 const guint8 in[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
408 const guint8 out[] = { 0xfc, 0x80, 0x80, 0xfd, 0x80, 0x80 };
409 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
410 "closedcaption/x-cea-608,format=(string)s334-1a",
411 "closedcaption/x-cea-708,format=(string)cc_data");
416 GST_START_TEST (convert_cea608_s334_1a_cea708_cdp)
418 const guint8 in[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
420 { 0x96, 0x69, 0x49, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xf4, 0xf8, 0x80, 0x80,
421 0xf9, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
422 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
423 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
424 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
425 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0xb7
427 check_conversion (in, sizeof (in), out, sizeof (out),
428 "closedcaption/x-cea-608,format=(string)s334-1a,framerate=(fraction)30/1",
429 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
435 GST_START_TEST (convert_cea708_cc_data_cea608_raw)
437 const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
438 const guint8 out[] = { 0x80, 0x80 };
439 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
440 "closedcaption/x-cea-708,format=(string)cc_data",
441 "closedcaption/x-cea-608,format=(string)raw");
446 GST_START_TEST (convert_cea708_cc_data_cea608_s334_1a)
448 const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
449 const guint8 out[] = { 0x80, 0x80, 0x80 };
450 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
451 "closedcaption/x-cea-708,format=(string)cc_data",
452 "closedcaption/x-cea-608,format=(string)s334-1a");
457 GST_START_TEST (convert_cea708_cc_data_cea708_cdp)
459 const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
461 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xf8, 0x80, 0x80,
462 0xfe, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
463 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
464 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6e
466 check_conversion (in, sizeof (in), out, sizeof (out),
467 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
468 "closedcaption/x-cea-708,format=(string)cdp", NULL, NULL);
473 GST_START_TEST (convert_cea708_cdp_cea608_raw)
476 { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
477 0xfd, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
479 const guint8 out1[] = { 0x80, 0x80, 0x80, 0x80 };
481 { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x81,
482 0xfd, 0x82, 0x83, 0x74, 0x00, 0x00, 0x8a
484 const guint8 out2[] = { 0x80, 0x81, 0x80, 0x80 };
485 check_conversion_tc_passthrough (in1, sizeof (in1), out1, sizeof (out1),
486 "closedcaption/x-cea-708,format=(string)cdp,framerate=30/1",
487 "closedcaption/x-cea-608,format=(string)raw");
488 check_conversion_tc_passthrough (in2, sizeof (in2), out2, sizeof (out2),
489 "closedcaption/x-cea-708,format=(string)cdp,framerate=30/1",
490 "closedcaption/x-cea-608,format=(string)raw");
495 GST_START_TEST (convert_cea708_cdp_cea608_s334_1a)
498 { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
499 0xfd, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
501 const guint8 out[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
502 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
503 "closedcaption/x-cea-708,format=(string)cdp,framerate=30/1",
504 "closedcaption/x-cea-608,format=(string)s334-1a");
509 GST_START_TEST (convert_cea708_cdp_cea708_cc_data)
512 { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
513 0xfd, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
515 const guint8 out[] = { 0xf8, 0x80, 0x80, 0xf9, 0x80, 0x80 };
516 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
517 "closedcaption/x-cea-708,format=(string)cdp",
518 "closedcaption/x-cea-708,format=(string)cc_data");
523 GST_START_TEST (convert_cea708_cdp_cea708_cc_data_too_big)
525 /* tests that too large input is truncated */
527 { 0x96, 0x69, 0x2e, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xeb, 0xfc, 0x80, 0x80,
528 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
529 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
530 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a,
532 const guint8 out[] = { 0xf8, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
533 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
534 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80
536 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
537 "closedcaption/x-cea-708,format=(string)cdp",
538 "closedcaption/x-cea-708,format=(string)cc_data");
543 GST_START_TEST (convert_cea708_cdp_cea708_cdp_double_framerate)
545 /* tests that packets are split exactly in half when doubling the framerate */
547 { 0x96, 0x69, 0x49, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xf4, 0xfc, 0x01, 0x02,
548 0xfd, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
549 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
550 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
551 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
552 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0x74, 0x00, 0x00, 0xd2
554 const guint8 *in[] = { in1 };
555 guint in_len[] = { sizeof (in1) };
556 GstVideoTimeCode in_tc1;
557 const GstVideoTimeCode *in_tc[] = { &in_tc1 };
559 const guint8 out1[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x00, 0x71, 0xc1,
560 0x82, 0x03, 0x08, 0x72, 0xea, 0xfc, 0x01, 0x02, 0xfe, 0x05, 0x06, 0xfe,
561 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe,
562 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0x74,
565 const guint8 out2[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x01, 0x71, 0xc1,
566 0x82, 0x03, 0x09, 0x72, 0xea, 0xfd, 0x03, 0x04, 0xfe, 0x17, 0x18, 0xfe,
567 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe,
568 0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0x74,
571 const guint8 *out[] = { out1, out2 };
572 guint out_len[] = { sizeof (out1), sizeof (out2) };
573 GstVideoTimeCode out_tc1, out_tc2;
574 const GstVideoTimeCode *out_tc[] = { &out_tc1, &out_tc2 };
576 gst_video_time_code_init (&in_tc1, 30, 1, NULL,
577 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 4, 0);
578 fail_unless (gst_video_time_code_is_valid (&in_tc1));
580 gst_video_time_code_init (&out_tc1, 60, 1, NULL,
581 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
582 fail_unless (gst_video_time_code_is_valid (&out_tc1));
583 gst_video_time_code_init (&out_tc2, 60, 1, NULL,
584 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 9, 0);
585 fail_unless (gst_video_time_code_is_valid (&out_tc2));
587 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
588 G_N_ELEMENTS (out_len), out, out_len,
589 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
590 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
593 gst_video_time_code_clear (&in_tc1);
594 gst_video_time_code_clear (&out_tc1);
595 gst_video_time_code_clear (&out_tc2);
600 GST_START_TEST (convert_cea708_cdp_cea708_cdp_half_framerate)
602 /* tests that two input packets are merged together when halving the
603 * framerate. With cc_data compaction! */
604 const guint8 in1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
605 0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08,
606 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10,
607 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0x74, 0x00, 0x00, 0x7a
609 const guint8 in2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
610 0xfd, 0x14, 0x15, 0xfe, 0x16, 0x17, 0xfe, 0x18, 0x19, 0xfe, 0x1a, 0x1b,
611 0xfe, 0x1c, 0x1d, 0xfe, 0x1e, 0x1f, 0xfe, 0x20, 0x21, 0xfe, 0x22, 0x23,
612 0xfe, 0x24, 0x25, 0xfe, 0x26, 0x27, 0x74, 0x00, 0x01, 0x70
614 const guint8 *in[] = { in1, in2 };
615 guint in_len[] = { sizeof (in1), sizeof (in2) };
616 GstVideoTimeCode in_tc1, in_tc2;
617 const GstVideoTimeCode *in_tc[] = { &in_tc1, &in_tc2 };
619 const guint8 out1[] =
620 { 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x00, 0x71, 0xc1, 0x82, 0x03, 0x04,
621 0x72, 0xf4, 0xfc, 0x01, 0x02, 0xfd, 0x14, 0x15, 0xfe, 0x03, 0x04, 0xfe,
622 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe,
623 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe,
624 0x16, 0x17, 0xfe, 0x18, 0x19, 0xfe, 0x1a, 0x1b, 0xfe, 0x1c, 0x1d, 0xfe,
625 0x1e, 0x1f, 0xfe, 0x20, 0x21, 0xfe, 0x22, 0x23, 0xfe, 0x24, 0x25, 0xfe,
626 0x26, 0x27, 0x74, 0x00, 0x00, 0x07
628 const guint8 *out[] = { out1 };
629 guint out_len[] = { sizeof (out1) };
630 GstVideoTimeCode out_tc1;
631 const GstVideoTimeCode *out_tc[] = { &out_tc1 };
633 gst_video_time_code_init (&in_tc1, 60, 1, NULL,
634 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
635 fail_unless (gst_video_time_code_is_valid (&in_tc1));
636 gst_video_time_code_init (&in_tc2, 60, 1, NULL,
637 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
638 fail_unless (gst_video_time_code_is_valid (&in_tc2));
640 gst_video_time_code_init (&out_tc1, 30, 1, NULL,
641 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 4, 0);
642 fail_unless (gst_video_time_code_is_valid (&out_tc1));
644 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
645 G_N_ELEMENTS (out_len), out, out_len,
646 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
647 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
650 gst_video_time_code_clear (&in_tc1);
651 gst_video_time_code_clear (&in_tc2);
652 gst_video_time_code_clear (&out_tc1);
657 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_merge)
659 /* check that 3 high framerate packets can be merged into 1 low framerate
660 * packets with the extra data on the third input packet being placed at the
661 * beginning of the second output packet */
662 const guint8 in1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
663 0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08,
664 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10,
665 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0x74, 0x00, 0x00, 0x7a
667 /* enough input to fully cover two output packets. Extra is discarded */
668 const guint8 *in[] = { in1, in1, in1, in1, in1, in1, in1 };
670 { sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1),
674 const guint8 out1[] =
675 { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
676 0xf9, 0x80, 0x80, 0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06,
677 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e,
678 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x03, 0x04,
679 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
680 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
681 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
682 0x74, 0x00, 0x00, 0xcb
684 const guint8 out2[] =
685 { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x01, 0x72, 0xf9, 0xf9, 0x80, 0x80,
686 0xfc, 0x01, 0x02, 0xf9, 0x80, 0x80, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e,
687 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x03, 0x04,
688 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
689 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
690 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
691 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
692 0x74, 0x00, 0x01, 0x8f
694 const guint8 *out[] = { out1, out2 };
695 guint out_len[] = { sizeof (out1), sizeof (out2) };
696 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
697 G_N_ELEMENTS (out_len), out, out_len,
698 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
699 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
705 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split)
707 /* test that a low framerate stream produces multiple output packets for a
710 { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
711 0xfd, 0x03, 0x04, 0xfc, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
712 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
713 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
714 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
715 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a,
716 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30, 0xfe, 0x31, 0x32,
717 0x74, 0x00, 0x00, 0x12
719 const guint8 *in[] = { in1, in1 };
720 guint in_len[] = { sizeof (in1), sizeof (in1) };
722 const guint8 out1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
723 0xfc, 0x01, 0x02, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
724 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
725 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0x74, 0x00, 0x00, 0x30
727 const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
728 0xfd, 0x03, 0x04, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
729 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26,
730 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a, 0x74, 0x00, 0x01, 0xe5
732 const guint8 out3[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea,
733 0xfc, 0x05, 0x06, 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30,
734 0xfe, 0x31, 0x32, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
735 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0x74, 0x00, 0x02, 0x54
737 const guint8 out4[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea,
738 0xfd, 0x03, 0x04, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16,
739 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
740 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0x74, 0x00, 0x03, 0x71
742 const guint8 *out[] = { out1, out2, out3, out4 };
744 { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4) };
745 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
746 G_N_ELEMENTS (out_len), out, out_len,
747 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
748 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
754 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split_eos)
756 /* test that a low framerate stream produces multiple output packets for a
757 * high framerate and that an EOS will push the pending data */
759 { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
760 0xfd, 0x03, 0x04, 0xfc, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
761 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
762 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
763 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
764 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a,
765 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30, 0xfe, 0x31, 0x32,
766 0x74, 0x00, 0x00, 0x12
768 const guint8 *in[] = { in1 };
769 guint in_len[] = { sizeof (in1) };
771 const guint8 out1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
772 0xfc, 0x01, 0x02, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
773 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
774 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0x74, 0x00, 0x00, 0x30
776 const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
777 0xfd, 0x03, 0x04, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
778 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26,
779 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a, 0x74, 0x00, 0x01, 0xe5
781 const guint8 out3[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea,
782 0xfc, 0x05, 0x06, 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30,
783 0xfe, 0x31, 0x32, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
784 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0xdb
786 const guint8 *out[] = { out1, out2, out3 };
787 guint out_len[] = { sizeof (out1), sizeof (out2), sizeof (out3) };
789 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
790 G_N_ELEMENTS (out_len), out, out_len,
791 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
792 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
793 NULL, NULL, FLAG_SEND_EOS);
798 GST_START_TEST (convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling)
800 const guint8 in1[] = { 0x96, 0x69, 0x10, 0x7f, 0x43, 0x00, 0x00, 0x72, 0xe1,
801 0xfc, 0x80, 0x80, 0x74, 0x00, 0x00, 0x7a
803 const guint8 *in[] = { in1, in1 };
804 guint in_len[] = { sizeof (in1), sizeof (in1) };
805 GstVideoTimeCode in_tc1, in_tc2;
806 const GstVideoTimeCode *in_tc[] = { &in_tc1, &in_tc2 };
808 const guint8 out1[] =
809 { 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x00, 0x71, 0xc0, 0x81, 0x59, 0x29,
810 0x72, 0xf4, 0xf8, 0x80, 0x80, 0xf9, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa,
811 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
812 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
813 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
814 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
815 0x00, 0x00, 0x74, 0x00, 0x00, 0xfe
817 const guint8 out2[] =
818 { 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x01, 0x71, 0xc0, 0x82, 0x00, 0x00,
819 0x72, 0xf4, 0xf8, 0x80, 0x80, 0xf9, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa,
820 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
821 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
822 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
823 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
824 0x00, 0x00, 0x74, 0x00, 0x01, 0x7d
826 const guint8 *out[] = { out1, out2 };
827 guint out_len[] = { sizeof (out1), sizeof (out2) };
828 GstVideoTimeCode out_tc1, out_tc2;
829 const GstVideoTimeCode *out_tc[] = { &out_tc1, &out_tc2 };
831 gst_video_time_code_init (&in_tc1, 30000, 1001, NULL,
832 GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME, 0, 1, 59, 29, 0);
833 fail_unless (gst_video_time_code_is_valid (&in_tc1));
835 gst_video_time_code_init (&in_tc2, 30000, 1001, NULL,
836 GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME, 0, 2, 0, 4, 0);
837 fail_unless (gst_video_time_code_is_valid (&in_tc2));
839 gst_video_time_code_init (&out_tc1, 30, 1, NULL,
840 GST_VIDEO_TIME_CODE_FLAGS_NONE, 0, 1, 59, 29, 0);
841 fail_unless (gst_video_time_code_is_valid (&out_tc1));
843 gst_video_time_code_init (&out_tc2, 30, 1, NULL,
844 GST_VIDEO_TIME_CODE_FLAGS_NONE, 0, 2, 0, 0, 0);
845 fail_unless (gst_video_time_code_is_valid (&out_tc2));
847 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
848 G_N_ELEMENTS (out_len), out, out_len,
849 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30000/1001",
850 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
851 in_tc, out_tc, FLAG_SEND_EOS);
853 gst_video_time_code_clear (&in_tc1);
854 gst_video_time_code_clear (&out_tc1);
859 GST_START_TEST (convert_cea708_cc_data_cea708_cdp_double_framerate)
861 const guint8 in1[] = { 0xfc, 0x80, 0x81, 0xfd, 0x82, 0x83, 0xfe, 0x84, 0x85 };
862 const guint8 in2[] = { 0xfc, 0x86, 0x87, 0xfd, 0x88, 0x89, 0xfe, 0x8a, 0x8b };
863 const guint8 *in[] = { in1, in2 };
864 guint in_len[] = { sizeof (in1), sizeof (in2) };
865 const guint8 out1[] =
866 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
867 0xfe, 0x84, 0x85, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
868 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
869 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x60
871 const guint8 out2[] =
872 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfd, 0x82, 0x83,
873 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
874 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
875 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x66
877 const guint8 out3[] =
878 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x86, 0x87,
879 0xfe, 0x8a, 0x8b, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
880 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
881 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x44
883 const guint8 out4[] =
884 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfd, 0x88, 0x89,
885 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
886 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
887 0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x56
889 const guint8 *out[] = { out1, out2, out3, out4, };
891 { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
892 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
893 G_N_ELEMENTS (out_len), out, out_len,
894 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1",
895 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
901 GST_START_TEST (convert_cea608_raw_cea708_cdp_double_framerate)
903 const guint8 in1[] = { 0x80, 0x81 };
904 const guint8 in2[] = { 0x82, 0x83 };
905 const guint8 *in[] = { in1, in2 };
906 guint in_len[] = { sizeof (in1), sizeof (in2) };
907 const guint8 out1[] =
908 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
909 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
910 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
911 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6d
913 const guint8 out2[] =
914 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x80, 0x80,
915 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
916 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
917 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x6f
919 const guint8 out3[] =
920 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x82, 0x83,
921 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
922 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
923 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x65
925 const guint8 out4[] =
926 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xf9, 0x80, 0x80,
927 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
928 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
929 0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x6b
931 const guint8 *out[] = { out1, out2, out3, out4, };
933 { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
934 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
935 G_N_ELEMENTS (out_len), out, out_len,
936 "closedcaption/x-cea-608,format=(string)raw,framerate=(fraction)30/1",
937 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
943 GST_START_TEST (convert_cea608_s334_1a_cea708_cdp_double_framerate)
945 const guint8 in1[] = { 0x80, 0x80, 0x81, 0x00, 0x82, 0x83 };
946 const guint8 in2[] = { 0x80, 0x84, 0x85, 0x00, 0x86, 0x87 };
947 const guint8 *in[] = { in1, in2 };
948 guint in_len[] = { sizeof (in1), sizeof (in2) };
949 const guint8 out1[] =
950 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
951 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
952 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
953 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6d
955 const guint8 out2[] =
956 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfd, 0x82, 0x83,
957 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
958 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
959 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x66
961 const guint8 out3[] =
962 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x84, 0x85,
963 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
964 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
965 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x61
967 const guint8 out4[] =
968 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfd, 0x86, 0x87,
969 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
970 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
971 0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x5a
973 const guint8 *out[] = { out1, out2, out3, out4, };
975 { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
976 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
977 G_N_ELEMENTS (out_len), out, out_len,
978 "closedcaption/x-cea-608,format=(string)s334-1a,framerate=(fraction)30/1",
979 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
985 GST_START_TEST (convert_cea708_cdp_cea708_cc_data_double_input_data)
987 /* caps say 60fps, data has 30fps. Ensure data is taken alternatatively from
988 * each field even if there is too much input data */
990 { 0x96, 0x69, 0x16, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe3, 0xfc, 0x81, 0x82,
991 0xfd, 0x83, 0x84, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0xff
995 { 0x96, 0x69, 0x16, 0x5f, 0x43, 0x00, 0x01, 0x72, 0xe3, 0xfc, 0x80, 0x80,
996 0xfd, 0x80, 0x80, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0xff
999 { 0x96, 0x69, 0x16, 0x5f, 0x43, 0x00, 0x02, 0x72, 0xe3, 0xfc, 0x85, 0x86,
1000 0xfd, 0x87, 0x88, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0xff
1002 const guint8 *in[] = { in1, in2, in3, };
1003 guint in_len[] = { sizeof (in1), sizeof (in2), sizeof (in3), };
1004 /* two buffers from the first buffer, then the first half of the third input
1006 const guint8 out1[] = { 0xfc, 0x81, 0x82, };
1007 const guint8 out2[] = { 0xfd, 0x83, 0x84, };
1008 const guint8 out3[] = { 0xfc, 0x85, 0x86, };
1009 const guint8 *out[] = { out1, out2, out3, };
1010 guint out_len[] = { sizeof (out1), sizeof (out2), sizeof (out3), };
1011 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
1012 G_N_ELEMENTS (out_len), out, out_len,
1013 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
1014 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
1020 GST_START_TEST (convert_cea708_cc_data_cea708_cdp_double_input_data)
1022 /* caps say 60fps, but every buffer is cea608 field 1. Ensure data is taken
1023 * alternatatively from each field even if there is too much input data */
1024 const guint8 in1[] = { 0xfc, 0x81, 0x82 };
1025 const guint8 in2[] = { 0xfc, 0x83, 0x84 };
1026 const guint8 in3[] = { 0xfc, 0x85, 0x86 };
1027 const guint8 *in[] = { in1, in2, in3, };
1028 guint in_len[] = { sizeof (in1), sizeof (in2), sizeof (in3), };
1029 /* two buffers from the first buffer, then the first half of the third input
1031 const guint8 out1[] =
1032 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x81, 0x82,
1033 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1034 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1035 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6b
1037 /* padding buffer */
1038 const guint8 out2[] =
1039 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x80, 0x80,
1040 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1041 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1042 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x6f
1044 const guint8 out3[] =
1045 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x83, 0x84,
1046 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1047 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1048 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x63
1050 const guint8 out4[] =
1051 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xf9, 0x80, 0x80,
1052 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1053 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1054 0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x6b
1056 const guint8 out5[] =
1057 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x04, 0x72, 0xea, 0xfc, 0x85, 0x86,
1058 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1059 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1060 0xfa, 0x00, 0x00, 0x74, 0x00, 0x04, 0x5b
1062 const guint8 *out[] = { out1, out2, out3, out4, out5 };
1064 { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4),
1067 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
1068 G_N_ELEMENTS (out_len), out, out_len,
1069 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
1070 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
1071 NULL, NULL, FLAG_SEND_EOS);
1077 calculate_cdp_checksum (guint8 * cdp, gsize len)
1079 guint8 checksum = 0;
1082 for (i = 0; i < len; i++) {
1086 return 256 - checksum;
1089 GST_START_TEST (convert_cea708_cc_data_cea708_cdp_field1_overflow)
1091 /* caps say 60fps, but every buffer is cea608 field 1. Ensure data is taken
1092 * alternatatively from each field even if there is too much input data.
1093 * Also ensure that overflow does something sane, like dropping previous data */
1094 #define N_INPUTS 100
1095 guint8 in_data[N_INPUTS * 3];
1096 guint in_len[N_INPUTS];
1097 guint8 *in[N_INPUTS];
1100 #define N_OUTPUTS 100
1101 guint8 out_data[N_OUTPUTS * 43];
1102 guint out_len[N_OUTPUTS];
1103 guint8 *out[N_OUTPUTS];
1105 const guint8 out_template[] =
1106 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x80, 0x80,
1107 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1108 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1109 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x6f
1112 G_STATIC_ASSERT (sizeof (out_template) == 43);
1114 /* generate input data */
1115 for (i = 0; i < N_INPUTS; i++) {
1117 in_data[i * 3 + 0] = 0xfc;
1118 in_data[i * 3 + 1] = 0x81 + i * 2;
1119 in_data[i * 3 + 2] = 0x81 + i * 2 + 1;
1120 in[i] = &in_data[i * 3];
1123 for (i = 0; i < N_OUTPUTS; i++) {
1125 memcpy (&out_data[i * 43], out_template, sizeof (out_template));
1126 /* write correct counters */
1127 out_data[i * 43 + 6] = i;
1128 out_data[i * 43 + 41] = i;
1129 /* write the correct cea608 data */
1131 gsize in_data_offset;
1132 /* take frames sequentially from the input */
1133 gsize in_idx = i / 2;
1134 /* take the first 16 input frames, then skip the next 16 frames and take
1135 * the next 16 frames etc.
1136 * 32 is the byte size of the internal cea608 field buffers that we are
1137 * overflowing but every second buffer will have cea608 field 1 in it.
1138 * 16 frames is 32 bytes stored and is enough to cause overflow */
1139 in_idx = (in_idx / 16) * 32 + in_idx % 16;
1140 in_data_offset = in_idx * 3;
1142 out_data[i * 43 + 9] = in_data[in_data_offset + 0];
1143 out_data[i * 43 + 10] = in_data[in_data_offset + 1];
1144 out_data[i * 43 + 11] = in_data[in_data_offset + 2];
1146 out_data[i * 43 + 9] = 0xf9;
1147 out_data[i * 43 + 10] = 0x80;
1148 out_data[i * 43 + 11] = 0x80;
1150 out_data[i * 43 + 42] = calculate_cdp_checksum (&out_data[i * 43], 42);
1151 out[i] = &out_data[i * 43];
1154 check_conversion_multiple (G_N_ELEMENTS (in_len), (const guint8 **) in,
1155 in_len, G_N_ELEMENTS (out_len), (const guint8 **) out, out_len,
1156 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
1157 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
1158 NULL, NULL, FLAG_SEND_EOS);
1164 ccextractor_suite (void)
1166 Suite *s = suite_create ("ccconverter");
1167 TCase *tc = tcase_create ("general");
1169 suite_add_tcase (s, tc);
1171 tcase_add_test (tc, cdp_requires_valid_framerate);
1172 tcase_add_test (tc, framerate_passthrough);
1173 tcase_add_test (tc, framerate_changes);
1174 tcase_add_test (tc, framerate_invalid_format);
1175 tcase_add_test (tc, convert_cea608_raw_cea608_s334_1a);
1176 tcase_add_test (tc, convert_cea608_raw_cea708_cc_data);
1177 tcase_add_test (tc, convert_cea608_raw_cea708_cdp);
1178 tcase_add_test (tc, convert_cea608_s334_1a_cea608_raw);
1179 tcase_add_test (tc, convert_cea608_s334_1a_cea608_raw_too_big);
1180 tcase_add_test (tc, convert_cea608_s334_1a_cea708_cc_data);
1181 tcase_add_test (tc, convert_cea608_s334_1a_cea708_cdp);
1182 tcase_add_test (tc, convert_cea708_cc_data_cea608_raw);
1183 tcase_add_test (tc, convert_cea708_cc_data_cea608_s334_1a);
1184 tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp);
1185 tcase_add_test (tc, convert_cea708_cdp_cea608_raw);
1186 tcase_add_test (tc, convert_cea708_cdp_cea608_s334_1a);
1187 tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data);
1188 tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data_too_big);
1189 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_half_framerate);
1190 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_double_framerate);
1191 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_merge);
1192 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_split);
1193 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_split_eos);
1194 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling);
1195 tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_double_framerate);
1196 tcase_add_test (tc, convert_cea608_raw_cea708_cdp_double_framerate);
1197 tcase_add_test (tc, convert_cea608_s334_1a_cea708_cdp_double_framerate);
1198 tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data_double_input_data);
1199 tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_double_input_data);
1200 tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_field1_overflow);
1205 GST_CHECK_MAIN (ccextractor);