mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
b5e119bbcc
This allows to handle CDP streams where the framerate is not provided by the caps and generally gives preference to the framerate inside the CDP packets over the one in the caps. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7532>
1368 lines
53 KiB
C
1368 lines
53 KiB
C
/* GStreamer
|
|
*
|
|
* Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
#include <gst/gst.h>
|
|
#include <gst/video/video.h>
|
|
#include <gst/check/gstcheck.h>
|
|
#include <gst/check/gstharness.h>
|
|
|
|
#include <string.h>
|
|
|
|
enum CheckConversionFlags
|
|
{
|
|
FLAG_NONE,
|
|
FLAG_SEND_EOS = 1,
|
|
};
|
|
|
|
GST_START_TEST (cdp_requires_valid_framerate)
|
|
{
|
|
GstHarness *h;
|
|
GstBuffer *buffer;
|
|
GstMapInfo map;
|
|
|
|
h = gst_harness_new ("ccconverter");
|
|
|
|
/* Enforce conversion to CDP */
|
|
gst_harness_set_sink_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cdp");
|
|
|
|
/* Try without a framerate first, this has to fail */
|
|
gst_harness_set_src_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cc_data");
|
|
|
|
buffer = gst_buffer_new_and_alloc (3);
|
|
gst_buffer_map (buffer, &map, GST_MAP_WRITE);
|
|
map.data[0] = 0xfc;
|
|
map.data[1] = 0x80;
|
|
map.data[2] = 0x80;
|
|
gst_buffer_unmap (buffer, &map);
|
|
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
|
GST_FLOW_NOT_NEGOTIATED);
|
|
|
|
/* Now set a framerate only on the sink caps, this should still fail:
|
|
* We can't come up with a framerate
|
|
*/
|
|
gst_harness_set_sink_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1");
|
|
|
|
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
|
GST_FLOW_NOT_NEGOTIATED);
|
|
|
|
/* Then try with a change of framerate, this should work */
|
|
gst_harness_set_sink_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cdp");
|
|
gst_harness_set_src_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
|
|
|
|
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
|
GST_FLOW_OK);
|
|
|
|
/* Then try with an invalid CDP framerate, this should fail */
|
|
gst_harness_set_sink_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cdp");
|
|
gst_harness_set_src_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)29/1");
|
|
|
|
fail_unless_equals_int (gst_harness_push (h, buffer),
|
|
GST_FLOW_NOT_NEGOTIATED);
|
|
|
|
gst_harness_teardown (h);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (framerate_passthrough)
|
|
{
|
|
GstHarness *h;
|
|
GstBuffer *buffer;
|
|
GstMapInfo map;
|
|
GstCaps *caps, *expected_caps;
|
|
|
|
h = gst_harness_new ("ccconverter");
|
|
|
|
gst_harness_set_src_caps_str (h,
|
|
"closedcaption/x-cea-608,format=(string)s334-1a,framerate=(fraction)30/1");
|
|
|
|
gst_harness_set_sink_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cc_data");
|
|
|
|
buffer = gst_buffer_new_and_alloc (3);
|
|
gst_buffer_map (buffer, &map, GST_MAP_WRITE);
|
|
map.data[0] = 0x00;
|
|
map.data[1] = 0x80;
|
|
map.data[2] = 0x80;
|
|
gst_buffer_unmap (buffer, &map);
|
|
|
|
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
|
GST_FLOW_OK);
|
|
|
|
caps = gst_pad_get_current_caps (h->sinkpad);
|
|
fail_unless (caps);
|
|
expected_caps =
|
|
gst_caps_from_string
|
|
("closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
|
|
gst_check_caps_equal (caps, expected_caps);
|
|
gst_caps_unref (caps);
|
|
gst_caps_unref (expected_caps);
|
|
|
|
/* Now try between the same formats, should still pass through */
|
|
gst_harness_set_src_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
|
|
|
|
gst_harness_set_sink_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cc_data");
|
|
|
|
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
|
GST_FLOW_OK);
|
|
|
|
caps = gst_pad_get_current_caps (h->sinkpad);
|
|
fail_unless (caps);
|
|
expected_caps =
|
|
gst_caps_from_string
|
|
("closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
|
|
gst_check_caps_equal (caps, expected_caps);
|
|
gst_caps_unref (caps);
|
|
gst_caps_unref (expected_caps);
|
|
|
|
/* And another time with the same format but only framerate on the output
|
|
* side. This should fail as we can't just come up with a framerate! */
|
|
gst_harness_set_src_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cc_data");
|
|
|
|
gst_harness_set_sink_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
|
|
|
|
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
|
GST_FLOW_NOT_NEGOTIATED);
|
|
|
|
/* Now try cdp -> cc_data with framerate passthrough */
|
|
gst_harness_set_src_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1");
|
|
|
|
gst_harness_set_sink_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cc_data");
|
|
|
|
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
|
GST_FLOW_OK);
|
|
|
|
gst_buffer_unref (buffer);
|
|
gst_harness_teardown (h);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (framerate_changes)
|
|
{
|
|
GstHarness *h;
|
|
GstBuffer *buffer;
|
|
GstMapInfo map;
|
|
|
|
h = gst_harness_new ("ccconverter");
|
|
|
|
buffer = gst_buffer_new_and_alloc (3);
|
|
gst_buffer_map (buffer, &map, GST_MAP_WRITE);
|
|
map.data[0] = 0x00;
|
|
map.data[1] = 0x80;
|
|
map.data[2] = 0x80;
|
|
gst_buffer_unmap (buffer, &map);
|
|
|
|
/* success case */
|
|
gst_harness_set_src_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1");
|
|
gst_harness_set_sink_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1");
|
|
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
|
GST_FLOW_OK);
|
|
|
|
/* test an invalid cdp framerate */
|
|
gst_harness_set_sink_caps_str (h,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)1111/1");
|
|
fail_unless_equals_int (gst_harness_push (h, buffer),
|
|
GST_FLOW_NOT_NEGOTIATED);
|
|
|
|
gst_harness_teardown (h);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (framerate_invalid_format)
|
|
{
|
|
GstHarness *h;
|
|
GstBuffer *buffer;
|
|
GstMapInfo map;
|
|
guint i, j;
|
|
|
|
const gchar *failure_caps[] = {
|
|
/* all of these combinations should fail with different framerates */
|
|
"closedcaption/x-cea-608,format=(string)raw",
|
|
"closedcaption/x-cea-608,format=(string)s334-1a",
|
|
"closedcaption/x-cea-708,format=(string)cc_data",
|
|
};
|
|
|
|
h = gst_harness_new ("ccconverter");
|
|
|
|
buffer = gst_buffer_new_and_alloc (3);
|
|
gst_buffer_map (buffer, &map, GST_MAP_WRITE);
|
|
map.data[0] = 0x00;
|
|
map.data[1] = 0x80;
|
|
map.data[2] = 0x80;
|
|
gst_buffer_unmap (buffer, &map);
|
|
|
|
/* framerate conversion failure cases */
|
|
for (i = 0; i < G_N_ELEMENTS (failure_caps); i++) {
|
|
for (j = 0; j < G_N_ELEMENTS (failure_caps); j++) {
|
|
gchar *srccaps, *sinkcaps;
|
|
|
|
srccaps =
|
|
g_strdup_printf ("%s%s", failure_caps[i],
|
|
",framerate=(fraction)30/1");
|
|
sinkcaps =
|
|
g_strdup_printf ("%s%s", failure_caps[i],
|
|
",framerate=(fraction)60/1");
|
|
|
|
GST_INFO ("attempting conversion from %s", srccaps);
|
|
GST_INFO (" to %s", sinkcaps);
|
|
|
|
gst_harness_set_src_caps_str (h, srccaps);
|
|
gst_harness_set_sink_caps_str (h, sinkcaps);
|
|
fail_unless_equals_int (gst_harness_push (h, gst_buffer_ref (buffer)),
|
|
GST_FLOW_NOT_NEGOTIATED);
|
|
|
|
g_free (srccaps);
|
|
g_free (sinkcaps);
|
|
}
|
|
}
|
|
|
|
gst_buffer_unref (buffer);
|
|
gst_harness_teardown (h);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
static void
|
|
check_conversion_multiple (guint n_in, const guint8 ** in, guint * in_len,
|
|
guint n_out, const guint8 ** out, guint * out_len, const gchar * in_caps,
|
|
const gchar * out_caps, const GstVideoTimeCode ** in_tc,
|
|
const GstVideoTimeCode ** out_tc, enum CheckConversionFlags flags)
|
|
{
|
|
GstHarness *h;
|
|
GstBuffer *buffer;
|
|
GstVideoTimeCodeMeta *out_tc_meta;
|
|
int i = 0;
|
|
|
|
h = gst_harness_new ("ccconverter");
|
|
|
|
gst_harness_set_src_caps_str (h, in_caps);
|
|
gst_harness_set_sink_caps_str (h, out_caps);
|
|
|
|
for (i = 0; i < n_in; i++) {
|
|
buffer =
|
|
gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, (gpointer) in[i],
|
|
in_len[i], 0, in_len[i], NULL, NULL);
|
|
GST_INFO ("pushing buffer %u %" GST_PTR_FORMAT, i, buffer);
|
|
if (in_tc && in_tc[i])
|
|
gst_buffer_add_video_time_code_meta (buffer, in_tc[i]);
|
|
fail_unless_equals_int (gst_harness_push (h, buffer), GST_FLOW_OK);
|
|
}
|
|
|
|
if (flags & FLAG_SEND_EOS)
|
|
fail_unless (gst_harness_push_event (h, gst_event_new_eos ()));
|
|
|
|
for (i = 0; i < n_out; i++) {
|
|
buffer = gst_harness_pull (h);
|
|
|
|
GST_INFO ("pulled buffer %u %" GST_PTR_FORMAT, i, buffer);
|
|
fail_unless (buffer != NULL);
|
|
gst_check_buffer_data (buffer, out[i], out_len[i]);
|
|
out_tc_meta = gst_buffer_get_video_time_code_meta (buffer);
|
|
fail_if (out_tc_meta == NULL && out_tc != NULL && out_tc[i] != NULL);
|
|
if (out_tc_meta && out_tc && out_tc[i])
|
|
fail_unless (gst_video_time_code_compare (&out_tc_meta->tc,
|
|
out_tc[i]) == 0);
|
|
|
|
gst_buffer_unref (buffer);
|
|
}
|
|
|
|
gst_harness_teardown (h);
|
|
}
|
|
|
|
static void
|
|
check_conversion (const guint8 * in, guint in_len, const guint8 * out,
|
|
guint out_len, const gchar * in_caps, const gchar * out_caps,
|
|
const GstVideoTimeCode * in_tc, const GstVideoTimeCode * out_tc)
|
|
{
|
|
check_conversion_multiple (1, &in, &in_len, 1, &out, &out_len, in_caps,
|
|
out_caps, &in_tc, &out_tc, 0);
|
|
}
|
|
|
|
static void
|
|
check_conversion_tc_passthrough (const guint8 * in, guint in_len,
|
|
const guint8 * out, guint out_len, const gchar * in_caps,
|
|
const gchar * out_caps)
|
|
{
|
|
GstVideoTimeCode tc;
|
|
gst_video_time_code_init (&tc, 30, 1, NULL, GST_VIDEO_TIME_CODE_FLAGS_NONE,
|
|
1, 2, 3, 4, 0);
|
|
check_conversion (in, in_len, out, out_len, in_caps, out_caps, &tc, &tc);
|
|
gst_video_time_code_clear (&tc);
|
|
}
|
|
|
|
GST_START_TEST (convert_cea608_raw_cea608_s334_1a)
|
|
{
|
|
const guint8 in[] = { 0x80, 0x80 };
|
|
const guint8 out[] = { 0x80, 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)raw",
|
|
"closedcaption/x-cea-608,format=(string)s334-1a");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_raw_cea708_cc_data)
|
|
{
|
|
const guint8 in[] = { 0x80, 0x80 };
|
|
const guint8 out[] = { 0xfc, 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)raw",
|
|
"closedcaption/x-cea-708,format=(string)cc_data");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_raw_cea708_cdp)
|
|
{
|
|
const guint8 in1[] = { 0x81, 0x82 };
|
|
const guint8 in2[] = { 0x80, 0x80 };
|
|
const guint8 out1[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x81, 0x82,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6b
|
|
};
|
|
const guint8 out2[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x6f
|
|
};
|
|
const guint8 *in[] = { in1, in2 };
|
|
guint in_len[] = { sizeof (in1), sizeof (in2) };
|
|
const guint8 *out[] = { out1, out2 };
|
|
guint out_len[] = { sizeof (out1), sizeof (out2) };
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-608,format=(string)raw,framerate=(fraction)60/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp", NULL, NULL, 0);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_s334_1a_cea608_raw)
|
|
{
|
|
const guint8 in[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
|
|
const guint8 out[] = { 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)s334-1a",
|
|
"closedcaption/x-cea-608,format=(string)raw");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_s334_1a_cea608_raw_too_big)
|
|
{
|
|
const guint8 in[] =
|
|
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80,
|
|
0x80
|
|
};
|
|
const guint8 out[] = { 0x80, 0x80, 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)s334-1a",
|
|
"closedcaption/x-cea-608,format=(string)raw");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_s334_1a_cea708_cc_data)
|
|
{
|
|
const guint8 in[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
|
|
const guint8 out[] = { 0xfc, 0x80, 0x80, 0xfd, 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)s334-1a",
|
|
"closedcaption/x-cea-708,format=(string)cc_data");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_s334_1a_cea708_cdp)
|
|
{
|
|
const guint8 in[] = { 0x80, 0x81, 0x82, 0x00, 0x83, 0x84 };
|
|
const guint8 out[] =
|
|
{ 0x96, 0x69, 0x49, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xf4, 0xfc, 0x81, 0x82,
|
|
0xfd, 0x83, 0x84, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0xa5
|
|
};
|
|
check_conversion (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)s334-1a,framerate=(fraction)30/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
|
|
NULL, NULL);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cc_data_cea608_raw)
|
|
{
|
|
const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
|
|
const guint8 out[] = { 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-708,format=(string)cc_data",
|
|
"closedcaption/x-cea-608,format=(string)raw");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cc_data_cea608_s334_1a)
|
|
{
|
|
const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
|
|
const guint8 out[] = { 0x80, 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-708,format=(string)cc_data",
|
|
"closedcaption/x-cea-608,format=(string)s334-1a");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cc_data_cea708_cdp)
|
|
{
|
|
const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
|
|
const guint8 out[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x80,
|
|
0xfe, 0x80, 0x80, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6a
|
|
};
|
|
check_conversion (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp", NULL, NULL);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea608_raw)
|
|
{
|
|
const guint8 in1[] =
|
|
{ 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
|
|
0xfd, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
|
|
};
|
|
const guint8 out1[] = { 0x80, 0x80, };
|
|
const guint8 in2[] =
|
|
{ 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x81,
|
|
0xfd, 0x82, 0x83, 0x74, 0x00, 0x00, 0x8a
|
|
};
|
|
const guint8 out2[] = { 0x80, 0x81, };
|
|
check_conversion_tc_passthrough (in1, sizeof (in1), out1, sizeof (out1),
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=30/1",
|
|
"closedcaption/x-cea-608,format=(string)raw");
|
|
check_conversion_tc_passthrough (in2, sizeof (in2), out2, sizeof (out2),
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=30/1",
|
|
"closedcaption/x-cea-608,format=(string)raw");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea608_s334_1a)
|
|
{
|
|
const guint8 in[] =
|
|
{ 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
|
|
0xfd, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
|
|
};
|
|
const guint8 out[] = { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=30/1",
|
|
"closedcaption/x-cea-608,format=(string)s334-1a");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea708_cc_data)
|
|
{
|
|
const guint8 in[] =
|
|
{ 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x80, 0x80,
|
|
0xfd, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
|
|
};
|
|
const guint8 out[] = { 0xfc, 0x80, 0x80, 0xfd, 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=30/1",
|
|
"closedcaption/x-cea-708,format=(string)cc_data");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea708_cc_data_too_big)
|
|
{
|
|
/* tests that too large input is truncated */
|
|
const guint8 in[] =
|
|
{ 0x96, 0x69, 0x4c, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xf5, 0xfc, 0x81, 0x82,
|
|
0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
|
0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
|
0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
|
0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
|
0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
|
0x74, 0x00, 0x00, 0x8a,
|
|
};
|
|
const guint8 out[] = { 0xfc, 0x81, 0x82, 0xf9, 0x00, 0x00, 0xfe, 0x80, 0x80,
|
|
0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
|
0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
|
0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
|
0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
|
|
0xfe, 0x80, 0x80
|
|
};
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=30/1",
|
|
"closedcaption/x-cea-708,format=(string)cc_data");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea708_cdp_double_framerate)
|
|
{
|
|
/* tests that packets are split exactly in half when doubling the framerate */
|
|
const guint8 in1[] =
|
|
{ 0x96, 0x69, 0x49, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xf4, 0xfc, 0x01, 0x02,
|
|
0xfd, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
|
|
0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
|
|
0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
|
|
0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
|
|
0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0x74, 0x00, 0x00, 0xd2
|
|
};
|
|
const guint8 *in[] = { in1 };
|
|
guint in_len[] = { sizeof (in1) };
|
|
GstVideoTimeCode in_tc1;
|
|
const GstVideoTimeCode *in_tc[] = { &in_tc1 };
|
|
|
|
const guint8 out1[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x00, 0x71, 0xc1,
|
|
0x82, 0x03, 0x08, 0x72, 0xea, 0xfc, 0x01, 0x02, 0xfe, 0x05, 0x06, 0xfe,
|
|
0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe,
|
|
0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0x74,
|
|
0x00, 0x00, 0x10
|
|
};
|
|
const guint8 out2[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x01, 0x71, 0xc1,
|
|
0x82, 0x03, 0x09, 0x72, 0xea, 0xfd, 0x03, 0x04, 0xfe, 0x17, 0x18, 0xfe,
|
|
0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe,
|
|
0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0x74,
|
|
0x00, 0x01, 0xc4
|
|
};
|
|
const guint8 *out[] = { out1, out2 };
|
|
guint out_len[] = { sizeof (out1), sizeof (out2) };
|
|
GstVideoTimeCode out_tc1, out_tc2;
|
|
const GstVideoTimeCode *out_tc[] = { &out_tc1, &out_tc2 };
|
|
|
|
gst_video_time_code_init (&in_tc1, 30, 1, NULL,
|
|
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 4, 0);
|
|
fail_unless (gst_video_time_code_is_valid (&in_tc1));
|
|
|
|
gst_video_time_code_init (&out_tc1, 60, 1, NULL,
|
|
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
|
|
fail_unless (gst_video_time_code_is_valid (&out_tc1));
|
|
gst_video_time_code_init (&out_tc2, 60, 1, NULL,
|
|
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 9, 0);
|
|
fail_unless (gst_video_time_code_is_valid (&out_tc2));
|
|
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
in_tc, out_tc, 0);
|
|
|
|
gst_video_time_code_clear (&in_tc1);
|
|
gst_video_time_code_clear (&out_tc1);
|
|
gst_video_time_code_clear (&out_tc2);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea708_cdp_half_framerate)
|
|
{
|
|
/* tests that two input packets are merged together when halving the
|
|
* framerate. With cc_data compaction! */
|
|
const guint8 in1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
|
|
0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08,
|
|
0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10,
|
|
0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0x74, 0x00, 0x00, 0x7a
|
|
};
|
|
const guint8 in2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
|
|
0xfd, 0x14, 0x15, 0xfe, 0x16, 0x17, 0xfe, 0x18, 0x19, 0xfe, 0x1a, 0x1b,
|
|
0xfe, 0x1c, 0x1d, 0xfe, 0x1e, 0x1f, 0xfe, 0x20, 0x21, 0xfe, 0x22, 0x23,
|
|
0xfe, 0x24, 0x25, 0xfe, 0x26, 0x27, 0x74, 0x00, 0x01, 0x70
|
|
};
|
|
const guint8 *in[] = { in1, in2 };
|
|
guint in_len[] = { sizeof (in1), sizeof (in2) };
|
|
GstVideoTimeCode in_tc1, in_tc2;
|
|
const GstVideoTimeCode *in_tc[] = { &in_tc1, &in_tc2 };
|
|
|
|
const guint8 out1[] =
|
|
{ 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x00, 0x71, 0xc1, 0x82, 0x03, 0x04,
|
|
0x72, 0xf4, 0xfc, 0x01, 0x02, 0xfd, 0x14, 0x15, 0xfe, 0x03, 0x04, 0xfe,
|
|
0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe,
|
|
0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe,
|
|
0x16, 0x17, 0xfe, 0x18, 0x19, 0xfe, 0x1a, 0x1b, 0xfe, 0x1c, 0x1d, 0xfe,
|
|
0x1e, 0x1f, 0xfe, 0x20, 0x21, 0xfe, 0x22, 0x23, 0xfe, 0x24, 0x25, 0xfe,
|
|
0x26, 0x27, 0x74, 0x00, 0x00, 0x07
|
|
};
|
|
const guint8 *out[] = { out1 };
|
|
guint out_len[] = { sizeof (out1) };
|
|
GstVideoTimeCode out_tc1;
|
|
const GstVideoTimeCode *out_tc[] = { &out_tc1 };
|
|
|
|
gst_video_time_code_init (&in_tc1, 60, 1, NULL,
|
|
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
|
|
fail_unless (gst_video_time_code_is_valid (&in_tc1));
|
|
gst_video_time_code_init (&in_tc2, 60, 1, NULL,
|
|
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 8, 0);
|
|
fail_unless (gst_video_time_code_is_valid (&in_tc2));
|
|
|
|
gst_video_time_code_init (&out_tc1, 30, 1, NULL,
|
|
GST_VIDEO_TIME_CODE_FLAGS_NONE, 1, 2, 3, 4, 0);
|
|
fail_unless (gst_video_time_code_is_valid (&out_tc1));
|
|
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
|
|
in_tc, out_tc, 0);
|
|
|
|
gst_video_time_code_clear (&in_tc1);
|
|
gst_video_time_code_clear (&in_tc2);
|
|
gst_video_time_code_clear (&out_tc1);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_merge)
|
|
{
|
|
/* check that 3 high framerate packets can be merged into 1 low framerate
|
|
* packets with the extra data on the third input packet being placed at the
|
|
* beginning of the second output packet */
|
|
const guint8 in1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
|
|
0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08,
|
|
0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10,
|
|
0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0x74, 0x00, 0x00, 0x7a
|
|
};
|
|
/* enough input to fully cover two output packets. Extra is discarded */
|
|
const guint8 *in[] = { in1, in1, in1, in1, in1, in1, in1 };
|
|
guint in_len[] =
|
|
{ sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1), sizeof (in1),
|
|
sizeof (in1)
|
|
};
|
|
|
|
const guint8 out1[] =
|
|
{ 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
|
|
0xf9, 0x00, 0x00, 0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06,
|
|
0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e,
|
|
0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x03, 0x04,
|
|
0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
|
|
0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
|
|
0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
|
|
0x74, 0x00, 0x00, 0xcb
|
|
};
|
|
const guint8 out2[] =
|
|
{ 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x01, 0x72, 0xf9, 0xf9, 0x00, 0x00,
|
|
0xfc, 0x01, 0x02, 0xf9, 0x00, 0x00, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e,
|
|
0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x03, 0x04,
|
|
0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
|
|
0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
|
|
0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
|
|
0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
|
|
0x74, 0x00, 0x01, 0x8f
|
|
};
|
|
const guint8 *out[] = { out1, out2 };
|
|
guint out_len[] = { sizeof (out1), sizeof (out2) };
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
|
|
NULL, NULL, 0);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split)
|
|
{
|
|
/* test that a low framerate stream produces multiple output packets for a
|
|
* high framerate */
|
|
const guint8 in1[] =
|
|
{ 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
|
|
0xfd, 0x03, 0x04, 0xfc, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
|
|
0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
|
|
0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
|
|
0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
|
|
0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a,
|
|
0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30, 0xfe, 0x31, 0x32,
|
|
0x74, 0x00, 0x00, 0x12
|
|
};
|
|
const guint8 *in[] = { in1, in1 };
|
|
guint in_len[] = { sizeof (in1), sizeof (in1) };
|
|
|
|
const guint8 out1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
|
|
0xfc, 0x01, 0x02, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
|
|
0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
|
|
0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0x74, 0x00, 0x00, 0x30
|
|
};
|
|
const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
|
|
0xfd, 0x03, 0x04, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
|
|
0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26,
|
|
0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a, 0x74, 0x00, 0x01, 0xe5
|
|
};
|
|
const guint8 out3[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea,
|
|
0xfc, 0x05, 0x06, 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30,
|
|
0xfe, 0x31, 0x32, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
|
|
0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0x74, 0x00, 0x02, 0x54
|
|
};
|
|
const guint8 out4[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea,
|
|
0xfd, 0x03, 0x04, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16,
|
|
0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
|
|
0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0x74, 0x00, 0x03, 0x71
|
|
};
|
|
const guint8 *out[] = { out1, out2, out3, out4 };
|
|
guint out_len[] =
|
|
{ sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4) };
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
NULL, NULL, 0);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea708_cdp_max_split_eos)
|
|
{
|
|
/* test that a low framerate stream produces multiple output packets for a
|
|
* high framerate and that an EOS will push the pending data */
|
|
const guint8 in1[] =
|
|
{ 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
|
|
0xfd, 0x03, 0x04, 0xfc, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
|
|
0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12,
|
|
0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0xfe, 0x19, 0x1a,
|
|
0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e, 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22,
|
|
0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26, 0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a,
|
|
0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30, 0xfe, 0x31, 0x32,
|
|
0x74, 0x00, 0x00, 0x12
|
|
};
|
|
const guint8 *in[] = { in1 };
|
|
guint in_len[] = { sizeof (in1) };
|
|
|
|
const guint8 out1[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea,
|
|
0xfc, 0x01, 0x02, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a, 0xfe, 0x0b, 0x0c,
|
|
0xfe, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14,
|
|
0xfe, 0x15, 0x16, 0xfe, 0x17, 0x18, 0x74, 0x00, 0x00, 0x30
|
|
};
|
|
const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
|
|
0xfd, 0x03, 0x04, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
|
|
0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0xfe, 0x23, 0x24, 0xfe, 0x25, 0x26,
|
|
0xfe, 0x27, 0x28, 0xfe, 0x29, 0x2a, 0x74, 0x00, 0x01, 0xe5
|
|
};
|
|
const guint8 out3[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea,
|
|
0xfc, 0x05, 0x06, 0xfe, 0x2b, 0x2c, 0xfe, 0x2d, 0x2e, 0xfe, 0x2f, 0x30,
|
|
0xfe, 0x31, 0x32, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0xdb
|
|
};
|
|
const guint8 *out[] = { out1, out2, out3 };
|
|
guint out_len[] = { sizeof (out1), sizeof (out2), sizeof (out3) };
|
|
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)24000/1001",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
NULL, NULL, FLAG_SEND_EOS);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling)
|
|
{
|
|
const guint8 in1[] = { 0x96, 0x69, 0x10, 0x7f, 0x43, 0x00, 0x00, 0x72, 0xe1,
|
|
0xfc, 0x80, 0x80, 0x74, 0x00, 0x00, 0x7a
|
|
};
|
|
const guint8 *in[] = { in1, in1 };
|
|
guint in_len[] = { sizeof (in1), sizeof (in1) };
|
|
GstVideoTimeCode in_tc1, in_tc2;
|
|
const GstVideoTimeCode *in_tc[] = { &in_tc1, &in_tc2 };
|
|
|
|
const guint8 out1[] =
|
|
{ 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x00, 0x71, 0xc0, 0x81, 0x59, 0x29,
|
|
0x72, 0xf4, 0xfc, 0x80, 0x80, 0xf9, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
|
|
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
|
|
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
|
|
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
|
|
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
|
|
0x00, 0x00, 0x74, 0x00, 0x00, 0xfa
|
|
};
|
|
const guint8 out2[] =
|
|
{ 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x01, 0x71, 0xc0, 0x82, 0x00, 0x00,
|
|
0x72, 0xf4, 0xfc, 0x80, 0x80, 0xf9, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
|
|
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
|
|
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
|
|
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
|
|
0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa,
|
|
0x00, 0x00, 0x74, 0x00, 0x01, 0x79
|
|
};
|
|
const guint8 *out[] = { out1, out2 };
|
|
guint out_len[] = { sizeof (out1), sizeof (out2) };
|
|
GstVideoTimeCode out_tc1, out_tc2;
|
|
const GstVideoTimeCode *out_tc[] = { &out_tc1, &out_tc2 };
|
|
|
|
gst_video_time_code_init (&in_tc1, 30000, 1001, NULL,
|
|
GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME, 0, 1, 59, 29, 0);
|
|
fail_unless (gst_video_time_code_is_valid (&in_tc1));
|
|
|
|
gst_video_time_code_init (&in_tc2, 30000, 1001, NULL,
|
|
GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME, 0, 2, 0, 4, 0);
|
|
fail_unless (gst_video_time_code_is_valid (&in_tc2));
|
|
|
|
gst_video_time_code_init (&out_tc1, 30, 1, NULL,
|
|
GST_VIDEO_TIME_CODE_FLAGS_NONE, 0, 1, 59, 29, 0);
|
|
fail_unless (gst_video_time_code_is_valid (&out_tc1));
|
|
|
|
gst_video_time_code_init (&out_tc2, 30, 1, NULL,
|
|
GST_VIDEO_TIME_CODE_FLAGS_NONE, 0, 2, 0, 0, 0);
|
|
fail_unless (gst_video_time_code_is_valid (&out_tc2));
|
|
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30000/1001",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
|
|
in_tc, out_tc, FLAG_SEND_EOS);
|
|
|
|
gst_video_time_code_clear (&in_tc1);
|
|
gst_video_time_code_clear (&out_tc1);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cc_data_cea708_cdp_double_framerate)
|
|
{
|
|
const guint8 in1[] = { 0xfc, 0x80, 0x81, 0xfd, 0x82, 0x83, 0xfe, 0x84, 0x85 };
|
|
const guint8 in2[] = { 0xfc, 0x86, 0x87, 0xfd, 0x88, 0x89, 0xfe, 0x8a, 0x8b };
|
|
const guint8 *in[] = { in1, in2 };
|
|
guint in_len[] = { sizeof (in1), sizeof (in2) };
|
|
const guint8 out1[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
|
|
0xfe, 0x84, 0x85, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x60
|
|
};
|
|
const guint8 out2[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfd, 0x82, 0x83,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x66
|
|
};
|
|
const guint8 out3[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x86, 0x87,
|
|
0xfe, 0x8a, 0x8b, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x44
|
|
};
|
|
const guint8 out4[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfd, 0x88, 0x89,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x56
|
|
};
|
|
const guint8 *out[] = { out1, out2, out3, out4, };
|
|
guint out_len[] =
|
|
{ sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)30/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
NULL, NULL, 0);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_raw_cea708_cdp_double_framerate)
|
|
{
|
|
const guint8 in1[] = { 0x80, 0x81 };
|
|
const guint8 in2[] = { 0x82, 0x83 };
|
|
const guint8 *in[] = { in1, in2 };
|
|
guint in_len[] = { sizeof (in1), sizeof (in2) };
|
|
const guint8 out1[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6d
|
|
};
|
|
const guint8 out2[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x6f
|
|
};
|
|
const guint8 out3[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x82, 0x83,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x65
|
|
};
|
|
const guint8 out4[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xf9, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x6b
|
|
};
|
|
const guint8 *out[] = { out1, out2, out3, out4, };
|
|
guint out_len[] =
|
|
{ sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-608,format=(string)raw,framerate=(fraction)30/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
NULL, NULL, 0);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_s334_1a_cea708_cdp_double_framerate)
|
|
{
|
|
const guint8 in1[] = { 0x80, 0x80, 0x81, 0x00, 0x82, 0x83 };
|
|
const guint8 in2[] = { 0x80, 0x84, 0x85, 0x00, 0x86, 0x87 };
|
|
const guint8 *in[] = { in1, in2 };
|
|
guint in_len[] = { sizeof (in1), sizeof (in2) };
|
|
const guint8 out1[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x81,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6d
|
|
};
|
|
const guint8 out2[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfd, 0x82, 0x83,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x66
|
|
};
|
|
const guint8 out3[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x84, 0x85,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x61
|
|
};
|
|
const guint8 out4[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfd, 0x86, 0x87,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x5a
|
|
};
|
|
const guint8 *out[] = { out1, out2, out3, out4, };
|
|
guint out_len[] =
|
|
{ sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4), };
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-608,format=(string)s334-1a,framerate=(fraction)30/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
NULL, NULL, 0);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_raw_cea608_s334_1a_field_one)
|
|
{
|
|
const guint8 in[] = { 0x80, 0x80 };
|
|
const guint8 out[] = { 0x00, 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)raw,field=(int)1",
|
|
"closedcaption/x-cea-608,format=(string)s334-1a");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_raw_cea708_cc_data_field_one)
|
|
{
|
|
const guint8 in[] = { 0x80, 0x80 };
|
|
const guint8 out[] = { 0xfd, 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)raw,field=(int)1",
|
|
"closedcaption/x-cea-708,format=(string)cc_data");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_raw_cea708_cdp_field_one)
|
|
{
|
|
const guint8 in[] = { 0x81, 0x82 };
|
|
const guint8 out[] =
|
|
{ 0x96, 0x69, 0x49, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xf4, 0xfc, 0x80, 0x80,
|
|
0xfd, 0x81, 0x82, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00,
|
|
0xac
|
|
};
|
|
|
|
check_conversion (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)raw,framerate=(fraction)30/1,field=(int)1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)30/1",
|
|
NULL, NULL);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_s334_1a_cea608_raw_field_one)
|
|
{
|
|
const guint8 in[] = { 0x80, 0x00, 0x00, 0x00, 0x80, 0x80 };
|
|
const guint8 out[] = { 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)s334-1a",
|
|
"closedcaption/x-cea-608,format=(string)raw,field=(int)1");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cc_data_cea608_raw_field_one)
|
|
{
|
|
const guint8 in[] = { 0xfc, 0x00, 0x00, 0xfd, 0x80, 0x80 };
|
|
const guint8 out[] = { 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-708,format=(string)cc_data",
|
|
"closedcaption/x-cea-608,format=(string)raw,field=(int)1");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea608_raw_field_one)
|
|
{
|
|
const guint8 in[] =
|
|
{ 0x96, 0x69, 0x13, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe2, 0xfc, 0x00, 0x00,
|
|
0xfd, 0x80, 0x80, 0x74, 0x00, 0x00, 0x8a
|
|
};
|
|
const guint8 out[] = { 0x80, 0x80 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=30/1",
|
|
"closedcaption/x-cea-608,format=(string)raw,framerate=30/1,field=(int)1");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_raw_cea608_raw_field_one)
|
|
{
|
|
/* Control codes must be translated when converting from field 0 to field 1 */
|
|
const guint8 in[] = { 0x94, 0x20 };
|
|
const guint8 out[] = { 0x15, 0x20 };
|
|
check_conversion_tc_passthrough (in, sizeof (in), out, sizeof (out),
|
|
"closedcaption/x-cea-608,format=(string)raw,field=(int)0",
|
|
"closedcaption/x-cea-608,format=(string)raw,field=(int)1");
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea708_cc_data_double_input_data)
|
|
{
|
|
/* caps say 60fps, data has 30fps. Ensure data is taken alternatatively from
|
|
* each field even if there is too much input data */
|
|
const guint8 in1[] =
|
|
{ 0x96, 0x69, 0x16, 0x5f, 0x43, 0x00, 0x00, 0x72, 0xe3, 0xfc, 0x81, 0x82,
|
|
0xfd, 0x83, 0x84, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0xff
|
|
};
|
|
/* padding buffer */
|
|
const guint8 in2[] =
|
|
{ 0x96, 0x69, 0x16, 0x5f, 0x43, 0x00, 0x01, 0x72, 0xe3, 0xfc, 0x80, 0x80,
|
|
0xfd, 0x80, 0x80, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0xff
|
|
};
|
|
const guint8 in3[] =
|
|
{ 0x96, 0x69, 0x16, 0x5f, 0x43, 0x00, 0x02, 0x72, 0xe3, 0xfc, 0x85, 0x86,
|
|
0xfd, 0x87, 0x88, 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0xff
|
|
};
|
|
const guint8 *in[] = { in1, in2, in3, };
|
|
guint in_len[] = { sizeof (in1), sizeof (in2), sizeof (in3), };
|
|
/* two buffers from the first buffer, then the first half of the third input
|
|
* buffer */
|
|
const guint8 out1[] = { 0xfc, 0x81, 0x82, };
|
|
const guint8 out2[] = { 0xfd, 0x83, 0x84, };
|
|
const guint8 out3[] = { 0xfc, 0x80, 0x80, };
|
|
const guint8 *out[] = { out1, out2, out3, };
|
|
guint out_len[] = { sizeof (out1), sizeof (out2), sizeof (out3), };
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
|
|
NULL, NULL, 0);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cc_data_cea708_cdp_double_input_data)
|
|
{
|
|
/* caps say 60fps, but every buffer is cea608 field 1. Ensure data is taken
|
|
* alternatatively from each field even if there is too much input data */
|
|
const guint8 in1[] = { 0xfc, 0x81, 0x82 };
|
|
const guint8 in2[] = { 0xfc, 0x83, 0x84 };
|
|
const guint8 in3[] = { 0xfc, 0x85, 0x86 };
|
|
const guint8 *in[] = { in1, in2, in3, };
|
|
guint in_len[] = { sizeof (in1), sizeof (in2), sizeof (in3), };
|
|
/* two buffers from the first buffer, then the first half of the third input
|
|
* buffer */
|
|
const guint8 out1[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x81, 0x82,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6b
|
|
};
|
|
/* padding buffer */
|
|
const guint8 out2[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x6f
|
|
};
|
|
const guint8 out3[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x83, 0x84,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x63
|
|
};
|
|
const guint8 out4[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xf9, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x6b
|
|
};
|
|
const guint8 out5[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x04, 0x72, 0xea, 0xfc, 0x85, 0x86,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x04, 0x5b
|
|
};
|
|
const guint8 *out[] = { out1, out2, out3, out4, out5 };
|
|
guint out_len[] =
|
|
{ sizeof (out1), sizeof (out2), sizeof (out3), sizeof (out4),
|
|
sizeof (out5)
|
|
};
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
NULL, NULL, FLAG_SEND_EOS);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
static guint8
|
|
calculate_cdp_checksum (guint8 * cdp, gsize len)
|
|
{
|
|
guint8 checksum = 0;
|
|
gsize i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
checksum += cdp[i];
|
|
}
|
|
checksum &= 0xff;
|
|
return 256 - checksum;
|
|
}
|
|
|
|
GST_START_TEST (convert_cea708_cc_data_cea708_cdp_field1_overflow)
|
|
{
|
|
/* caps say 60fps, but every buffer is cea608 field 1. Ensure data is taken
|
|
* alternatatively from each field even if there is too much input data.
|
|
* Also ensure that overflow does something sane, like dropping previous data */
|
|
#define N_INPUTS 100
|
|
guint8 in_data[N_INPUTS * 3];
|
|
guint in_len[N_INPUTS];
|
|
guint8 *in[N_INPUTS];
|
|
guint i;
|
|
|
|
#define N_OUTPUTS 100
|
|
guint8 out_data[N_OUTPUTS * 43];
|
|
guint out_len[N_OUTPUTS];
|
|
guint8 *out[N_OUTPUTS];
|
|
|
|
const guint8 out_template[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xf9, 0x80, 0x80,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x6f
|
|
};
|
|
|
|
G_STATIC_ASSERT (sizeof (out_template) == 43);
|
|
|
|
/* generate input data */
|
|
for (i = 0; i < N_INPUTS; i++) {
|
|
in_len[i] = 3;
|
|
in_data[i * 3 + 0] = 0xfc;
|
|
in_data[i * 3 + 1] = 0x81 + i * 2;
|
|
in_data[i * 3 + 2] = 0x81 + i * 2 + 1;
|
|
in[i] = &in_data[i * 3];
|
|
}
|
|
|
|
for (i = 0; i < N_OUTPUTS; i++) {
|
|
out_len[i] = 43;
|
|
memcpy (&out_data[i * 43], out_template, sizeof (out_template));
|
|
/* write correct counters */
|
|
out_data[i * 43 + 6] = i;
|
|
out_data[i * 43 + 41] = i;
|
|
/* write the correct cea608 data */
|
|
if (i % 2 == 0) {
|
|
gsize in_data_offset;
|
|
/* take frames sequentially from the input */
|
|
gsize in_idx = i / 2;
|
|
/* take the first 12 input frames, then skip the next 12 frames and take
|
|
* the next 12 frames etc.
|
|
* 24 is the byte size of the internal cea608 field buffers that we are
|
|
* overflowing but every second buffer will have cea608 field 1 in it.
|
|
* 12 frames is 24 bytes stored and is enough to cause overflow */
|
|
in_idx = (in_idx / 6) * 12 + in_idx % 6;
|
|
in_data_offset = in_idx * 3;
|
|
|
|
out_data[i * 43 + 9] = in_data[in_data_offset + 0];
|
|
out_data[i * 43 + 10] = in_data[in_data_offset + 1];
|
|
out_data[i * 43 + 11] = in_data[in_data_offset + 2];
|
|
} else {
|
|
out_data[i * 43 + 9] = 0xf9;
|
|
out_data[i * 43 + 10] = 0x00;
|
|
out_data[i * 43 + 11] = 0x00;
|
|
}
|
|
out_data[i * 43 + 42] = calculate_cdp_checksum (&out_data[i * 43], 42);
|
|
out[i] = &out_data[i * 43];
|
|
}
|
|
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), (const guint8 **) in,
|
|
in_len, G_N_ELEMENTS (out_len), (const guint8 **) out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=(fraction)60/1",
|
|
NULL, NULL, FLAG_SEND_EOS);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea608_raw_field1_cea708_cdp_60fps)
|
|
{
|
|
const guint8 in1[] = { 0x81, 0x82 };
|
|
const guint8 *in[] = { in1 };
|
|
guint in_len[] = { sizeof (in1) };
|
|
const guint8 out1[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x80,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6e,
|
|
};
|
|
const guint8 out2[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfd, 0x81, 0x82,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x68,
|
|
};
|
|
const guint8 *out[] = { out1, out2 };
|
|
guint out_len[] = { sizeof (out1), sizeof (out2) };
|
|
check_conversion_multiple (1, in, in_len, G_N_ELEMENTS (out_len), out,
|
|
out_len,
|
|
"closedcaption/x-cea-608,format=(string)raw,framerate=30/1,field=1",
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=60/1", NULL, NULL,
|
|
0);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
GST_START_TEST (convert_cea708_cdp_cea608_raw_field_one_60fps)
|
|
{
|
|
const guint8 in1[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xfc, 0x80, 0x80,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6e,
|
|
};
|
|
const guint8 in2[] =
|
|
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfd, 0x81, 0x82,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00, 0xfa, 0x00, 0x00,
|
|
0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x68,
|
|
};
|
|
const guint8 *in[] = { in1, in2 };
|
|
guint in_len[] = { sizeof (in1), sizeof (in2) };
|
|
const guint8 out1[] = { 0x81, 0x82 };
|
|
const guint8 *out[] = { out1 };
|
|
guint out_len[] = { sizeof (out1) };
|
|
check_conversion_multiple (G_N_ELEMENTS (in_len), in, in_len,
|
|
G_N_ELEMENTS (out_len), out, out_len,
|
|
"closedcaption/x-cea-708,format=(string)cdp,framerate=60/1",
|
|
"closedcaption/x-cea-608,format=(string)raw,framerate=60/1,field=1", NULL,
|
|
NULL, 0);
|
|
}
|
|
|
|
GST_END_TEST;
|
|
|
|
static Suite *
|
|
ccextractor_suite (void)
|
|
{
|
|
Suite *s = suite_create ("ccconverter");
|
|
TCase *tc = tcase_create ("general");
|
|
|
|
suite_add_tcase (s, tc);
|
|
|
|
tcase_add_test (tc, cdp_requires_valid_framerate);
|
|
tcase_add_test (tc, framerate_passthrough);
|
|
tcase_add_test (tc, framerate_changes);
|
|
tcase_add_test (tc, framerate_invalid_format);
|
|
tcase_add_test (tc, convert_cea608_raw_cea608_s334_1a);
|
|
tcase_add_test (tc, convert_cea608_raw_cea708_cc_data);
|
|
tcase_add_test (tc, convert_cea608_raw_cea708_cdp);
|
|
tcase_add_test (tc, convert_cea608_s334_1a_cea608_raw);
|
|
tcase_add_test (tc, convert_cea608_s334_1a_cea608_raw_too_big);
|
|
tcase_add_test (tc, convert_cea608_s334_1a_cea708_cc_data);
|
|
tcase_add_test (tc, convert_cea608_s334_1a_cea708_cdp);
|
|
tcase_add_test (tc, convert_cea708_cc_data_cea608_raw);
|
|
tcase_add_test (tc, convert_cea708_cc_data_cea608_s334_1a);
|
|
tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea608_raw);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea608_s334_1a);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data_too_big);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_half_framerate);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_double_framerate);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_merge);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_split);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_max_split_eos);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea708_cdp_from_drop_frame_scaling);
|
|
tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_double_framerate);
|
|
tcase_add_test (tc, convert_cea608_raw_cea708_cdp_double_framerate);
|
|
tcase_add_test (tc, convert_cea608_s334_1a_cea708_cdp_double_framerate);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea708_cc_data_double_input_data);
|
|
tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_double_input_data);
|
|
tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_field1_overflow);
|
|
|
|
tcase_add_test (tc, convert_cea608_raw_cea608_s334_1a_field_one);
|
|
tcase_add_test (tc, convert_cea608_raw_cea708_cc_data_field_one);
|
|
tcase_add_test (tc, convert_cea608_raw_cea708_cdp_field_one);
|
|
tcase_add_test (tc, convert_cea608_s334_1a_cea608_raw_field_one);
|
|
tcase_add_test (tc, convert_cea708_cc_data_cea608_raw_field_one);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea608_raw_field_one);
|
|
tcase_add_test (tc, convert_cea708_cdp_cea608_raw_field_one_60fps);
|
|
tcase_add_test (tc, convert_cea608_raw_cea608_raw_field_one);
|
|
tcase_add_test (tc, convert_cea608_raw_field1_cea708_cdp_60fps);
|
|
|
|
return s;
|
|
}
|
|
|
|
GST_CHECK_MAIN (ccextractor);
|