video-anc: Handle SD formats correctly

VANC is stored linearly in SD formats instead of separating the Y and YV
components from each other and having first all Y and then all UV
values.
This commit is contained in:
Sebastian Dröge 2019-04-22 17:06:09 +03:00 committed by Sebastian Dröge
parent 1dea6d52ce
commit cbccda6f3b
2 changed files with 149 additions and 68 deletions

View file

@ -404,6 +404,16 @@ convert_line_from_uyvy (GstVideoVBIParser * parser, const guint8 * data)
{ {
guint i; guint i;
guint8 *y = parser->work_data; guint8 *y = parser->work_data;
/* Data is stored differently in SD, making no distinction between Y and UV */
if (parser->info.width < 1280) {
for (i = 0; i < parser->info.width - 3; i += 4) {
*y++ = data[(i / 4) * 4 + 0];
*y++ = data[(i / 4) * 4 + 1];
*y++ = data[(i / 4) * 4 + 2];
*y++ = data[(i / 4) * 4 + 3];
}
} else {
guint8 *uv = y + parser->info.width; guint8 *uv = y + parser->info.width;
for (i = 0; i < parser->info.width - 3; i += 4) { for (i = 0; i < parser->info.width - 3; i += 4) {
@ -412,6 +422,7 @@ convert_line_from_uyvy (GstVideoVBIParser * parser, const guint8 * data)
*uv++ = data[(i / 4) * 4 + 2]; *uv++ = data[(i / 4) * 4 + 2];
*y++ = data[(i / 4) * 4 + 3]; *y++ = data[(i / 4) * 4 + 3];
} }
}
GST_MEMDUMP ("Converted line", parser->work_data, 128); GST_MEMDUMP ("Converted line", parser->work_data, 128);
} }
@ -446,9 +457,35 @@ convert_line_from_v210 (GstVideoVBIParser * parser, const guint8 * data)
{ {
guint i; guint i;
guint16 *y = (guint16 *) parser->work_data; guint16 *y = (guint16 *) parser->work_data;
guint16 *uv = y + parser->info.width;
guint32 a, b, c, d; guint32 a, b, c, d;
/* Data is stored differently in SD, making no distinction between Y and UV */
if (parser->info.width < 1280) {
/* 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);
c = GST_READ_UINT32_LE (data + (i / 6) * 16 + 8);
d = GST_READ_UINT32_LE (data + (i / 6) * 16 + 12);
*y++ = (a >> 0) & 0x3ff;
*y++ = (a >> 10) & 0x3ff;
*y++ = (a >> 20) & 0x3ff;
*y++ = (b >> 0) & 0x3ff;
*y++ = (b >> 10) & 0x3ff;
*y++ = (b >> 20) & 0x3ff;
*y++ = (c >> 0) & 0x3ff;
*y++ = (c >> 10) & 0x3ff;
*y++ = (c >> 20) & 0x3ff;
*y++ = (d >> 0) & 0x3ff;
*y++ = (d >> 10) & 0x3ff;
*y++ = (d >> 20) & 0x3ff;
}
} else {
guint16 *uv = y + parser->info.width;
/* Convert the line */ /* Convert the line */
for (i = 0; i < parser->info.width - 5; i += 6) { for (i = 0; i < parser->info.width - 5; i += 6) {
a = GST_READ_UINT32_LE (data + (i / 6) * 16 + 0); a = GST_READ_UINT32_LE (data + (i / 6) * 16 + 0);
@ -471,6 +508,7 @@ convert_line_from_v210 (GstVideoVBIParser * parser, const guint8 * data)
*uv++ = (d >> 10) & 0x3ff; *uv++ = (d >> 10) & 0x3ff;
*y++ = (d >> 20) & 0x3ff; *y++ = (d >> 20) & 0x3ff;
} }
}
if (0) { if (0) {
guint off = 0; guint off = 0;
@ -767,9 +805,40 @@ convert_line_to_v210 (GstVideoVBIEncoder * encoder, guint8 * data)
{ {
guint i; guint i;
const guint16 *y = (const guint16 *) encoder->work_data; const guint16 *y = (const guint16 *) encoder->work_data;
const guint16 *uv = y + encoder->info.width;
guint32 a, b, c, d; guint32 a, b, c, d;
/* Data is stored differently in SD, making no distinction between Y and UV */
if (encoder->info.width < 1280) {
/* Convert the line */
for (i = 0; i < encoder->info.width - 5; i += 6) {
a = ((y[0] & 0x3ff) << 0)
| ((y[1] & 0x3ff) << 10)
| ((y[2] & 0x3ff) << 20);
y += 3;
b = ((y[0] & 0x3ff) << 0)
| ((y[1] & 0x3ff) << 10)
| ((y[2] & 0x3ff) << 20);
y += 3;
c = ((y[0] & 0x3ff) << 0)
| ((y[1] & 0x3ff) << 10)
| ((y[2] & 0x3ff) << 20);
y += 3;
d = ((y[0] & 0x3ff) << 0)
| ((y[1] & 0x3ff) << 10)
| ((y[2] & 0x3ff) << 20);
y += 3;
GST_WRITE_UINT32_LE (data + (i / 6) * 16 + 0, a);
GST_WRITE_UINT32_LE (data + (i / 6) * 16 + 4, b);
GST_WRITE_UINT32_LE (data + (i / 6) * 16 + 8, c);
GST_WRITE_UINT32_LE (data + (i / 6) * 16 + 12, d);
}
} else {
const guint16 *uv = y + encoder->info.width;
/* Convert the line */ /* Convert the line */
for (i = 0; i < encoder->info.width - 5; i += 6) { for (i = 0; i < encoder->info.width - 5; i += 6) {
a = ((uv[0] & 0x3ff) << 0) a = ((uv[0] & 0x3ff) << 0)
@ -802,12 +871,23 @@ convert_line_to_v210 (GstVideoVBIEncoder * encoder, guint8 * data)
GST_WRITE_UINT32_LE (data + (i / 6) * 16 + 12, d); GST_WRITE_UINT32_LE (data + (i / 6) * 16 + 12, d);
} }
} }
}
static void static void
convert_line_to_uyvy (GstVideoVBIEncoder * encoder, guint8 * data) convert_line_to_uyvy (GstVideoVBIEncoder * encoder, guint8 * data)
{ {
guint i; guint i;
const guint8 *y = encoder->work_data; const guint8 *y = encoder->work_data;
/* Data is stored differently in SD, making no distinction between Y and UV */
if (encoder->info.width < 1280) {
for (i = 0; i < encoder->info.width - 3; i += 4) {
data[(i / 4) * 4 + 0] = *y++;
data[(i / 4) * 4 + 1] = *y++;
data[(i / 4) * 4 + 2] = *y++;
data[(i / 4) * 4 + 3] = *y++;
}
} else {
const guint8 *uv = y + encoder->info.width; const guint8 *uv = y + encoder->info.width;
for (i = 0; i < encoder->info.width - 3; i += 4) { for (i = 0; i < encoder->info.width - 3; i += 4) {
@ -817,6 +897,7 @@ convert_line_to_uyvy (GstVideoVBIEncoder * encoder, guint8 * data)
data[(i / 4) * 4 + 3] = *y++; data[(i / 4) * 4 + 3] = *y++;
} }
} }
}
void void
gst_video_vbi_encoder_write_line (GstVideoVBIEncoder * encoder, guint8 * data) gst_video_vbi_encoder_write_line (GstVideoVBIEncoder * encoder, guint8 * data)

View file

@ -28,10 +28,10 @@
GST_START_TEST (parse_8bit) GST_START_TEST (parse_8bit)
{ {
GstVideoVBIParser *parser; GstVideoVBIParser *parser;
guint8 line[1440] = { 0, }; guint8 line[2560] = { 0, };
GstVideoAncillary vanc; GstVideoAncillary vanc;
parser = gst_video_vbi_parser_new (GST_VIDEO_FORMAT_UYVY, 720); parser = gst_video_vbi_parser_new (GST_VIDEO_FORMAT_UYVY, 1280);
fail_unless (parser != NULL); fail_unless (parser != NULL);
/* empty line */ /* empty line */
@ -124,10 +124,10 @@ GST_END_TEST;
GST_START_TEST (parse_10bit) GST_START_TEST (parse_10bit)
{ {
GstVideoVBIParser *parser; GstVideoVBIParser *parser;
guint8 line[1920] = { 0, }; guint8 line[3414] = { 0, };
GstVideoAncillary vanc; GstVideoAncillary vanc;
parser = gst_video_vbi_parser_new (GST_VIDEO_FORMAT_v210, 720); parser = gst_video_vbi_parser_new (GST_VIDEO_FORMAT_v210, 1280);
fail_unless (parser != NULL); fail_unless (parser != NULL);
/* empty line */ /* empty line */
@ -220,15 +220,15 @@ GST_START_TEST (encode_8bit)
{ {
GstVideoVBIParser *parser; GstVideoVBIParser *parser;
GstVideoVBIEncoder *encoder; GstVideoVBIEncoder *encoder;
guint8 line[1440] = { 0, }; guint8 line[2560] = { 0, };
const guint8 data1[] = { 0x01, 0x02, 0x03, 0x04, 0x50, 0x60, 0x70, 0x80 }; const guint8 data1[] = { 0x01, 0x02, 0x03, 0x04, 0x50, 0x60, 0x70, 0x80 };
const guint8 data2[] = { 0x04, 0x03, 0x02, 0x01 }; const guint8 data2[] = { 0x04, 0x03, 0x02, 0x01 };
GstVideoAncillary vanc; GstVideoAncillary vanc;
parser = gst_video_vbi_parser_new (GST_VIDEO_FORMAT_UYVY, 720); parser = gst_video_vbi_parser_new (GST_VIDEO_FORMAT_UYVY, 1280);
fail_unless (parser != NULL); fail_unless (parser != NULL);
encoder = gst_video_vbi_encoder_new (GST_VIDEO_FORMAT_UYVY, 720); encoder = gst_video_vbi_encoder_new (GST_VIDEO_FORMAT_UYVY, 1280);
fail_unless (encoder != NULL); fail_unless (encoder != NULL);
/* Write a single ADF packet and try to parse it back again */ /* Write a single ADF packet and try to parse it back again */
@ -282,15 +282,15 @@ GST_START_TEST (encode_10bit)
{ {
GstVideoVBIParser *parser; GstVideoVBIParser *parser;
GstVideoVBIEncoder *encoder; GstVideoVBIEncoder *encoder;
guint8 line[1920] = { 0, }; guint8 line[3414] = { 0, };
const guint8 data1[] = { 0x01, 0x02, 0x03, 0x04, 0x50, 0x60, 0x70, 0x80 }; const guint8 data1[] = { 0x01, 0x02, 0x03, 0x04, 0x50, 0x60, 0x70, 0x80 };
const guint8 data2[] = { 0x04, 0x03, 0x02, 0x01 }; const guint8 data2[] = { 0x04, 0x03, 0x02, 0x01 };
GstVideoAncillary vanc; GstVideoAncillary vanc;
parser = gst_video_vbi_parser_new (GST_VIDEO_FORMAT_v210, 720); parser = gst_video_vbi_parser_new (GST_VIDEO_FORMAT_v210, 1280);
fail_unless (parser != NULL); fail_unless (parser != NULL);
encoder = gst_video_vbi_encoder_new (GST_VIDEO_FORMAT_v210, 720); encoder = gst_video_vbi_encoder_new (GST_VIDEO_FORMAT_v210, 1280);
fail_unless (encoder != NULL); fail_unless (encoder != NULL);
/* Write a single ADF packet and try to parse it back again */ /* Write a single ADF packet and try to parse it back again */