1 /* GStreamer
2 * Copyright (C) <2013> Wim Taymans <wim.taymans@gmail.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <gst/video/video-tile.h>
24
25 /**
26 * gst_video_tile_get_index:
27 * @mode: a #GstVideoTileMode
28 * @x: x coordinate
29 * @y: y coordinate
30 * @x_tiles: number of horizintal tiles
31 * @y_tiles: number of vertical tiles
32 *
33 * Get the tile index of the tile at coordinates @x and @y in the tiled
34 * image of @x_tiles by @y_tiles.
35 *
36 * Use this method when @mode is of type %GST_VIDEO_TILE_TYPE_INDEXED.
37 *
38 * Returns: the index of the tile at @x and @y in the tiled image of
39 * @x_tiles by @y_tiles.
40 *
41 * Since: 1.4
42 */
43 guint
gst_video_tile_get_index(GstVideoTileMode mode,gint x,gint y,gint x_tiles,gint y_tiles)44 gst_video_tile_get_index (GstVideoTileMode mode, gint x, gint y,
45 gint x_tiles, gint y_tiles)
46 {
47 gsize offset;
48
49 g_return_val_if_fail (GST_VIDEO_TILE_MODE_IS_INDEXED (mode), 0);
50
51 switch (mode) {
52 case GST_VIDEO_TILE_MODE_ZFLIPZ_2X2:
53 /* Due to the zigzag pattern we know that tiles are numbered like:
54 * (see http://linuxtv.org/downloads/v4l-dvb-apis/re31.html)
55 *
56 * | Column (x)
57 * | 0 1 2 3 4 5 6 7
58 * -------|---------------------------------------
59 * 0 | 0 1 6 7 8 9 14 15
60 * R 1 | 2 3 4 5 10 11 12 13
61 * o 2 | 16 17 22 23 24 25 30 31
62 * w 3 | 18 19 20 21 26 27 28 29
63 * 4 | 32 33 38 39 40 41 46 47
64 * (y) 5 | 34 35 36 37 42 43 44 45
65 * 6 | 48 49 50 51 52 53 54 55
66 *
67 * From this we can see that:
68 *
69 * For even rows:
70 * - The first block in a row is always mapped to memory block 'y * width'.
71 * - For all even rows, except for the last one when 'y' is odd, from the first
72 * block number an offset is then added to obtain the block number for
73 * the other blocks in the row. The offset is 'x' plus the corresponding
74 * number in the series [0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, ...], which can be
75 * expressed as 'GST_ROUND_DOWN_4 (x + 2)'.
76 * f(x,y,width,height) = y * width + x + GST_ROUND_DOWN_4 (x + 2)
77 *
78 * - For the last row when 'y' is odd the offset is simply 'x'.
79 * f(x,y,width,height) = y * width + x
80 * - Note that 'y' is even, so 'GST_ROUNDOWN_2 (y) == y' in this case
81 *
82 * For odd rows:
83 * - The first block in the row is always mapped to memory block
84 * 'GST_ROUND_DOWN_2(y) * width + 2'.
85 * - From the first block number an offset is then added to obtain the block
86 * number for the other blocks in the row. The offset is 'x' plus the
87 * corresponding number in the series [0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, ...],
88 * which can be expressed as GST_ROUND_DOWN_4 (x).
89 * f(x,y,width,height) = GST_ROUND_DOWN_2 (y) * width + bx 2 + GST_ROUND_DOWN_4 (x)
90 */
91 /* Common to all cases */
92 offset = GST_ROUND_DOWN_2 (y) * x_tiles + x;
93
94 if (y & 1) {
95 /* For odd row */
96 offset += 2 + GST_ROUND_DOWN_4 (x);
97 } else if ((y_tiles & 1) == 0 || y != (y_tiles - 1)) {
98 /* For even row except for the last row when odd height */
99 offset += GST_ROUND_DOWN_4 (x + 2);
100 }
101 break;
102 case GST_VIDEO_TILE_MODE_LINEAR:
103 offset = y * x_tiles + x;
104 break;
105 default:
106 offset = 0;
107 break;
108 }
109 return offset;
110 }
111