summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2013-12-20 21:27:46 +0100
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2014-01-13 10:45:26 -0500
commitf8d3b9b4fcc5e08b771314fa95e9ed8f750b54e6 (patch)
tree5e81fd6f5909e9b824d09519198e1541a8e8c3fe
parent67a271723562eb259f67bece7f08a1af090d166e (diff)
video: add NV12T support
https://bugzilla.gnome.org/show_bug.cgi?id=707361
-rw-r--r--docs/design/part-mediatype-video-raw.txt43
-rw-r--r--gst-libs/gst/video/video-format.c241
-rw-r--r--gst-libs/gst/video/video-format.h4
-rw-r--r--gst-libs/gst/video/video-info.c10
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: