write_cea608 (GstCCConverter * self, gboolean pad_cea608,
const struct cdp_fps_entry *out_fps_entry, const guint8 * cea608_1,
guint cea608_1_len, const guint8 * cea608_2, guint cea608_2_len,
- guint8 * out, guint * out_size)
+ guint8 * out, guint * out_size, gboolean * is_last_cea608_field1)
{
guint i = 0, out_i = 0, max_size = 0, cea608_1_i = 0, cea608_2_i = 0;
guint cea608_output_count;
guint total_cea608_1_count, total_cea608_2_count;
+ gboolean write_cea608_field2_first = FALSE;
+ gboolean wrote_field1_last = FALSE;
+ gboolean wrote_first = FALSE;
g_assert (out);
g_assert (out_size);
g_assert (!cea608_2 || cea608_2_len % 2 == 0);
g_assert (cea608_1 || cea608_2);
+ if (is_last_cea608_field1)
+ write_cea608_field2_first = *is_last_cea608_field1;
+
cea608_1_len /= 2;
cea608_2_len /= 2;
#if 0
g_assert_cmpint (cea608_1_len + cea608_2_len, <=,
out_fps_entry->max_cea608_count);
- total_cea608_1_count = cea608_1_len;
- total_cea608_2_count = cea608_2_len;
-
#if 0
/* FIXME: if cea608 field 2 is generated, field 1 needs to be generated. */
if (cea608_1_len < cea608_2_len)
if (pad_cea608) {
max_size = out_fps_entry->max_cea608_count * 3;
} else {
- max_size = total_cea608_1_count + total_cea608_2_count * 3;
+ max_size = (cea608_1_len + cea608_2_len) * 3;
}
if (*out_size < max_size) {
GST_WARNING_OBJECT (self, "Output data too small (%u < %u) for cea608 data",
/* FIXME: interlacing, tff, rff, ensuring cea608 field1 is generated if
* field2 exists even across packets */
+ total_cea608_1_count = cea608_1_len;
+ total_cea608_2_count = cea608_2_len;
cea608_output_count = cea608_1_len + cea608_2_len;
if (pad_cea608) {
- for (i = total_cea608_1_count + total_cea608_2_count;
- i < out_fps_entry->max_cea608_count; i++) {
- /* try to pad evenly */
- if (!cea608_2 || i > cea608_1_len / 2)
- total_cea608_1_count++;
- else
+ guint max_cea608_count = out_fps_entry->max_cea608_count;
+
+ total_cea608_1_count = max_cea608_count / 2;
+ total_cea608_2_count = max_cea608_count / 2;
+
+ if (total_cea608_1_count + total_cea608_2_count < max_cea608_count) {
+ if (write_cea608_field2_first) {
total_cea608_2_count++;
- cea608_output_count++;
+ } else {
+ total_cea608_1_count++;
+ }
}
+
+ cea608_output_count = total_cea608_1_count + total_cea608_2_count;
}
GST_LOG ("writing %u cea608-1 fields and %u cea608-2 fields",
g_assert_cmpint (total_cea608_1_count + total_cea608_2_count, <=,
out_fps_entry->max_cea608_count);
+ wrote_first = !write_cea608_field2_first;
while (cea608_1_i + cea608_2_i < cea608_output_count) {
- if (cea608_1_i < cea608_1_len) {
- out[out_i++] = 0xfc;
- out[out_i++] = cea608_1[cea608_1_i * 2];
- out[out_i++] = cea608_1[cea608_1_i * 2 + 1];
- cea608_1_i++;
- i++;
- } else if (cea608_1_i < total_cea608_1_count) {
- out[out_i++] = 0xf8;
- out[out_i++] = 0x80;
- out[out_i++] = 0x80;
- cea608_1_i++;
- i++;
+ if (wrote_first) {
+ if (cea608_1_i < cea608_1_len) {
+ out[out_i++] = 0xfc;
+ out[out_i++] = cea608_1[cea608_1_i * 2];
+ out[out_i++] = cea608_1[cea608_1_i * 2 + 1];
+ cea608_1_i++;
+ i++;
+ wrote_field1_last = TRUE;
+ } else if (cea608_1_i < total_cea608_1_count) {
+ out[out_i++] = 0xf8;
+ out[out_i++] = 0x80;
+ out[out_i++] = 0x80;
+ cea608_1_i++;
+ i++;
+ wrote_field1_last = TRUE;
+ }
}
if (cea608_2_i < cea608_2_len) {
out[out_i++] = cea608_2[cea608_2_i * 2 + 1];
cea608_2_i++;
i++;
+ wrote_field1_last = FALSE;
} else if (cea608_2_i < total_cea608_2_count) {
out[out_i++] = 0xf9;
out[out_i++] = 0x80;
out[out_i++] = 0x80;
cea608_2_i++;
i++;
+ wrote_field1_last = FALSE;
}
+
+ wrote_first = TRUE;
}
g_assert_cmpint (out_i / 3, <=, out_fps_entry->max_cea608_count);
*out_size = out_i;
+ if (is_last_cea608_field1)
+ *is_last_cea608_field1 = wrote_field1_last;
return TRUE;
}
combine_cc_data (GstCCConverter * self, gboolean pad_cea608,
const struct cdp_fps_entry *out_fps_entry, const guint8 * ccp_data,
guint ccp_data_len, const guint8 * cea608_1, guint cea608_1_len,
- const guint8 * cea608_2, guint cea608_2_len, guint8 * out, guint * out_size)
+ const guint8 * cea608_2, guint cea608_2_len, guint8 * out, guint * out_size,
+ gboolean * last_cea608_is_field1)
{
guint out_i = 0, max_size = 0;
guint cea608_size = *out_size;
if (cea608_1 || cea608_2) {
if (!write_cea608 (self, pad_cea608, out_fps_entry, cea608_1, cea608_1_len,
- cea608_2, cea608_2_len, out, &cea608_size))
+ cea608_2, cea608_2_len, out, &cea608_size, last_cea608_is_field1))
return FALSE;
} else {
cea608_size = 0;
const struct cdp_fps_entry *in_fps_entry,
const struct cdp_fps_entry *out_fps_entry, const guint8 * ccp_data,
guint * ccp_data_len, const guint8 * cea608_1, guint * cea608_1_len,
- const guint8 * cea608_2, guint * cea608_2_len, const GstVideoTimeCode * tc)
+ const guint8 * cea608_2, guint * cea608_2_len, const GstVideoTimeCode * tc,
+ gboolean use_cea608_field2_first)
{
if (!in_fps_entry || in_fps_entry->fps_n == 0) {
in_fps_entry = cdp_fps_entry_from_fps (self->in_fps_n, self->in_fps_d);
* size. Split them where necessary. */
gint extra_ccp = 0, extra_cea608_1 = 0, extra_cea608_2 = 0;
gint ccp_off = 0, cea608_1_off = 0, cea608_2_off = 0;
+ gboolean wrote_first = FALSE;
+ gint field2_padding = 0;
if (output_time_cmp == 0) {
/* we have completed a cycle and can reset our counters to avoid
extra_cea608_1 = VAL_OR_0 (cea608_1_len);
extra_cea608_2 = VAL_OR_0 (cea608_2_len);
+ wrote_first = !use_cea608_field2_first;
/* try to push data into the packets. Anything 'extra' will be
* stored for later */
while (extra_cea608_1 > 0 || extra_cea608_2 > 0) {
avail_1 = VAL_OR_0 (cea608_1_len) - extra_cea608_1;
avail_2 = VAL_OR_0 (cea608_2_len) - extra_cea608_2;
- if (avail_1 + avail_2 >= 2 * out_fps_entry->max_cea608_count)
+ if (avail_1 + avail_2 + field2_padding >=
+ 2 * out_fps_entry->max_cea608_count)
break;
- if (extra_cea608_1 > 0) {
+ if (wrote_first && extra_cea608_1 > 0) {
extra_cea608_1 -= 2;
g_assert_cmpint (extra_cea608_1, >=, 0);
cea608_1_off += 2;
avail_1 = VAL_OR_0 (cea608_1_len) - extra_cea608_1;
avail_2 = VAL_OR_0 (cea608_2_len) - extra_cea608_2;
- if (avail_1 + avail_2 >= 2 * out_fps_entry->max_cea608_count)
+ if (avail_1 + avail_2 + field2_padding >=
+ 2 * out_fps_entry->max_cea608_count)
break;
if (extra_cea608_2 > 0) {
g_assert_cmpint (extra_cea608_2, >=, 0);
cea608_2_off += 2;
g_assert_cmpint (cea608_2_off, <=, *cea608_2_len);
+ } else if (!wrote_first) {
+ /* we need to insert field 2 padding if we don't have data and are
+ * requested to start with field2 */
+ field2_padding += 2;
}
+ wrote_first = TRUE;
}
+ GST_TRACE_OBJECT (self, "allocated sizes ccp:%u, cea608-1:%u, "
+ "cea608-2:%u", ccp_off, cea608_1_off, cea608_2_off);
+
if (extra_ccp > 0 || extra_cea608_1 > 0 || extra_cea608_2 > 0) {
/* packet would overflow, push extra bytes into the next packet */
GST_DEBUG_OBJECT (self, "buffer would overflow by %u ccp bytes, "
cc_count &= 0x1f;
len = 3 * cc_count;
- if (gst_byte_reader_get_remaining (&br) < len)
+ if (gst_byte_reader_get_remaining (&br) < len) {
+ GST_WARNING_OBJECT (self, "not enough bytes (%u) left for the number of "
+ "byte triples (%u)", gst_byte_reader_get_remaining (&br), cc_count);
return 0;
+ }
memcpy (cc_data, gst_byte_reader_get_data_unchecked (&br, len), len);
}
g_assert_not_reached ();
if (!fit_and_scale_cc_data (self, in_fps_entry, out_fps_entry, NULL, 0,
- cea608_1, &cea608_1_len, NULL, 0, tc_meta ? &tc_meta->tc : NULL))
+ cea608_1, &cea608_1_len, NULL, 0, tc_meta ? &tc_meta->tc : NULL,
+ FALSE))
goto drop;
if (!combine_cc_data (self, TRUE, out_fps_entry, NULL, 0, cea608_1,
- cea608_1_len, (guint8 *) 0x1, 0, cc_data, &cc_data_len))
+ cea608_1_len, NULL, 0, cc_data, &cc_data_len,
+ &self->last_cea608_written_was_field1))
goto drop;
gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
if (!fit_and_scale_cc_data (self, in_fps_entry, out_fps_entry, NULL, 0,
cea608_1, &cea608_1_len, cea608_2, &cea608_2_len,
- tc_meta ? &tc_meta->tc : NULL)) {
+ tc_meta ? &tc_meta->tc : NULL,
+ self->last_cea608_written_was_field1)) {
goto drop;
}
if (!combine_cc_data (self, TRUE, out_fps_entry, NULL, 0, cea608_1,
- cea608_1_len, cea608_2, cea608_2_len, cc_data, &cc_data_len)) {
+ cea608_1_len, cea608_2, cea608_2_len, cc_data, &cc_data_len,
+ &self->last_cea608_written_was_field1)) {
goto drop;
}
if (!fit_and_scale_cc_data (self, in_fps_entry, out_fps_entry, ccp_data,
&ccp_data_len, cea608_1, &cea608_1_len, cea608_2, &cea608_2_len,
- tc_meta ? &tc_meta->tc : NULL))
+ tc_meta ? &tc_meta->tc : NULL, self->last_cea608_written_was_field1))
goto drop;
if (!combine_cc_data (self, TRUE, out_fps_entry, ccp_data, ccp_data_len,
cea608_1, cea608_1_len, cea608_2, cea608_2_len, cc_data,
- &cc_data_len))
+ &cc_data_len, &self->last_cea608_written_was_field1))
goto drop;
gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
out_fps_entry = in_fps_entry;
if (fit_and_scale_cc_data (self, in_fps_entry, out_fps_entry, NULL, 0,
- cea608_1, &cea608_1_len, NULL, NULL, &tc)) {
+ cea608_1, &cea608_1_len, NULL, NULL, &tc, FALSE)) {
guint i, out_size = (guint) out.size;
self->output_frames++;
if (!write_cea608 (self, TRUE, out_fps_entry, cea608_1, cea608_1_len, NULL,
- 0, out.data, &out_size)) {
+ 0, out.data, &out_size, NULL)) {
gst_buffer_unmap (outbuf, &out);
return GST_FLOW_ERROR;
}
out_fps_entry = in_fps_entry;
if (!fit_and_scale_cc_data (self, in_fps_entry, out_fps_entry, NULL, 0,
- cea608_1, &cea608_1_len, cea608_2, &cea608_2_len, &tc))
+ cea608_1, &cea608_1_len, cea608_2, &cea608_2_len, &tc,
+ self->last_cea608_written_was_field1))
goto drop;
cc_data_len = gst_buffer_get_sizes (outbuf, NULL, NULL);
gst_buffer_map (outbuf, &out, GST_MAP_READWRITE);
if (!combine_cc_data (self, TRUE, out_fps_entry, NULL, 0, cea608_1,
- cea608_1_len, cea608_2, cea608_2_len, out.data, &cc_data_len)) {
+ cea608_1_len, cea608_2, cea608_2_len, out.data, &cc_data_len,
+ &self->last_cea608_written_was_field1)) {
gst_buffer_unmap (outbuf, &out);
goto drop;
}
out_fps_entry = in_fps_entry;
if (!fit_and_scale_cc_data (self, in_fps_entry, out_fps_entry, ccp_data,
- &ccp_data_len, cea608_1, &cea608_1_len, cea608_2, &cea608_2_len, &tc))
+ &ccp_data_len, cea608_1, &cea608_1_len, cea608_2, &cea608_2_len, &tc,
+ self->last_cea608_written_was_field1))
goto out;
gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
out_len = (guint) out.size;
if (!combine_cc_data (self, TRUE, out_fps_entry, ccp_data, ccp_data_len,
- cea608_1, cea608_1_len, cea608_2, cea608_2_len, out.data, &out_len)) {
+ cea608_1, cea608_1_len, cea608_2, cea608_2_len, out.data, &out_len,
+ &self->last_cea608_written_was_field1)) {
gst_buffer_unmap (outbuf, &out);
out_len = 0;
goto out;
out_fps_entry = in_fps_entry;
if (!fit_and_scale_cc_data (self, in_fps_entry, out_fps_entry, ccp_data,
- &ccp_data_len, cea608_1, &cea608_1_len, cea608_2, &cea608_2_len, &tc))
+ &ccp_data_len, cea608_1, &cea608_1_len, cea608_2, &cea608_2_len, &tc,
+ self->last_cea608_written_was_field1))
goto out;
if (!combine_cc_data (self, TRUE, out_fps_entry, ccp_data, ccp_data_len,
cea608_1, cea608_1_len, cea608_2, cea608_2_len, cc_data,
- &cc_data_len)) {
+ &cc_data_len, &self->last_cea608_written_was_field1)) {
goto out;
}
self->output_frames = 1;
gst_video_time_code_clear (&self->current_output_timecode);
gst_clear_buffer (&self->previous_buffer);
+ self->last_cea608_written_was_field1 = FALSE;
}
static GstFlowReturn
/* Resetting this is not really needed but makes debugging easier */
self->cdp_hdr_sequence_cntr = 0;
self->current_output_timecode = (GstVideoTimeCode) GST_VIDEO_TIME_CODE_INIT;
- self->input_frames = 0;
- self->output_frames = 1;
- self->scratch_ccp_len = 0;
- self->scratch_cea608_1_len = 0;
- self->scratch_cea608_2_len = 0;
+ reset_counters (self);
return TRUE;
}
{
const guint8 in[] = { 0xfc, 0x80, 0x80, 0xfe, 0x80, 0x80 };
const guint8 out[] =
- { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xf9, 0x80, 0x80,
+ { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x00, 0x72, 0xea, 0xf8, 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, 0x6d
+ 0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6e
};
check_conversion (in, sizeof (in), out, sizeof (out),
"closedcaption/x-cea-708,format=(string)cc_data,framerate=(fraction)60/1",
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[] = { 0xf9, 0x80, 0x80, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x80,
+ const guint8 out[] = { 0xf8, 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
};
/* 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,
- 0xfc, 0x03, 0x04, 0xfe, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
+ 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,
0x00, 0x00, 0x10
};
const guint8 out2[] = { 0x96, 0x69, 0x30, 0x8f, 0xc3, 0x00, 0x01, 0x71, 0xc1,
- 0x82, 0x03, 0x09, 0x72, 0xea, 0xfc, 0x03, 0x04, 0xfe, 0x17, 0x18, 0xfe,
+ 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, 0xc5
+ 0x00, 0x01, 0xc4
};
const guint8 *out[] = { out1, out2 };
guint out_len[] = { sizeof (out1), sizeof (out2) };
0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0x74, 0x00, 0x00, 0x7a
};
const guint8 in2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
- 0xfc, 0x14, 0x15, 0xfe, 0x16, 0x17, 0xfe, 0x18, 0x19, 0xfe, 0x1a, 0x1b,
+ 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 out1[] =
{ 0x96, 0x69, 0x4e, 0x5f, 0xc3, 0x00, 0x00, 0x71, 0xc1, 0x82, 0x03, 0x04,
- 0x72, 0xf4, 0xfc, 0x01, 0x02, 0xfc, 0x14, 0x15, 0xfe, 0x03, 0x04, 0xfe,
+ 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, 0x08
+ 0x26, 0x27, 0x74, 0x00, 0x00, 0x07
};
const guint8 *out[] = { out1 };
guint out_len[] = { sizeof (out1) };
const guint8 out1[] =
{ 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
- 0xfc, 0x01, 0x02, 0xfc, 0x01, 0x02, 0xfe, 0x03, 0x04, 0xfe, 0x05, 0x06,
+ 0xf9, 0x80, 0x80, 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, 0xc5
+ 0x74, 0x00, 0x00, 0xcb
};
const guint8 out2[] =
- { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x01, 0x72, 0xf9, 0xfc, 0x01, 0x02,
- 0xfc, 0x01, 0x02, 0xfc, 0x01, 0x02, 0xfe, 0x0b, 0x0c, 0xfe, 0x0d, 0x0e,
+ { 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x01, 0x72, 0xf9, 0xf9, 0x80, 0x80,
+ 0xfc, 0x01, 0x02, 0xf9, 0x80, 0x80, 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, 0x83
+ 0x74, 0x00, 0x01, 0x8f
};
const guint8 *out[] = { out1, out2 };
guint out_len[] = { sizeof (out1), sizeof (out2) };
* high framerate */
const guint8 in1[] =
{ 0x96, 0x69, 0x58, 0x1f, 0x43, 0x00, 0x00, 0x72, 0xf9, 0xfc, 0x01, 0x02,
- 0xfc, 0x03, 0x04, 0xfc, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
+ 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, 0x15, 0x16, 0xfe, 0x17, 0x18, 0x74, 0x00, 0x00, 0x30
};
const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
- 0xfc, 0x03, 0x04, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
+ 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, 0xe6
+ 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, 0x0d, 0x0e, 0xfe, 0x0f, 0x10, 0x74, 0x00, 0x02, 0x54
};
const guint8 out4[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea,
- 0xfc, 0x01, 0x02, 0xfe, 0x11, 0x12, 0xfe, 0x13, 0x14, 0xfe, 0x15, 0x16,
+ 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, 0x76
+ 0xfe, 0x1f, 0x20, 0xfe, 0x21, 0x22, 0x74, 0x00, 0x03, 0x71
};
const guint8 *out[] = { out1, out2, out3, out4 };
guint out_len[] =
* 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,
- 0xfc, 0x03, 0x04, 0xfc, 0x05, 0x06, 0xfe, 0x07, 0x08, 0xfe, 0x09, 0x0a,
+ 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, 0x15, 0x16, 0xfe, 0x17, 0x18, 0x74, 0x00, 0x00, 0x30
};
const guint8 out2[] = { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea,
- 0xfc, 0x03, 0x04, 0xfe, 0x19, 0x1a, 0xfe, 0x1b, 0x1c, 0xfe, 0x1d, 0x1e,
+ 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, 0xe6
+ 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,
GST_START_TEST (convert_cea708_cc_data_cea708_cdp_double_framerate)
{
- const guint8 in1[] = { 0xfc, 0x80, 0x81, 0xfc, 0x82, 0x83, 0xfe, 0x84, 0x85 };
- const guint8 in2[] = { 0xfc, 0x86, 0x87, 0xfc, 0x88, 0x89, 0xfe, 0x8a, 0x8b };
+ 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[] =
0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x60
};
const guint8 out2[] =
- { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfc, 0x82, 0x83,
+ { 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, 0x67
+ 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x66
};
const guint8 out3[] =
{ 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x86, 0x87,
0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x44
};
const guint8 out4[] =
- { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfc, 0x88, 0x89,
+ { 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, 0x57
+ 0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x56
};
const guint8 *out[] = { out1, out2, out3, out4, };
guint out_len[] =
GST_START_TEST (convert_cea608_raw_cea708_cdp_double_framerate)
{
- const guint8 in1[] = { 0x80, 0x81, 0x82, 0x83 };
- const guint8 in2[] = { 0x84, 0x85, 0x86, 0x87 };
+ 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[] =
0xfa, 0x00, 0x00, 0x74, 0x00, 0x00, 0x6d
};
const guint8 out2[] =
- { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x01, 0x72, 0xea, 0xfc, 0x82, 0x83,
+ { 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, 0x67
+ 0xfa, 0x00, 0x00, 0x74, 0x00, 0x01, 0x6f
};
const guint8 out3[] =
- { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x02, 0x72, 0xea, 0xfc, 0x84, 0x85,
+ { 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, 0x61
+ 0xfa, 0x00, 0x00, 0x74, 0x00, 0x02, 0x65
};
const guint8 out4[] =
- { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 0x72, 0xea, 0xfc, 0x86, 0x87,
+ { 0x96, 0x69, 0x2b, 0x8f, 0x43, 0x00, 0x03, 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, 0x03, 0x5b
+ 0xfa, 0x00, 0x00, 0x74, 0x00, 0x03, 0x6b
};
const guint8 *out[] = { out1, out2, out3, out4, };
guint out_len[] =
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, 0x85, 0x86, };
+ 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;
+
static Suite *
ccextractor_suite (void)
{
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);
return s;
}