diff options
author | Wim Taymans <wtaymans@redhat.com> | 2013-12-20 21:27:46 +0100 |
---|---|---|
committer | Nicolas Dufresne <nicolas.dufresne@collabora.com> | 2014-01-13 10:45:26 -0500 |
commit | f8d3b9b4fcc5e08b771314fa95e9ed8f750b54e6 (patch) | |
tree | 5e81fd6f5909e9b824d09519198e1541a8e8c3fe | |
parent | 67a271723562eb259f67bece7f08a1af090d166e (diff) |
video: add NV12T support
https://bugzilla.gnome.org/show_bug.cgi?id=707361
-rw-r--r-- | docs/design/part-mediatype-video-raw.txt | 43 | ||||
-rw-r--r-- | gst-libs/gst/video/video-format.c | 241 | ||||
-rw-r--r-- | gst-libs/gst/video/video-format.h | 4 | ||||
-rw-r--r-- | gst-libs/gst/video/video-info.c | 10 |
4 files changed, 297 insertions, 1 deletions
diff --git a/docs/design/part-mediatype-video-raw.txt b/docs/design/part-mediatype-video-raw.txt index 5e74dec34..c66a075c7 100644 --- a/docs/design/part-mediatype-video-raw.txt +++ b/docs/design/part-mediatype-video-raw.txt @@ -1188,3 +1188,46 @@ Formats default size: size (component0) + size (component1) + size (component2) + + "Y444_10BE" planar 4:4:4 YUV, 10 bits per channel + "Y444_10LE" planar 4:4:4 YUV, 10 bits per channel + + "GBR" planar 4:4:4 RGB, 8 bits per channel + "GBR_10BE" planar 4:4:4 RGB, 10 bits per channel + "GBR_10LE" planar 4:4:4 RGB, 10 bits per channel + + "NV16" planar 4:2:2 YUV with interleaved UV plane + "NV24" planar 4:4:4 YUV with interleaved UV plane + + + "NV12T" planar 4:2:0 YUV with interleaved UV plane in 64x32 tiles zigzag + + Component 0: Y + depth: 8 + pstride: 1 + default offset: 0 + default rstride: RU128 (width) + default size: rstride (component0) * RU32 (height) + + Component 1: U + depth 8 + pstride: 2 + default offset: size (component0) + default rstride: RU128 (width) + + Component 2: V + depth: 8 + pstride: 2 + default offset: offset (component1) + 1 + default rstride: RU128 (width) + + Component 3: T + pstride TileMode zigzag + w_sub 6 + h_sub 5 + default offset: 0 + default rstride: y_tiles + + Image + default size: RU128 (width) * RU32 (height) * 3 / 2 + diff --git a/gst-libs/gst/video/video-format.c b/gst-libs/gst/video/video-format.c index 2b3f4b0f6..85977a292 100644 --- a/gst-libs/gst/video/video-format.c +++ b/gst-libs/gst/video/video-format.c @@ -2082,6 +2082,238 @@ pack_I422_10BE (const GstVideoFormatInfo * info, GstVideoPackFlags flags, } } +/** + * GstVideoTileMode: + * @GST_VIDEO_TILE_MODE_UNKNOWN: Unknown or unset video format id + * @GST_VIDEO_TILE_MODE_ZFLIPZ_2X2: Every four adjacent buffers - two + * horizontally and two vertically are grouped together and are located + * in memory in Z or flipped Z order. + * + * Enum value describing the most common video formats. + */ +typedef enum +{ + GST_VIDEO_TILE_MODE_NONE, + GST_VIDEO_TILE_MODE_ZFLIPZ_2X2, +} GstVideoTileMode; + +/** + * gst_video_tile_get_index: + * @mode: a #GstVideoTileMode + * @x: x coordinate + * @y: y coordinate + * @x_tiles: number of horizintal tiles + * @y_tiles: number of vertical tiles + * + * Get the tile index of the tile at coordinates @x and @y. + * + * Returns: the index of the tile at @x and @y in the tiled image of + * @x_tiles by @y_tiles. + */ +static gsize +gst_video_tile_get_index (GstVideoTileMode mode, gint x, gint y, + gint x_tiles, gint y_tiles) +{ + gsize offset; + + switch (mode) { + case GST_VIDEO_TILE_MODE_ZFLIPZ_2X2: + /* Due to the zigzag pattern we know that tiles are numbered like: + * (see http://linuxtv.org/downloads/v4l-dvb-apis/re31.html) + * + * | Column (x) + * | 0 1 2 3 4 5 6 7 + * -------|--------------------------------------- + * 0 | 0 1 6 7 8 9 14 15 + * R 1 | 2 3 4 5 10 11 12 13 + * o 2 | 16 17 22 23 24 25 30 31 + * w 3 | 18 19 20 21 26 27 28 29 + * 4 | 32 33 38 39 40 41 46 47 + * (y) 5 | 34 35 36 37 42 43 44 45 + * 6 | 48 49 50 51 52 53 54 55 + * + * From this we can see that: + * + * For even rows: + * - The first block in a row is always mapped to memory block 'y * width'. + * - For all even rows, except for the last one when 'y' is odd, from the first + * block number an offset is then added to obtain the block number for + * the other blocks in the row. The offset is 'x' plus the corresponding + * number in the series [0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, ...], which can be + * expressed as 'GST_ROUND_DOWN_4 (x + 2)'. + * f(x,y,width,height) = y * width + x + GST_ROUND_DOWN_4 (x + 2) + * + * - For the last row when 'y' is odd the offset is simply 'x'. + * f(x,y,width,height) = y * width + x + * - Note that 'y' is even, so 'GST_ROUNDOWN_2 (y) == y' in this case + * + * For odd rows: + * - The first block in the row is always mapped to memory block + * 'GST_ROUND_DOWN_2(y) * width + 2'. + * - From the first block number an offset is then added to obtain the block + * number for the other blocks in the row. The offset is 'x' plus the + * corresponding number in the series [0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, ...], + * which can be expressed as GST_ROUND_DOWN_4 (x). + * f(x,y,width,height) = GST_ROUND_DOWN_2 (y) * width + bx 2 + GST_ROUND_DOWN_4 (x) + */ + /* Common to all cases */ + offset = GST_ROUND_DOWN_2 (y) * x_tiles + x; + + if (y & 1) { + /* For odd row */ + offset += 2 + GST_ROUND_DOWN_4 (x); + } else if ((y_tiles & 1) == 0 || y != (y_tiles - 1)) { + /* For even row except for the last row when odd height */ + offset += GST_ROUND_DOWN_4 (x + 2); + } + break; + default: + offset = 0; + break; + } + return offset; +} + +static void +get_tile_NV12 (gint tile_width, gint tile_height, gint tile_size, gint tx, + gint ty, gint x_tiles, gint y_tiles, + const gpointer data[GST_VIDEO_MAX_PLANES], + const gint stride[GST_VIDEO_MAX_PLANES], + gpointer tile_data[GST_VIDEO_MAX_PLANES], + gint tile_stride[GST_VIDEO_MAX_PLANES]) +{ + gsize offset; + + /* index of Y tile */ + offset = gst_video_tile_get_index (GST_VIDEO_TILE_MODE_ZFLIPZ_2X2, + tx, ty, x_tiles, y_tiles); + offset *= tile_size; + tile_data[0] = ((guint8 *) data[0]) + offset; + tile_stride[0] = tile_width; + + /* index of UV tile */ + offset = gst_video_tile_get_index (GST_VIDEO_TILE_MODE_ZFLIPZ_2X2, + tx, ty >> 1, x_tiles, (y_tiles + 1) >> 1); + offset *= tile_size; + /* On odd rows we return the second part of the UV tile */ + if (ty & 1) + offset += tile_width * (tile_height >> 1); + tile_data[1] = ((guint8 *) data[1]) + offset; + tile_stride[1] = tile_width; +} + +#define PACK_NV12T GST_VIDEO_FORMAT_AYUV, unpack_NV12T, 1, pack_NV12T +static void +unpack_NV12T (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) +{ + const GstVideoFormatInfo *unpack_info, *finfo; + guint8 *line = dest; + gint x_tiles, y_tiles; + gint tile_width, tile_height, tile_size; + gint ntx, tx, ty; + gint unpack_pstride; + + tile_width = 1 << info->w_sub[3]; + tile_height = 1 << info->h_sub[3]; + tile_size = tile_width * tile_height; + + x_tiles = stride[0] / 64; + y_tiles = stride[2]; + + /* we reuse these unpack functions */ + finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_NV12); + + /* get pstride of unpacked format */ + unpack_info = gst_video_format_get_info (info->unpack_format); + unpack_pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (unpack_info, 0); + + /* first x tile to convert */ + tx = x / tile_width; + /* Last tile to convert */ + ntx = (x + width) / tile_width; + /* The row we are going to convert */ + ty = y / tile_height; + + /* y position in a tile */ + y = y & (tile_height - 1); + /* x position in a tile */ + x = x & (tile_width - 1); + + for (; tx <= ntx; tx++) { + gpointer tdata[GST_VIDEO_MAX_PLANES]; + gint tstride[GST_VIDEO_MAX_PLANES]; + gint unpack_width; + + get_tile_NV12 (tile_width, tile_height, tile_size, tx, ty, x_tiles, y_tiles, + data, stride, tdata, tstride); + + /* the number of bytes left to unpack */ + unpack_width = MIN (width - x, tile_width - x); + + finfo->unpack_func (finfo, flags, line, tdata, tstride, x, y, unpack_width); + + x = 0; + width -= unpack_width; + line += unpack_width * unpack_pstride; + } +} + +static void +pack_NV12T (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) +{ + const GstVideoFormatInfo *pack_info, *finfo; + guint8 *line = src; + gint x_tiles, y_tiles; + gint tile_width, tile_height, tile_size; + gint ntx, tx, ty; + gint pack_pstride; + + tile_width = 1 << info->w_sub[3]; + tile_height = 1 << info->h_sub[3]; + tile_size = tile_width * tile_height; + + x_tiles = stride[0] / 64; + y_tiles = stride[2]; + + /* we reuse these pack functions */ + finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_NV12); + + /* get pstride of packed format */ + pack_info = gst_video_format_get_info (info->unpack_format); + pack_pstride = GST_VIDEO_FORMAT_INFO_PSTRIDE (pack_info, 0); + + /* Last tile to convert */ + ntx = width / tile_width; + /* The row we are going to convert */ + ty = y / tile_height; + + /* y position in a tile */ + y = y & (tile_height - 1); + + for (tx = 0; tx < ntx; tx++) { + gpointer tdata[GST_VIDEO_MAX_PLANES]; + gint tstride[GST_VIDEO_MAX_PLANES]; + gint pack_width; + + get_tile_NV12 (tile_width, tile_height, tile_size, tx, ty, x_tiles, y_tiles, + data, stride, tdata, tstride); + + /* the number of bytes left to pack */ + pack_width = MIN (width, tile_width); + + finfo->pack_func (finfo, flags, line, sstride, tdata, tstride, + chroma_site, y, pack_width); + + width -= pack_width; + line += pack_width * pack_pstride; + } +} + typedef struct { guint32 fourcc; @@ -2094,6 +2326,7 @@ typedef struct #define DPTH8_32 8, 2, { 0, 0, 0, 0 }, { 8, 32, 0, 0 } #define DPTH888 8, 3, { 0, 0, 0, 0 }, { 8, 8, 8, 0 } #define DPTH8888 8, 4, { 0, 0, 0, 0 }, { 8, 8, 8, 8 } +#define DPTH8880 8, 4, { 0, 0, 0, 0 }, { 8, 8, 8, 0 } #define DPTH10_10_10 10, 3, { 0, 0, 0, 0 }, { 10, 10, 10, 0 } #define DPTH16 16, 1, { 0, 0, 0, 0 }, { 16, 0, 0, 0 } #define DPTH16_16_16 16, 3, { 0, 0, 0, 0 }, { 16, 16, 16, 0 } @@ -2108,6 +2341,7 @@ typedef struct #define PSTR111 { 1, 1, 1, 0 } #define PSTR1111 { 1, 1, 1, 1 } #define PSTR122 { 1, 2, 2, 0 } +#define PSTR122T(mode) { 1, 2, 2, GST_VIDEO_TILE_MODE_ ##mode } #define PSTR2 { 2, 0, 0, 0 } #define PSTR222 { 2, 2, 2, 0 } #define PSTR244 { 2, 4, 4, 0 } @@ -2122,6 +2356,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 PLANE0110 3, { 0, 1, 1, 0 } #define PLANE012 3, { 0, 1, 2, 0 } #define PLANE0123 4, { 0, 1, 2, 3 } #define PLANE021 3, { 0, 2, 1, 0 } @@ -2150,6 +2385,7 @@ typedef struct #define SUB410 { 0, 2, 2, 0 }, { 0, 2, 2, 0 } #define SUB411 { 0, 2, 2, 0 }, { 0, 0, 0, 0 } #define SUB420 { 0, 1, 1, 0 }, { 0, 1, 1, 0 } +#define SUB420T64x32 { 0, 1, 1, 6 }, { 0, 1, 1, 5 } #define SUB422 { 0, 1, 1, 0 }, { 0, 0, 0, 0 } #define SUB4 { 0, 0, 0, 0 }, { 0, 0, 0, 0 } #define SUB44 { 0, 0, 0, 0 }, { 0, 0, 0, 0 } @@ -2169,6 +2405,8 @@ typedef struct { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_ALPHA | GST_VIDEO_FORMAT_FLAG_UNPACK | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub, pack } } #define MAKE_YUV_C_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \ { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_COMPLEX, depth, pstride, plane, offs, sub, pack } } +#define MAKE_YUV_T_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub, pack) \ + { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_COMPLEX | GST_VIDEO_FORMAT_FLAG_TILED, depth, pstride, plane, offs, sub, pack } } #define MAKE_RGB_FORMAT(name, desc, depth, pstride, plane, offs, sub, pack) \ { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB, depth, pstride, plane, offs, sub, pack } } @@ -2322,6 +2560,9 @@ static VideoFormat formats[] = { DPTH888, PSTR111, PLANE011, OFFS001, SUB422, PACK_NV16), MAKE_YUV_FORMAT (NV24, "raw video", GST_MAKE_FOURCC ('N', 'V', '2', '4'), DPTH888, PSTR111, PLANE011, OFFS001, SUB444, PACK_NV24), + MAKE_YUV_T_FORMAT (NV12T, "raw video", + GST_MAKE_FOURCC ('T', 'M', '1', '2'), DPTH8880, PSTR122T (ZFLIPZ_2X2), + PLANE0110, OFFS001, SUB420T64x32, PACK_NV12T), }; static GstVideoFormat diff --git a/gst-libs/gst/video/video-format.h b/gst-libs/gst/video/video-format.h index f75e2bee8..3060c4c87 100644 --- a/gst-libs/gst/video/video-format.h +++ b/gst-libs/gst/video/video-format.h @@ -84,6 +84,7 @@ G_BEGIN_DECLS * @GST_VIDEO_FORMAT_GBR_10LE: planar 4:4:4 RGB, 10 bits per channel * @GST_VIDEO_FORMAT_NV16: planar 4:2:2 YUV with interleaved UV plane * @GST_VIDEO_FORMAT_NV24: planar 4:4:4 YUV with interleaved UV plane + * @GST_VIDEO_FORMAT_NV12T: NV12 with tiling * * Enum value describing the most common video formats. */ @@ -141,6 +142,7 @@ typedef enum { GST_VIDEO_FORMAT_GBR_10LE, GST_VIDEO_FORMAT_NV16, GST_VIDEO_FORMAT_NV24, + GST_VIDEO_FORMAT_NV12T, } GstVideoFormat; #define GST_VIDEO_MAX_PLANES 4 @@ -444,7 +446,7 @@ gconstpointer gst_video_format_get_palette (GstVideoFormat format, gsi "YVYU, Y444, v210, v216, NV12, NV21, NV16, NV24, GRAY8, GRAY16_BE, GRAY16_LE, " \ "v308, RGB16, BGR16, RGB15, BGR15, UYVP, A420, RGB8P, YUV9, YVU9, " \ "IYU1, ARGB64, AYUV64, r210, I420_10LE, I420_10BE, I422_10LE, I422_10BE, " \ - " Y444_10LE, Y444_10BE, GBR, GBR_10LE, GBR_10BE }" + " Y444_10LE, Y444_10BE, GBR, GBR_10LE, GBR_10BE, NV12T }" /** * GST_VIDEO_CAPS_MAKE: diff --git a/gst-libs/gst/video/video-info.c b/gst-libs/gst/video/video-info.c index 5e07b915a..6234b37bb 100644 --- a/gst-libs/gst/video/video-info.c +++ b/gst-libs/gst/video/video-info.c @@ -573,6 +573,16 @@ fill_planes (GstVideoInfo * info) info->offset[2] = info->offset[1] * 2; info->size = info->stride[0] * height * 3; break; + case GST_VIDEO_FORMAT_NV12T: + info->stride[0] = GST_ROUND_UP_128 (width); + info->stride[1] = info->stride[0]; + info->stride[2] = GST_ROUND_UP_32 (height) / 32; + info->offset[0] = 0; + info->offset[1] = info->stride[0] * GST_ROUND_UP_32 (height); + info->offset[2] = 0; + info->size = + info->offset[1] + info->stride[0] * GST_ROUND_UP_64 (height) / 2; + break; case GST_VIDEO_FORMAT_ENCODED: break; case GST_VIDEO_FORMAT_UNKNOWN: |