return len;
}
+
+/* Converts CDP into raw CEA708 cc_data */
+guint
+convert_cea708_cdp_to_cc_data (GstObject * dbg_obj,
+ const guint8 * cdp, guint cdp_len, guint8 * cc_data,
+ GstVideoTimeCode * tc, const cdp_fps_entry ** out_fps_entry)
+{
+ GstByteReader br;
+ guint16 u16;
+ guint8 u8;
+ guint8 flags;
+ guint len = 0;
+ const struct cdp_fps_entry *fps_entry;
+
+ *out_fps_entry = &null_fps_entry;
+ memset (tc, 0, sizeof (*tc));
+
+ /* Header + footer length */
+ if (cdp_len < 11) {
+ GST_WARNING_OBJECT (dbg_obj, "cdp packet too short (%u). expected at "
+ "least %u", cdp_len, 11);
+ return 0;
+ }
+
+ gst_byte_reader_init (&br, cdp, cdp_len);
+ u16 = gst_byte_reader_get_uint16_be_unchecked (&br);
+ if (u16 != 0x9669) {
+ GST_WARNING_OBJECT (dbg_obj, "cdp packet does not have initial magic bytes "
+ "of 0x9669");
+ return 0;
+ }
+
+ u8 = gst_byte_reader_get_uint8_unchecked (&br);
+ if (u8 != cdp_len) {
+ GST_WARNING_OBJECT (dbg_obj, "cdp packet length (%u) does not match passed "
+ "in value (%u)", u8, cdp_len);
+ return 0;
+ }
+
+ u8 = gst_byte_reader_get_uint8_unchecked (&br);
+ fps_entry = cdp_fps_entry_from_id (u8);
+ if (!fps_entry || fps_entry->fps_n == 0) {
+ GST_WARNING_OBJECT (dbg_obj, "cdp packet does not have a valid framerate "
+ "id (0x%02x", u8);
+ return 0;
+ }
+
+ flags = gst_byte_reader_get_uint8_unchecked (&br);
+ /* No cc_data? */
+ if ((flags & 0x40) == 0) {
+ GST_DEBUG_OBJECT (dbg_obj, "cdp packet does have any cc_data");
+ return 0;
+ }
+
+ /* cdp_hdr_sequence_cntr */
+ gst_byte_reader_skip_unchecked (&br, 2);
+
+ /* time_code_present */
+ if (flags & 0x80) {
+ guint8 hours, minutes, seconds, frames, fields;
+ gboolean drop_frame;
+
+ if (gst_byte_reader_get_remaining (&br) < 5) {
+ GST_WARNING_OBJECT (dbg_obj, "cdp packet does not have enough data to "
+ "contain a timecode (%u). Need at least 5 bytes",
+ gst_byte_reader_get_remaining (&br));
+ return 0;
+ }
+ u8 = gst_byte_reader_get_uint8_unchecked (&br);
+ if (u8 != 0x71) {
+ GST_WARNING_OBJECT (dbg_obj, "cdp packet does not have timecode start "
+ "byte of 0x71, found 0x%02x", u8);
+ return 0;
+ }
+
+ u8 = gst_byte_reader_get_uint8_unchecked (&br);
+ if ((u8 & 0xc0) != 0xc0) {
+ GST_WARNING_OBJECT (dbg_obj, "reserved bits are not 0xc0, found 0x%02x",
+ u8);
+ return 0;
+ }
+
+ hours = ((u8 >> 4) & 0x3) * 10 + (u8 & 0xf);
+
+ u8 = gst_byte_reader_get_uint8_unchecked (&br);
+ if ((u8 & 0x80) != 0x80) {
+ GST_WARNING_OBJECT (dbg_obj, "reserved bit is not 0x80, found 0x%02x",
+ u8);
+ return 0;
+ }
+ minutes = ((u8 >> 4) & 0x7) * 10 + (u8 & 0xf);
+
+ u8 = gst_byte_reader_get_uint8_unchecked (&br);
+ if (u8 & 0x80)
+ fields = 2;
+ else
+ fields = 1;
+ seconds = ((u8 >> 4) & 0x7) * 10 + (u8 & 0xf);
+
+ u8 = gst_byte_reader_get_uint8_unchecked (&br);
+ if (u8 & 0x40) {
+ GST_WARNING_OBJECT (dbg_obj, "reserved bit is not 0x0, found 0x%02x", u8);
+ return 0;
+ }
+
+ drop_frame = !(!(u8 & 0x80));
+ frames = ((u8 >> 4) & 0x3) * 10 + (u8 & 0xf);
+
+ gst_video_time_code_init (tc, fps_entry->fps_n, fps_entry->fps_d, NULL,
+ drop_frame ? GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME :
+ GST_VIDEO_TIME_CODE_FLAGS_NONE, hours, minutes, seconds, frames,
+ fields);
+ }
+
+ /* ccdata_present */
+ if (flags & 0x40) {
+ guint8 cc_count;
+
+ if (gst_byte_reader_get_remaining (&br) < 2) {
+ GST_WARNING_OBJECT (dbg_obj, "not enough data to contain valid cc_data");
+ return 0;
+ }
+ u8 = gst_byte_reader_get_uint8_unchecked (&br);
+ if (u8 != 0x72) {
+ GST_WARNING_OBJECT (dbg_obj, "missing cc_data start code of 0x72, "
+ "found 0x%02x", u8);
+ return 0;
+ }
+
+ cc_count = gst_byte_reader_get_uint8_unchecked (&br);
+ if ((cc_count & 0xe0) != 0xe0) {
+ GST_WARNING_OBJECT (dbg_obj, "reserved bits are not 0xe0, found 0x%02x",
+ u8);
+ return 0;
+ }
+ cc_count &= 0x1f;
+
+ len = 3 * cc_count;
+ if (gst_byte_reader_get_remaining (&br) < len) {
+ GST_WARNING_OBJECT (dbg_obj, "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);
+ }
+
+ *out_fps_entry = fps_entry;
+
+ /* skip everything else we don't care about */
+ return len;
+}
const GstVideoTimeCode * tc,
const struct cdp_fps_entry *fps_entry);
+guint convert_cea708_cdp_to_cc_data (GstObject * dbg_obj,
+ const guint8 * cdp,
+ guint cdp_len,
+ guint8 *cc_data,
+ GstVideoTimeCode * tc,
+ const struct cdp_fps_entry **out_fps_entry);
+
+#define MAX_CDP_PACKET_LEN 256
+
G_END_DECLS
#endif
#define GST_FLOW_NEED_DATA GST_FLOW_CUSTOM_SUCCESS
-static const guint8 *
-extract_cdp (const guint8 * cdp, guint cdp_len, guint * cc_data_len)
+static guint
+extract_cdp (GstCCCombiner * self, const guint8 * cdp, guint cdp_len,
+ guint8 * cc_data)
{
- GstByteReader br;
- guint16 u16;
- guint8 u8;
- guint8 flags;
- guint len = 0;
- const guint8 *cc_data = NULL;
+ const struct cdp_fps_entry *out_fps_entry;
+ GstVideoTimeCode tc = GST_VIDEO_TIME_CODE_INIT;
- *cc_data_len = 0;
-
- /* Header + footer length */
- if (cdp_len < 11) {
- goto done;
- }
-
- gst_byte_reader_init (&br, cdp, cdp_len);
- u16 = gst_byte_reader_get_uint16_be_unchecked (&br);
- if (u16 != 0x9669) {
- goto done;
- }
-
- u8 = gst_byte_reader_get_uint8_unchecked (&br);
- if (u8 != cdp_len) {
- goto done;
- }
-
- gst_byte_reader_skip_unchecked (&br, 1);
-
- flags = gst_byte_reader_get_uint8_unchecked (&br);
-
- /* No cc_data? */
- if ((flags & 0x40) == 0) {
- goto done;
- }
-
- /* cdp_hdr_sequence_cntr */
- gst_byte_reader_skip_unchecked (&br, 2);
-
- /* time_code_present */
- if (flags & 0x80) {
- if (gst_byte_reader_get_remaining (&br) < 5) {
- goto done;
- }
- gst_byte_reader_skip_unchecked (&br, 5);
- }
-
- /* ccdata_present */
- if (flags & 0x40) {
- guint8 cc_count;
-
- if (gst_byte_reader_get_remaining (&br) < 2) {
- goto done;
- }
- u8 = gst_byte_reader_get_uint8_unchecked (&br);
- if (u8 != 0x72) {
- goto done;
- }
-
- cc_count = gst_byte_reader_get_uint8_unchecked (&br);
- if ((cc_count & 0xe0) != 0xe0) {
- goto done;
- }
- cc_count &= 0x1f;
-
- if (cc_count == 0)
- return 0;
-
- len = 3 * cc_count;
- if (gst_byte_reader_get_remaining (&br) < len)
- goto done;
-
- cc_data = gst_byte_reader_get_data_unchecked (&br, len);
- *cc_data_len = len;
- }
-
-done:
- return cc_data;
+ return convert_cea708_cdp_to_cc_data (GST_OBJECT (self), cdp, cdp_len,
+ cc_data, &tc, &out_fps_entry);
}
-#define MAX_CDP_PACKET_LEN 256
#define MAX_CEA608_LEN 32
#define CDP_MODE (GST_CC_CDP_MODE_CC_DATA | GST_CC_CDP_MODE_TIME_CODE)
schedule_cdp (GstCCCombiner * self, const GstVideoTimeCode * tc,
const guint8 * data, guint len, GstClockTime pts, GstClockTime duration)
{
- const guint8 *cc_data;
+ guint8 cc_data[MAX_CDP_PACKET_LEN];
guint cc_data_len;
gboolean inject = FALSE;
- if ((cc_data = extract_cdp (data, len, &cc_data_len))) {
+ cc_data_len = extract_cdp (self, data, len, cc_data);
+ if (cc_data_len > 0) {
guint8 i;
for (i = 0; i < cc_data_len / 3; i++) {
return ret;
}
-/* Converts CDP into raw CEA708 cc_data */
-static guint
-convert_cea708_cdp_cea708_cc_data_internal (GstCCConverter * self,
- const guint8 * cdp, guint cdp_len, guint8 cc_data[MAX_CDP_PACKET_LEN],
- GstVideoTimeCode * tc, const struct cdp_fps_entry **out_fps_entry)
-{
- GstByteReader br;
- guint16 u16;
- guint8 u8;
- guint8 flags;
- guint len = 0;
- const struct cdp_fps_entry *fps_entry;
-
- *out_fps_entry = &null_fps_entry;
- memset (tc, 0, sizeof (*tc));
-
- /* Header + footer length */
- if (cdp_len < 11) {
- GST_WARNING_OBJECT (self, "cdp packet too short (%u). expected at "
- "least %u", cdp_len, 11);
- return 0;
- }
-
- gst_byte_reader_init (&br, cdp, cdp_len);
- u16 = gst_byte_reader_get_uint16_be_unchecked (&br);
- if (u16 != 0x9669) {
- GST_WARNING_OBJECT (self, "cdp packet does not have initial magic bytes "
- "of 0x9669");
- return 0;
- }
-
- u8 = gst_byte_reader_get_uint8_unchecked (&br);
- if (u8 != cdp_len) {
- GST_WARNING_OBJECT (self, "cdp packet length (%u) does not match passed "
- "in value (%u)", u8, cdp_len);
- return 0;
- }
-
- u8 = gst_byte_reader_get_uint8_unchecked (&br);
- fps_entry = cdp_fps_entry_from_id (u8);
- if (!fps_entry || fps_entry->fps_n == 0) {
- GST_WARNING_OBJECT (self, "cdp packet does not have a valid framerate "
- "id (0x%02x", u8);
- return 0;
- }
-
- flags = gst_byte_reader_get_uint8_unchecked (&br);
- /* No cc_data? */
- if ((flags & 0x40) == 0) {
- GST_DEBUG_OBJECT (self, "cdp packet does have any cc_data");
- return 0;
- }
-
- /* cdp_hdr_sequence_cntr */
- gst_byte_reader_skip_unchecked (&br, 2);
-
- /* time_code_present */
- if (flags & 0x80) {
- guint8 hours, minutes, seconds, frames, fields;
- gboolean drop_frame;
-
- if (gst_byte_reader_get_remaining (&br) < 5) {
- GST_WARNING_OBJECT (self, "cdp packet does not have enough data to "
- "contain a timecode (%u). Need at least 5 bytes",
- gst_byte_reader_get_remaining (&br));
- return 0;
- }
- u8 = gst_byte_reader_get_uint8_unchecked (&br);
- if (u8 != 0x71) {
- GST_WARNING_OBJECT (self, "cdp packet does not have timecode start byte "
- "of 0x71, found 0x%02x", u8);
- return 0;
- }
-
- u8 = gst_byte_reader_get_uint8_unchecked (&br);
- if ((u8 & 0xc0) != 0xc0) {
- GST_WARNING_OBJECT (self, "reserved bits are not 0xc0, found 0x%02x", u8);
- return 0;
- }
-
- hours = ((u8 >> 4) & 0x3) * 10 + (u8 & 0xf);
-
- u8 = gst_byte_reader_get_uint8_unchecked (&br);
- if ((u8 & 0x80) != 0x80) {
- GST_WARNING_OBJECT (self, "reserved bit is not 0x80, found 0x%02x", u8);
- return 0;
- }
- minutes = ((u8 >> 4) & 0x7) * 10 + (u8 & 0xf);
-
- u8 = gst_byte_reader_get_uint8_unchecked (&br);
- if (u8 & 0x80)
- fields = 2;
- else
- fields = 1;
- seconds = ((u8 >> 4) & 0x7) * 10 + (u8 & 0xf);
-
- u8 = gst_byte_reader_get_uint8_unchecked (&br);
- if (u8 & 0x40) {
- GST_WARNING_OBJECT (self, "reserved bit is not 0x0, found 0x%02x", u8);
- return 0;
- }
-
- drop_frame = !(!(u8 & 0x80));
- frames = ((u8 >> 4) & 0x3) * 10 + (u8 & 0xf);
-
- gst_video_time_code_init (tc, fps_entry->fps_n, fps_entry->fps_d, NULL,
- drop_frame ? GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME :
- GST_VIDEO_TIME_CODE_FLAGS_NONE, hours, minutes, seconds, frames,
- fields);
- }
-
- /* ccdata_present */
- if (flags & 0x40) {
- guint8 cc_count;
-
- if (gst_byte_reader_get_remaining (&br) < 2) {
- GST_WARNING_OBJECT (self, "not enough data to contain valid cc_data");
- return 0;
- }
- u8 = gst_byte_reader_get_uint8_unchecked (&br);
- if (u8 != 0x72) {
- GST_WARNING_OBJECT (self, "missing cc_data start code of 0x72, "
- "found 0x%02x", u8);
- return 0;
- }
-
- cc_count = gst_byte_reader_get_uint8_unchecked (&br);
- if ((cc_count & 0xe0) != 0xe0) {
- GST_WARNING_OBJECT (self, "reserved bits are not 0xe0, found 0x%02x", u8);
- return 0;
- }
- cc_count &= 0x1f;
-
- len = 3 * cc_count;
- 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);
- }
-
- *out_fps_entry = fps_entry;
-
- /* skip everything else we don't care about */
- return len;
-}
-
static gboolean
copy_from_stored_data (GstCCConverter * self, guint8 * out_ccp,
guint * ccp_size, guint8 * cea608_1, guint * cea608_1_len,
gst_buffer_map (inbuf, &in, GST_MAP_READ);
cc_data_len =
- convert_cea708_cdp_cea708_cc_data_internal (self, in.data, in.size,
+ convert_cea708_cdp_to_cc_data (GST_OBJECT (self), in.data, in.size,
cc_data, out_tc, in_fps_entry);
gst_buffer_unmap (inbuf, &in);