ccconverter: fix framerate caps negotiation from non-cdp to cdp
[platform/upstream/gstreamer.git] / 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 in[] = { 0x80, 0x80 };
355   const guint8 out[] =
356       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x80,
357     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
358     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
359     0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6e
360   };
361   check_conversion (in, sizeof (in), out, sizeof (out),
362       "closedcaption/x-cea-608,format=(string)raw,framerate=(fraction)60/1",
363       "closedcaption/x-cea-708,format=(string)cdp", NULL, NULL);
364 }
365
366 GST_END_TEST;
367
368 GST_START_TEST (convert_cea608_s334_1a_cea608_raw)
369 {
370   const guint8 in[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
371   const guint8 out[] = { 0x80, 0x80 };
372   check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
373       "closedcaption/x-cea-608,format=(string)s334-1a",
374       "closedcaption/x-cea-608,format=(string)raw");
375 }
376
377 GST_END_TEST;
378
379 GST_START_TEST (convert_cea608_s334_1a_cea608_raw_too_big)
380 {
381   const guint8 in[] =
382       { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80,
383     0x80
384   };
385   const guint8 out[] = { 0x80, 0x80, 0x80, 0x80 };
386   check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
387       "closedcaption/x-cea-608,format=(string)s334-1a",
388       "closedcaption/x-cea-608,format=(string)raw");
389 }
390
391 GST_END_TEST;
392
393 GST_START_TEST (convert_cea608_s334_1a_cea708_cc_data)
394 {
395   const guint8 in[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
396   const guint8 out[] = { 0xfc, 0x80, 0x80, 0xfd, 0x80, 0x80 };
397   check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
398       "closedcaption/x-cea-608,format=(string)s334-1a",
399       "closedcaption/x-cea-708,format=(string)cc_data");
400 }
401
402 GST_END_TEST;
403
404 GST_START_TEST (convert_cea608_s334_1a_cea708_cdp)
405 {
406   const guint8 in[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
407   const guint8 out[] =
408       { 0x96, 0x69, 0x49, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xf4, 0xfc, 0x80, 0x80,
409     0xfd, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
410     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
411     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
412     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
413     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0xaf
414   };
415   check_conversion (in, sizeof (in), out, sizeof (out),
416       "closedcaption/x-cea-608,format=(string)s334-1a,framerate=(fraction)30/1",
417       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
418       NULL, NULL);
419 }
420
421 GST_END_TEST;
422
423 GST_START_TEST (convert_cea708_cc_data_cea608_raw)
424 {
425   const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
426   const guint8 out[] = { 0x80, 0x80 };
427   check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
428       "closedcaption/x-cea-708,format=(string)cc_data",
429       "closedcaption/x-cea-608,format=(string)raw");
430 }
431
432 GST_END_TEST;
433
434 GST_START_TEST (convert_cea708_cc_data_cea608_s334_1a)
435 {
436   const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
437   const guint8 out[] = { 0x80, 0x80, 0x80 };
438   check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
439       "closedcaption/x-cea-708,format=(string)cc_data",
440       "closedcaption/x-cea-608,format=(string)s334-1a");
441 }
442
443 GST_END_TEST;
444
445 GST_START_TEST (convert_cea708_cc_data_cea708_cdp)
446 {
447   const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
448   const guint8 out[] =
449       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x80,
450     0xfe, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
451     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
452     0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6a
453   };
454   check_conversion (in, sizeof (in), out, sizeof (out),
455       "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
456       "closedcaption/x-cea-708,format=(string)cdp", NULL, NULL);
457 }
458
459 GST_END_TEST;
460
461 GST_START_TEST (convert_cea708_cdp_cea608_raw)
462 {
463   const guint8 in[] =
464       { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
465     0xfe, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
466   };
467   const guint8 out[] = { 0x80, 0x80 };
468   check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
469       "closedcaption/x-cea-708,format=(string)cdp",
470       "closedcaption/x-cea-608,format=(string)raw");
471 }
472
473 GST_END_TEST;
474
475 GST_START_TEST (convert_cea708_cdp_cea608_s334_1a)
476 {
477   const guint8 in[] =
478       { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
479     0xfe, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
480   };
481   const guint8 out[] = { 0x80, 0x80, 0x80 };
482   check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
483       "closedcaption/x-cea-708,format=(string)cdp",
484       "closedcaption/x-cea-608,format=(string)s334-1a");
485 }
486
487 GST_END_TEST;
488
489 GST_START_TEST (convert_cea708_cdp_cea708_cc_data)
490 {
491   const guint8 in[] =
492       { 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
493     0xfe, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
494   };
495   const guint8 out[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
496   check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
497       "closedcaption/x-cea-708,format=(string)cdp",
498       "closedcaption/x-cea-708,format=(string)cc_data");
499 }
500
501 GST_END_TEST;
502
503 GST_START_TEST (convert_cea708_cdp_cea708_cc_data_too_big)
504 {
505   /* tests that too large input is truncated */
506   const guint8 in[] =
507       { 0x96, 0x69, 0x2e, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xeb, 0xfc, 0x80, 0x80,
508     0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
509     0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
510     0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a,
511   };
512   const guint8 out[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
513     0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
514     0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80
515   };
516   check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
517       "closedcaption/x-cea-708,format=(string)cdp",
518       "closedcaption/x-cea-708,format=(string)cc_data");
519 }
520
521 GST_END_TEST;
522
523 GST_START_TEST (convert_cea708_cdp_cea708_cdp_double_framerate)
524 {
525   /* tests that packets are split exactly in half when doubling the framerate */
526   const guint8 in1[] =
527       { 0x96, 0x69, 0x49, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xf4, 0xfc, 0x01, 0x02,
528     0xfc, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
529     0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
530     0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
531     0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
532     0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0x74, 0x00, 0x00, 0xd2
533   };
534   const guint8 *in[] = { in1 };
535   guint in_len[] = { sizeof (in1) };
536   GstVideoTimeCode in_tc1;
537   const GstVideoTimeCode *in_tc[] = { &in_tc1 };
538
539   const guint8 out1[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x00, 0x71, 0xc1,
540     0x82, 0x03, 0x08, 0x72, 0xea, 0xfc, 0x01, 0x02, 0xfe, 0x05, 0x06, 0xfe,
541     0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe,
542     0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0x74,
543     0x00, 0x00, 0x10
544   };
545   const guint8 out2[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x01, 0x71, 0xc1,
546     0x82, 0x03, 0x09, 0x72, 0xea, 0xfc, 0x03, 0x04, 0xfe, 0x17, 0x18, 0xfe,
547     0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe,
548     0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0x74,
549     0x00, 0x01, 0xc5
550   };
551   const guint8 *out[] = { out1, out2 };
552   guint out_len[] = { sizeof (out1), sizeof (out2) };
553   GstVideoTimeCode out_tc1, out_tc2;
554   const GstVideoTimeCode *out_tc[] = { &out_tc1, &out_tc2 };
555
556   gst_video_time_code_init (&in_tc1, 30, 1, NULL,
557       GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 4, 0);
558   fail_unless (gst_video_time_code_is_valid (&in_tc1));
559
560   gst_video_time_code_init (&out_tc1, 60, 1, NULL,
561       GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
562   fail_unless (gst_video_time_code_is_valid (&out_tc1));
563   gst_video_time_code_init (&out_tc2, 60, 1, NULL,
564       GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 9, 0);
565   fail_unless (gst_video_time_code_is_valid (&out_tc2));
566
567   check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
568       G_N_ELEMENTS (out_len), out, out_len,
569       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
570       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
571       in_tc, out_tc, 0);
572
573   gst_video_time_code_clear (&in_tc1);
574   gst_video_time_code_clear (&out_tc1);
575   gst_video_time_code_clear (&out_tc2);
576 }
577
578 GST_END_TEST;
579
580 GST_START_TEST (convert_cea708_cdp_cea708_cdp_half_framerate)
581 {
582   /* tests that two input packets are merged together when halving the
583    * framerate.  With cc_data compaction! */
584   const guint8 in1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
585     0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08,
586     0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10,
587     0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0x74, 0x00, 0x00, 0x7a
588   };
589   const guint8 in2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
590     0xfc, 0x14, 0x15, 0xfe, 0x16, 0x17, 0xfe, 0x18, 0x19, 0xfe, 0x1a, 0x1b,
591     0xfe, 0x1c, 0x1d, 0xfe, 0x1e, 0x1f, 0xfe, 0x20, 0x21, 0xfe, 0x22, 0x23,
592     0xfe, 0x24, 0x25, 0xfe, 0x26, 0x27, 0x74, 0x00, 0x01, 0x70
593   };
594   const guint8 *in[] = { in1, in2 };
595   guint in_len[] = { sizeof (in1), sizeof (in2) };
596   GstVideoTimeCode in_tc1, in_tc2;
597   const GstVideoTimeCode *in_tc[] = { &in_tc1, &in_tc2 };
598
599   const guint8 out1[] =
600       { 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x00, 0x71, 0xc1, 0x82, 0x03, 0x04,
601     0x72, 0xf4, 0xfc, 0x01, 0x02, 0xfc, 0x14, 0x15, 0xfe, 0x03, 0x04, 0xfe,
602     0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe,
603     0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe,
604     0x16, 0x17, 0xfe, 0x18, 0x19, 0xfe, 0x1a, 0x1b, 0xfe, 0x1c, 0x1d, 0xfe,
605     0x1e, 0x1f, 0xfe, 0x20, 0x21, 0xfe, 0x22, 0x23, 0xfe, 0x24, 0x25, 0xfe,
606     0x26, 0x27, 0x74, 0x00, 0x00, 0x08
607   };
608   const guint8 *out[] = { out1 };
609   guint out_len[] = { sizeof (out1) };
610   GstVideoTimeCode out_tc1;
611   const GstVideoTimeCode *out_tc[] = { &out_tc1 };
612
613   gst_video_time_code_init (&in_tc1, 60, 1, NULL,
614       GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
615   fail_unless (gst_video_time_code_is_valid (&in_tc1));
616   gst_video_time_code_init (&in_tc2, 60, 1, NULL,
617       GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
618   fail_unless (gst_video_time_code_is_valid (&in_tc2));
619
620   gst_video_time_code_init (&out_tc1, 30, 1, NULL,
621       GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 4, 0);
622   fail_unless (gst_video_time_code_is_valid (&out_tc1));
623
624   check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
625       G_N_ELEMENTS (out_len), out, out_len,
626       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
627       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
628       in_tc, out_tc, 0);
629
630   gst_video_time_code_clear (&in_tc1);
631   gst_video_time_code_clear (&in_tc2);
632   gst_video_time_code_clear (&out_tc1);
633 }
634
635 GST_END_TEST;
636
637 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_merge)
638 {
639   /* check that 3 high framerate packets can be merged into 1 low framerate
640    * packets with the extra data on the third input packet being placed at the
641    * beginning of the second output packet */
642   const guint8 in1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
643     0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08,
644     0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10,
645     0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0x74, 0x00, 0x00, 0x7a
646   };
647   /* enough input to fully cover two output packets. Extra is discarded */
648   const guint8 *in[] = { in1, in1, in1, in1, in1, in1, in1 };
649   guint in_len[] =
650       { sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1),
651     sizeof (in1)
652   };
653
654   const guint8 out1[] =
655       { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
656     0xfc, 0x01, 0x02, 0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06,
657     0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e,
658     0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x03, 0x04,
659     0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
660     0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
661     0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
662     0x74, 0x00, 0x00, 0xc5
663   };
664   const guint8 out2[] =
665       { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x01, 0x72, 0xf9, 0xfc, 0x01, 0x02,
666     0xfc, 0x01, 0x02, 0xfc, 0x01, 0x02, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e,
667     0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x03, 0x04,
668     0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
669     0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
670     0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
671     0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
672     0x74, 0x00, 0x01, 0x83
673   };
674   const guint8 *out[] = { out1, out2 };
675   guint out_len[] = { sizeof (out1), sizeof (out2) };
676   check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
677       G_N_ELEMENTS (out_len), out, out_len,
678       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
679       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
680       NULL, NULL, 0);
681 }
682
683 GST_END_TEST;
684
685 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split)
686 {
687   /* test that a low framerate stream produces multiple output packets for a
688    * high framerate */
689   const guint8 in1[] =
690       { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
691     0xfc, 0x03, 0x04, 0xfc, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
692     0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
693     0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
694     0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
695     0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a,
696     0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30, 0xfe, 0x31, 0x32,
697     0x74, 0x00, 0x00, 0x12
698   };
699   const guint8 *in[] = { in1, in1 };
700   guint in_len[] = { sizeof (in1), sizeof (in1) };
701
702   const guint8 out1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
703     0xfc, 0x01, 0x02, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
704     0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
705     0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0x74, 0x00, 0x00, 0x30
706   };
707   const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
708     0xfc, 0x03, 0x04, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
709     0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26,
710     0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a, 0x74, 0x00, 0x01, 0xe6
711   };
712   const guint8 out3[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea,
713     0xfc, 0x05, 0x06, 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30,
714     0xfe, 0x31, 0x32, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
715     0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0x74, 0x00, 0x02, 0x54
716   };
717   const guint8 out4[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea,
718     0xfc, 0x01, 0x02, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16,
719     0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
720     0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0x74, 0x00, 0x03, 0x76
721   };
722   const guint8 *out[] = { out1, out2, out3, out4 };
723   guint out_len[] =
724       { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4) };
725   check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
726       G_N_ELEMENTS (out_len), out, out_len,
727       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
728       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
729       NULL, NULL, 0);
730 }
731
732 GST_END_TEST;
733
734 GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split_eos)
735 {
736   /* test that a low framerate stream produces multiple output packets for a
737    * high framerate and that an EOS will push the pending data */
738   const guint8 in1[] =
739       { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
740     0xfc, 0x03, 0x04, 0xfc, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
741     0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
742     0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
743     0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
744     0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a,
745     0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30, 0xfe, 0x31, 0x32,
746     0x74, 0x00, 0x00, 0x12
747   };
748   const guint8 *in[] = { in1 };
749   guint in_len[] = { sizeof (in1) };
750
751   const guint8 out1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
752     0xfc, 0x01, 0x02, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
753     0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
754     0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0x74, 0x00, 0x00, 0x30
755   };
756   const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
757     0xfc, 0x03, 0x04, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
758     0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26,
759     0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a, 0x74, 0x00, 0x01, 0xe6
760   };
761   const guint8 out3[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea,
762     0xfc, 0x05, 0x06, 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30,
763     0xfe, 0x31, 0x32, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
764     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0xdb
765   };
766   const guint8 *out[] = { out1, out2, out3 };
767   guint out_len[] = { sizeof (out1), sizeof (out2), sizeof (out3) };
768
769   check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
770       G_N_ELEMENTS (out_len), out, out_len,
771       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
772       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
773       NULL, NULL, FLAG_SEND_EOS);
774 }
775
776 GST_END_TEST;
777
778 GST_START_TEST (convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling)
779 {
780   const guint8 in1[] = { 0x96, 0x69, 0x10, 0x7f, 0x43, 0x00, 0x00, 0x72, 0xe1,
781     0xfc, 0x80, 0x80, 0x74, 0x00, 0x00, 0x7a
782   };
783   const guint8 *in[] = { in1, in1 };
784   guint in_len[] = { sizeof (in1), sizeof (in1) };
785   GstVideoTimeCode in_tc1, in_tc2;
786   const GstVideoTimeCode *in_tc[] = { &in_tc1, &in_tc2 };
787
788   const guint8 out1[] =
789       { 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x00, 0x71, 0xc0, 0x81, 0x59, 0x29,
790     0x72, 0xf4, 0xfc, 0x80, 0x80, 0xf8, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa,
791     0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
792     0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
793     0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
794     0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
795     0x00, 0x00, 0x74, 0x00, 0x00, 0xfb
796   };
797   const guint8 out2[] =
798       { 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x01, 0x71, 0xc0, 0x82, 0x00, 0x00,
799     0x72, 0xf4, 0xfc, 0x80, 0x80, 0xf8, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa,
800     0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
801     0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
802     0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
803     0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
804     0x00, 0x00, 0x74, 0x00, 0x01, 0x7a
805   };
806   const guint8 *out[] = { out1, out2 };
807   guint out_len[] = { sizeof (out1), sizeof (out2) };
808   GstVideoTimeCode out_tc1, out_tc2;
809   const GstVideoTimeCode *out_tc[] = { &out_tc1, &out_tc2 };
810
811   gst_video_time_code_init (&in_tc1, 30000, 1001, NULL,
812       GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME, 0, 1, 59, 29, 0);
813   fail_unless (gst_video_time_code_is_valid (&in_tc1));
814
815   gst_video_time_code_init (&in_tc2, 30000, 1001, NULL,
816       GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME, 0, 2, 0, 4, 0);
817   fail_unless (gst_video_time_code_is_valid (&in_tc2));
818
819   gst_video_time_code_init (&out_tc1, 30, 1, NULL,
820       GST_VIDEO_TIME_CODE_FLAGS_NONE, 0, 1, 59, 29, 0);
821   fail_unless (gst_video_time_code_is_valid (&out_tc1));
822
823   gst_video_time_code_init (&out_tc2, 30, 1, NULL,
824       GST_VIDEO_TIME_CODE_FLAGS_NONE, 0, 2, 0, 0, 0);
825   fail_unless (gst_video_time_code_is_valid (&out_tc2));
826
827   check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
828       G_N_ELEMENTS (out_len), out, out_len,
829       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30000/1001",
830       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
831       in_tc, out_tc, FLAG_SEND_EOS);
832
833   gst_video_time_code_clear (&in_tc1);
834   gst_video_time_code_clear (&out_tc1);
835 }
836
837 GST_END_TEST;
838
839 GST_START_TEST (convert_cea708_cc_data_cea708_cdp_double_framerate)
840 {
841   const guint8 in1[] = { 0xfc, 0x80, 0x81, 0xfc, 0x82, 0x83, 0xfe, 0x84, 0x85 };
842   const guint8 in2[] = { 0xfc, 0x86, 0x87, 0xfc, 0x88, 0x89, 0xfe, 0x8a, 0x8b };
843   const guint8 *in[] = { in1, in2 };
844   guint in_len[] = { sizeof (in1), sizeof (in2) };
845   const guint8 out1[] =
846       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
847     0xfe, 0x84, 0x85, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
848     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
849     0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x60
850   };
851   const guint8 out2[] =
852       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfc, 0x82, 0x83,
853     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
854     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
855     0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x67
856   };
857   const guint8 out3[] =
858       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x86, 0x87,
859     0xfe, 0x8a, 0x8b, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
860     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
861     0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x44
862   };
863   const guint8 out4[] =
864       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfc, 0x88, 0x89,
865     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
866     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
867     0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x57
868   };
869   const guint8 *out[] = { out1, out2, out3, out4, };
870   guint out_len[] =
871       { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
872   check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
873       G_N_ELEMENTS (out_len), out, out_len,
874       "closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1",
875       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
876       NULL, NULL, 0);
877 }
878
879 GST_END_TEST;
880
881 GST_START_TEST (convert_cea608_raw_cea708_cdp_double_framerate)
882 {
883   const guint8 in1[] = { 0x80, 0x81, 0x82, 0x83 };
884   const guint8 in2[] = { 0x84, 0x85, 0x86, 0x87 };
885   const guint8 *in[] = { in1, in2 };
886   guint in_len[] = { sizeof (in1), sizeof (in2) };
887   const guint8 out1[] =
888       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
889     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
890     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
891     0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6d
892   };
893   const guint8 out2[] =
894       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfc, 0x82, 0x83,
895     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
896     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
897     0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x67
898   };
899   const guint8 out3[] =
900       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x84, 0x85,
901     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
902     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
903     0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x61
904   };
905   const guint8 out4[] =
906       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfc, 0x86, 0x87,
907     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
908     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
909     0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x5b
910   };
911   const guint8 *out[] = { out1, out2, out3, out4, };
912   guint out_len[] =
913       { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
914   check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
915       G_N_ELEMENTS (out_len), out, out_len,
916       "closedcaption/x-cea-608,format=(string)raw,framerate=(fraction)30/1",
917       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
918       NULL, NULL, 0);
919 }
920
921 GST_END_TEST;
922
923 GST_START_TEST (convert_cea608_s334_1a_cea708_cdp_double_framerate)
924 {
925   const guint8 in1[] = { 0x80, 0x80, 0x81, 0x00, 0x82, 0x83 };
926   const guint8 in2[] = { 0x80, 0x84, 0x85, 0x00, 0x86, 0x87 };
927   const guint8 *in[] = { in1, in2 };
928   guint in_len[] = { sizeof (in1), sizeof (in2) };
929   const guint8 out1[] =
930       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
931     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
932     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
933     0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6d
934   };
935   const guint8 out2[] =
936       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfd, 0x82, 0x83,
937     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
938     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
939     0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x66
940   };
941   const guint8 out3[] =
942       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x84, 0x85,
943     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
944     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
945     0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x61
946   };
947   const guint8 out4[] =
948       { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfd, 0x86, 0x87,
949     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
950     0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
951     0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x5a
952   };
953   const guint8 *out[] = { out1, out2, out3, out4, };
954   guint out_len[] =
955       { sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
956   check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
957       G_N_ELEMENTS (out_len), out, out_len,
958       "closedcaption/x-cea-608,format=(string)s334-1a,framerate=(fraction)30/1",
959       "closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
960       NULL, NULL, 0);
961 }
962
963 GST_END_TEST;
964
965 static Suite *
966 ccextractor_suite (void)
967 {
968   Suite *s = suite_create ("ccconverter");
969   TCase *tc = tcase_create ("general");
970
971   suite_add_tcase (s, tc);
972
973   tcase_add_test (tc, cdp_requires_valid_framerate);
974   tcase_add_test (tc, framerate_passthrough);
975   tcase_add_test (tc, framerate_changes);
976   tcase_add_test (tc, framerate_invalid_format);
977   tcase_add_test (tc, convert_cea608_raw_cea608_s334_1a);
978   tcase_add_test (tc, convert_cea608_raw_cea708_cc_data);
979   tcase_add_test (tc, convert_cea608_raw_cea708_cdp);
980   tcase_add_test (tc, convert_cea608_s334_1a_cea608_raw);
981   tcase_add_test (tc, convert_cea608_s334_1a_cea608_raw_too_big);
982   tcase_add_test (tc, convert_cea608_s334_1a_cea708_cc_data);
983   tcase_add_test (tc, convert_cea608_s334_1a_cea708_cdp);
984   tcase_add_test (tc, convert_cea708_cc_data_cea608_raw);
985   tcase_add_test (tc, convert_cea708_cc_data_cea608_s334_1a);
986   tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp);
987   tcase_add_test (tc, convert_cea708_cdp_cea608_raw);
988   tcase_add_test (tc, convert_cea708_cdp_cea608_s334_1a);
989   tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data);
990   tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data_too_big);
991   tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_half_framerate);
992   tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_double_framerate);
993   tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_merge);
994   tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_split);
995   tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_split_eos);
996   tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling);
997   tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_double_framerate);
998   tcase_add_test (tc, convert_cea608_raw_cea708_cdp_double_framerate);
999   tcase_add_test (tc, convert_cea608_s334_1a_cea708_cdp_double_framerate);
1000
1001   return s;
1002 }
1003
1004 GST_CHECK_MAIN (ccextractor);