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, };
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, };
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,framerate=30/1",
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, 0x4c, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xf5, 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, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
531 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
532 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
533 0x74, 0x00, 0x00, 0x8a,
535 const guint8 out[] = { 0xf8, 0x80, 0x80, 0xf9, 0x80, 0x80, 0xfe, 0x80, 0x80,
536 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
537 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
538 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
539 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
542 check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
543 "closedcaption/x-cea-708,format=(string)cdp,framerate=30/1",
544 "closedcaption/x-cea-708,format=(string)cc_data");
549 GST_START_TEST (convert_cea708_cdp_cea708_cdp_double_framerate)
551 /* tests that packets are split exactly in half when doubling the framerate */
553 { 0x96, 0x69, 0x49, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xf4, 0xfc, 0x01, 0x02,
554 0xfd, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
555 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
556 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
557 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
558 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0x74, 0x00, 0x00, 0xd2
560 const guint8 *in[] = { in1 };
561 guint in_len[] = { sizeof (in1) };
562 GstVideoTimeCode in_tc1;
563 const GstVideoTimeCode *in_tc[] = { &in_tc1 };
565 const guint8 out1[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x00, 0x71, 0xc1,
566 0x82, 0x03, 0x08, 0x72, 0xea, 0xfc, 0x01, 0x02, 0xfe, 0x05, 0x06, 0xfe,
567 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe,
568 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0x74,
571 const guint8 out2[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x01, 0x71, 0xc1,
572 0x82, 0x03, 0x09, 0x72, 0xea, 0xfd, 0x03, 0x04, 0xfe, 0x17, 0x18, 0xfe,
573 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe,
574 0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0x74,
577 const guint8 *out[] = { out1, out2 };
578 guint out_len[] = { sizeof (out1), sizeof (out2) };
579 GstVideoTimeCode out_tc1, out_tc2;
580 const GstVideoTimeCode *out_tc[] = { &out_tc1, &out_tc2 };
582 gst_video_time_code_init (&in_tc1, 30, 1, NULL,
583 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 4, 0);
584 fail_unless (gst_video_time_code_is_valid (&in_tc1));
586 gst_video_time_code_init (&out_tc1, 60, 1, NULL,
587 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
588 fail_unless (gst_video_time_code_is_valid (&out_tc1));
589 gst_video_time_code_init (&out_tc2, 60, 1, NULL,
590 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 9, 0);
591 fail_unless (gst_video_time_code_is_valid (&out_tc2));
593 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
594 G_N_ELEMENTS (out_len), out, out_len,
595 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
596 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
599 gst_video_time_code_clear (&in_tc1);
600 gst_video_time_code_clear (&out_tc1);
601 gst_video_time_code_clear (&out_tc2);
606 GST_START_TEST (convert_cea708_cdp_cea708_cdp_half_framerate)
608 /* tests that two input packets are merged together when halving the
609 * framerate. With cc_data compaction! */
610 const guint8 in1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
611 0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08,
612 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10,
613 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0x74, 0x00, 0x00, 0x7a
615 const guint8 in2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
616 0xfd, 0x14, 0x15, 0xfe, 0x16, 0x17, 0xfe, 0x18, 0x19, 0xfe, 0x1a, 0x1b,
617 0xfe, 0x1c, 0x1d, 0xfe, 0x1e, 0x1f, 0xfe, 0x20, 0x21, 0xfe, 0x22, 0x23,
618 0xfe, 0x24, 0x25, 0xfe, 0x26, 0x27, 0x74, 0x00, 0x01, 0x70
620 const guint8 *in[] = { in1, in2 };
621 guint in_len[] = { sizeof (in1), sizeof (in2) };
622 GstVideoTimeCode in_tc1, in_tc2;
623 const GstVideoTimeCode *in_tc[] = { &in_tc1, &in_tc2 };
625 const guint8 out1[] =
626 { 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x00, 0x71, 0xc1, 0x82, 0x03, 0x04,
627 0x72, 0xf4, 0xfc, 0x01, 0x02, 0xfd, 0x14, 0x15, 0xfe, 0x03, 0x04, 0xfe,
628 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe,
629 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe,
630 0x16, 0x17, 0xfe, 0x18, 0x19, 0xfe, 0x1a, 0x1b, 0xfe, 0x1c, 0x1d, 0xfe,
631 0x1e, 0x1f, 0xfe, 0x20, 0x21, 0xfe, 0x22, 0x23, 0xfe, 0x24, 0x25, 0xfe,
632 0x26, 0x27, 0x74, 0x00, 0x00, 0x07
634 const guint8 *out[] = { out1 };
635 guint out_len[] = { sizeof (out1) };
636 GstVideoTimeCode out_tc1;
637 const GstVideoTimeCode *out_tc[] = { &out_tc1 };
639 gst_video_time_code_init (&in_tc1, 60, 1, NULL,
640 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
641 fail_unless (gst_video_time_code_is_valid (&in_tc1));
642 gst_video_time_code_init (&in_tc2, 60, 1, NULL,
643 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
644 fail_unless (gst_video_time_code_is_valid (&in_tc2));
646 gst_video_time_code_init (&out_tc1, 30, 1, NULL,
647 GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 4, 0);
648 fail_unless (gst_video_time_code_is_valid (&out_tc1));
650 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
651 G_N_ELEMENTS (out_len), out, out_len,
652 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
653 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
656 gst_video_time_code_clear (&in_tc1);
657 gst_video_time_code_clear (&in_tc2);
658 gst_video_time_code_clear (&out_tc1);
663 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_merge)
665 /* check that 3 high framerate packets can be merged into 1 low framerate
666 * packets with the extra data on the third input packet being placed at the
667 * beginning of the second output packet */
668 const guint8 in1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
669 0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08,
670 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10,
671 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0x74, 0x00, 0x00, 0x7a
673 /* enough input to fully cover two output packets. Extra is discarded */
674 const guint8 *in[] = { in1, in1, in1, in1, in1, in1, in1 };
676 { sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1),
680 const guint8 out1[] =
681 { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
682 0xf9, 0x80, 0x80, 0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06,
683 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e,
684 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x03, 0x04,
685 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
686 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
687 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
688 0x74, 0x00, 0x00, 0xcb
690 const guint8 out2[] =
691 { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x01, 0x72, 0xf9, 0xf9, 0x80, 0x80,
692 0xfc, 0x01, 0x02, 0xf9, 0x80, 0x80, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e,
693 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x03, 0x04,
694 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
695 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
696 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
697 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
698 0x74, 0x00, 0x01, 0x8f
700 const guint8 *out[] = { out1, out2 };
701 guint out_len[] = { sizeof (out1), sizeof (out2) };
702 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
703 G_N_ELEMENTS (out_len), out, out_len,
704 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
705 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
711 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split)
713 /* test that a low framerate stream produces multiple output packets for a
716 { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
717 0xfd, 0x03, 0x04, 0xfc, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
718 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
719 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
720 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
721 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a,
722 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30, 0xfe, 0x31, 0x32,
723 0x74, 0x00, 0x00, 0x12
725 const guint8 *in[] = { in1, in1 };
726 guint in_len[] = { sizeof (in1), sizeof (in1) };
728 const guint8 out1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
729 0xfc, 0x01, 0x02, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
730 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
731 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0x74, 0x00, 0x00, 0x30
733 const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
734 0xfd, 0x03, 0x04, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
735 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26,
736 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a, 0x74, 0x00, 0x01, 0xe5
738 const guint8 out3[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea,
739 0xfc, 0x05, 0x06, 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30,
740 0xfe, 0x31, 0x32, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
741 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0x74, 0x00, 0x02, 0x54
743 const guint8 out4[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea,
744 0xfd, 0x03, 0x04, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16,
745 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
746 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0x74, 0x00, 0x03, 0x71
748 const guint8 *out[] = { out1, out2, out3, out4 };
750 { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4) };
751 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
752 G_N_ELEMENTS (out_len), out, out_len,
753 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
754 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
760 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split_eos)
762 /* test that a low framerate stream produces multiple output packets for a
763 * high framerate and that an EOS will push the pending data */
765 { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
766 0xfd, 0x03, 0x04, 0xfc, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
767 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
768 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
769 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
770 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a,
771 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30, 0xfe, 0x31, 0x32,
772 0x74, 0x00, 0x00, 0x12
774 const guint8 *in[] = { in1 };
775 guint in_len[] = { sizeof (in1) };
777 const guint8 out1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
778 0xfc, 0x01, 0x02, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
779 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
780 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0x74, 0x00, 0x00, 0x30
782 const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
783 0xfd, 0x03, 0x04, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
784 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26,
785 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a, 0x74, 0x00, 0x01, 0xe5
787 const guint8 out3[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea,
788 0xfc, 0x05, 0x06, 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30,
789 0xfe, 0x31, 0x32, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
790 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0xdb
792 const guint8 *out[] = { out1, out2, out3 };
793 guint out_len[] = { sizeof (out1), sizeof (out2), sizeof (out3) };
795 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
796 G_N_ELEMENTS (out_len), out, out_len,
797 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
798 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
799 NULL, NULL, FLAG_SEND_EOS);
804 GST_START_TEST (convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling)
806 const guint8 in1[] = { 0x96, 0x69, 0x10, 0x7f, 0x43, 0x00, 0x00, 0x72, 0xe1,
807 0xfc, 0x80, 0x80, 0x74, 0x00, 0x00, 0x7a
809 const guint8 *in[] = { in1, in1 };
810 guint in_len[] = { sizeof (in1), sizeof (in1) };
811 GstVideoTimeCode in_tc1, in_tc2;
812 const GstVideoTimeCode *in_tc[] = { &in_tc1, &in_tc2 };
814 const guint8 out1[] =
815 { 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x00, 0x71, 0xc0, 0x81, 0x59, 0x29,
816 0x72, 0xf4, 0xf8, 0x80, 0x80, 0xf9, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa,
817 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
818 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
819 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
820 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
821 0x00, 0x00, 0x74, 0x00, 0x00, 0xfe
823 const guint8 out2[] =
824 { 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x01, 0x71, 0xc0, 0x82, 0x00, 0x00,
825 0x72, 0xf4, 0xf8, 0x80, 0x80, 0xf9, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa,
826 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
827 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
828 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
829 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
830 0x00, 0x00, 0x74, 0x00, 0x01, 0x7d
832 const guint8 *out[] = { out1, out2 };
833 guint out_len[] = { sizeof (out1), sizeof (out2) };
834 GstVideoTimeCode out_tc1, out_tc2;
835 const GstVideoTimeCode *out_tc[] = { &out_tc1, &out_tc2 };
837 gst_video_time_code_init (&in_tc1, 30000, 1001, NULL,
838 GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME, 0, 1, 59, 29, 0);
839 fail_unless (gst_video_time_code_is_valid (&in_tc1));
841 gst_video_time_code_init (&in_tc2, 30000, 1001, NULL,
842 GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME, 0, 2, 0, 4, 0);
843 fail_unless (gst_video_time_code_is_valid (&in_tc2));
845 gst_video_time_code_init (&out_tc1, 30, 1, NULL,
846 GST_VIDEO_TIME_CODE_FLAGS_NONE, 0, 1, 59, 29, 0);
847 fail_unless (gst_video_time_code_is_valid (&out_tc1));
849 gst_video_time_code_init (&out_tc2, 30, 1, NULL,
850 GST_VIDEO_TIME_CODE_FLAGS_NONE, 0, 2, 0, 0, 0);
851 fail_unless (gst_video_time_code_is_valid (&out_tc2));
853 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
854 G_N_ELEMENTS (out_len), out, out_len,
855 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30000/1001",
856 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
857 in_tc, out_tc, FLAG_SEND_EOS);
859 gst_video_time_code_clear (&in_tc1);
860 gst_video_time_code_clear (&out_tc1);
865 GST_START_TEST (convert_cea708_cc_data_cea708_cdp_double_framerate)
867 const guint8 in1[] = { 0xfc, 0x80, 0x81, 0xfd, 0x82, 0x83, 0xfe, 0x84, 0x85 };
868 const guint8 in2[] = { 0xfc, 0x86, 0x87, 0xfd, 0x88, 0x89, 0xfe, 0x8a, 0x8b };
869 const guint8 *in[] = { in1, in2 };
870 guint in_len[] = { sizeof (in1), sizeof (in2) };
871 const guint8 out1[] =
872 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
873 0xfe, 0x84, 0x85, 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, 0x00, 0x60
877 const guint8 out2[] =
878 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfd, 0x82, 0x83,
879 0xfa, 0x00, 0x00, 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, 0x01, 0x66
883 const guint8 out3[] =
884 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x86, 0x87,
885 0xfe, 0x8a, 0x8b, 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, 0x02, 0x44
889 const guint8 out4[] =
890 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfd, 0x88, 0x89,
891 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
892 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
893 0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x56
895 const guint8 *out[] = { out1, out2, out3, out4, };
897 { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
898 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
899 G_N_ELEMENTS (out_len), out, out_len,
900 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1",
901 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
907 GST_START_TEST (convert_cea608_raw_cea708_cdp_double_framerate)
909 const guint8 in1[] = { 0x80, 0x81 };
910 const guint8 in2[] = { 0x82, 0x83 };
911 const guint8 *in[] = { in1, in2 };
912 guint in_len[] = { sizeof (in1), sizeof (in2) };
913 const guint8 out1[] =
914 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
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, 0x00, 0x6d
919 const guint8 out2[] =
920 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x80, 0x80,
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, 0x01, 0x6f
925 const guint8 out3[] =
926 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x82, 0x83,
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, 0x02, 0x65
931 const guint8 out4[] =
932 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xf9, 0x80, 0x80,
933 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
934 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
935 0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x6b
937 const guint8 *out[] = { out1, out2, out3, out4, };
939 { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
940 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
941 G_N_ELEMENTS (out_len), out, out_len,
942 "closedcaption/x-cea-608,format=(string)raw,framerate=(fraction)30/1",
943 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
949 GST_START_TEST (convert_cea608_s334_1a_cea708_cdp_double_framerate)
951 const guint8 in1[] = { 0x80, 0x80, 0x81, 0x00, 0x82, 0x83 };
952 const guint8 in2[] = { 0x80, 0x84, 0x85, 0x00, 0x86, 0x87 };
953 const guint8 *in[] = { in1, in2 };
954 guint in_len[] = { sizeof (in1), sizeof (in2) };
955 const guint8 out1[] =
956 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
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, 0x00, 0x6d
961 const guint8 out2[] =
962 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfd, 0x82, 0x83,
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, 0x01, 0x66
967 const guint8 out3[] =
968 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x84, 0x85,
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, 0x02, 0x61
973 const guint8 out4[] =
974 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfd, 0x86, 0x87,
975 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
976 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
977 0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x5a
979 const guint8 *out[] = { out1, out2, out3, out4, };
981 { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
982 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
983 G_N_ELEMENTS (out_len), out, out_len,
984 "closedcaption/x-cea-608,format=(string)s334-1a,framerate=(fraction)30/1",
985 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
991 GST_START_TEST (convert_cea708_cdp_cea708_cc_data_double_input_data)
993 /* caps say 60fps, data has 30fps. Ensure data is taken alternatatively from
994 * each field even if there is too much input data */
996 { 0x96, 0x69, 0x16, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe3, 0xfc, 0x81, 0x82,
997 0xfd, 0x83, 0x84, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0xff
1000 const guint8 in2[] =
1001 { 0x96, 0x69, 0x16, 0x5f, 0x43, 0x00, 0x01, 0x72, 0xe3, 0xfc, 0x80, 0x80,
1002 0xfd, 0x80, 0x80, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0xff
1004 const guint8 in3[] =
1005 { 0x96, 0x69, 0x16, 0x5f, 0x43, 0x00, 0x02, 0x72, 0xe3, 0xfc, 0x85, 0x86,
1006 0xfd, 0x87, 0x88, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0xff
1008 const guint8 *in[] = { in1, in2, in3, };
1009 guint in_len[] = { sizeof (in1), sizeof (in2), sizeof (in3), };
1010 /* two buffers from the first buffer, then the first half of the third input
1012 const guint8 out1[] = { 0xfc, 0x81, 0x82, };
1013 const guint8 out2[] = { 0xfd, 0x83, 0x84, };
1014 const guint8 out3[] = { 0xfc, 0x85, 0x86, };
1015 const guint8 *out[] = { out1, out2, out3, };
1016 guint out_len[] = { sizeof (out1), sizeof (out2), sizeof (out3), };
1017 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
1018 G_N_ELEMENTS (out_len), out, out_len,
1019 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
1020 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
1026 GST_START_TEST (convert_cea708_cc_data_cea708_cdp_double_input_data)
1028 /* caps say 60fps, but every buffer is cea608 field 1. Ensure data is taken
1029 * alternatatively from each field even if there is too much input data */
1030 const guint8 in1[] = { 0xfc, 0x81, 0x82 };
1031 const guint8 in2[] = { 0xfc, 0x83, 0x84 };
1032 const guint8 in3[] = { 0xfc, 0x85, 0x86 };
1033 const guint8 *in[] = { in1, in2, in3, };
1034 guint in_len[] = { sizeof (in1), sizeof (in2), sizeof (in3), };
1035 /* two buffers from the first buffer, then the first half of the third input
1037 const guint8 out1[] =
1038 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x81, 0x82,
1039 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1040 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1041 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6b
1043 /* padding buffer */
1044 const guint8 out2[] =
1045 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x80, 0x80,
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, 0x01, 0x6f
1050 const guint8 out3[] =
1051 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x83, 0x84,
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, 0x02, 0x63
1056 const guint8 out4[] =
1057 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xf9, 0x80, 0x80,
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, 0x03, 0x6b
1062 const guint8 out5[] =
1063 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x04, 0x72, 0xea, 0xfc, 0x85, 0x86,
1064 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1065 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1066 0xfa, 0x00, 0x00, 0x74, 0x00, 0x04, 0x5b
1068 const guint8 *out[] = { out1, out2, out3, out4, out5 };
1070 { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4),
1073 check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
1074 G_N_ELEMENTS (out_len), out, out_len,
1075 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
1076 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
1077 NULL, NULL, FLAG_SEND_EOS);
1083 calculate_cdp_checksum (guint8 * cdp, gsize len)
1085 guint8 checksum = 0;
1088 for (i = 0; i < len; i++) {
1092 return 256 - checksum;
1095 GST_START_TEST (convert_cea708_cc_data_cea708_cdp_field1_overflow)
1097 /* caps say 60fps, but every buffer is cea608 field 1. Ensure data is taken
1098 * alternatatively from each field even if there is too much input data.
1099 * Also ensure that overflow does something sane, like dropping previous data */
1100 #define N_INPUTS 100
1101 guint8 in_data[N_INPUTS * 3];
1102 guint in_len[N_INPUTS];
1103 guint8 *in[N_INPUTS];
1106 #define N_OUTPUTS 100
1107 guint8 out_data[N_OUTPUTS * 43];
1108 guint out_len[N_OUTPUTS];
1109 guint8 *out[N_OUTPUTS];
1111 const guint8 out_template[] =
1112 { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x80, 0x80,
1113 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1114 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
1115 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x6f
1118 G_STATIC_ASSERT (sizeof (out_template) == 43);
1120 /* generate input data */
1121 for (i = 0; i < N_INPUTS; i++) {
1123 in_data[i * 3 + 0] = 0xfc;
1124 in_data[i * 3 + 1] = 0x81 + i * 2;
1125 in_data[i * 3 + 2] = 0x81 + i * 2 + 1;
1126 in[i] = &in_data[i * 3];
1129 for (i = 0; i < N_OUTPUTS; i++) {
1131 memcpy (&out_data[i * 43], out_template, sizeof (out_template));
1132 /* write correct counters */
1133 out_data[i * 43 + 6] = i;
1134 out_data[i * 43 + 41] = i;
1135 /* write the correct cea608 data */
1137 gsize in_data_offset;
1138 /* take frames sequentially from the input */
1139 gsize in_idx = i / 2;
1140 /* take the first 12 input frames, then skip the next 12 frames and take
1141 * the next 12 frames etc.
1142 * 24 is the byte size of the internal cea608 field buffers that we are
1143 * overflowing but every second buffer will have cea608 field 1 in it.
1144 * 12 frames is 24 bytes stored and is enough to cause overflow */
1145 in_idx = (in_idx / 6) * 12 + in_idx % 6;
1146 in_data_offset = in_idx * 3;
1148 out_data[i * 43 + 9] = in_data[in_data_offset + 0];
1149 out_data[i * 43 + 10] = in_data[in_data_offset + 1];
1150 out_data[i * 43 + 11] = in_data[in_data_offset + 2];
1152 out_data[i * 43 + 9] = 0xf9;
1153 out_data[i * 43 + 10] = 0x80;
1154 out_data[i * 43 + 11] = 0x80;
1156 out_data[i * 43 + 42] = calculate_cdp_checksum (&out_data[i * 43], 42);
1157 out[i] = &out_data[i * 43];
1160 check_conversion_multiple (G_N_ELEMENTS (in_len), (const guint8 **) in,
1161 in_len, G_N_ELEMENTS (out_len), (const guint8 **) out, out_len,
1162 "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
1163 "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
1164 NULL, NULL, FLAG_SEND_EOS);
1170 ccextractor_suite (void)
1172 Suite *s = suite_create ("ccconverter");
1173 TCase *tc = tcase_create ("general");
1175 suite_add_tcase (s, tc);
1177 tcase_add_test (tc, cdp_requires_valid_framerate);
1178 tcase_add_test (tc, framerate_passthrough);
1179 tcase_add_test (tc, framerate_changes);
1180 tcase_add_test (tc, framerate_invalid_format);
1181 tcase_add_test (tc, convert_cea608_raw_cea608_s334_1a);
1182 tcase_add_test (tc, convert_cea608_raw_cea708_cc_data);
1183 tcase_add_test (tc, convert_cea608_raw_cea708_cdp);
1184 tcase_add_test (tc, convert_cea608_s334_1a_cea608_raw);
1185 tcase_add_test (tc, convert_cea608_s334_1a_cea608_raw_too_big);
1186 tcase_add_test (tc, convert_cea608_s334_1a_cea708_cc_data);
1187 tcase_add_test (tc, convert_cea608_s334_1a_cea708_cdp);
1188 tcase_add_test (tc, convert_cea708_cc_data_cea608_raw);
1189 tcase_add_test (tc, convert_cea708_cc_data_cea608_s334_1a);
1190 tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp);
1191 tcase_add_test (tc, convert_cea708_cdp_cea608_raw);
1192 tcase_add_test (tc, convert_cea708_cdp_cea608_s334_1a);
1193 tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data);
1194 tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data_too_big);
1195 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_half_framerate);
1196 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_double_framerate);
1197 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_merge);
1198 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_split);
1199 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_split_eos);
1200 tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling);
1201 tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_double_framerate);
1202 tcase_add_test (tc, convert_cea608_raw_cea708_cdp_double_framerate);
1203 tcase_add_test (tc, convert_cea608_s334_1a_cea708_cdp_double_framerate);
1204 tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data_double_input_data);
1205 tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_double_input_data);
1206 tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_field1_overflow);
1211 GST_CHECK_MAIN (ccextractor);