ccconverter: add support for advertising / selecting field

Raw 608 caps can now contain a "field" field. On the input side it
signifies that the input raw 608 is attached to either field 0 or 1,
on the output side it allows selecting whether to extract the raw 608
data for field 0 or 1 for field-aware formats.

In addition, it is also allowed to use ccconverter to "convert" 608
field 0 to 608 field 1 (and conversely), this is passthrough as the
change only needs to happen in the caps.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4031>
This commit is contained in:
Mathieu Duponchelle 2023-02-21 19:47:42 +01:00 committed by GStreamer Marge Bot
parent 88a8d9e8cd
commit 9e8d1dccb4
4 changed files with 171 additions and 35 deletions

View file

@ -5186,12 +5186,12 @@
"long-name": "Closed Caption Converter", "long-name": "Closed Caption Converter",
"pad-templates": { "pad-templates": {
"sink": { "sink": {
"caps": "closedcaption/x-cea-708:\n format: cdp\nclosedcaption/x-cea-708:\n format: cc_data\nclosedcaption/x-cea-608:\n format: s334-1a\nclosedcaption/x-cea-608:\n format: raw\n", "caps": "closedcaption/x-cea-708:\n format: cdp\nclosedcaption/x-cea-708:\n format: cc_data\nclosedcaption/x-cea-608:\n format: s334-1a\nclosedcaption/x-cea-608:\n format: raw\n field: { (int)0, (int)1 }\n",
"direction": "sink", "direction": "sink",
"presence": "always" "presence": "always"
}, },
"src": { "src": {
"caps": "closedcaption/x-cea-708:\n format: cdp\nclosedcaption/x-cea-708:\n format: cc_data\nclosedcaption/x-cea-608:\n format: s334-1a\nclosedcaption/x-cea-608:\n format: raw\n", "caps": "closedcaption/x-cea-708:\n format: cdp\nclosedcaption/x-cea-708:\n format: cc_data\nclosedcaption/x-cea-608:\n format: s334-1a\nclosedcaption/x-cea-608:\n format: raw\n field: { (int)0, (int)1 }\n",
"direction": "src", "direction": "src",
"presence": "always" "presence": "always"
} }

View file

@ -50,13 +50,14 @@ enum
}; };
#define DEFAULT_CDP_MODE (GST_CC_CONVERTER_CDP_MODE_TIME_CODE | GST_CC_CONVERTER_CDP_MODE_CC_DATA | GST_CC_CONVERTER_CDP_MODE_CC_SVC_INFO) #define DEFAULT_CDP_MODE (GST_CC_CONVERTER_CDP_MODE_TIME_CODE | GST_CC_CONVERTER_CDP_MODE_CC_DATA | GST_CC_CONVERTER_CDP_MODE_CC_SVC_INFO)
#define DEFAULT_FIELD 0
/* Ordered by the amount of information they can contain */ /* Ordered by the amount of information they can contain */
#define CC_CAPS \ #define CC_CAPS \
"closedcaption/x-cea-708,format=(string) cdp; " \ "closedcaption/x-cea-708,format=(string) cdp; " \
"closedcaption/x-cea-708,format=(string) cc_data; " \ "closedcaption/x-cea-708,format=(string) cc_data; " \
"closedcaption/x-cea-608,format=(string) s334-1a; " \ "closedcaption/x-cea-608,format=(string) s334-1a; " \
"closedcaption/x-cea-608,format=(string) raw" "closedcaption/x-cea-608,format=(string) raw, field=(int) {0, 1}"
#define VAL_OR_0(v) ((v) ? (*(v)) : 0) #define VAL_OR_0(v) ((v) ? (*(v)) : 0)
@ -126,12 +127,14 @@ gst_cc_converter_transform_caps (GstBaseTransform * base,
static GstStaticCaps non_cdp_caps = static GstStaticCaps non_cdp_caps =
GST_STATIC_CAPS ("closedcaption/x-cea-708, format=(string)cc_data; " GST_STATIC_CAPS ("closedcaption/x-cea-708, format=(string)cc_data; "
"closedcaption/x-cea-608,format=(string) s334-1a; " "closedcaption/x-cea-608,format=(string) s334-1a; "
"closedcaption/x-cea-608,format=(string) raw"); "closedcaption/x-cea-608,format=(string) raw, field=(int) {0, 1}");
static GstStaticCaps cdp_caps = static GstStaticCaps cdp_caps =
GST_STATIC_CAPS ("closedcaption/x-cea-708, format=(string)cdp"); GST_STATIC_CAPS ("closedcaption/x-cea-708, format=(string)cdp");
static GstStaticCaps cdp_caps_framerate = static GstStaticCaps cdp_caps_framerate =
GST_STATIC_CAPS ("closedcaption/x-cea-708, format=(string)cdp, " GST_STATIC_CAPS ("closedcaption/x-cea-708, format=(string)cdp, "
"framerate=(fraction){60/1, 60000/1001, 50/1, 30/1, 30000/1001, 25/1, 24/1, 24000/1001}"); "framerate=(fraction){60/1, 60000/1001, 50/1, 30/1, 30000/1001, 25/1, 24/1, 24000/1001}");
static GstStaticCaps raw_608_caps =
GST_STATIC_CAPS ("closedcaption/x-cea-608,format=(string) raw");
GstCCConverter *self = GST_CCCONVERTER (base); GstCCConverter *self = GST_CCCONVERTER (base);
guint i, n; guint i, n;
@ -149,8 +152,17 @@ gst_cc_converter_transform_caps (GstBaseTransform * base,
const GValue *framerate = gst_structure_get_value (s, "framerate"); const GValue *framerate = gst_structure_get_value (s, "framerate");
if (gst_structure_has_name (s, "closedcaption/x-cea-608")) { if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
const GValue *field = gst_structure_get_value (s, "field");
if (direction == GST_PAD_SRC) { if (direction == GST_PAD_SRC) {
GstCaps *tmp;
tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps));
if (!field) {
tmp = gst_caps_merge (tmp, gst_static_caps_get (&raw_608_caps));
}
/* SRC direction: We produce upstream caps /* SRC direction: We produce upstream caps
* *
* Downstream wanted CEA608 caps. If it had a framerate, we * Downstream wanted CEA608 caps. If it had a framerate, we
@ -162,14 +174,9 @@ gst_cc_converter_transform_caps (GstBaseTransform * base,
res = gst_caps_merge (res, gst_static_caps_get (&cdp_caps_framerate)); res = gst_caps_merge (res, gst_static_caps_get (&cdp_caps_framerate));
if (framerate) { if (framerate) {
/* we can only keep the same framerate for non-cdp */ /* we can only keep the same framerate for non-cdp */
GstCaps *tmp;
tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps));
gst_caps_set_value (tmp, "framerate", framerate); gst_caps_set_value (tmp, "framerate", framerate);
res = gst_caps_merge (res, tmp);
} else {
res = gst_caps_merge (res, gst_static_caps_get (&non_cdp_caps));
} }
res = gst_caps_merge (res, tmp);
} else { } else {
/* SINK: We produce downstream caps /* SINK: We produce downstream caps
* *
@ -205,10 +212,19 @@ gst_cc_converter_transform_caps (GstBaseTransform * base,
} }
/* And we can convert to everything else with the given framerate */ /* And we can convert to everything else with the given framerate */
tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps)); tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps));
if (!field) {
tmp = gst_caps_merge (tmp, gst_static_caps_get (&raw_608_caps));
}
gst_caps_set_value (tmp, "framerate", framerate); gst_caps_set_value (tmp, "framerate", framerate);
res = gst_caps_merge (res, tmp); res = gst_caps_merge (res, tmp);
} else { } else {
res = gst_caps_merge (res, gst_static_caps_get (&non_cdp_caps)); res = gst_caps_merge (res, gst_static_caps_get (&non_cdp_caps));
if (!field) {
res = gst_caps_merge (res, gst_static_caps_get (&raw_608_caps));
}
} }
} }
} else if (gst_structure_has_name (s, "closedcaption/x-cea-708")) { } else if (gst_structure_has_name (s, "closedcaption/x-cea-708")) {
@ -247,6 +263,7 @@ gst_cc_converter_transform_caps (GstBaseTransform * base,
* into CDP with exactly those framerates from anything else */ * into CDP with exactly those framerates from anything else */
cdp_framerate = gst_structure_get_value (t, "framerate"); cdp_framerate = gst_structure_get_value (t, "framerate");
tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps)); tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps));
tmp = gst_caps_merge (tmp, gst_static_caps_get (&raw_608_caps));
gst_caps_set_value (tmp, "framerate", cdp_framerate); gst_caps_set_value (tmp, "framerate", cdp_framerate);
res = gst_caps_merge (res, tmp); res = gst_caps_merge (res, tmp);
} else { } else {
@ -261,6 +278,7 @@ gst_cc_converter_transform_caps (GstBaseTransform * base,
"framerate"); "framerate");
tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps)); tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps));
tmp = gst_caps_merge (tmp, gst_static_caps_get (&raw_608_caps));
gst_caps_set_value (tmp, "framerate", cdp_framerate); gst_caps_set_value (tmp, "framerate", cdp_framerate);
gst_caps_unref (cdp_caps); gst_caps_unref (cdp_caps);
@ -274,10 +292,12 @@ gst_cc_converter_transform_caps (GstBaseTransform * base,
GstCaps *tmp; GstCaps *tmp;
tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps)); tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps));
tmp = gst_caps_merge (tmp, gst_static_caps_get (&raw_608_caps));
gst_caps_set_value (tmp, "framerate", framerate); gst_caps_set_value (tmp, "framerate", framerate);
res = gst_caps_merge (res, tmp); res = gst_caps_merge (res, tmp);
} else { } else {
res = gst_caps_merge (res, gst_static_caps_get (&non_cdp_caps)); res = gst_caps_merge (res, gst_static_caps_get (&non_cdp_caps));
res = gst_caps_merge (res, gst_static_caps_get (&raw_608_caps));
} }
} }
} else { } else {
@ -330,10 +350,12 @@ gst_cc_converter_transform_caps (GstBaseTransform * base,
GstCaps *tmp; GstCaps *tmp;
tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps)); tmp = gst_caps_make_writable (gst_static_caps_get (&non_cdp_caps));
tmp = gst_caps_merge (tmp, gst_static_caps_get (&raw_608_caps));
gst_caps_set_value (tmp, "framerate", framerate); gst_caps_set_value (tmp, "framerate", framerate);
res = gst_caps_merge (res, tmp); res = gst_caps_merge (res, tmp);
} else { } else {
res = gst_caps_merge (res, gst_static_caps_get (&non_cdp_caps)); res = gst_caps_merge (res, gst_static_caps_get (&non_cdp_caps));
res = gst_caps_merge (res, gst_static_caps_get (&raw_608_caps));
} }
} }
} else { } else {
@ -433,6 +455,8 @@ gst_cc_converter_set_caps (GstBaseTransform * base, GstCaps * incaps,
GstCCConverter *self = GST_CCCONVERTER (base); GstCCConverter *self = GST_CCCONVERTER (base);
const GstStructure *s; const GstStructure *s;
gboolean passthrough; gboolean passthrough;
static GstStaticCaps raw_608_caps =
GST_STATIC_CAPS ("closedcaption/x-cea-608,format=(string) raw");
self->input_caption_type = gst_video_caption_type_from_caps (incaps); self->input_caption_type = gst_video_caption_type_from_caps (incaps);
self->output_caption_type = gst_video_caption_type_from_caps (outcaps); self->output_caption_type = gst_video_caption_type_from_caps (outcaps);
@ -446,16 +470,32 @@ gst_cc_converter_set_caps (GstBaseTransform * base, GstCaps * incaps,
&self->in_fps_d)) &self->in_fps_d))
self->in_fps_n = self->in_fps_d = 0; self->in_fps_n = self->in_fps_d = 0;
if (!gst_structure_get_int (s, "field", &self->in_field))
self->in_field = 0;
s = gst_caps_get_structure (outcaps, 0); s = gst_caps_get_structure (outcaps, 0);
if (!gst_structure_get_fraction (s, "framerate", &self->out_fps_n, if (!gst_structure_get_fraction (s, "framerate", &self->out_fps_n,
&self->out_fps_d)) &self->out_fps_d))
self->out_fps_n = self->out_fps_d = 0; self->out_fps_n = self->out_fps_d = 0;
if (!gst_structure_get_int (s, "field", &self->out_field))
self->out_field = 0;
gst_video_time_code_clear (&self->current_output_timecode); gst_video_time_code_clear (&self->current_output_timecode);
/* Caps can be different but we can passthrough as long as they can /* For raw 608 caps in and out, we can ignore the field to determine
* intersect, i.e. have same caps name and format */ * passthrough. We can also ignore framerate at this point, as our transform_caps
passthrough = gst_caps_can_intersect (incaps, outcaps); * implementation guarantees that it is either absent or present on both sides.
*/
if (gst_caps_is_subset (incaps, gst_static_caps_get (&raw_608_caps)) &&
gst_caps_is_subset (outcaps, gst_static_caps_get (&raw_608_caps))) {
passthrough = TRUE;
} else {
/* Caps can be different but we can passthrough as long as they can
* intersect, i.e. have same caps name and format */
passthrough = gst_caps_can_intersect (incaps, outcaps);
}
gst_base_transform_set_passthrough (base, passthrough); gst_base_transform_set_passthrough (base, passthrough);
GST_DEBUG_OBJECT (self, GST_DEBUG_OBJECT (self,
@ -677,10 +717,9 @@ convert_cea608_raw_cea608_s334_1a (GstCCConverter * self, GstBuffer * inbuf,
gst_buffer_map (inbuf, &in, GST_MAP_READ); gst_buffer_map (inbuf, &in, GST_MAP_READ);
gst_buffer_map (outbuf, &out, GST_MAP_WRITE); gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
/* We have to assume that each value is from the first field and /* We don't know from which line offset it originally is */
* don't know from which line offset it originally is */
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
out.data[i * 3] = 0x80; out.data[i * 3] = self->in_field == 0 ? 0x80 : 0x00;
out.data[i * 3 + 1] = in.data[i * 2]; out.data[i * 3 + 1] = in.data[i * 2];
out.data[i * 3 + 2] = in.data[i * 2 + 1]; out.data[i * 3 + 2] = in.data[i * 2 + 1];
} }
@ -718,10 +757,9 @@ convert_cea608_raw_cea708_cc_data (GstCCConverter * self, GstBuffer * inbuf,
gst_buffer_map (inbuf, &in, GST_MAP_READ); gst_buffer_map (inbuf, &in, GST_MAP_READ);
gst_buffer_map (outbuf, &out, GST_MAP_WRITE); gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
/* We have to assume that each value is from the first field and /* We don't know from which line offset it originally is */
* don't know from which line offset it originally is */
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
out.data[i * 3] = 0xfc; out.data[i * 3] = self->in_field == 0 ? 0xfc : 0xfd;
out.data[i * 3 + 1] = in.data[i * 2]; out.data[i * 3 + 1] = in.data[i * 2];
out.data[i * 3 + 2] = in.data[i * 2 + 1]; out.data[i * 3 + 2] = in.data[i * 2 + 1];
} }
@ -764,8 +802,13 @@ convert_cea608_raw_cea708_cdp (GstCCConverter * self, GstBuffer * inbuf,
} }
gst_buffer_map (inbuf, &in, GST_MAP_READ); gst_buffer_map (inbuf, &in, GST_MAP_READ);
cc_buffer_push_separated (self->cc_buffer, in.data, in.size, NULL, 0, NULL, if (self->in_field == 0) {
0); cc_buffer_push_separated (self->cc_buffer, in.data, in.size, NULL, 0,
NULL, 0);
} else {
cc_buffer_push_separated (self->cc_buffer, NULL, 0, in.data, in.size,
NULL, 0);
}
gst_buffer_unmap (inbuf, &in); gst_buffer_unmap (inbuf, &in);
self->input_frames++; self->input_frames++;
} }
@ -823,9 +866,10 @@ convert_cea608_s334_1a_cea608_raw (GstCCConverter * self, GstBuffer * inbuf,
gst_buffer_map (outbuf, &out, GST_MAP_WRITE); gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (in.data[i * 3] & 0x80) { if ((in.data[i * 3] & 0x80 && self->out_field == 0) ||
out.data[i * 2] = in.data[i * 3 + 1]; (!(in.data[i * 3] & 0x80) && self->out_field == 1)) {
out.data[i * 2 + 1] = in.data[i * 3 + 2]; out.data[cea608 * 2] = in.data[i * 3 + 1];
out.data[cea608 * 2 + 1] = in.data[i * 3 + 2];
cea608++; cea608++;
} }
} }
@ -983,11 +1027,8 @@ convert_cea708_cc_data_cea608_raw (GstCCConverter * self, GstBuffer * inbuf,
gst_buffer_map (outbuf, &out, GST_MAP_WRITE); gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
/* We can only really copy the first field here as there can't be any if ((in.data[i * 3] == 0xfc && self->out_field == 0) ||
* signalling in raw CEA608 and we must not mix the streams of different (in.data[i * 3] == 0xfd && self->out_field == 1)) {
* fields
*/
if (in.data[i * 3] == 0xfc) {
out.data[cea608 * 2] = in.data[i * 3 + 1]; out.data[cea608 * 2] = in.data[i * 3 + 1];
out.data[cea608 * 2 + 1] = in.data[i * 3 + 2]; out.data[cea608 * 2 + 1] = in.data[i * 3 + 2];
cea608++; cea608++;
@ -1107,7 +1148,7 @@ convert_cea708_cdp_cea608_raw (GstCCConverter * self, GstBuffer * inbuf,
{ {
GstMapInfo out; GstMapInfo out;
GstVideoTimeCode tc = GST_VIDEO_TIME_CODE_INIT; GstVideoTimeCode tc = GST_VIDEO_TIME_CODE_INIT;
guint cea608_1_len; guint cea608_len;
const struct cdp_fps_entry *in_fps_entry = NULL, *out_fps_entry; const struct cdp_fps_entry *in_fps_entry = NULL, *out_fps_entry;
if (!push_cdp_buffer (self, inbuf, &tc, &in_fps_entry)) { if (!push_cdp_buffer (self, inbuf, &tc, &in_fps_entry)) {
@ -1124,9 +1165,14 @@ convert_cea708_cdp_cea608_raw (GstCCConverter * self, GstBuffer * inbuf,
goto drop; goto drop;
gst_buffer_map (outbuf, &out, GST_MAP_WRITE); gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
cea608_1_len = out.size; cea608_len = out.size;
cc_buffer_take_separated (self->cc_buffer, out_fps_entry, out.data, if (self->out_field == 0) {
&cea608_1_len, NULL, 0, NULL, 0); cc_buffer_take_separated (self->cc_buffer, out_fps_entry, out.data,
&cea608_len, NULL, 0, NULL, 0);
} else {
cc_buffer_take_separated (self->cc_buffer, out_fps_entry, NULL, 0, out.data,
&cea608_len, NULL, 0);
}
gst_buffer_unmap (outbuf, &out); gst_buffer_unmap (outbuf, &out);
self->output_frames++; self->output_frames++;
@ -1137,11 +1183,11 @@ convert_cea708_cdp_cea608_raw (GstCCConverter * self, GstBuffer * inbuf,
} }
out: out:
gst_buffer_set_size (outbuf, cea608_1_len); gst_buffer_set_size (outbuf, cea608_len);
return GST_FLOW_OK; return GST_FLOW_OK;
drop: drop:
cea608_1_len = 0; cea608_len = 0;
goto out; goto out;
} }
@ -1744,5 +1790,7 @@ static void
gst_cc_converter_init (GstCCConverter * self) gst_cc_converter_init (GstCCConverter * self)
{ {
self->cdp_mode = DEFAULT_CDP_MODE; self->cdp_mode = DEFAULT_CDP_MODE;
self->in_field = 0;
self->out_field = 0;
self->cc_buffer = cc_buffer_new (); self->cc_buffer = cc_buffer_new ();
} }

View file

@ -53,6 +53,8 @@ struct _GstCCConverter
GstBaseTransform parent; GstBaseTransform parent;
GstCCConverterCDPMode cdp_mode; GstCCConverterCDPMode cdp_mode;
gint in_field;
gint out_field;
GstVideoCaptionType input_caption_type; GstVideoCaptionType input_caption_type;
GstVideoCaptionType output_caption_type; GstVideoCaptionType output_caption_type;

View file

@ -988,6 +988,85 @@ GST_START_TEST (convert_cea608_s334_1a_cea708_cdp_double_framerate)
GST_END_TEST; 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, 0xf8, 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,
0xb0
};
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_cea708_cdp_cea708_cc_data_double_input_data) GST_START_TEST (convert_cea708_cdp_cea708_cc_data_double_input_data)
{ {
/* caps say 60fps, data has 30fps. Ensure data is taken alternatatively from /* caps say 60fps, data has 30fps. Ensure data is taken alternatatively from
@ -1205,6 +1284,13 @@ ccextractor_suite (void)
tcase_add_test (tc, convert_cea708_cc_data_cea708_cdp_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_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);
return s; return s;
} }