typedef struct cdp_fps_entry cdp_fps_entry;
+#define VAL_OR_0(v) ((v) ? (*(v)) : 0)
+
static const struct cdp_fps_entry cdp_fps_table[] = {
{0x1f, 24000, 1001, 25, 22, 3 /* FIXME: alternating max cea608 count! */ },
{0x2f, 24, 1, 25, 22, 2},
/* skip everything else we don't care about */
return len;
}
+
+#define CC_DATA_EXTRACT_TOO_MANY_FIELD1 -2
+#define CC_DATA_EXTRACT_TOO_MANY_FIELD2 -3
+
+static gint
+cc_data_extract_cea608 (const guint8 * cc_data, guint cc_data_len,
+ guint8 * cea608_field1, guint * cea608_field1_len,
+ guint8 * cea608_field2, guint * cea608_field2_len)
+{
+ guint i, field_1_len = 0, field_2_len = 0;
+
+ if (cea608_field1_len) {
+ field_1_len = *cea608_field1_len;
+ *cea608_field1_len = 0;
+ }
+ if (cea608_field2_len) {
+ field_2_len = *cea608_field2_len;
+ *cea608_field2_len = 0;
+ }
+
+ if (cc_data_len % 3 != 0) {
+ GST_WARNING ("Invalid cc_data buffer size %u. Truncating to a multiple "
+ "of 3", cc_data_len);
+ cc_data_len = cc_data_len - (cc_data_len % 3);
+ }
+
+ for (i = 0; i < cc_data_len / 3; i++) {
+ guint8 byte0 = cc_data[i * 3 + 0];
+ guint8 byte1 = cc_data[i * 3 + 1];
+ guint8 byte2 = cc_data[i * 3 + 2];
+ gboolean cc_valid = (byte0 & 0x04) == 0x04;
+ guint8 cc_type = byte0 & 0x03;
+
+ GST_TRACE ("0x%02x 0x%02x 0x%02x, valid: %u, type: 0b%u%u", byte0, byte1,
+ byte2, cc_valid, (cc_type & 0x2) == 0x2, (cc_type & 0x1) == 0x1);
+
+ if (cc_type == 0x00) {
+ if (!cc_valid)
+ continue;
+
+ if (cea608_field1 && cea608_field1_len) {
+ if (*cea608_field1_len + 2 > field_1_len) {
+ GST_WARNING ("Too many cea608 input bytes %u for field 1",
+ *cea608_field1_len + 2);
+ return CC_DATA_EXTRACT_TOO_MANY_FIELD1;
+ }
+
+ if (byte1 != 0x80 || byte2 != 0x80) {
+ cea608_field1[(*cea608_field1_len)++] = byte1;
+ cea608_field1[(*cea608_field1_len)++] = byte2;
+ }
+ }
+ } else if (cc_type == 0x01) {
+ if (!cc_valid)
+ continue;
+
+ if (cea608_field2 && cea608_field2_len) {
+ if (*cea608_field2_len + 2 > field_2_len) {
+ GST_WARNING ("Too many cea608 input bytes %u for field 2",
+ *cea608_field2_len + 2);
+ return CC_DATA_EXTRACT_TOO_MANY_FIELD2;
+ }
+ if (byte1 != 0x80 || byte2 != 0x80) {
+ cea608_field2[(*cea608_field2_len)++] = byte1;
+ cea608_field2[(*cea608_field2_len)++] = byte2;
+ }
+ }
+ } else {
+ /* all cea608 packets must be at the beginning of a cc_data */
+ break;
+ }
+ }
+
+ g_assert_cmpint (i * 3, <=, cc_data_len);
+
+ GST_LOG ("Extracted cea608-1 of length %u and cea608-2 of length %u, "
+ "ccp_offset %i", VAL_OR_0 (cea608_field1_len),
+ VAL_OR_0 (cea608_field2_len), i * 3);
+
+ return i * 3;
+}
+
+gint
+drop_ccp_from_cc_data (guint8 * cc_data, guint cc_data_len)
+{
+ return cc_data_extract_cea608 (cc_data, cc_data_len, NULL, NULL, NULL, NULL);
+}
+
+#define DEFAULT_MAX_BUFFER_TIME (100 * GST_MSECOND)
+
+struct _CCBuffer
+{
+ GstObject parent;
+ GArray *cea608_1;
+ GArray *cea608_2;
+ GArray *cc_data;
+ /* used for tracking which field to write across output buffer boundaries */
+ gboolean last_cea608_written_was_field1;
+
+ GstClockTime max_buffer_time;
+};
+
+G_DEFINE_TYPE (CCBuffer, cc_buffer, G_TYPE_OBJECT);
+
+CCBuffer *
+cc_buffer_new (void)
+{
+ return g_object_new (cc_buffer_get_type (), NULL);
+}
+
+static void
+cc_buffer_init (CCBuffer * buf)
+{
+ buf->cea608_1 = g_array_new (FALSE, FALSE, sizeof (guint8));
+ buf->cea608_2 = g_array_new (FALSE, FALSE, sizeof (guint8));
+ buf->cc_data = g_array_new (FALSE, FALSE, sizeof (guint8));
+
+ buf->max_buffer_time = DEFAULT_MAX_BUFFER_TIME;
+}
+
+static void
+cc_buffer_finalize (GObject * object)
+{
+ CCBuffer *buf = GST_CC_BUFFER (object);
+
+ g_array_unref (buf->cea608_1);
+ buf->cea608_1 = NULL;
+ g_array_unref (buf->cea608_2);
+ buf->cea608_2 = NULL;
+ g_array_unref (buf->cc_data);
+ buf->cc_data = NULL;
+
+ G_OBJECT_CLASS (cc_buffer_parent_class)->finalize (object);
+}
+
+static void
+cc_buffer_class_init (CCBufferClass * buf_class)
+{
+ GObjectClass *gobject_class = (GObjectClass *) buf_class;
+
+ gobject_class->finalize = cc_buffer_finalize;
+}
+
+/* remove padding bytes from a cc_data packet. Returns the length of the new
+ * data in @cc_data */
+static guint
+compact_cc_data (guint8 * cc_data, guint cc_data_len)
+{
+ gboolean started_ccp = FALSE;
+ guint out_len = 0;
+ guint i;
+
+ if (cc_data_len % 3 != 0) {
+ GST_WARNING ("Invalid cc_data buffer size");
+ cc_data_len = cc_data_len - (cc_data_len % 3);
+ }
+
+ for (i = 0; i < cc_data_len / 3; i++) {
+ gboolean cc_valid = (cc_data[i * 3] & 0x04) == 0x04;
+ guint8 cc_type = cc_data[i * 3] & 0x03;
+
+ if (!started_ccp && (cc_type == 0x00 || cc_type == 0x01)) {
+ if (cc_valid) {
+ /* copy over valid 608 data */
+ cc_data[out_len++] = cc_data[i * 3];
+ cc_data[out_len++] = cc_data[i * 3 + 1];
+ cc_data[out_len++] = cc_data[i * 3 + 2];
+ }
+ continue;
+ }
+
+ if (cc_type & 0x10)
+ started_ccp = TRUE;
+
+ if (!cc_valid)
+ continue;
+
+ if (cc_type == 0x00 || cc_type == 0x01) {
+ GST_WARNING ("Invalid cc_data. cea608 bytes after cea708");
+ return 0;
+ }
+
+ cc_data[out_len++] = cc_data[i * 3];
+ cc_data[out_len++] = cc_data[i * 3 + 1];
+ cc_data[out_len++] = cc_data[i * 3 + 2];
+ }
+
+ GST_LOG ("compacted cc_data from %u to %u", cc_data_len, out_len);
+
+ return out_len;
+}
+
+static guint
+calculate_n_cea608_doubles_from_time_ceil (CCBuffer * buf, GstClockTime ns)
+{
+ /* cea608 has a maximum bitrate of 60000/1001 * 2 bytes/s */
+ guint ret = gst_util_uint64_scale_ceil (ns, 120000, 1001 * GST_SECOND);
+
+ return GST_ROUND_UP_2 (ret);
+}
+
+static guint
+calculate_n_cea708_doubles_from_time_ceil (CCBuffer * buf, GstClockTime ns)
+{
+ /* ccp has a maximum bitrate of 9600000/1001 bits/s */
+ guint ret = gst_util_uint64_scale_ceil (ns, 9600000 / 8, 1001 * GST_SECOND);
+
+ return GST_ROUND_UP_2 (ret);
+}
+
+static void
+push_internal (CCBuffer * buf, const guint8 * cea608_1,
+ guint cea608_1_len, const guint8 * cea608_2, guint cea608_2_len,
+ const guint8 * cc_data, guint cc_data_len)
+{
+ guint max_cea608_bytes;
+
+ GST_DEBUG_OBJECT (buf, "pushing cea608-1: %u cea608-2: %u ccp: %u",
+ cea608_1_len, cea608_2_len, cc_data_len);
+ max_cea608_bytes =
+ calculate_n_cea608_doubles_from_time_ceil (buf, buf->max_buffer_time);
+
+ if (cea608_1_len > 0) {
+ if (cea608_1_len + buf->cea608_1->len > max_cea608_bytes) {
+ GST_WARNING_OBJECT (buf, "cea608 field 1 overflow, dropping all "
+ "previous data, max %u, attempted to hold %u", max_cea608_bytes,
+ cea608_1_len + buf->cea608_1->len);
+ g_array_set_size (buf->cea608_1, 0);
+ }
+ g_array_append_vals (buf->cea608_1, cea608_1, cea608_1_len);
+ }
+ if (cea608_2_len > 0) {
+ if (cea608_2_len + buf->cea608_2->len > max_cea608_bytes) {
+ GST_WARNING_OBJECT (buf, "cea608 field 2 overflow, dropping all "
+ "previous data, max %u, attempted to hold %u", max_cea608_bytes,
+ cea608_2_len + buf->cea608_2->len);
+ g_array_set_size (buf->cea608_2, 0);
+ }
+ g_array_append_vals (buf->cea608_2, cea608_2, cea608_2_len);
+ }
+ if (cc_data_len > 0) {
+ guint max_cea708_bytes =
+ calculate_n_cea708_doubles_from_time_ceil (buf, buf->max_buffer_time);
+ if (cc_data_len + buf->cc_data->len > max_cea708_bytes) {
+ GST_WARNING_OBJECT (buf, "ccp data overflow, dropping all "
+ "previous data, max %u, attempted to hold %u", max_cea708_bytes,
+ cc_data_len + buf->cc_data->len);
+ g_array_set_size (buf->cea608_2, 0);
+ }
+ g_array_append_vals (buf->cc_data, cc_data, cc_data_len);
+ }
+}
+
+void
+cc_buffer_push_separated (CCBuffer * buf, const guint8 * cea608_1,
+ guint cea608_1_len, const guint8 * cea608_2, guint cea608_2_len,
+ const guint8 * cc_data, guint cc_data_len)
+{
+ guint8 cea608_1_copy[MAX_CEA608_LEN];
+ guint8 cea608_2_copy[MAX_CEA608_LEN];
+ guint8 cc_data_copy[MAX_CDP_PACKET_LEN];
+ guint i;
+
+ if (cea608_1 && cea608_1_len > 0) {
+ guint out_i = 0;
+ for (i = 0; i < cea608_1_len / 2; i++) {
+ if (cea608_1[i] != 0x80 || cea608_1[i + 1] != 0x80) {
+ cea608_1_copy[out_i++] = cea608_1[i];
+ cea608_1_copy[out_i++] = cea608_1[i + 1];
+ }
+ }
+ cea608_1_len = out_i;
+ } else {
+ cea608_1_len = 0;
+ }
+
+ if (cea608_2 && cea608_2_len > 0) {
+ guint out_i = 0;
+ for (i = 0; i < cea608_2_len / 2; i++) {
+ if (cea608_2[i] != 0x80 || cea608_2[i + 1] != 0x80) {
+ cea608_2_copy[out_i++] = cea608_2[i];
+ cea608_2_copy[out_i++] = cea608_2[i + 1];
+ }
+ }
+ cea608_2_len = out_i;
+ } else {
+ cea608_2_len = 0;
+ }
+
+ if (cc_data && cc_data_len > 0) {
+ memcpy (cc_data_copy, cc_data, cc_data_len);
+ cc_data_len = compact_cc_data (cc_data_copy, cc_data_len);
+ } else {
+ cc_data_len = 0;
+ }
+
+ push_internal (buf, cea608_1_copy, cea608_1_len, cea608_2_copy,
+ cea608_2_len, cc_data_copy, cc_data_len);
+}
+
+void
+cc_buffer_push_cc_data (CCBuffer * buf, const guint8 * cc_data,
+ guint cc_data_len)
+{
+ guint8 cea608_1[MAX_CEA608_LEN];
+ guint8 cea608_2[MAX_CEA608_LEN];
+ guint8 cc_data_copy[MAX_CDP_PACKET_LEN];
+ guint cea608_1_len = MAX_CEA608_LEN;
+ guint cea608_2_len = MAX_CEA608_LEN;
+ int ccp_offset;
+
+ memcpy (cc_data_copy, cc_data, cc_data_len);
+
+ cc_data_len = compact_cc_data (cc_data_copy, cc_data_len);
+
+ ccp_offset = cc_data_extract_cea608 (cc_data_copy, cc_data_len, cea608_1,
+ &cea608_1_len, cea608_2, &cea608_2_len);
+
+ if (ccp_offset < 0) {
+ GST_WARNING_OBJECT (buf, "Failed to extract cea608 from cc_data");
+ return;
+ }
+
+ push_internal (buf, cea608_1, cea608_1_len, cea608_2,
+ cea608_2_len, &cc_data_copy[ccp_offset], cc_data_len - ccp_offset);
+}
+
+void
+cc_buffer_get_stored_size (CCBuffer * buf, guint * cea608_1_len,
+ guint * cea608_2_len, guint * cc_data_len)
+{
+ if (cea608_1_len)
+ *cea608_1_len = buf->cea608_1->len;
+ if (cea608_2_len)
+ *cea608_2_len = buf->cea608_2->len;
+ if (cc_data_len)
+ *cc_data_len = buf->cc_data->len;
+}
+
+void
+cc_buffer_discard (CCBuffer * buf)
+{
+ g_array_set_size (buf->cea608_1, 0);
+ g_array_set_size (buf->cea608_2, 0);
+ g_array_set_size (buf->cc_data, 0);
+}
+
+#if 0
+void
+cc_buffer_peek (CCBuffer * buf, guint8 ** cea608_1, guint * cea608_1_len,
+ guint8 ** cea608_2, guint * cea608_2_len, guint8 ** cc_data,
+ guint * cc_data_len)
+{
+ if (cea608_1_len) {
+ if (cea608_1) {
+ *cea608_1 = (guint8 *) buf->cea608_1->data;
+ }
+ *cea608_1_len = buf->cea608_1->len;
+ }
+ if (cea608_1_len) {
+ if (cea608_2) {
+ *cea608_2 = (guint8 *) buf->cea608_2->data;
+ }
+ *cea608_2_len = buf->cea608_2->len;
+ }
+ if (cc_data_len) {
+ if (cc_data) {
+ *cc_data = (guint8 *) buf->cc_data->data;
+ }
+ *cc_data_len = buf->cc_data->len;
+ }
+}
+#endif
+static void
+cc_buffer_get_out_sizes (CCBuffer * buf, const struct cdp_fps_entry *fps_entry,
+ guint * cea608_1_len, guint * field1_padding, guint * cea608_2_len,
+ guint * field2_padding, guint * cc_data_len)
+{
+ gint extra_ccp = 0, extra_cea608_1 = 0, extra_cea608_2 = 0;
+ gint write_ccp_size = 0, write_cea608_1_size = 0, write_cea608_2_size = 0;
+ gboolean wrote_first = FALSE;
+
+ if (buf->cc_data->len) {
+ extra_ccp = buf->cc_data->len - 3 * fps_entry->max_ccp_count;
+ extra_ccp = MAX (0, extra_ccp);
+ write_ccp_size = buf->cc_data->len - extra_ccp;
+ }
+
+ extra_cea608_1 = buf->cea608_1->len;
+ extra_cea608_2 = buf->cea608_2->len;
+ *field1_padding = 0;
+ *field2_padding = 0;
+
+ wrote_first = !buf->last_cea608_written_was_field1;
+ /* try to push data into the packets. Anything 'extra' will be
+ * stored for later */
+ while (TRUE) {
+ gint avail_1, avail_2;
+
+ avail_1 = buf->cea608_1->len - extra_cea608_1 + *field1_padding;
+ avail_2 = buf->cea608_2->len - extra_cea608_2 + *field2_padding;
+ if (avail_1 + avail_2 >= 2 * fps_entry->max_cea608_count)
+ break;
+
+ if (wrote_first) {
+ if (extra_cea608_1 > 0) {
+ extra_cea608_1 -= 2;
+ g_assert_cmpint (extra_cea608_1, >=, 0);
+ write_cea608_1_size += 2;
+ g_assert_cmpint (write_cea608_1_size, <=, buf->cea608_1->len);
+ } else {
+ *field1_padding += 2;
+ }
+ }
+
+ avail_1 = buf->cea608_1->len - extra_cea608_1 + *field1_padding;
+ avail_2 = buf->cea608_2->len - extra_cea608_2 + *field2_padding;
+ if (avail_1 + avail_2 >= 2 * fps_entry->max_cea608_count)
+ break;
+
+ if (extra_cea608_2 > 0) {
+ extra_cea608_2 -= 2;
+ g_assert_cmpint (extra_cea608_2, >=, 0);
+ write_cea608_2_size += 2;
+ g_assert_cmpint (write_cea608_2_size, <=, buf->cea608_2->len);
+ } else {
+ /* 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 (buf, "allocated sizes ccp:%u, cea608-1:%u (pad:%u), "
+ "cea608-2:%u (pad:%u)", write_ccp_size, write_cea608_1_size,
+ *field1_padding, write_cea608_2_size, *field2_padding);
+
+ *cea608_1_len = write_cea608_1_size;
+ *cea608_2_len = write_cea608_2_size;
+ *cc_data_len = write_ccp_size;
+}
+
+void
+cc_buffer_take_separated (CCBuffer * buf,
+ const struct cdp_fps_entry *fps_entry, guint8 * cea608_1,
+ guint * cea608_1_len, guint8 * cea608_2, guint * cea608_2_len,
+ guint8 * cc_data, guint * cc_data_len)
+{
+ guint write_cea608_1_size, write_cea608_2_size, write_ccp_size;
+ guint field1_padding, field2_padding;
+
+ cc_buffer_get_out_sizes (buf, fps_entry, &write_cea608_1_size,
+ &field1_padding, &write_cea608_2_size, &field2_padding, &write_ccp_size);
+
+ if (cea608_1_len) {
+ if (*cea608_1_len < write_cea608_1_size + field1_padding) {
+ GST_WARNING_OBJECT (buf, "output cea608 field 1 buffer (%u) is too "
+ "small to hold output (%u)", *cea608_1_len,
+ write_cea608_1_size + field1_padding);
+ *cea608_1_len = 0;
+ } else if (cea608_1) {
+ memcpy (cea608_1, buf->cea608_1->data, write_cea608_1_size);
+ memset (&cea608_1[write_cea608_1_size], 0x80, field1_padding);
+ *cea608_1_len = write_cea608_1_size + field1_padding;
+ } else {
+ *cea608_1_len = 0;
+ }
+ }
+ if (cea608_2_len) {
+ if (*cea608_2_len < write_cea608_2_size + field2_padding) {
+ GST_WARNING_OBJECT (buf, "output cea608 field 2 buffer (%u) is too "
+ "small to hold output (%u)", *cea608_2_len, write_cea608_2_size);
+ *cea608_2_len = 0;
+ } else if (cea608_2) {
+ memcpy (cea608_2, buf->cea608_2->data, write_cea608_2_size);
+ memset (&cea608_2[write_cea608_2_size], 0x80, field2_padding);
+ *cea608_2_len = write_cea608_2_size + field2_padding;
+ } else {
+ *cea608_2_len = 0;
+ }
+ }
+ if (cc_data_len) {
+ if (*cc_data_len < write_ccp_size) {
+ GST_WARNING_OBJECT (buf, "output ccp buffer (%u) is too "
+ "small to hold output (%u)", *cc_data_len, write_ccp_size);
+ *cc_data_len = 0;
+ } else if (cc_data) {
+ memcpy (cc_data, buf->cc_data->data, write_ccp_size);
+ *cc_data_len = write_ccp_size;
+ } else {
+ *cc_data_len = 0;
+ }
+ }
+
+ g_array_remove_range (buf->cea608_1, 0, write_cea608_1_size);
+ g_array_remove_range (buf->cea608_2, 0, write_cea608_2_size);
+ g_array_remove_range (buf->cc_data, 0, write_ccp_size);
+
+ GST_LOG_OBJECT (buf, "bytes currently stored, cea608-1:%u, cea608-2:%u "
+ "ccp:%u", buf->cea608_1->len, buf->cea608_2->len, buf->cc_data->len);
+}
+
+void
+cc_buffer_take_cc_data (CCBuffer * buf,
+ const struct cdp_fps_entry *fps_entry, guint8 * cc_data,
+ guint * cc_data_len)
+{
+ guint write_cea608_1_size, write_cea608_2_size, write_ccp_size;
+ guint field1_padding, field2_padding;
+ gboolean wrote_first;
+
+ cc_buffer_get_out_sizes (buf, fps_entry, &write_cea608_1_size,
+ &field1_padding, &write_cea608_2_size, &field2_padding, &write_ccp_size);
+
+ {
+ guint cea608_1_i = 0, cea608_2_i = 0;
+ guint out_i = 0;
+ guint8 *cea608_1 = (guint8 *) buf->cea608_1->data;
+ guint8 *cea608_2 = (guint8 *) buf->cea608_2->data;
+ guint cea608_output_count =
+ write_cea608_1_size + write_cea608_2_size + field1_padding +
+ field2_padding;
+
+ wrote_first = !buf->last_cea608_written_was_field1;
+ while (cea608_1_i + cea608_2_i < cea608_output_count) {
+ if (wrote_first) {
+ if (cea608_1_i < write_cea608_1_size) {
+ cc_data[out_i++] = 0xfc;
+ cc_data[out_i++] = cea608_1[cea608_1_i];
+ cc_data[out_i++] = cea608_1[cea608_1_i + 1];
+ cea608_1_i += 2;
+ buf->last_cea608_written_was_field1 = TRUE;
+ } else if (cea608_1_i < write_cea608_1_size + field1_padding) {
+ cc_data[out_i++] = 0xf8;
+ cc_data[out_i++] = 0x80;
+ cc_data[out_i++] = 0x80;
+ cea608_1_i += 2;
+ buf->last_cea608_written_was_field1 = TRUE;
+ }
+ }
+
+ if (cea608_2_i < write_cea608_2_size) {
+ cc_data[out_i++] = 0xfd;
+ cc_data[out_i++] = cea608_2[cea608_2_i];
+ cc_data[out_i++] = cea608_2[cea608_2_i + 1];
+ cea608_2_i += 2;
+ buf->last_cea608_written_was_field1 = FALSE;
+ } else if (cea608_2_i < write_cea608_2_size + field2_padding) {
+ cc_data[out_i++] = 0xf9;
+ cc_data[out_i++] = 0x80;
+ cc_data[out_i++] = 0x80;
+ cea608_2_i += 2;
+ buf->last_cea608_written_was_field1 = FALSE;
+ }
+
+ wrote_first = TRUE;
+ }
+
+ if (write_ccp_size > 0)
+ memcpy (&cc_data[out_i], buf->cc_data->data, write_ccp_size);
+ *cc_data_len = out_i + write_ccp_size;
+ }
+
+ g_array_remove_range (buf->cea608_1, 0, write_cea608_1_size);
+ g_array_remove_range (buf->cea608_2, 0, write_cea608_2_size);
+ g_array_remove_range (buf->cc_data, 0, write_ccp_size);
+
+ GST_LOG_OBJECT (buf, "bytes currently stored, cea608-1:%u, cea608-2:%u "
+ "ccp:%u", buf->cea608_1->len, buf->cea608_2->len, buf->cc_data->len);
+}
guint output_frame;
GstVideoTimeCodeFlags flags;
- g_return_val_if_fail (tc != NULL, FALSE);
g_return_val_if_fail (out != NULL, FALSE);
/* out_n/d can only be 0 if scale_n/d are 1/1 */
g_return_val_if_fail ((scale_n == 1 && scale_d == 1) || (out_fps_n != 0
return TRUE;
}
-/* remove padding bytes from a cc_data packet. Returns the length of the new
- * data in @cc_data */
-static guint
-compact_cc_data (guint8 * cc_data, guint cc_data_len)
-{
- gboolean started_ccp = FALSE;
- guint out_len = 0;
- guint i;
-
- if (cc_data_len % 3 != 0) {
- GST_WARNING ("Invalid cc_data buffer size");
- cc_data_len = cc_data_len - (cc_data_len % 3);
- }
-
- for (i = 0; i < cc_data_len / 3; i++) {
- gboolean cc_valid = (cc_data[i * 3] & 0x04) == 0x04;
- guint8 cc_type = cc_data[i * 3] & 0x03;
-
- if (!started_ccp && (cc_type == 0x00 || cc_type == 0x01)) {
- if (cc_valid) {
- /* copy over valid 608 data */
- cc_data[out_len++] = cc_data[i * 3];
- cc_data[out_len++] = cc_data[i * 3 + 1];
- cc_data[out_len++] = cc_data[i * 3 + 2];
- }
- continue;
- }
-
- if (cc_type & 0x10)
- started_ccp = TRUE;
-
- if (!cc_valid)
- continue;
-
- if (cc_type == 0x00 || cc_type == 0x01) {
- GST_WARNING ("Invalid cc_data. cea608 bytes after cea708");
- return 0;
- }
-
- cc_data[out_len++] = cc_data[i * 3];
- cc_data[out_len++] = cc_data[i * 3 + 1];
- cc_data[out_len++] = cc_data[i * 3 + 2];
- }
-
- GST_LOG ("compacted cc_data from %u to %u", cc_data_len, out_len);
-
- return out_len;
-}
-
-#define CC_DATA_EXTRACT_TOO_MANY_FIELD1 -2
-#define CC_DATA_EXTRACT_TOO_MANY_FIELD2 -3
-
-static gint
-cc_data_extract_cea608 (guint8 * cc_data, guint cc_data_len,
- guint8 * cea608_field1, guint * cea608_field1_len,
- guint8 * cea608_field2, guint * cea608_field2_len)
-{
- guint i, field_1_len = 0, field_2_len = 0;
-
- if (cea608_field1_len) {
- field_1_len = *cea608_field1_len;
- *cea608_field1_len = 0;
- }
- if (cea608_field2_len) {
- field_2_len = *cea608_field2_len;
- *cea608_field2_len = 0;
- }
-
- if (cc_data_len % 3 != 0) {
- GST_WARNING ("Invalid cc_data buffer size %u. Truncating to a multiple "
- "of 3", cc_data_len);
- cc_data_len = cc_data_len - (cc_data_len % 3);
- }
-
- for (i = 0; i < cc_data_len / 3; i++) {
- guint8 byte0 = cc_data[i * 3 + 0];
- guint8 byte1 = cc_data[i * 3 + 1];
- guint8 byte2 = cc_data[i * 3 + 2];
- gboolean cc_valid = (byte0 & 0x04) == 0x04;
- guint8 cc_type = byte0 & 0x03;
-
- GST_TRACE ("0x%02x 0x%02x 0x%02x, valid: %u, type: 0b%u%u", byte0, byte1,
- byte2, cc_valid, (cc_type & 0x2) == 0x2, (cc_type & 0x1) == 0x1);
-
- if (cc_type == 0x00) {
- if (!cc_valid)
- continue;
-
- if (cea608_field1 && cea608_field1_len) {
- if (*cea608_field1_len + 2 > field_1_len) {
- GST_WARNING ("Too many cea608 input bytes %u for field 1",
- *cea608_field1_len + 2);
- return CC_DATA_EXTRACT_TOO_MANY_FIELD1;
- }
-
- if (byte1 != 0x80 || byte2 != 0x80) {
- cea608_field1[(*cea608_field1_len)++] = byte1;
- cea608_field1[(*cea608_field1_len)++] = byte2;
- }
- }
- } else if (cc_type == 0x01) {
- if (!cc_valid)
- continue;
-
- if (cea608_field2 && cea608_field2_len) {
- if (*cea608_field2_len + 2 > field_2_len) {
- GST_WARNING ("Too many cea608 input bytes %u for field 2",
- *cea608_field2_len + 2);
- return CC_DATA_EXTRACT_TOO_MANY_FIELD2;
- }
- if (byte1 != 0x80 || byte2 != 0x80) {
- cea608_field2[(*cea608_field2_len)++] = byte1;
- cea608_field2[(*cea608_field2_len)++] = byte2;
- }
- }
- } else {
- /* all cea608 packets must be at the beginning of a cc_data */
- break;
- }
- }
-
- g_assert_cmpint (i * 3, <=, cc_data_len);
-
- GST_LOG ("Extracted cea608-1 of length %u and cea608-2 of length %u",
- VAL_OR_0 (cea608_field1_len), VAL_OR_0 (cea608_field2_len));
-
- return i * 3;
-}
-
-static void
-store_cc_data (GstCCConverter * self, const guint8 * ccp_data,
- guint ccp_data_len, const guint8 * cea608_1, guint cea608_1_len,
- const guint8 * cea608_2, guint cea608_2_len)
-{
- GST_TRACE_OBJECT (self, "attempting to hold data of len ccp:%u, cea608 1:%u, "
- "cea608 2:%u until next output buffer", ccp_data_len, cea608_1_len,
- cea608_2_len);
-
- if (ccp_data && ccp_data_len > 0) {
- if (ccp_data_len > sizeof (self->scratch_ccp)) {
- GST_ELEMENT_WARNING (self, STREAM, DECODE,
- ("Closed Caption internal buffer overun. Dropping data"),
- ("CCP scratch buffer requires space for %u bytes but only %"
- G_GSIZE_FORMAT " bytes are available", ccp_data_len,
- sizeof (self->scratch_ccp)));
- self->scratch_ccp_len = 0;
- } else {
- memcpy (self->scratch_ccp, ccp_data, ccp_data_len);
- self->scratch_ccp_len = ccp_data_len;
- }
- } else {
- self->scratch_ccp_len = 0;
- }
- g_assert_cmpint (self->scratch_ccp_len, <=, sizeof (self->scratch_ccp));
-
- if (cea608_1 && cea608_1_len > 0) {
- if (cea608_1_len > sizeof (self->scratch_cea608_1)) {
- GST_ELEMENT_WARNING (self, STREAM, DECODE,
- ("Closed Caption internal buffer overun. Dropping data"),
- ("CEA608 field 1 scratch buffer requires space for %u bytes but "
- "only %" G_GSIZE_FORMAT " bytes are available", cea608_1_len,
- sizeof (self->scratch_cea608_1_len)));
- self->scratch_cea608_1_len = 0;
- } else {
- memcpy (self->scratch_cea608_1, cea608_1, cea608_1_len);
- self->scratch_cea608_1_len = cea608_1_len;
- }
- } else {
- self->scratch_cea608_1_len = 0;
- }
- g_assert_cmpint (self->scratch_cea608_1_len, <=,
- sizeof (self->scratch_cea608_1));
-
- if (cea608_2 && cea608_2_len > 0) {
- if (cea608_2_len > sizeof (self->scratch_cea608_2)) {
- GST_ELEMENT_WARNING (self, STREAM, DECODE,
- ("Closed Caption internal buffer overun. Dropping data"),
- ("CEA608 field 2 scratch buffer requires space for %u bytes but "
- "only %" G_GSIZE_FORMAT " bytes are available", cea608_2_len,
- sizeof (self->scratch_cea608_2_len)));
- self->scratch_cea608_2_len = 0;
- } else {
- memcpy (self->scratch_cea608_2, cea608_2, cea608_2_len);
- self->scratch_cea608_2_len = cea608_2_len;
- }
- } else {
- self->scratch_cea608_2_len = 0;
- }
- g_assert_cmpint (self->scratch_cea608_2_len, <=,
- sizeof (self->scratch_cea608_2));
-
- GST_DEBUG_OBJECT (self, "holding data of len ccp:%u, cea608 1:%u, "
- "cea608 2:%u until next output buffer", self->scratch_ccp_len,
- self->scratch_cea608_1_len, self->scratch_cea608_2_len);
-}
-
static gboolean
-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, gboolean * is_last_cea608_field1)
+can_take_buffer (GstCCConverter * self,
+ const struct cdp_fps_entry *in_fps_entry,
+ const struct cdp_fps_entry *out_fps_entry,
+ const GstVideoTimeCode * in_tc, GstVideoTimeCode * out_tc)
{
- 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_1 || cea608_1_len % 2 == 0);
- 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
- /* FIXME: if cea608 field 2 is generated, field 1 needs to be generated,
- * However that is not possible for 60fps (where only one cea608 field fits)
- * without adding previous output buffer tracking */
- g_assert_cmpint (cea608_1_len >= cea608_2_len);
-#endif
- g_assert_cmpint (cea608_1_len + cea608_2_len, <=,
- out_fps_entry->max_cea608_count);
+ int input_frame_n, input_frame_d, output_frame_n, output_frame_d;
+ int output_time_cmp, scale_n, scale_d;
-#if 0
- /* FIXME: if cea608 field 2 is generated, field 1 needs to be generated. */
- if (cea608_1_len < cea608_2_len)
- total_cea608_1_count += cea608_2_len - cea608_1_len;
-#endif
+ /* TODO: handle input discont */
- if (pad_cea608) {
- max_size = out_fps_entry->max_cea608_count * 3;
+ if (self->in_fps_n == 0) {
+ input_frame_n = self->input_frames;
+ input_frame_d = 1;
} else {
- 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",
- *out_size, max_size);
- return FALSE;
- }
-
- /* 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) {
- 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++;
- } 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",
- total_cea608_1_count, total_cea608_2_count);
- 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 (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++] = 0xfd;
- out[out_i++] = cea608_2[cea608_2_i * 2];
- 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;
+ /* compute the relative frame count for each */
+ if (!gst_util_fraction_multiply (self->in_fps_d, self->in_fps_n,
+ self->input_frames, 1, &input_frame_n, &input_frame_d))
+ /* we should never overflow */
+ g_assert_not_reached ();
}
- 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;
-}
-
-static gboolean
-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,
- gboolean * last_cea608_is_field1)
-{
- guint out_i = 0, max_size = 0;
- guint cea608_size = *out_size;
-
- g_assert (out);
- g_assert (out_size);
- g_assert (!ccp_data || ccp_data_len % 3 == 0);
-
- 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, last_cea608_is_field1))
- return FALSE;
+ if (self->in_fps_n == 0) {
+ output_frame_n = self->output_frames;
+ output_frame_d = 1;
} else {
- cea608_size = 0;
- }
-
- max_size = ccp_data_len + cea608_size;
- if (*out_size < max_size) {
- GST_WARNING_OBJECT (self, "Output data too small (%u < %u)", *out_size,
- max_size);
- return FALSE;
- }
-
- *out_size = cea608_size;
- out_i = cea608_size;
- if (ccp_data) {
- memcpy (&out[out_i], ccp_data, ccp_data_len);
- *out_size += ccp_data_len;
- }
-
- g_assert_cmpint (*out_size, <, MAX_CDP_PACKET_LEN);
-
- return TRUE;
-}
-
-/* takes cc_data cea608_1, cea608_2 and attempts to fit it into a hypothetical
- * output packet. Any leftover data is stored for later addition. Returns
- * whether any output can be generated. @ccp_data_len, @cea608_1_len,
- * @cea608_2_len are also updated to reflect the size of that data to add to
- * the output packet */
-static gboolean
-fit_and_scale_cc_data (GstCCConverter * self,
- 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,
- 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);
- if (!in_fps_entry || in_fps_entry->fps_n == 0)
+ if (!gst_util_fraction_multiply (self->out_fps_d, self->out_fps_n,
+ self->output_frames, 1, &output_frame_n, &output_frame_d))
+ /* we should never overflow */
g_assert_not_reached ();
}
- /* This is slightly looser than checking for the exact framerate as the cdp
- * spec allow for 0.1% difference between framerates to be considered equal */
- {
- int input_frame_n, input_frame_d, output_frame_n, output_frame_d;
- int output_time_cmp, scale_n, scale_d;
-
- /* TODO: handle input discont */
-
- if (self->in_fps_n == 0) {
- input_frame_n = self->input_frames;
- input_frame_d = 1;
- } else {
- /* compute the relative frame count for each */
- if (!gst_util_fraction_multiply (self->in_fps_d, self->in_fps_n,
- self->input_frames, 1, &input_frame_n, &input_frame_d))
- /* we should never overflow */
- g_assert_not_reached ();
- }
-
- if (self->in_fps_n == 0) {
- output_frame_n = self->output_frames;
- output_frame_d = 1;
- } else {
- if (!gst_util_fraction_multiply (self->out_fps_d, self->out_fps_n,
- self->output_frames, 1, &output_frame_n, &output_frame_d))
- /* we should never overflow */
- g_assert_not_reached ();
- }
-
- output_time_cmp = gst_util_fraction_compare (input_frame_n, input_frame_d,
- output_frame_n, output_frame_d);
-
- /* compute the relative rates of the two framerates */
- get_framerate_output_scale (self, in_fps_entry, &scale_n, &scale_d);
-
- GST_TRACE_OBJECT (self, "performing conversion at scale %d/%d "
- "of cc data of with sizes, ccp:%u, cea608-1:%u, cea608-2:%u", scale_n,
- scale_d, VAL_OR_0 (ccp_data_len), VAL_OR_0 (cea608_1_len),
- VAL_OR_0 (cea608_2_len));
-
- if (output_time_cmp < 0) {
- /* we can't generate an output yet */
- guint cd_len = ccp_data_len ? *ccp_data_len : 0;
- guint c1_len = cea608_1_len ? *cea608_1_len : 0;
- guint c2_len = cea608_2_len ? *cea608_2_len : 0;
-
- store_cc_data (self, ccp_data, cd_len, cea608_1, c1_len, cea608_2,
- c2_len);
- if (ccp_data_len)
- *ccp_data_len = 0;
- if (cea608_1_len)
- *cea608_1_len = 0;
- if (cea608_2_len)
- *cea608_2_len = 0;
- return FALSE;
- } else {
- /* we are changing the framerate and may overflow the max output packet
- * 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
- * overflow. Anything that fits into the output packet will be written */
- GST_LOG_OBJECT (self, "cycle completed, resetting frame counters");
- self->scratch_ccp_len = 0;
- self->scratch_cea608_1_len = 0;
- self->scratch_cea608_2_len = 0;
- self->input_frames = 0;
- self->output_frames = 0;
- }
-
- if (ccp_data_len) {
- extra_ccp = *ccp_data_len - 3 * out_fps_entry->max_ccp_count;
- extra_ccp = MAX (0, extra_ccp);
- ccp_off = *ccp_data_len - extra_ccp;
- }
-
- 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) {
- gint avail_1, avail_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 + field2_padding >=
- 2 * out_fps_entry->max_cea608_count)
- break;
-
- if (wrote_first && extra_cea608_1 > 0) {
- extra_cea608_1 -= 2;
- g_assert_cmpint (extra_cea608_1, >=, 0);
- cea608_1_off += 2;
- g_assert_cmpint (cea608_1_off, <=, *cea608_1_len);
- }
+ output_time_cmp = gst_util_fraction_compare (input_frame_n, input_frame_d,
+ output_frame_n, output_frame_d);
- 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 + field2_padding >=
- 2 * out_fps_entry->max_cea608_count)
- break;
+ in_fps_entry = cdp_fps_entry_from_fps (self->in_fps_n, self->in_fps_d);
+ if (!in_fps_entry || in_fps_entry->fps_n == 0)
+ g_assert_not_reached ();
- if (extra_cea608_2 > 0) {
- extra_cea608_2 -= 2;
- 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;
- }
+ /* compute the relative rates of the two framerates */
+ get_framerate_output_scale (self, in_fps_entry, &scale_n, &scale_d);
- 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, "
- "%u cea608 field 1 bytes, or %u cea608 field 2 bytes", extra_ccp,
- extra_cea608_1, extra_cea608_2);
- store_cc_data (self, &ccp_data[ccp_off], extra_ccp,
- &cea608_1[cea608_1_off], extra_cea608_1, &cea608_2[cea608_2_off],
- extra_cea608_2);
- if (ccp_data_len)
- *ccp_data_len = MIN (*ccp_data_len, ccp_off);
- if (cea608_1_len)
- *cea608_1_len = MIN (*cea608_1_len, cea608_1_off);
- if (cea608_2_len)
- *cea608_2_len = MIN (*cea608_2_len, cea608_2_off);
- } else {
- GST_DEBUG_OBJECT (self, "section sizes of %u ccp bytes, "
- "%u cea608 field 1 bytes, and %u cea608 field 2 bytes fit within "
- "output packet", VAL_OR_0 (ccp_data_len), VAL_OR_0 (cea608_1_len),
- VAL_OR_0 (cea608_2_len));
- self->scratch_ccp_len = 0;
- self->scratch_cea608_1_len = 0;
- self->scratch_cea608_2_len = 0;
- }
- }
+ GST_TRACE_OBJECT (self, "performing conversion at scale %d/%d, "
+ "time comparison %i", scale_n, scale_d, output_time_cmp);
- if (tc && tc->config.fps_n != 0)
- interpolate_time_code_with_framerate (self, tc, out_fps_entry->fps_n,
- out_fps_entry->fps_d, scale_n, scale_d,
- &self->current_output_timecode);
+ if (output_time_cmp < 0) {
+ /* we can't generate an output yet */
+ return FALSE;
+ } else {
+ interpolate_time_code_with_framerate (self, in_tc, out_fps_entry->fps_n,
+ out_fps_entry->fps_d, scale_n, scale_d, out_tc);
+ return TRUE;
}
-
- g_assert_cmpint (VAL_OR_0 (ccp_data_len) + (VAL_OR_0 (cea608_1_len) +
- VAL_OR_0 (cea608_2_len)) / 2 * 3, <=,
- 3 * out_fps_entry->max_cc_count);
-
- GST_DEBUG_OBJECT (self, "write out packet with lengths ccp:%u, cea608-1:%u, "
- "cea608-2:%u", VAL_OR_0 (ccp_data_len), VAL_OR_0 (cea608_1_len),
- VAL_OR_0 (cea608_2_len));
-
- return TRUE;
}
static guint
}
static gboolean
-copy_from_stored_data (GstCCConverter * self, guint8 * out_ccp,
- guint * ccp_size, guint8 * cea608_1, guint * cea608_1_len,
- guint8 * cea608_2, guint * cea608_2_len)
-{
- guint ccp_in_size = 0, cea608_1_in_size = 0, cea608_2_in_size = 0;
-
- g_assert ((out_ccp && ccp_size) || (!out_ccp && !ccp_size));
- g_assert ((cea608_1 && cea608_1_len) || (!cea608_1 && !cea608_1_len));
- g_assert ((cea608_2 && cea608_2_len) || (!cea608_2 && !cea608_2_len));
-
- if (ccp_size) {
- ccp_in_size = *ccp_size;
- *ccp_size = 0;
- }
- if (cea608_1_len) {
- cea608_1_in_size = *cea608_1_len;
- *cea608_1_len = 0;
- }
- if (cea608_2_len) {
- cea608_2_in_size = *cea608_2_len;
- *cea608_2_len = 0;
- }
-
- if (out_ccp && self->scratch_ccp_len > 0) {
- GST_DEBUG_OBJECT (self, "copying from previous scratch ccp buffer of "
- "%u bytes", self->scratch_ccp_len);
- if (ccp_in_size < *ccp_size + self->scratch_ccp_len) {
- GST_WARNING_OBJECT (self, "output buffer too small %u < %u", ccp_in_size,
- *ccp_size + self->scratch_ccp_len);
- goto fail;
- }
- memcpy (&out_ccp[*ccp_size], self->scratch_ccp, self->scratch_ccp_len);
- *ccp_size += self->scratch_ccp_len;
- }
-
- if (cea608_1 && self->scratch_cea608_1_len > 0) {
- GST_DEBUG_OBJECT (self, "copying from previous scratch cea608 field 1 "
- "buffer of %u bytes", self->scratch_cea608_1_len);
- if (cea608_1_in_size < *cea608_1_len + self->scratch_cea608_1_len) {
- GST_WARNING_OBJECT (self, "output buffer too small %u < %u",
- cea608_1_in_size, *cea608_1_len + self->scratch_cea608_1_len);
- goto fail;
- }
- memcpy (&cea608_1[*cea608_1_len], self->scratch_cea608_1,
- self->scratch_cea608_1_len);
- *cea608_1_len += self->scratch_cea608_1_len;
- }
-
- if (cea608_2 && self->scratch_cea608_2_len > 0) {
- GST_DEBUG_OBJECT (self, "copying from previous scratch cea608 field 2 "
- "buffer of %u bytes", self->scratch_cea608_2_len);
- if (cea608_2_in_size < *cea608_2_len + self->scratch_cea608_2_len) {
- GST_WARNING_OBJECT (self, "output buffer too small %u < %u",
- cea608_2_in_size, *cea608_2_len + self->scratch_cea608_2_len);
- goto fail;
- }
- memcpy (&cea608_2[*cea608_2_len], self->scratch_cea608_2,
- self->scratch_cea608_2_len);
- *cea608_2_len += self->scratch_cea608_2_len;
- }
-
- return TRUE;
-
-fail:
- if (ccp_size)
- *ccp_size = 0;
- if (cea608_1_len)
- *cea608_1_len = 0;
- if (cea608_2_len)
- *cea608_2_len = 0;
- return FALSE;
-}
-
-static gboolean
-cc_data_to_cea608_ccp (GstCCConverter * self, guint8 * cc_data,
- guint cc_data_len, guint8 * out_ccp, guint * ccp_size, guint8 * cea608_1,
- guint * cea608_1_len, guint8 * cea608_2, guint * cea608_2_len,
- const struct cdp_fps_entry *in_fps_entry)
-{
- guint ccp_in_size = 0, cea608_1_in_size = 0, cea608_2_in_size = 0;
-
- g_assert (cc_data || cc_data_len == 0);
-
- if (ccp_size)
- ccp_in_size = *ccp_size;
- if (cea608_1_len)
- cea608_1_in_size = *cea608_1_len;
- if (cea608_2_len)
- cea608_2_in_size = *cea608_2_len;
-
- if (!copy_from_stored_data (self, out_ccp, ccp_size, cea608_1, cea608_1_len,
- cea608_2, cea608_2_len))
- goto fail;
-
- if (cc_data) {
- gint ccp_offset = 0;
- guint new_cea608_1_len = 0, new_cea608_2_len = 0;
- guint8 *new_cea608_1 = cea608_1, *new_cea608_2 = cea608_2;
-
- cc_data_len = compact_cc_data (cc_data, cc_data_len);
-
- if (cc_data_len / 3 > in_fps_entry->max_cc_count) {
- GST_WARNING_OBJECT (self, "Too many cc_data triples in CDP packet %u. "
- "Truncating to %u", cc_data_len / 3, in_fps_entry->max_cc_count);
- cc_data_len = 3 * in_fps_entry->max_cc_count;
- }
-
- while (TRUE) {
- if (cea608_1_len) {
- new_cea608_1_len = cea608_1_in_size - *cea608_1_len;
- new_cea608_1 = &cea608_1[*cea608_1_len];
- }
- if (cea608_2_len) {
- new_cea608_2_len = cea608_2_in_size - *cea608_2_len;
- new_cea608_2 = &cea608_2[*cea608_2_len];
- }
-
- ccp_offset = cc_data_extract_cea608 (cc_data, cc_data_len, new_cea608_1,
- &new_cea608_1_len, new_cea608_2, &new_cea608_2_len);
-
- if (ccp_offset == CC_DATA_EXTRACT_TOO_MANY_FIELD1 && cea608_1_len) {
- GST_WARNING_OBJECT (self, "cea608 field 1 overflow, dropping all "
- "previously stored field 1 data and trying again");
- *cea608_1_len = 0;
- } else if (ccp_offset == CC_DATA_EXTRACT_TOO_MANY_FIELD2 && cea608_2_len) {
- GST_WARNING_OBJECT (self, "cea608 field 2 overflow, dropping all "
- "previously stored field 2 data and trying again");
- *cea608_2_len = 0;
- } else if (ccp_offset < 0) {
- GST_WARNING_OBJECT (self, "Failed to extract cea608 from cc_data");
- goto fail;
- } else {
- /* success */
- break;
- }
- }
-
- if ((new_cea608_1_len + new_cea608_2_len) / 2 >
- in_fps_entry->max_cea608_count) {
- GST_WARNING_OBJECT (self, "Too many cea608 triples in CDP packet %u. "
- "Truncating to %u", (new_cea608_1_len + new_cea608_2_len) / 2,
- in_fps_entry->max_cea608_count);
- if ((new_cea608_1_len + new_cea608_2_len) / 2 >
- in_fps_entry->max_cea608_count) {
- new_cea608_1_len = 2 * in_fps_entry->max_cea608_count;
- new_cea608_2_len = 0;
- } else {
- new_cea608_2_len =
- 2 * in_fps_entry->max_cea608_count - new_cea608_1_len;
- }
- }
-
- if (cea608_1_len)
- *cea608_1_len += new_cea608_1_len;
- if (cea608_2_len)
- *cea608_2_len += new_cea608_2_len;
-
- if (out_ccp) {
- if (ccp_in_size < *ccp_size + cc_data_len - ccp_offset) {
- GST_WARNING_OBJECT (self, "output buffer too small %u < %u",
- ccp_in_size, *ccp_size + cc_data_len - ccp_offset);
- goto fail;
- }
- memcpy (&out_ccp[*ccp_size], &cc_data[ccp_offset],
- cc_data_len - ccp_offset);
- *ccp_size += cc_data_len - ccp_offset;
- }
- }
-
- return TRUE;
-
-fail:
- if (ccp_size)
- *ccp_size = 0;
- if (cea608_1_len)
- *cea608_1_len = 0;
- if (cea608_2_len)
- *cea608_2_len = 0;
- return FALSE;
-}
-
-static gboolean
-cdp_to_cea608_cc_data (GstCCConverter * self, GstBuffer * inbuf,
- guint8 * out_ccp, guint * ccp_size, guint8 * cea608_1, guint * cea608_1_len,
- guint8 * cea608_2, guint * cea608_2_len, GstVideoTimeCode * out_tc,
- const struct cdp_fps_entry **in_fps_entry)
+push_cdp_buffer (GstCCConverter * self, GstBuffer * inbuf,
+ GstVideoTimeCode * out_tc, const struct cdp_fps_entry **in_fps_entry)
{
guint8 cc_data[MAX_CDP_PACKET_LEN];
guint cc_data_len = 0;
convert_cea708_cdp_to_cc_data (GST_OBJECT (self), in.data, in.size,
cc_data, out_tc, in_fps_entry);
+ cc_buffer_push_cc_data (self->cc_buffer, cc_data, cc_data_len);
+
gst_buffer_unmap (inbuf, &in);
self->input_frames++;
}
- return cc_data_to_cea608_ccp (self, inbuf ? cc_data : NULL, cc_data_len,
- out_ccp, ccp_size, cea608_1, cea608_1_len, cea608_2, cea608_2_len,
- inbuf ? *in_fps_entry : NULL);
+ return TRUE;
}
static GstFlowReturn
GstMapInfo in, out;
const struct cdp_fps_entry *in_fps_entry, *out_fps_entry;
guint cc_data_len = MAX_CDP_PACKET_LEN;
- guint cea608_1_len = MAX_CDP_PACKET_LEN;
- guint8 cc_data[MAX_CDP_PACKET_LEN], cea608_1[MAX_CEA608_LEN];
+ guint8 cc_data[MAX_CDP_PACKET_LEN];
in_fps_entry = cdp_fps_entry_from_fps (self->in_fps_n, self->in_fps_d);
if (!in_fps_entry || in_fps_entry->fps_n == 0)
g_assert_not_reached ();
- if (!copy_from_stored_data (self, NULL, 0, cea608_1, &cea608_1_len, NULL, 0))
- goto drop;
-
if (inbuf) {
- guint n = 0, i;
+ guint n = 0;
n = gst_buffer_get_size (inbuf);
if (n & 1) {
}
gst_buffer_map (inbuf, &in, GST_MAP_READ);
- for (i = 0; i < n; i++) {
- guint byte1 = in.data[i * 2 + 0];
- guint byte2 = in.data[i * 2 + 1];
- if (byte1 != 0x80 || byte2 != 0x80) {
- cea608_1[cea608_1_len++] = byte1;
- cea608_1[cea608_1_len++] = byte2;
- }
- }
+ cc_buffer_push_separated (self->cc_buffer, in.data, in.size, NULL, 0, NULL,
+ 0);
gst_buffer_unmap (inbuf, &in);
self->input_frames++;
}
if (!out_fps_entry || out_fps_entry->fps_n == 0)
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,
- FALSE))
+ if (!can_take_buffer (self, in_fps_entry, out_fps_entry,
+ tc_meta ? &tc_meta->tc : NULL, &self->current_output_timecode))
goto drop;
- if (!combine_cc_data (self, TRUE, out_fps_entry, NULL, 0, cea608_1,
- cea608_1_len, NULL, 0, cc_data, &cc_data_len,
- &self->last_cea608_written_was_field1))
- goto drop;
+ cc_buffer_take_cc_data (self->cc_buffer, out_fps_entry, cc_data,
+ &cc_data_len);
gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
cc_data_len =
GstMapInfo in, out;
const struct cdp_fps_entry *in_fps_entry, *out_fps_entry;
guint cc_data_len = MAX_CDP_PACKET_LEN;
- guint cea608_1_len = MAX_CDP_PACKET_LEN, cea608_2_len = MAX_CDP_PACKET_LEN;
+ guint cea608_1_len = 0, cea608_2_len = 0;
guint8 cc_data[MAX_CDP_PACKET_LEN];
guint8 cea608_1[MAX_CEA608_LEN], cea608_2[MAX_CEA608_LEN];
guint i, n;
if (!in_fps_entry || in_fps_entry->fps_n == 0)
g_assert_not_reached ();
- if (!copy_from_stored_data (self, NULL, 0, cea608_1, &cea608_1_len,
- cea608_2, &cea608_2_len))
- goto drop;
-
if (inbuf) {
n = gst_buffer_get_size (inbuf);
if (n % 3 != 0) {
}
}
gst_buffer_unmap (inbuf, &in);
+
+ cc_buffer_push_separated (self->cc_buffer, cea608_1, cea608_1_len,
+ cea608_2, cea608_2_len, NULL, 0);
self->input_frames++;
}
if (!out_fps_entry || out_fps_entry->fps_n == 0)
g_assert_not_reached ();
- 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,
- self->last_cea608_written_was_field1)) {
+ if (!can_take_buffer (self, in_fps_entry, out_fps_entry,
+ tc_meta ? &tc_meta->tc : NULL, &self->current_output_timecode))
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,
- &self->last_cea608_written_was_field1)) {
- goto drop;
- }
+ cc_buffer_take_cc_data (self->cc_buffer, out_fps_entry, cc_data,
+ &cc_data_len);
gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
cc_data_len =
GstMapInfo in, out;
const struct cdp_fps_entry *in_fps_entry, *out_fps_entry;
guint in_cc_data_len;
- guint cc_data_len = MAX_CDP_PACKET_LEN, ccp_data_len = MAX_CDP_PACKET_LEN;
- guint cea608_1_len = MAX_CEA608_LEN, cea608_2_len = MAX_CEA608_LEN;
- guint8 cc_data[MAX_CDP_PACKET_LEN], ccp_data[MAX_CDP_PACKET_LEN];
- guint8 cea608_1[MAX_CEA608_LEN], cea608_2[MAX_CEA608_LEN];
+ guint cc_data_len = MAX_CDP_PACKET_LEN;
+ guint8 cc_data[MAX_CDP_PACKET_LEN];
guint8 *in_cc_data;
if (inbuf) {
if (!out_fps_entry || out_fps_entry->fps_n == 0)
g_assert_not_reached ();
- if (!cc_data_to_cea608_ccp (self, in_cc_data, in_cc_data_len, ccp_data,
- &ccp_data_len, cea608_1, &cea608_1_len, cea608_2, &cea608_2_len,
- in_fps_entry)) {
- if (inbuf)
- gst_buffer_unmap (inbuf, &in);
- goto drop;
- }
-
+ cc_buffer_push_cc_data (self->cc_buffer, in_cc_data, in_cc_data_len);
if (inbuf)
gst_buffer_unmap (inbuf, &in);
- 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, self->last_cea608_written_was_field1))
+ if (!can_take_buffer (self, in_fps_entry, out_fps_entry,
+ tc_meta ? &tc_meta->tc : NULL, &self->current_output_timecode))
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, &self->last_cea608_written_was_field1))
- goto drop;
+ cc_buffer_take_cc_data (self->cc_buffer, out_fps_entry, cc_data,
+ &cc_data_len);
gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
cc_data_len =
{
GstMapInfo out;
GstVideoTimeCode tc = GST_VIDEO_TIME_CODE_INIT;
- guint8 cea608_1[MAX_CEA608_LEN];
- guint cea608_1_len = MAX_CEA608_LEN;
+ guint cea608_1_len;
const struct cdp_fps_entry *in_fps_entry = NULL, *out_fps_entry;
- gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
- if (!cdp_to_cea608_cc_data (self, inbuf, NULL, NULL, cea608_1, &cea608_1_len,
- NULL, NULL, &tc, &in_fps_entry)) {
+ if (!push_cdp_buffer (self, inbuf, &tc, &in_fps_entry)) {
gst_buffer_set_size (outbuf, 0);
return GST_FLOW_OK;
}
if (!out_fps_entry || out_fps_entry->fps_n == 0)
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, 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, NULL)) {
- gst_buffer_unmap (outbuf, &out);
- return GST_FLOW_ERROR;
- }
+ if (!can_take_buffer (self, in_fps_entry, out_fps_entry, &tc,
+ &self->current_output_timecode))
+ goto drop;
- /* remove the first byte from each cea608 packet */
- for (i = 0; i < out_size / 3; i++) {
- out.data[i * 2 + 0] = out.data[i * 3 + 1];
- out.data[i * 2 + 1] = out.data[i * 3 + 2];
- }
- cea608_1_len = out_size / 3 * 2;
- } else {
- cea608_1_len = 0;
- }
+ gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
+ cea608_1_len = out.size;
+ cc_buffer_take_separated (self->cc_buffer, out_fps_entry, out.data,
+ &cea608_1_len, NULL, 0, NULL, 0);
gst_buffer_unmap (outbuf, &out);
-
- gst_buffer_set_size (outbuf, cea608_1_len);
+ self->output_frames++;
if (self->current_output_timecode.config.fps_n != 0 && !tc_meta) {
gst_buffer_add_video_time_code_meta (outbuf,
gst_video_time_code_increment_frame (&self->current_output_timecode);
}
+out:
+ gst_buffer_set_size (outbuf, cea608_1_len);
return GST_FLOW_OK;
+
+drop:
+ cea608_1_len = 0;
+ goto out;
}
static GstFlowReturn
GstMapInfo out;
GstVideoTimeCode tc = GST_VIDEO_TIME_CODE_INIT;
const struct cdp_fps_entry *in_fps_entry = NULL, *out_fps_entry;
- guint8 cea608_1[MAX_CEA608_LEN], cea608_2[MAX_CEA608_LEN];
- guint cea608_1_len = MAX_CEA608_LEN, cea608_2_len = MAX_CEA608_LEN;
- guint i, cc_data_len;
+ guint cc_data_len;
+ int s334_len;
+ guint i;
- if (!cdp_to_cea608_cc_data (self, inbuf, NULL, NULL, cea608_1, &cea608_1_len,
- cea608_2, &cea608_2_len, &tc, &in_fps_entry))
+ if (!push_cdp_buffer (self, inbuf, &tc, &in_fps_entry))
goto drop;
out_fps_entry = cdp_fps_entry_from_fps (self->out_fps_n, self->out_fps_d);
if (!out_fps_entry || out_fps_entry->fps_n == 0)
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,
- self->last_cea608_written_was_field1))
+ if (!can_take_buffer (self, in_fps_entry, out_fps_entry, &tc,
+ &self->current_output_timecode))
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,
- &self->last_cea608_written_was_field1)) {
- gst_buffer_unmap (outbuf, &out);
+
+ cc_data_len = out.size;
+ cc_buffer_take_cc_data (self->cc_buffer, out_fps_entry, out.data,
+ &cc_data_len);
+ s334_len = drop_ccp_from_cc_data (out.data, cc_data_len);
+ if (s334_len < 0)
goto drop;
- }
- for (i = 0; i < cc_data_len / 3; i++) {
+ for (i = 0; i < s334_len / 3; i++) {
guint byte = out.data[i * 3];
/* We have to assume a line offset of 0 */
out.data[i * 3] = (byte == 0xfc || byte == 0xf8) ? 0x80 : 0x00;
gst_buffer_unmap (outbuf, &out);
self->output_frames++;
- gst_buffer_set_size (outbuf, cc_data_len);
+ gst_buffer_set_size (outbuf, s334_len);
if (self->current_output_timecode.config.fps_n != 0 && !tc_meta) {
gst_buffer_add_video_time_code_meta (outbuf,
GstMapInfo out;
GstVideoTimeCode tc = GST_VIDEO_TIME_CODE_INIT;
const struct cdp_fps_entry *in_fps_entry = NULL, *out_fps_entry;
- guint8 cea608_1[MAX_CEA608_LEN], cea608_2[MAX_CEA608_LEN];
- guint8 ccp_data[MAX_CDP_PACKET_LEN];
- guint cea608_1_len = MAX_CEA608_LEN, cea608_2_len = MAX_CEA608_LEN;
- guint ccp_data_len = MAX_CDP_PACKET_LEN;
guint out_len = 0;
- if (!cdp_to_cea608_cc_data (self, inbuf, ccp_data, &ccp_data_len,
- cea608_1, &cea608_1_len, cea608_2, &cea608_2_len, &tc, &in_fps_entry))
+ if (!push_cdp_buffer (self, inbuf, &tc, &in_fps_entry))
goto out;
out_fps_entry = cdp_fps_entry_from_fps (self->out_fps_n, self->out_fps_d);
if (!out_fps_entry || out_fps_entry->fps_n == 0)
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,
- self->last_cea608_written_was_field1))
+ if (!can_take_buffer (self, in_fps_entry, out_fps_entry, &tc,
+ &self->current_output_timecode))
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,
- &self->last_cea608_written_was_field1)) {
- gst_buffer_unmap (outbuf, &out);
- out_len = 0;
- goto out;
- }
+ cc_buffer_take_cc_data (self->cc_buffer, out_fps_entry, out.data, &out_len);
gst_buffer_unmap (outbuf, &out);
self->output_frames++;
GstMapInfo out;
GstVideoTimeCode tc = GST_VIDEO_TIME_CODE_INIT;
const struct cdp_fps_entry *in_fps_entry = NULL, *out_fps_entry;
- guint8 cea608_1[MAX_CEA608_LEN], cea608_2[MAX_CEA608_LEN];
- guint8 ccp_data[MAX_CDP_PACKET_LEN], cc_data[MAX_CDP_PACKET_LEN];
- guint cea608_1_len = MAX_CEA608_LEN, cea608_2_len = MAX_CEA608_LEN;
- guint ccp_data_len = MAX_CDP_PACKET_LEN, cc_data_len = MAX_CDP_PACKET_LEN;
+ guint8 cc_data[MAX_CDP_PACKET_LEN];
+ guint cc_data_len = MAX_CDP_PACKET_LEN;
guint out_len = 0;
- if (!cdp_to_cea608_cc_data (self, inbuf, ccp_data, &ccp_data_len,
- cea608_1, &cea608_1_len, cea608_2, &cea608_2_len, &tc, &in_fps_entry))
+ if (!push_cdp_buffer (self, inbuf, &tc, &in_fps_entry))
goto out;
out_fps_entry = cdp_fps_entry_from_fps (self->out_fps_n, self->out_fps_d);
if (!out_fps_entry || out_fps_entry->fps_n == 0)
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,
- self->last_cea608_written_was_field1))
+ if (!can_take_buffer (self, in_fps_entry, out_fps_entry, &tc,
+ &self->current_output_timecode))
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, &self->last_cea608_written_was_field1)) {
- goto out;
- }
+ cc_buffer_take_cc_data (self->cc_buffer, out_fps_entry, cc_data,
+ &cc_data_len);
gst_buffer_map (outbuf, &out, GST_MAP_WRITE);
out_len =
static void
reset_counters (GstCCConverter * self)
{
- self->scratch_ccp_len = 0;
- self->scratch_cea608_1_len = 0;
- self->scratch_cea608_2_len = 0;
self->input_frames = 0;
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;
+ cc_buffer_discard (self->cc_buffer);
}
static GstFlowReturn
GstBaseTransformClass *bclass = GST_BASE_TRANSFORM_GET_CLASS (self);
GstBaseTransform *trans = GST_BASE_TRANSFORM (self);
GstFlowReturn ret = GST_FLOW_OK;
+ guint cea608_1_len, cea608_2_len, ccp_len;
+
+ cc_buffer_get_stored_size (self->cc_buffer, &cea608_1_len, &cea608_2_len,
+ &ccp_len);
- while (self->scratch_ccp_len > 0 || self->scratch_cea608_1_len > 0
- || self->scratch_cea608_2_len > 0 || can_generate_output (self)) {
+ while (ccp_len > 0 || cea608_1_len > 0 || cea608_2_len > 0
+ || can_generate_output (self)) {
GstBuffer *outbuf;
if (!self->previous_buffer) {
}
ret = gst_cc_converter_transform (self, NULL, outbuf);
+ cc_buffer_get_stored_size (self->cc_buffer, &cea608_1_len, &cea608_2_len,
+ &ccp_len);
if (gst_buffer_get_size (outbuf) <= 0) {
/* try to move the output along */
self->input_frames++;
}
static void
+gst_cc_converter_finalize (GObject * object)
+{
+ GstCCConverter *self = GST_CCCONVERTER (object);
+
+ gst_clear_object (&self->cc_buffer);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
gst_cc_converter_class_init (GstCCConverterClass * klass)
{
GObjectClass *gobject_class;
gobject_class->set_property = gst_cc_converter_set_property;
gobject_class->get_property = gst_cc_converter_get_property;
+ gobject_class->finalize = gst_cc_converter_finalize;
/**
* GstCCConverter:cdp-mode
gst_cc_converter_init (GstCCConverter * self)
{
self->cdp_mode = DEFAULT_CDP_MODE;
+ self->cc_buffer = cc_buffer_new ();
}