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,13 +404,24 @@ convert_line_from_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];
/* 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;
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);
}
@ -446,30 +457,57 @@ convert_line_from_v210 (GstVideoVBIParser * parser, const guint8 * data)
{
guint i;
guint16 *y = (guint16 *) parser->work_data;
guint16 *uv = y + parser->info.width;
guint32 a, b, c, d;
/* 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);
/* 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);
*uv++ = (a >> 0) & 0x3ff;
*y++ = (a >> 10) & 0x3ff;
*uv++ = (a >> 20) & 0x3ff;
*y++ = (b >> 0) & 0x3ff;
*y++ = (a >> 0) & 0x3ff;
*y++ = (a >> 10) & 0x3ff;
*y++ = (a >> 20) & 0x3ff;
*y++ = (b >> 0) & 0x3ff;
*uv++ = (b >> 10) & 0x3ff;
*y++ = (b >> 20) & 0x3ff;
*uv++ = (c >> 0) & 0x3ff;
*y++ = (c >> 10) & 0x3ff;
*y++ = (b >> 10) & 0x3ff;
*y++ = (b >> 20) & 0x3ff;
*y++ = (c >> 0) & 0x3ff;
*y++ = (c >> 10) & 0x3ff;
*uv++ = (c >> 20) & 0x3ff;
*y++ = (d >> 0) & 0x3ff;
*uv++ = (d >> 10) & 0x3ff;
*y++ = (d >> 20) & 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 */
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);
*uv++ = (a >> 0) & 0x3ff;
*y++ = (a >> 10) & 0x3ff;
*uv++ = (a >> 20) & 0x3ff;
*y++ = (b >> 0) & 0x3ff;
*uv++ = (b >> 10) & 0x3ff;
*y++ = (b >> 20) & 0x3ff;
*uv++ = (c >> 0) & 0x3ff;
*y++ = (c >> 10) & 0x3ff;
*uv++ = (c >> 20) & 0x3ff;
*y++ = (d >> 0) & 0x3ff;
*uv++ = (d >> 10) & 0x3ff;
*y++ = (d >> 20) & 0x3ff;
}
}
if (0) {
@ -767,39 +805,71 @@ convert_line_to_v210 (GstVideoVBIEncoder * encoder, guint8 * data)
{
guint i;
const guint16 *y = (const guint16 *) encoder->work_data;
const guint16 *uv = y + encoder->info.width;
guint32 a, b, c, d;
/* Convert the line */
for (i = 0; i < encoder->info.width - 5; i += 6) {
a = ((uv[0] & 0x3ff) << 0)
| ((y[0] & 0x3ff) << 10)
| ((uv[1] & 0x3ff) << 20);
uv += 2;
y++;
/* 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)
| ((uv[0] & 0x3ff) << 10)
| ((y[1] & 0x3ff) << 20);
y += 2;
uv++;
b = ((y[0] & 0x3ff) << 0)
| ((y[1] & 0x3ff) << 10)
| ((y[2] & 0x3ff) << 20);
y += 3;
c = ((uv[0] & 0x3ff) << 0)
| ((y[0] & 0x3ff) << 10)
| ((uv[1] & 0x3ff) << 20);
uv += 2;
y++;
c = ((y[0] & 0x3ff) << 0)
| ((y[1] & 0x3ff) << 10)
| ((y[2] & 0x3ff) << 20);
y += 3;
d = ((y[0] & 0x3ff) << 0)
| ((uv[0] & 0x3ff) << 10)
| ((y[1] & 0x3ff) << 20);
y += 2;
uv++;
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);
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 */
for (i = 0; i < encoder->info.width - 5; i += 6) {
a = ((uv[0] & 0x3ff) << 0)
| ((y[0] & 0x3ff) << 10)
| ((uv[1] & 0x3ff) << 20);
uv += 2;
y++;
b = ((y[0] & 0x3ff) << 0)
| ((uv[0] & 0x3ff) << 10)
| ((y[1] & 0x3ff) << 20);
y += 2;
uv++;
c = ((uv[0] & 0x3ff) << 0)
| ((y[0] & 0x3ff) << 10)
| ((uv[1] & 0x3ff) << 20);
uv += 2;
y++;
d = ((y[0] & 0x3ff) << 0)
| ((uv[0] & 0x3ff) << 10)
| ((y[1] & 0x3ff) << 20);
y += 2;
uv++;
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);
}
}
}
@ -808,13 +878,24 @@ convert_line_to_uyvy (GstVideoVBIEncoder * encoder, guint8 * data)
{
guint i;
const guint8 *y = encoder->work_data;
const guint8 *uv = y + encoder->info.width;
for (i = 0; i < encoder->info.width - 3; i += 4) {
data[(i / 4) * 4 + 0] = *uv++;
data[(i / 4) * 4 + 1] = *y++;
data[(i / 4) * 4 + 2] = *uv++;
data[(i / 4) * 4 + 3] = *y++;
/* 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;
for (i = 0; i < encoder->info.width - 3; i += 4) {
data[(i / 4) * 4 + 0] = *uv++;
data[(i / 4) * 4 + 1] = *y++;
data[(i / 4) * 4 + 2] = *uv++;
data[(i / 4) * 4 + 3] = *y++;
}
}
}

View file

@ -28,10 +28,10 @@
GST_START_TEST (parse_8bit)
{
GstVideoVBIParser *parser;
guint8 line[1440] = { 0, };
guint8 line[2560] = { 0, };
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);
/* empty line */
@ -124,10 +124,10 @@ GST_END_TEST;
GST_START_TEST (parse_10bit)
{
GstVideoVBIParser *parser;
guint8 line[1920] = { 0, };
guint8 line[3414] = { 0, };
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);
/* empty line */
@ -220,15 +220,15 @@ GST_START_TEST (encode_8bit)
{
GstVideoVBIParser *parser;
GstVideoVBIEncoder *encoder;
guint8 line[1440] = { 0, };
guint8 line[2560] = { 0, };
const guint8 data1[] = { 0x01, 0x02, 0x03, 0x04, 0x50, 0x60, 0x70, 0x80 };
const guint8 data2[] = { 0x04, 0x03, 0x02, 0x01 };
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);
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);
/* Write a single ADF packet and try to parse it back again */
@ -282,15 +282,15 @@ GST_START_TEST (encode_10bit)
{
GstVideoVBIParser *parser;
GstVideoVBIEncoder *encoder;
guint8 line[1920] = { 0, };
guint8 line[3414] = { 0, };
const guint8 data1[] = { 0x01, 0x02, 0x03, 0x04, 0x50, 0x60, 0x70, 0x80 };
const guint8 data2[] = { 0x04, 0x03, 0x02, 0x01 };
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);
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);
/* Write a single ADF packet and try to parse it back again */