diff options
author | Edward Hervey <edward@centricular.com> | 2018-02-27 16:06:15 +0100 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2018-02-27 16:06:15 +0100 |
commit | fde4c29860e14ab47c7b851a5f22f4b25d1ff60a (patch) | |
tree | 3fa0ba2b2088a6fb8303ecb2c805a6bbc564be76 | |
parent | 31fcd8f14da837dcc773d7c61aed3753d9e818a4 (diff) |
WIP VBI 8bit support
-rw-r--r-- | gst-libs/gst/video/video-vbi.c | 158 |
1 files changed, 133 insertions, 25 deletions
diff --git a/gst-libs/gst/video/video-vbi.c b/gst-libs/gst/video/video-vbi.c index 727261b07..71b25b487 100644 --- a/gst-libs/gst/video/video-vbi.c +++ b/gst-libs/gst/video/video-vbi.c @@ -49,19 +49,20 @@ ensure_debug_category (void) struct _GstVideoVBIParser { GstVideoInfo info; /* format of the lines provided */ - guint16 *work_data; /* Converted line in planar 16bit format */ - guint32 work_data_size; /* Size (in guint16) of work_data */ - guint offset; /* Current offset (in guint16) in work_data */ + guint8 *work_data; /* Converted line in planar 16bit format */ + guint32 work_data_size; /* Size in bytes of work_data */ + guint offset; /* Current offset (in bytes) in work_data */ + gboolean bit16; /* Data is stored as 16bit if TRUE. Else 8bit(without parity) */ }; /* Smallest ANC size (which would have a size Data Count of 0 though) */ #define SMALLEST_ANC_SIZE 7 -GstVideoVBIParserResult -gst_video_vbi_parser_get_ancillary (GstVideoVBIParser * parser, - GstVideoAncillary * anc) +static GstVideoVBIParserResult +get_ancillary_16 (GstVideoVBIParser * parser, GstVideoAncillary * anc) { gboolean found = FALSE; + guint16 *data = (guint16 *) parser->work_data; g_return_val_if_fail (parser != NULL, GST_VIDEO_VBI_PARSER_RESULT_ERROR); g_return_val_if_fail (anc != NULL, GST_VIDEO_VBI_PARSER_RESULT_ERROR); @@ -72,9 +73,9 @@ gst_video_vbi_parser_get_ancillary (GstVideoVBIParser * parser, /* Look for ADF * FIXME : This assumes 10bit data with parity ! */ - if (parser->work_data[parser->offset] != 0x000 || - parser->work_data[parser->offset + 1] != 0x3ff || - parser->work_data[parser->offset + 2] != 0x3ff) { + if (data[parser->offset] != 0x000 || + data[parser->offset + 1] != 0x3ff || + data[parser->offset + 2] != 0x3ff) { parser->offset += 1; continue; } @@ -83,9 +84,64 @@ gst_video_vbi_parser_get_ancillary (GstVideoVBIParser * parser, * 10bit data */ /* We have a valid ADF */ - DID = parser->work_data[parser->offset + 3] & 0xff; - SDID = parser->work_data[parser->offset + 4] & 0xff; - DC = parser->work_data[parser->offset + 5] & 0xff; + DID = data[parser->offset + 3] & 0xff; + SDID = data[parser->offset + 4] & 0xff; + DC = data[parser->offset + 5] & 0xff; + /* Check if we have enough room to get the User Data */ + if (parser->offset >= parser->work_data_size + SMALLEST_ANC_SIZE + DC) + goto not_enough_data; + + /* We found a valid ANC \o/ */ + anc->DID = DID; + anc->SDID_block_number = SDID; + anc->data_count = DC; + anc->data = g_malloc0 (anc->data_count); + for (i = 0; i < anc->data_count; i++) + anc->data[i] = data[parser->offset + 6 + i] & 0xff; + found = TRUE; + parser->offset += SMALLEST_ANC_SIZE + DC; + break; + } + + if (found) + return GST_VIDEO_VBI_PARSER_RESULT_OK; + + return GST_VIDEO_VBI_PARSER_RESULT_DONE; + + /* ERRORS */ +not_enough_data: + { + GST_WARNING ("ANC requires more User Data that available line size"); + /* Avoid further calls to go in the same error */ + parser->offset = parser->work_data_size; + return GST_VIDEO_VBI_PARSER_RESULT_ERROR; + } +} + +static GstVideoVBIParserResult +get_ancillary_8 (GstVideoVBIParser * parser, GstVideoAncillary * anc) +{ + gboolean found = FALSE; + guint8 *data = parser->work_data; + + g_return_val_if_fail (parser != NULL, GST_VIDEO_VBI_PARSER_RESULT_ERROR); + g_return_val_if_fail (anc != NULL, GST_VIDEO_VBI_PARSER_RESULT_ERROR); + + while (parser->offset < parser->work_data_size + SMALLEST_ANC_SIZE) { + guint8 DID, SDID, DC; + guint i; + + /* Look for 8bit ADF (0x00 0xff 0xff) */ + if (data[parser->offset] != 0x00 || + data[parser->offset + 1] != 0xff || data[parser->offset + 2] != 0xff) { + parser->offset += 1; + continue; + } + + /* We have a valid ADF */ + DID = data[parser->offset + 3]; + SDID = data[parser->offset + 4]; + DC = data[parser->offset + 5]; /* Check if we have enough room to get the User Data */ if (parser->offset >= parser->work_data_size + SMALLEST_ANC_SIZE + DC) goto not_enough_data; @@ -96,7 +152,7 @@ gst_video_vbi_parser_get_ancillary (GstVideoVBIParser * parser, anc->data_count = DC; anc->data = g_malloc0 (anc->data_count); for (i = 0; i < anc->data_count; i++) - anc->data[i] = parser->work_data[parser->offset + 6 + i] & 0xff; + anc->data[i] = data[parser->offset + 6 + i]; found = TRUE; parser->offset += SMALLEST_ANC_SIZE + DC; break; @@ -117,6 +173,15 @@ not_enough_data: } } +GstVideoVBIParserResult +gst_video_vbi_parser_get_ancillary (GstVideoVBIParser * parser, + GstVideoAncillary * anc) +{ + if (parser->bit16) + return get_ancillary_16 (parser, anc); + return get_ancillary_8 (parser, anc); +} + GstVideoVBIParser * gst_video_vbi_parser_new (GstVideoFormat format, guint32 pixel_width) { @@ -125,6 +190,11 @@ gst_video_vbi_parser_new (GstVideoFormat format, guint32 pixel_width) switch (format) { case GST_VIDEO_FORMAT_v210: parser = g_new0 (GstVideoVBIParser, 1); + parser->bit16 = TRUE; + break; + case GST_VIDEO_FORMAT_UYVY: + parser = g_new0 (GstVideoVBIParser, 1); + parser->bit16 = FALSE; break; default: GST_WARNING ("Format not supported by GstVideoVBIParser"); @@ -138,9 +208,15 @@ gst_video_vbi_parser_new (GstVideoFormat format, guint32 pixel_width) return NULL; } - /* Allocate the workspace which is going to be 2 * pixel_width * data big */ + /* Allocate the workspace which is going to be 2 * pixel_width big + * 2 : number of pixels per "component" (we only deal with 4:2:2) + * We use 1 or 2 bytes per pixel depending on whether we are internally + * working in 8 or 16bit */ parser->work_data_size = 2 * pixel_width; - parser->work_data = g_new0 (guint16, parser->work_data_size); + if (parser->bit16) + parser->work_data = g_malloc0 (parser->work_data_size * 2); + else + parser->work_data = g_malloc0 (parser->work_data_size); parser->offset = 0; return parser; @@ -153,6 +229,23 @@ gst_video_vbi_parser_free (GstVideoVBIParser * parser) g_free (parser); } + +static void +convert_line_uyvy (GstVideoVBIParser * parser, const guint8 * data) +{ + guint i; + guint8 *y = parser->work_data; + guint8 *uv = y + parser->info.width; + + for (i = 0; i < parser->info.width - 3; i += 4) { + *uv++ = data[(i / 4) * 4 + 0]; + *y++ = data[(i / 4) * 4 + 1]; + *uv++ = data[(i / 4) * 4 + 2]; + *y++ = data[(i / 4) * 4 + 3]; + } + GST_MEMDUMP ("Converted line", parser->work_data, 128); +} + static void gst_info_dump_mem16_line (gchar * linebuf, gsize linebuf_size, const guint16 * mem, gsize mem_offset, gsize mem_size) @@ -179,19 +272,15 @@ gst_info_dump_mem16_line (gchar * linebuf, gsize linebuf_size, (guint) mem_offset, hexstr); } - -void -gst_video_vbi_parser_add_line (GstVideoVBIParser * parser, const guint8 * data) +static void +convert_line_v210 (GstVideoVBIParser * parser, const guint8 * data) { guint i; - guint16 *y = parser->work_data; + guint16 *y = (guint16 *) parser->work_data; guint16 *uv = y + parser->info.width; guint32 a, b, c, d; - parser->offset = 0; - /* FIXME : Only supports v210 ! */ - - /* Convert the line \o/ */ + /* Convert the line */ for (i = 0; i < parser->info.width - 5; i += 6) { a = GST_READ_UINT32_LE (data + (i / 6) * 16 + 0); b = GST_READ_UINT32_LE (data + (i / 6) * 16 + 4); @@ -224,8 +313,8 @@ gst_video_vbi_parser_add_line (GstVideoVBIParser * parser, const guint8 * data) gchar buf[128]; /* gst_info_dump_mem_line will process 16 bytes (8 16bit chunks) at most */ - gst_info_dump_mem16_line (buf, sizeof (buf), parser->work_data, off, - length - off); + gst_info_dump_mem16_line (buf, sizeof (buf), + (guint16 *) parser->work_data, off, length - off); GST_TRACE ("%s", buf); off += 8; } @@ -233,3 +322,22 @@ gst_video_vbi_parser_add_line (GstVideoVBIParser * parser, const guint8 * data) "-------------------------------------------------------------------"); } } + +void +gst_video_vbi_parser_add_line (GstVideoVBIParser * parser, const guint8 * data) +{ + /* Reset offset */ + parser->offset = 0; + + switch (GST_VIDEO_INFO_FORMAT (&parser->info)) { + case GST_VIDEO_FORMAT_v210: + convert_line_v210 (parser, data); + break; + case GST_VIDEO_FORMAT_UYVY: + convert_line_uyvy (parser, data); + break; + default: + GST_ERROR ("UNSUPPORTED FORMAT !"); + break; + } +} |