closedcaption: move CC buffering to helper object
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / tests / check / elements / ccconverter.c
1 /* GStreamer
2  *
3  * Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include <gst/gst.h>
25 #include <gst/video/video.h>
26 #include <gst/check/gstcheck.h>
27 #include <gst/check/gstharness.h>
28
29 #include <string.h>
30
31 enum CheckConversionFlags
32 {
33   FLAG_NONE,
34   FLAG_SEND_EOS = 1,
35 };
36
37 GST_START_TEST (cdp_requires_valid_framerate)
38 {
39   GstHarness *h;
40   GstBuffer *buffer;
41   GstMapInfo map;
42
43   h = gst_harness_new ("ccconverter");
44
45   /* Enforce conversion to CDP */
46   gst_harness_set_sink_caps_str (h,
47       "closedcaption/x-cea-708,format=(string)cdp");
48
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");
52
53   buffer = gst_buffer_new_and_alloc (3);
54   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
55   map.data[0] = 0xfc;
56   map.data[1] = 0x80;
57   map.data[2] = 0x80;
58   gst_buffer_unmap (buffer, &map);
59   fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
60       GST_FLOW_NOT_NEGOTIATED);
61
62   /* Now set a framerate only on the sink caps, this should still fail:
63    * We can't come up with a framerate
64    */
65   gst_harness_set_sink_caps_str (h,
66       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1");
67
68   fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
69       GST_FLOW_NOT_NEGOTIATED);
70
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");
76
77   fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
78       GST_FLOW_OK);
79
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");
85
86   fail_unless_equals_int (gst_harness_push (h, buffer),
87       GST_FLOW_NOT_NEGOTIATED);
88
89   gst_harness_teardown (h);
90 }
91
92 GST_END_TEST;
93
94 GST_START_TEST (framerate_passthrough)
95 {
96   GstHarness *h;
97   GstBuffer *buffer;
98   GstMapInfo map;
99   GstCaps *caps, *expected_caps;
100
101   h = gst_harness_new ("ccconverter");
102
103   gst_harness_set_src_caps_str (h,
104       "closedcaption/x-cea-608,format=(string)s334-1a,framerate=(fraction)30/1");
105
106   gst_harness_set_sink_caps_str (h,
107       "closedcaption/x-cea-708,format=(string)cc_data");
108
109   buffer = gst_buffer_new_and_alloc (3);
110   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
111   map.data[0] = 0x00;
112   map.data[1] = 0x80;
113   map.data[2] = 0x80;
114   gst_buffer_unmap (buffer, &map);
115
116   fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
117       GST_FLOW_OK);
118
119   caps = gst_pad_get_current_caps (h->sinkpad);
120   fail_unless (caps);
121   expected_caps =
122       gst_caps_from_string
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);
127
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");
131
132   gst_harness_set_sink_caps_str (h,
133       "closedcaption/x-cea-708,format=(string)cc_data");
134
135   fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
136       GST_FLOW_OK);
137
138   caps = gst_pad_get_current_caps (h->sinkpad);
139   fail_unless (caps);
140   expected_caps =
141       gst_caps_from_string
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);
146
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");
151
152   gst_harness_set_sink_caps_str (h,
153       "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
154
155   fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
156       GST_FLOW_NOT_NEGOTIATED);
157
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");
161
162   gst_harness_set_sink_caps_str (h,
163       "closedcaption/x-cea-708,format=(string)cc_data");
164
165   fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
166       GST_FLOW_OK);
167
168   gst_buffer_unref (buffer);
169   gst_harness_teardown (h);
170 }
171
172 GST_END_TEST;
173
174 GST_START_TEST (framerate_changes)
175 {
176   GstHarness *h;
177   GstBuffer *buffer;
178   GstMapInfo map;
179
180   h = gst_harness_new ("ccconverter");
181
182   buffer = gst_buffer_new_and_alloc (3);
183   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
184   map.data[0] = 0x00;
185   map.data[1] = 0x80;
186   map.data[2] = 0x80;
187   gst_buffer_unmap (buffer, &map);
188
189   /* success case */
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)),
195       GST_FLOW_OK);
196
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);
202
203   gst_harness_teardown (h);
204 }
205
206 GST_END_TEST;
207
208 GST_START_TEST (framerate_invalid_format)
209 {
210   GstHarness *h;
211   GstBuffer *buffer;
212   GstMapInfo map;
213   guint i, j;
214
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",
220   };
221
222   h = gst_harness_new ("ccconverter");
223
224   buffer = gst_buffer_new_and_alloc (3);
225   gst_buffer_map (buffer, &map, GST_MAP_WRITE);
226   map.data[0] = 0x00;
227   map.data[1] = 0x80;
228   map.data[2] = 0x80;
229   gst_buffer_unmap (buffer, &map);
230
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;
235
236       srccaps =
237           g_strdup_printf ("%s%s", failure_caps[i],
238           ",framerate=(fraction)30/1");
239       sinkcaps =
240           g_strdup_printf ("%s%s", failure_caps[i],
241           ",framerate=(fraction)60/1");
242
243       GST_INFO ("attempting conversion from %s", srccaps);
244       GST_INFO ("                        to %s", sinkcaps);
245
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);
250
251       g_free (srccaps);
252       g_free (sinkcaps);
253     }
254   }
255
256   gst_buffer_unref (buffer);
257   gst_harness_teardown (h);
258 }
259
260 GST_END_TEST;
261
262 static void
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)
267 {
268   GstHarness *h;
269   GstBuffer *buffer;
270   GstVideoTimeCodeMeta *out_tc_meta;
271   int i = 0;
272
273   h = gst_harness_new ("ccconverter");
274
275   gst_harness_set_src_caps_str (h, in_caps);
276   gst_harness_set_sink_caps_str (h, out_caps);
277
278   for (i = 0; i < n_in; i++) {
279     buffer =
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);
286   }
287
288   if (flags & FLAG_SEND_EOS)
289     fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
290
291   for (i = 0; i < n_out; i++) {
292     buffer = gst_harness_pull (h);
293
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,
301               out_tc[i]) == 0);
302
303     gst_buffer_unref (buffer);
304   }
305
306   gst_harness_teardown (h);
307 }
308
309 static void
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)
313 {
314   check_conversion_multiple (1, &in, &in_len, 1, &out, &out_len, in_caps,
315       out_caps, &in_tc, &out_tc, 0);
316 }
317
318 static void
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)
322 {
323   GstVideoTimeCode tc;
324   gst_video_time_code_init (&tc, 30, 1, NULL, GST_VIDEO_TIME_CODE_FLAGS_NONE,
325       1, 2, 3, 4, 0);
326   check_conversion (in, in_len, out, out_len, in_caps, out_caps, &tc, &tc);
327   gst_video_time_code_clear (&tc);
328 }
329
330 GST_START_TEST (convert_cea608_raw_cea608_s334_1a)
331 {
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");
337 }
338
339 GST_END_TEST;
340
341 GST_START_TEST (convert_cea608_raw_cea708_cc_data)
342 {
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");
348 }
349
350 GST_END_TEST;
351
352 GST_START_TEST (convert_cea608_raw_cea708_cdp)
353 {
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
361   };
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
367   };
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);
376 }
377
378 GST_END_TEST;
379
380 GST_START_TEST (convert_cea608_s334_1a_cea608_raw)
381 {
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");
387 }
388
389 GST_END_TEST;
390
391 GST_START_TEST (convert_cea608_s334_1a_cea608_raw_too_big)
392 {
393   const guint8 in[] =
394       { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80,
395     0x80
396   };
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");
401 }
402
403 GST_END_TEST;
404
405 GST_START_TEST (convert_cea608_s334_1a_cea708_cc_data)
406 {
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");
412 }
413
414 GST_END_TEST;
415
416 GST_START_TEST (convert_cea608_s334_1a_cea708_cdp)
417 {
418   const guint8 in[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
419   const guint8 out[] =
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
426   };
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",
430       NULL, NULL);
431 }
432
433 GST_END_TEST;
434
435 GST_START_TEST (convert_cea708_cc_data_cea608_raw)
436 {
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");
442 }
443
444 GST_END_TEST;
445
446 GST_START_TEST (convert_cea708_cc_data_cea608_s334_1a)
447 {
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");
453 }
454
455 GST_END_TEST;
456
457 GST_START_TEST (convert_cea708_cc_data_cea708_cdp)
458 {
459   const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
460   const guint8 out[] =
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
465   };
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);
469 }
470
471 GST_END_TEST;
472
473 GST_START_TEST (convert_cea708_cdp_cea608_raw)
474 {
475   const guint8 in1[] =
476       { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
477     0xfd, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
478   };
479   const guint8 out1[] = { 0x80, 0x80, };
480   const guint8 in2[] =
481       { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x81,
482     0xfd, 0x82, 0x83, 0x74, 0x00, 0x00, 0x8a
483   };
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");
491 }
492
493 GST_END_TEST;
494
495 GST_START_TEST (convert_cea708_cdp_cea608_s334_1a)
496 {
497   const guint8 in[] =
498       { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
499     0xfd, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
500   };
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");
505 }
506
507 GST_END_TEST;
508
509 GST_START_TEST (convert_cea708_cdp_cea708_cc_data)
510 {
511   const guint8 in[] =
512       { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
513     0xfd, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
514   };
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");
519 }
520
521 GST_END_TEST;
522
523 GST_START_TEST (convert_cea708_cdp_cea708_cc_data_too_big)
524 {
525   /* tests that too large input is truncated */
526   const guint8 in[] =
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,
534   };
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,
540     0xfe, 0x80, 0x80
541   };
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");
545 }
546
547 GST_END_TEST;
548
549 GST_START_TEST (convert_cea708_cdp_cea708_cdp_double_framerate)
550 {
551   /* tests that packets are split exactly in half when doubling the framerate */
552   const guint8 in1[] =
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
559   };
560   const guint8 *in[] = { in1 };
561   guint in_len[] = { sizeof (in1) };
562   GstVideoTimeCode in_tc1;
563   const GstVideoTimeCode *in_tc[] = { &in_tc1 };
564
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,
569     0x00, 0x00, 0x10
570   };
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,
575     0x00, 0x01, 0xc4
576   };
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 };
581
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));
585
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));
592
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",
597       in_tc, out_tc, 0);
598
599   gst_video_time_code_clear (&in_tc1);
600   gst_video_time_code_clear (&out_tc1);
601   gst_video_time_code_clear (&out_tc2);
602 }
603
604 GST_END_TEST;
605
606 GST_START_TEST (convert_cea708_cdp_cea708_cdp_half_framerate)
607 {
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
614   };
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
619   };
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 };
624
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
633   };
634   const guint8 *out[] = { out1 };
635   guint out_len[] = { sizeof (out1) };
636   GstVideoTimeCode out_tc1;
637   const GstVideoTimeCode *out_tc[] = { &out_tc1 };
638
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));
645
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));
649
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",
654       in_tc, out_tc, 0);
655
656   gst_video_time_code_clear (&in_tc1);
657   gst_video_time_code_clear (&in_tc2);
658   gst_video_time_code_clear (&out_tc1);
659 }
660
661 GST_END_TEST;
662
663 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_merge)
664 {
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
672   };
673   /* enough input to fully cover two output packets. Extra is discarded */
674   const guint8 *in[] = { in1, in1, in1, in1, in1, in1, in1 };
675   guint in_len[] =
676       { sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1),
677     sizeof (in1)
678   };
679
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
689   };
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
699   };
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",
706       NULL, NULL, 0);
707 }
708
709 GST_END_TEST;
710
711 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split)
712 {
713   /* test that a low framerate stream produces multiple output packets for a
714    * high framerate */
715   const guint8 in1[] =
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
724   };
725   const guint8 *in[] = { in1, in1 };
726   guint in_len[] = { sizeof (in1), sizeof (in1) };
727
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
732   };
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
737   };
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
742   };
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
747   };
748   const guint8 *out[] = { out1, out2, out3, out4 };
749   guint out_len[] =
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",
755       NULL, NULL, 0);
756 }
757
758 GST_END_TEST;
759
760 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split_eos)
761 {
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 */
764   const guint8 in1[] =
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
773   };
774   const guint8 *in[] = { in1 };
775   guint in_len[] = { sizeof (in1) };
776
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
781   };
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
786   };
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
791   };
792   const guint8 *out[] = { out1, out2, out3 };
793   guint out_len[] = { sizeof (out1), sizeof (out2), sizeof (out3) };
794
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);
800 }
801
802 GST_END_TEST;
803
804 GST_START_TEST (convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling)
805 {
806   const guint8 in1[] = { 0x96, 0x69, 0x10, 0x7f, 0x43, 0x00, 0x00, 0x72, 0xe1,
807     0xfc, 0x80, 0x80, 0x74, 0x00, 0x00, 0x7a
808   };
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 };
813
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
822   };
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
831   };
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 };
836
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));
840
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));
844
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));
848
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));
852
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);
858
859   gst_video_time_code_clear (&in_tc1);
860   gst_video_time_code_clear (&out_tc1);
861 }
862
863 GST_END_TEST;
864
865 GST_START_TEST (convert_cea708_cc_data_cea708_cdp_double_framerate)
866 {
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
876   };
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
882   };
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
888   };
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
894   };
895   const guint8 *out[] = { out1, out2, out3, out4, };
896   guint out_len[] =
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",
902       NULL, NULL, 0);
903 }
904
905 GST_END_TEST;
906
907 GST_START_TEST (convert_cea608_raw_cea708_cdp_double_framerate)
908 {
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
918   };
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
924   };
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
930   };
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
936   };
937   const guint8 *out[] = { out1, out2, out3, out4, };
938   guint out_len[] =
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",
944       NULL, NULL, 0);
945 }
946
947 GST_END_TEST;
948
949 GST_START_TEST (convert_cea608_s334_1a_cea708_cdp_double_framerate)
950 {
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
960   };
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
966   };
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
972   };
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
978   };
979   const guint8 *out[] = { out1, out2, out3, out4, };
980   guint out_len[] =
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",
986       NULL, NULL, 0);
987 }
988
989 GST_END_TEST;
990
991 GST_START_TEST (convert_cea708_cdp_cea708_cc_data_double_input_data)
992 {
993   /* caps say 60fps, data has 30fps. Ensure data is taken alternatatively from
994    * each field even if there is too much input data */
995   const guint8 in1[] =
996       { 0x96, 0x69, 0x16, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe3, 0xfc, 0x81, 0x82,
997     0xfd, 0x83, 0x84, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0xff
998   };
999   /* padding buffer */
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
1003   };
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
1007   };
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
1011    * buffer */
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",
1021       NULL, NULL, 0);
1022 }
1023
1024 GST_END_TEST;
1025
1026 GST_START_TEST (convert_cea708_cc_data_cea708_cdp_double_input_data)
1027 {
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
1036    * buffer */
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
1042   };
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
1049   };
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
1055   };
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
1061   };
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
1067   };
1068   const guint8 *out[] = { out1, out2, out3, out4, out5 };
1069   guint out_len[] =
1070       { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4),
1071     sizeof (out5)
1072   };
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);
1078 }
1079
1080 GST_END_TEST;
1081
1082 static guint8
1083 calculate_cdp_checksum (guint8 * cdp, gsize len)
1084 {
1085   guint8 checksum = 0;
1086   gsize i;
1087
1088   for (i = 0; i < len; i++) {
1089     checksum += cdp[i];
1090   }
1091   checksum &= 0xff;
1092   return 256 - checksum;
1093 }
1094
1095 GST_START_TEST (convert_cea708_cc_data_cea708_cdp_field1_overflow)
1096 {
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];
1104   guint i;
1105
1106 #define N_OUTPUTS 100
1107   guint8 out_data[N_OUTPUTS * 43];
1108   guint out_len[N_OUTPUTS];
1109   guint8 *out[N_OUTPUTS];
1110
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
1116   };
1117
1118   G_STATIC_ASSERT (sizeof (out_template) == 43);
1119
1120   /* generate input data */
1121   for (i = 0; i < N_INPUTS; i++) {
1122     in_len[i] = 3;
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];
1127   }
1128
1129   for (i = 0; i < N_OUTPUTS; i++) {
1130     out_len[i] = 43;
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 */
1136     if (i % 2 == 0) {
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;
1147
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];
1151     } else {
1152       out_data[i * 43 + 9] = 0xf9;
1153       out_data[i * 43 + 10] = 0x80;
1154       out_data[i * 43 + 11] = 0x80;
1155     }
1156     out_data[i * 43 + 42] = calculate_cdp_checksum (&out_data[i * 43], 42);
1157     out[i] = &out_data[i * 43];
1158   }
1159
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);
1165 }
1166
1167 GST_END_TEST;
1168
1169 static Suite *
1170 ccextractor_suite (void)
1171 {
1172   Suite *s = suite_create ("ccconverter");
1173   TCase *tc = tcase_create ("general");
1174
1175   suite_add_tcase (s, tc);
1176
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);
1207
1208   return s;
1209 }
1210
1211 GST_CHECK_MAIN (ccextractor);