1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
35 #define BLOCK_HEIGHT 8
36 #define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT)
37 #define MACROBLOCK_WIDTH 16
38 #define MACROBLOCK_HEIGHT 16
39 #define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH)
40 #define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT)
41 #define BLOCKS_PER_MACROBLOCK 6
43 #define INPUT_WIDTH 16
44 #define INPUT_HEIGHT 16
45 #define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH)
46 #define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT)
47 #define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS)
49 #define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH
50 #define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT
51 #define DEFAULT_ACCEPTABLE_ERR 0.01
53 void ParseArgs(int argc
, char **argv
, unsigned int *output_width
, unsigned int *output_height
, double *acceptable_error
, int *prompt
);
54 void Gradient(short *block
, unsigned int start
, unsigned int stop
, int horizontal
);
56 void ParseArgs(int argc
, char **argv
, unsigned int *output_width
, unsigned int *output_height
, double *acceptable_error
, int *prompt
)
61 *output_width
= DEFAULT_OUTPUT_WIDTH
;
62 *output_height
= DEFAULT_OUTPUT_WIDTH
;
63 *acceptable_error
= DEFAULT_ACCEPTABLE_ERR
;
66 for (i
= 1; i
< argc
&& !fail
; ++i
)
68 if (!strcmp(argv
[i
], "-w"))
70 if (sscanf(argv
[++i
], "%u", output_width
) != 1)
73 else if (!strcmp(argv
[i
], "-h"))
75 if (sscanf(argv
[++i
], "%u", output_height
) != 1)
78 else if (!strcmp(argv
[i
], "-e"))
80 if (sscanf(argv
[++i
], "%lf", acceptable_error
) != 1)
83 else if (strcmp(argv
[i
], "-n"))
95 "Usage: %s [options]\n"
96 "\t-w <width>\tOutput width\n"
97 "\t-h <height>\tOutput height\n"
98 "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
99 "\t-n\tDon't prompt for quit\n",
104 void Gradient(short *block
, unsigned int start
, unsigned int stop
, int horizontal
)
107 unsigned int range
= stop
- start
;
111 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
112 for (x
= 0; x
< BLOCK_WIDTH
; ++x
)
113 block
[y
* BLOCK_WIDTH
+ x
] = (short)(start
+ range
* (x
/ (float)(BLOCK_WIDTH
- 1)));
117 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
118 for (x
= 0; x
< BLOCK_WIDTH
; ++x
)
119 block
[y
* BLOCK_WIDTH
+ x
] = (short)(start
+ range
* (y
/ (float)(BLOCK_HEIGHT
- 1)));
123 int main(int argc
, char **argv
)
125 unsigned int output_width
;
126 unsigned int output_height
;
127 double acceptable_error
;
131 const unsigned int mc_types
[2] = {XVMC_MOCOMP
| XVMC_MPEG_2
, XVMC_IDCT
| XVMC_MPEG_2
};
134 unsigned int is_overlay
, intra_unsigned
;
138 XvMCBlockArray block_array
;
139 XvMCMacroBlockArray mb_array
;
140 int mbx
, mby
, bx
, by
;
145 ParseArgs(argc
, argv
, &output_width
, &output_height
, &acceptable_error
, &prompt
);
147 display
= XOpenDisplay(NULL
);
154 XVMC_CHROMA_FORMAT_420
,
163 XCloseDisplay(display
);
164 error(1, 0, "Error, unable to find a good port.\n");
169 Atom xv_colorkey
= XInternAtom(display
, "XV_COLORKEY", 0);
170 XvGetPortAttribute(display
, port_num
, xv_colorkey
, &colorkey
);
173 root
= XDefaultRootWindow(display
);
174 window
= XCreateSimpleWindow(display
, root
, 0, 0, output_width
, output_height
, 0, 0, colorkey
);
176 assert(XvMCCreateContext(display
, port_num
, surface_type_id
, INPUT_WIDTH
, INPUT_HEIGHT
, XVMC_DIRECT
, &context
) == Success
);
177 assert(XvMCCreateSurface(display
, &context
, &surface
) == Success
);
178 assert(XvMCCreateBlocks(display
, &context
, NUM_MACROBLOCKS
* BLOCKS_PER_MACROBLOCK
, &block_array
) == Success
);
179 assert(XvMCCreateMacroBlocks(display
, &context
, NUM_MACROBLOCKS
, &mb_array
) == Success
);
181 mb
= mb_array
.macro_blocks
;
182 blocks
= block_array
.blocks
;
184 for (mby
= 0; mby
< INPUT_HEIGHT_IN_MACROBLOCKS
; ++mby
)
185 for (mbx
= 0; mbx
< INPUT_WIDTH_IN_MACROBLOCKS
; ++mbx
)
189 mb
->macroblock_type
= XVMC_MB_TYPE_INTRA
;
190 /*mb->motion_type = ;*/
191 /*mb->motion_vertical_field_select = ;*/
192 mb
->dct_type
= XVMC_DCT_TYPE_FRAME
;
193 /*mb->PMV[0][0][0] = ;
200 mb->PMV[1][1][1] = ;*/
201 mb
->index
= (mby
* INPUT_WIDTH_IN_MACROBLOCKS
+ mbx
) * BLOCKS_PER_MACROBLOCK
;
202 mb
->coded_block_pattern
= 0x3F;
206 for (by
= 0; by
< MACROBLOCK_HEIGHT_IN_BLOCKS
; ++by
)
207 for (bx
= 0; bx
< MACROBLOCK_WIDTH_IN_BLOCKS
; ++bx
)
209 const int start
= 16, stop
= 235, range
= stop
- start
;
214 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
) / (float)(INPUT_WIDTH
- 1))),
215 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
+ BLOCK_WIDTH
- 1) / (float)(INPUT_WIDTH
- 1))),
219 blocks
+= BLOCK_SIZE
;
222 for (by
= 0; by
< MACROBLOCK_HEIGHT_IN_BLOCKS
/ 2; ++by
)
223 for (bx
= 0; bx
< MACROBLOCK_WIDTH_IN_BLOCKS
/ 2; ++bx
)
225 const int start
= 16, stop
= 240, range
= stop
- start
;
230 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
) / (float)(INPUT_WIDTH
- 1))),
231 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
+ BLOCK_WIDTH
- 1) / (float)(INPUT_WIDTH
- 1))),
235 blocks
+= BLOCK_SIZE
;
240 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
) / (float)(INPUT_WIDTH
- 1))),
241 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
+ BLOCK_WIDTH
- 1) / (float)(INPUT_WIDTH
- 1))),
245 blocks
+= BLOCK_SIZE
;
249 XSelectInput(display
, window
, ExposureMask
| KeyPressMask
);
250 XMapWindow(display
, window
);
253 /* Test NULL context */
254 assert(XvMCRenderSurface(display
, NULL
, XVMC_FRAME_PICTURE
, &surface
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == XvMCBadContext
);
255 /* Test NULL surface */
256 assert(XvMCRenderSurface(display
, &context
, XVMC_FRAME_PICTURE
, NULL
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == XvMCBadSurface
);
257 /* Test bad picture structure */
258 assert(XvMCRenderSurface(display
, &context
, 0, &surface
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == BadValue
);
259 /* Test valid params */
260 assert(XvMCRenderSurface(display
, &context
, XVMC_FRAME_PICTURE
, &surface
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == Success
);
262 /* Test NULL surface */
263 assert(XvMCPutSurface(display
, NULL
, window
, 0, 0, INPUT_WIDTH
, INPUT_HEIGHT
, 0, 0, output_width
, output_height
, XVMC_FRAME_PICTURE
) == XvMCBadSurface
);
264 /* Test bad window */
265 /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
266 /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
270 puts("Press any button to quit...");
274 if (XPending(display
) > 0)
278 XNextEvent(display
, &event
);
284 /* Test valid params */
289 display
, &surface
, window
,
290 0, 0, INPUT_WIDTH
, INPUT_HEIGHT
,
291 0, 0, output_width
, output_height
,
307 assert(XvMCDestroyBlocks(display
, &block_array
) == Success
);
308 assert(XvMCDestroyMacroBlocks(display
, &mb_array
) == Success
);
309 assert(XvMCDestroySurface(display
, &surface
) == Success
);
310 assert(XvMCDestroyContext(display
, &context
) == Success
);
312 XvUngrabPort(display
, port_num
, CurrentTime
);
313 XDestroyWindow(display
, window
);
314 XCloseDisplay(display
);