From cecb900704ff393e35efc159a57f30a51180830d Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 6 Nov 2014 09:34:59 +0100 Subject: [PATCH] video-format: fix pack of 4:2:0 formats When packing 4:2:0 formats, we need to take the chroma from the even lines, for the odd lines we only take luminance. --- gst-libs/gst/video/video-format.c | 169 ++++++++++++++++++++++---------------- gst-libs/gst/video/video-orc.orc | 18 ++++ 2 files changed, 115 insertions(+), 72 deletions(-) diff --git a/gst-libs/gst/video/video-format.c b/gst-libs/gst/video/video-format.c index 9afb85a..9fbc39d 100644 --- a/gst-libs/gst/video/video-format.c +++ b/gst-libs/gst/video/video-format.c @@ -101,17 +101,19 @@ pack_planar_420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags, guint8 *v_line = GET_V_LINE (uv); const guint8 *ayuv = src; - g_return_if_fail (IS_ALIGNED (src, 8)); + if (!(y & 1)) { + g_return_if_fail (IS_ALIGNED (src, 8)); - video_orc_pack_I420 (y_line, u_line, v_line, src, width / 2); + video_orc_pack_I420 (y_line, u_line, v_line, src, width / 2); + if (width & 1) { + gint i = width - 1; - if (width & 1) { - gint i = width - 1; - - y_line[i] = ayuv[i * 4 + 1]; - u_line[i >> 1] = ayuv[i * 4 + 2]; - v_line[i >> 1] = ayuv[i * 4 + 3]; - } + y_line[i] = ayuv[i * 4 + 1]; + u_line[i >> 1] = ayuv[i * 4 + 2]; + v_line[i >> 1] = ayuv[i * 4 + 3]; + } + } else + video_orc_pack_Y (y_line, src, width); } #define PACK_YUY2 GST_VIDEO_FORMAT_AYUV, unpack_YUY2, 1, pack_YUY2 @@ -1085,17 +1087,20 @@ pack_NV12 (const GstVideoFormatInfo * info, GstVideoPackFlags flags, guint8 *uv_line = GET_PLANE_LINE (1, uv); const guint8 *ayuv = src; - g_return_if_fail (IS_ALIGNED (src, 8)); + if (!(y & 1)) { + g_return_if_fail (IS_ALIGNED (src, 8)); - video_orc_pack_NV12 (y_line, uv_line, src, width / 2); + video_orc_pack_NV12 (y_line, uv_line, src, width / 2); - if (width & 1) { - gint i = width - 1; + if (width & 1) { + gint i = width - 1; - y_line[i] = ayuv[i * 4 + 1]; - uv_line[i + 0] = ayuv[i * 4 + 2]; - uv_line[i + 1] = ayuv[i * 4 + 3]; - } + y_line[i] = ayuv[i * 4 + 1]; + uv_line[i + 0] = ayuv[i * 4 + 2]; + uv_line[i + 1] = ayuv[i * 4 + 3]; + } + } else + video_orc_pack_Y (y_line, src, width); } #define PACK_NV21 GST_VIDEO_FORMAT_AYUV, unpack_NV21, 1, pack_NV21 @@ -1134,17 +1139,20 @@ pack_NV21 (const GstVideoFormatInfo * info, GstVideoPackFlags flags, guint8 *uv_line = GET_PLANE_LINE (1, uv); const guint8 *ayuv = src; - g_return_if_fail (IS_ALIGNED (src, 8)); + if (!(y & 1)) { + g_return_if_fail (IS_ALIGNED (src, 8)); - video_orc_pack_NV21 (y_line, uv_line, src, width / 2); + video_orc_pack_NV21 (y_line, uv_line, src, width / 2); - if (width & 1) { - gint i = width - 1; + if (width & 1) { + gint i = width - 1; - y_line[i] = ayuv[i * 4 + 1]; - uv_line[i + 0] = ayuv[i * 4 + 3]; - uv_line[i + 1] = ayuv[i * 4 + 2]; - } + y_line[i] = ayuv[i * 4 + 1]; + uv_line[i + 0] = ayuv[i * 4 + 3]; + uv_line[i + 1] = ayuv[i * 4 + 2]; + } + } else + video_orc_pack_Y (y_line, src, width); } #define PACK_NV16 GST_VIDEO_FORMAT_AYUV, unpack_NV16, 1, pack_NV16 @@ -1312,18 +1320,21 @@ pack_A420 (const GstVideoFormatInfo * info, GstVideoPackFlags flags, guint8 *a_line = GET_A_LINE (y); const guint8 *ayuv = src; - g_return_if_fail (IS_ALIGNED (src, 8)); + if (!(y & 1)) { + g_return_if_fail (IS_ALIGNED (src, 8)); - video_orc_pack_A420 (y_line, u_line, v_line, a_line, src, width / 2); + video_orc_pack_A420 (y_line, u_line, v_line, a_line, src, width / 2); - if (width & 1) { - gint i = width - 1; + if (width & 1) { + gint i = width - 1; - a_line[i] = ayuv[i * 4 + 0]; - y_line[i] = ayuv[i * 4 + 1]; - u_line[i >> 1] = ayuv[i * 4 + 2]; - v_line[i >> 1] = ayuv[i * 4 + 3]; - } + a_line[i] = ayuv[i * 4 + 0]; + y_line[i] = ayuv[i * 4 + 1]; + u_line[i >> 1] = ayuv[i * 4 + 2]; + v_line[i >> 1] = ayuv[i * 4 + 3]; + } + } else + video_orc_pack_AY (y_line, a_line, src, width); } #define PACK_RGB8P GST_VIDEO_FORMAT_ARGB, unpack_RGB8P, 1, pack_RGB8P @@ -1888,25 +1899,32 @@ pack_I420_10LE (const GstVideoFormatInfo * info, GstVideoPackFlags flags, guint16 Y0, Y1, U, V; const guint16 *s = src; - for (i = 0; i < width - 1; i += 2) { - Y0 = s[i * 4 + 1] >> 6; - Y1 = s[i * 4 + 5] >> 6; - U = s[i * 4 + 2] >> 6; - V = s[i * 4 + 3] >> 6; - - GST_WRITE_UINT16_LE (destY + i + 0, Y0); - GST_WRITE_UINT16_LE (destY + i + 1, Y1); - GST_WRITE_UINT16_LE (destU + (i >> 1), U); - GST_WRITE_UINT16_LE (destV + (i >> 1), V); - } - if (i == width - 1) { - Y0 = s[i * 4 + 1] >> 6; - U = s[i * 4 + 2] >> 6; - V = s[i * 4 + 3] >> 6; - - GST_WRITE_UINT16_LE (destY + i, Y0); - GST_WRITE_UINT16_LE (destU + (i >> 1), U); - GST_WRITE_UINT16_LE (destV + (i >> 1), V); + if (!(y & 1)) { + for (i = 0; i < width - 1; i += 2) { + Y0 = s[i * 4 + 1] >> 6; + Y1 = s[i * 4 + 5] >> 6; + U = s[i * 4 + 2] >> 6; + V = s[i * 4 + 3] >> 6; + + GST_WRITE_UINT16_LE (destY + i + 0, Y0); + GST_WRITE_UINT16_LE (destY + i + 1, Y1); + GST_WRITE_UINT16_LE (destU + (i >> 1), U); + GST_WRITE_UINT16_LE (destV + (i >> 1), V); + } + if (i == width - 1) { + Y0 = s[i * 4 + 1] >> 6; + U = s[i * 4 + 2] >> 6; + V = s[i * 4 + 3] >> 6; + + GST_WRITE_UINT16_LE (destY + i, Y0); + GST_WRITE_UINT16_LE (destU + (i >> 1), U); + GST_WRITE_UINT16_LE (destV + (i >> 1), V); + } + } else { + for (i = 0; i < width; i++) { + Y0 = s[i * 4 + 1] >> 6; + GST_WRITE_UINT16_LE (destY + i, Y0); + } } } @@ -1955,25 +1973,32 @@ pack_I420_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags, guint16 Y0, Y1, U, V; const guint16 *s = src; - for (i = 0; i < width - 1; i += 2) { - Y0 = s[i * 4 + 1] >> 6; - Y1 = s[i * 4 + 5] >> 6; - U = s[i * 4 + 2] >> 6; - V = s[i * 4 + 3] >> 6; - - GST_WRITE_UINT16_BE (destY + i + 0, Y0); - GST_WRITE_UINT16_BE (destY + i + 1, Y1); - GST_WRITE_UINT16_BE (destU + (i >> 1), U); - GST_WRITE_UINT16_BE (destV + (i >> 1), V); - } - if (i == width - 1) { - Y0 = s[i * 4 + 1] >> 6; - U = s[i * 4 + 2] >> 6; - V = s[i * 4 + 3] >> 6; - - GST_WRITE_UINT16_BE (destY + i, Y0); - GST_WRITE_UINT16_BE (destU + (i >> 1), U); - GST_WRITE_UINT16_BE (destV + (i >> 1), V); + if (!(y & 1)) { + for (i = 0; i < width - 1; i += 2) { + Y0 = s[i * 4 + 1] >> 6; + Y1 = s[i * 4 + 5] >> 6; + U = s[i * 4 + 2] >> 6; + V = s[i * 4 + 3] >> 6; + + GST_WRITE_UINT16_BE (destY + i + 0, Y0); + GST_WRITE_UINT16_BE (destY + i + 1, Y1); + GST_WRITE_UINT16_BE (destU + (i >> 1), U); + GST_WRITE_UINT16_BE (destV + (i >> 1), V); + } + if (i == width - 1) { + Y0 = s[i * 4 + 1] >> 6; + U = s[i * 4 + 2] >> 6; + V = s[i * 4 + 3] >> 6; + + GST_WRITE_UINT16_BE (destY + i, Y0); + GST_WRITE_UINT16_BE (destU + (i >> 1), U); + GST_WRITE_UINT16_BE (destV + (i >> 1), V); + } + } else { + for (i = 0; i < width; i++) { + Y0 = s[i * 4 + 1] >> 6; + GST_WRITE_UINT16_BE (destY + i, Y0); + } } } diff --git a/gst-libs/gst/video/video-orc.orc b/gst-libs/gst/video/video-orc.orc index d414451..1ea3231 100644 --- a/gst-libs/gst/video/video-orc.orc +++ b/gst-libs/gst/video/video-orc.orc @@ -96,6 +96,14 @@ x2 splitwb vv, uu, uv select0wb u, uu select0wb v, vv +.function video_orc_pack_Y +.dest 1 y guint8 +.source 4 ayuv guint8 +.temp 2 ay + +select0lw ay, ayuv +select1wb y, ay + .function video_orc_unpack_YUY2 .dest 8 ayuv guint8 .source 4 yuy2 guint8 @@ -477,6 +485,16 @@ x2 splitwb vv, uu, uv select0wb u, uu select0wb v, vv +.function video_orc_pack_AY +.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_resample_bilinear_u32 .dest 4 d1 guint8 .source 4 s1 guint8 -- 2.7.4