mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
video: add support for AV12
AV12 is an internally conceived format that is actually the combination of NV12 and an alpha plane. This format is to add to gstreamer's webM transparency support for vp8 and vp9. To this end, two I420 streams are independently decoded simultaneously for the actual content and the alpha plane respectively and these are then combined into A420. Since most hardware decoders output NV12, this patch adds NV12+A to make the same workflow possible. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1152>
This commit is contained in:
parent
038ba1bffe
commit
6760c7fd76
5 changed files with 158 additions and 2 deletions
|
@ -6595,6 +6595,10 @@ get_scale_format (GstVideoFormat format, gint plane)
|
|||
case GST_VIDEO_FORMAT_NV24:
|
||||
res = plane == 0 ? GST_VIDEO_FORMAT_GRAY8 : GST_VIDEO_FORMAT_NV12;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_AV12:
|
||||
res = (plane == 0
|
||||
|| plane == 2) ? GST_VIDEO_FORMAT_GRAY8 : GST_VIDEO_FORMAT_NV12;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_UNKNOWN:
|
||||
case GST_VIDEO_FORMAT_ENCODED:
|
||||
case GST_VIDEO_FORMAT_v210:
|
||||
|
|
|
@ -1753,6 +1753,98 @@ unpack_NV21 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
|
|||
}
|
||||
}
|
||||
|
||||
#define PACK_AV12 GST_VIDEO_FORMAT_AYUV, unpack_AV12, 1, pack_AV12
|
||||
static void
|
||||
unpack_AV12 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
|
||||
gpointer dest, const gpointer data[GST_VIDEO_MAX_PLANES],
|
||||
const gint stride[GST_VIDEO_MAX_PLANES], gint x, gint y, gint width)
|
||||
{
|
||||
gint uv = GET_UV_420 (y, flags);
|
||||
const guint8 *restrict sy = GET_PLANE_LINE (0, y);
|
||||
const guint8 *restrict suv = GET_PLANE_LINE (1, uv);
|
||||
const guint8 *restrict sa = GET_PLANE_LINE (2, y); /* a is for 'alpha' */
|
||||
guint8 *restrict d = dest;
|
||||
|
||||
sy += x;
|
||||
sa += x;
|
||||
suv += (x & ~1);
|
||||
|
||||
if (x & 1) {
|
||||
d[0] = *sa++;
|
||||
d[1] = *sy++;
|
||||
d[2] = suv[0];
|
||||
d[3] = suv[1];
|
||||
width--;
|
||||
d += 4;
|
||||
suv += 2;
|
||||
}
|
||||
|
||||
if (IS_ALIGNED (d, 8)) {
|
||||
video_orc_unpack_AV12 (d, sy, suv, sa, width / 2);
|
||||
} else {
|
||||
gint i;
|
||||
for (i = 0; i < width / 2; i++) {
|
||||
d[i * 8 + 0] = sa[i * 2 + 0];
|
||||
d[i * 8 + 1] = sy[i * 2 + 0];
|
||||
d[i * 8 + 2] = suv[i * 2 + 0];
|
||||
d[i * 8 + 3] = suv[i * 2 + 1];
|
||||
d[i * 8 + 4] = sa[i * 2 + 1];
|
||||
d[i * 8 + 5] = sy[i * 2 + 1];
|
||||
d[i * 8 + 6] = suv[i * 2 + 0];
|
||||
d[i * 8 + 7] = suv[i * 2 + 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (width & 1) {
|
||||
gint i = width - 1;
|
||||
|
||||
d[i * 4 + 0] = sa[i];
|
||||
d[i * 4 + 1] = sy[i];
|
||||
d[i * 4 + 2] = suv[i + 0];
|
||||
d[i * 4 + 3] = suv[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pack_AV12 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
|
||||
const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
|
||||
const gint stride[GST_VIDEO_MAX_PLANES], GstVideoChromaSite chroma_site,
|
||||
gint y, gint width)
|
||||
{
|
||||
gint uv = GET_UV_420 (y, flags);
|
||||
guint8 *restrict dy = GET_PLANE_LINE (0, y);
|
||||
guint8 *restrict duv = GET_PLANE_LINE (1, uv);
|
||||
guint8 *restrict da = GET_PLANE_LINE (2, y); /* a is for 'alpha' */
|
||||
const guint8 *restrict s = src;
|
||||
|
||||
if (IS_CHROMA_LINE_420 (y, flags)) {
|
||||
if (IS_ALIGNED (s, 8)) {
|
||||
video_orc_pack_AV12 (dy, duv, da, s, width / 2);
|
||||
} else {
|
||||
gint i;
|
||||
for (i = 0; i < width / 2; i++) {
|
||||
/* AYUV_AYUV: alpha is on bytes 0 and 4 */
|
||||
da[i * 2 + 0] = s[i * 8 + 0];
|
||||
da[i * 2 + 1] = s[i * 8 + 4];
|
||||
dy[i * 2 + 0] = s[i * 8 + 1];
|
||||
dy[i * 2 + 1] = s[i * 8 + 5];
|
||||
duv[i * 2 + 0] = s[i * 8 + 2];
|
||||
duv[i * 2 + 1] = s[i * 8 + 3];
|
||||
}
|
||||
}
|
||||
if (width & 1) {
|
||||
gint i = width - 1;
|
||||
|
||||
da[i] = s[i * 4 + 0]; /* AYUV: alpha is byte 0 */
|
||||
dy[i] = s[i * 4 + 1];
|
||||
duv[i + 0] = s[i * 4 + 2];
|
||||
duv[i + 1] = s[i * 4 + 3];
|
||||
}
|
||||
} else {
|
||||
video_orc_pack_YA (dy, da, s, width);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pack_NV21 (const GstVideoFormatInfo * info, GstVideoPackFlags flags,
|
||||
const gpointer src, gint sstride, gpointer data[GST_VIDEO_MAX_PLANES],
|
||||
|
@ -6374,6 +6466,7 @@ typedef struct
|
|||
#define PSTR111 { 1, 1, 1, 0 }
|
||||
#define PSTR1111 { 1, 1, 1, 1 }
|
||||
#define PSTR122 { 1, 2, 2, 0 }
|
||||
#define PSTR1221 { 1, 2, 2, 1 }
|
||||
#define PSTR2 { 2, 0, 0, 0 }
|
||||
#define PSTR222 { 2, 2, 2, 0 }
|
||||
#define PSTR2222 { 2, 2, 2, 2 }
|
||||
|
@ -6389,6 +6482,7 @@ typedef struct
|
|||
#define PLANE0 1, { 0, 0, 0, 0 }
|
||||
#define PLANE01 2, { 0, 1, 0, 0 }
|
||||
#define PLANE011 2, { 0, 1, 1, 0 }
|
||||
#define PLANE0112 3, { 0, 1, 1, 2 }
|
||||
#define PLANE012 3, { 0, 1, 2, 0 }
|
||||
#define PLANE0123 4, { 0, 1, 2, 3 }
|
||||
#define PLANE021 3, { 0, 2, 1, 0 }
|
||||
|
@ -6708,6 +6802,8 @@ static const VideoFormat formats[] = {
|
|||
PACK_RGBP),
|
||||
MAKE_RGB_FORMAT (BGRP, "raw video", DPTH888, PSTR111, PLANE210, OFFS0, SUB444,
|
||||
PACK_BGRP),
|
||||
MAKE_YUV_FORMAT (AV12, "raw video", GST_MAKE_FOURCC ('A', 'V', '1', '2'),
|
||||
DPTH8888, PSTR1221, PLANE0112, OFFS001, SUB4204, PACK_AV12),
|
||||
};
|
||||
|
||||
static GstVideoFormat
|
||||
|
|
|
@ -133,6 +133,7 @@ G_BEGIN_DECLS
|
|||
* @GST_VIDEO_FORMAT_NV12_32L32: NV12 with 32x32 tiles in linear order (Since: 1.18)
|
||||
* @GST_VIDEO_FORMAT_RGBP: planar 4:4:4 RGB, 8 bits per channel (Since: 1.20)
|
||||
* @GST_VIDEO_FORMAT_BGRP: planar 4:4:4 RGB, 8 bits per channel (Since: 1.20)
|
||||
* @GST_VIDEO_FORMAT_AV12: Planar 4:2:0 YUV with interleaved UV plane with alpha as 3rd plane (Since: 1.20)
|
||||
*
|
||||
* Enum value describing the most common video formats.
|
||||
*
|
||||
|
@ -271,6 +272,16 @@ typedef enum {
|
|||
* Since: 1.20
|
||||
*/
|
||||
GST_VIDEO_FORMAT_BGRP,
|
||||
|
||||
/**
|
||||
* GST_VIDEO_FORMAT_AV12:
|
||||
*
|
||||
* Planar 4:2:0 YUV with interleaved UV plane with alpha as
|
||||
* 3rd plane.
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
GST_VIDEO_FORMAT_AV12,
|
||||
} GstVideoFormat;
|
||||
|
||||
#define GST_VIDEO_MAX_PLANES 4
|
||||
|
@ -645,7 +656,7 @@ gconstpointer gst_video_format_get_palette (GstVideoFormat format, gsi
|
|||
"I422_10BE, I422_10LE, NV16_10LE32, Y210, v210, UYVP, I420_10BE, I420_10LE, " \
|
||||
"P010_10BE, P010_10LE, NV12_10LE32, NV12_10LE40, Y444, GBR, RGBP, BGRP, NV24, xBGR, BGRx, " \
|
||||
"xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, " \
|
||||
"YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, " \
|
||||
"YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, AV12, Y41B, IYU1, YVU9, YUV9, RGB16, " \
|
||||
"BGR16, RGB15, BGR15, RGB8P, GRAY16_BE, GRAY16_LE, GRAY10_LE32, GRAY8 }"
|
||||
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define GST_VIDEO_FORMATS_ALL "{ AYUV64, ARGB64, GBRA_12LE, GBRA_12BE, Y412_LE, " \
|
||||
|
@ -657,7 +668,7 @@ gconstpointer gst_video_format_get_palette (GstVideoFormat format, gsi
|
|||
"I422_10LE, I422_10BE, NV16_10LE32, Y210, v210, UYVP, I420_10LE, I420_10BE, " \
|
||||
"P010_10LE, NV12_10LE32, NV12_10LE40, P010_10BE, Y444, GBR, RGBP, BGRP, NV24, xBGR, BGRx, " \
|
||||
"xRGB, RGBx, BGR, IYU2, v308, RGB, Y42B, NV61, NV16, VYUY, UYVY, YVYU, YUY2, I420, " \
|
||||
"YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, Y41B, IYU1, YVU9, YUV9, RGB16, " \
|
||||
"YV12, NV21, NV12, NV12_64Z32, NV12_4L4, NV12_32L32, AV12, Y41B, IYU1, YVU9, YUV9, RGB16, " \
|
||||
"BGR16, RGB15, BGR15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE32, GRAY8 }"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -944,6 +944,16 @@ fill_planes (GstVideoInfo * info, gsize plane_size[GST_VIDEO_MAX_PLANES])
|
|||
cr_h = GST_ROUND_UP_2 (cr_h);
|
||||
info->size = info->offset[1] + info->stride[0] * cr_h;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_AV12:
|
||||
info->stride[0] = GST_ROUND_UP_4 (width);
|
||||
info->stride[1] = info->stride[0];
|
||||
info->stride[2] = info->stride[0];
|
||||
info->offset[0] = 0;
|
||||
info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
|
||||
info->offset[2] =
|
||||
info->offset[1] + (info->stride[1] * GST_ROUND_UP_2 (height) / 2);
|
||||
info->size = info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_NV16:
|
||||
case GST_VIDEO_FORMAT_NV61:
|
||||
info->stride[0] = GST_ROUND_UP_4 (width);
|
||||
|
|
|
@ -104,6 +104,16 @@ select0wb v, vv
|
|||
select0lw ay, ayuv
|
||||
select1wb y, ay
|
||||
|
||||
.function video_orc_pack_YA
|
||||
.dest 1 y guint8
|
||||
.dest 1 a guint8
|
||||
.source 4 ayuv guint8
|
||||
.temp 2 ay
|
||||
|
||||
select0lw ay, ayuv
|
||||
select1wb y, ay
|
||||
select0wb a, ay
|
||||
|
||||
.function video_orc_unpack_YUY2
|
||||
.dest 8 ayuv guint8
|
||||
.source 4 yuy2 guint8
|
||||
|
@ -446,6 +456,31 @@ x2 splitlw uvuv, ay, ayuv
|
|||
x2 select1wb y, ay
|
||||
select0lw uv, uvuv
|
||||
|
||||
.function video_orc_unpack_AV12
|
||||
.dest 8 d guint8
|
||||
.source 2 y guint8
|
||||
.source 2 uv guint8
|
||||
.source 2 a guint8
|
||||
.temp 4 ay
|
||||
.temp 4 uvuv
|
||||
|
||||
mergewl uvuv, uv, uv
|
||||
x2 mergebw ay, a, y
|
||||
x2 mergewl d, ay, uvuv
|
||||
|
||||
.function video_orc_pack_AV12
|
||||
.dest 2 y guint8
|
||||
.dest 2 uv guint8
|
||||
.dest 2 a guint8
|
||||
.source 8 ayuv guint8
|
||||
.temp 4 ay
|
||||
.temp 4 uvuv
|
||||
|
||||
x2 splitlw uvuv, ay, ayuv
|
||||
x2 select1wb y, ay
|
||||
x2 select0wb a, ay
|
||||
select0lw uv, uvuv
|
||||
|
||||
.function video_orc_unpack_NV21
|
||||
.dest 8 d guint8
|
||||
.source 2 y guint8
|
||||
|
|
Loading…
Reference in a new issue