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 VMWARE 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 **************************************************************************/
28 /* Force assertions, even on release builds. */
37 #define BLOCK_HEIGHT 8
38 #define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT)
39 #define MACROBLOCK_WIDTH 16
40 #define MACROBLOCK_HEIGHT 16
41 #define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH)
42 #define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT)
43 #define BLOCKS_PER_MACROBLOCK 6
45 #define INPUT_WIDTH 64
46 #define INPUT_HEIGHT 64
47 #define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH)
48 #define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT)
49 #define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS)
51 #define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH
52 #define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT
53 #define DEFAULT_ACCEPTABLE_ERR 0.01
55 static void ParseArgs(int argc
, char **argv
, unsigned int *output_width
, unsigned int *output_height
, double *acceptable_error
, int *prompt
)
60 *output_width
= DEFAULT_OUTPUT_WIDTH
;
61 *output_height
= DEFAULT_OUTPUT_HEIGHT
;
62 *acceptable_error
= DEFAULT_ACCEPTABLE_ERR
;
65 for (i
= 1; i
< argc
&& !fail
; ++i
)
67 if (!strcmp(argv
[i
], "-w"))
69 if (sscanf(argv
[++i
], "%u", output_width
) != 1)
72 else if (!strcmp(argv
[i
], "-h"))
74 if (sscanf(argv
[++i
], "%u", output_height
) != 1)
77 else if (!strcmp(argv
[i
], "-e"))
79 if (sscanf(argv
[++i
], "%lf", acceptable_error
) != 1)
82 else if (!strcmp(argv
[i
], "-p"))
94 "Usage: %s [options]\n"
95 "\t-w <width>\tOutput width\n"
96 "\t-h <height>\tOutput height\n"
97 "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
98 "\t-p\tPrompt for quit\n",
105 static void Gradient(short *block
, unsigned int start
, unsigned int stop
, int horizontal
, unsigned int intra_unsigned
)
108 unsigned int range
= stop
- start
;
112 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
113 for (x
= 0; x
< BLOCK_WIDTH
; ++x
) {
114 *block
= (short)(start
+ range
* (x
/ (float)(BLOCK_WIDTH
- 1)));
122 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
123 for (x
= 0; x
< BLOCK_WIDTH
; ++x
) {
124 *block
= (short)(start
+ range
* (y
/ (float)(BLOCK_WIDTH
- 1)));
132 int main(int argc
, char **argv
)
134 unsigned int output_width
;
135 unsigned int output_height
;
136 double acceptable_error
;
140 const unsigned int mc_types
[] = {XVMC_MOCOMP
| XVMC_MPEG_2
};
143 unsigned int is_overlay
, intra_unsigned
;
147 XvMCBlockArray block_array
;
148 XvMCMacroBlockArray mb_array
;
149 int mbx
, mby
, bx
, by
;
154 ParseArgs(argc
, argv
, &output_width
, &output_height
, &acceptable_error
, &prompt
);
156 display
= XOpenDisplay(NULL
);
163 XVMC_CHROMA_FORMAT_420
,
165 sizeof(mc_types
)/sizeof(*mc_types
),
172 XCloseDisplay(display
);
173 fprintf(stderr
, "Error, unable to find a good port.\n");
179 Atom xv_colorkey
= XInternAtom(display
, "XV_COLORKEY", 0);
180 XvGetPortAttribute(display
, port_num
, xv_colorkey
, &colorkey
);
183 root
= XDefaultRootWindow(display
);
184 window
= XCreateSimpleWindow(display
, root
, 0, 0, output_width
, output_height
, 0, 0, colorkey
);
186 assert(XvMCCreateContext(display
, port_num
, surface_type_id
, INPUT_WIDTH
, INPUT_HEIGHT
, XVMC_DIRECT
, &context
) == Success
);
187 assert(XvMCCreateSurface(display
, &context
, &surface
) == Success
);
188 assert(XvMCCreateBlocks(display
, &context
, NUM_MACROBLOCKS
* BLOCKS_PER_MACROBLOCK
, &block_array
) == Success
);
189 assert(XvMCCreateMacroBlocks(display
, &context
, NUM_MACROBLOCKS
, &mb_array
) == Success
);
191 mb
= mb_array
.macro_blocks
;
192 blocks
= block_array
.blocks
;
194 for (mby
= 0; mby
< INPUT_HEIGHT_IN_MACROBLOCKS
; ++mby
)
195 for (mbx
= 0; mbx
< INPUT_WIDTH_IN_MACROBLOCKS
; ++mbx
)
199 mb
->macroblock_type
= XVMC_MB_TYPE_INTRA
;
200 /*mb->motion_type = ;*/
201 /*mb->motion_vertical_field_select = ;*/
202 mb
->dct_type
= XVMC_DCT_TYPE_FRAME
;
203 /*mb->PMV[0][0][0] = ;
210 mb->PMV[1][1][1] = ;*/
211 mb
->index
= (mby
* INPUT_WIDTH_IN_MACROBLOCKS
+ mbx
) * BLOCKS_PER_MACROBLOCK
;
212 mb
->coded_block_pattern
= 0x3F;
216 for (by
= 0; by
< MACROBLOCK_HEIGHT_IN_BLOCKS
; ++by
)
217 for (bx
= 0; bx
< MACROBLOCK_WIDTH_IN_BLOCKS
; ++bx
)
219 const int start
= 16, stop
= 235, range
= stop
- start
;
224 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
) / (float)(INPUT_WIDTH
- 1))),
225 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
+ BLOCK_WIDTH
- 1) / (float)(INPUT_WIDTH
- 1))),
230 blocks
+= BLOCK_SIZE
;
233 for (by
= 0; by
< MACROBLOCK_HEIGHT_IN_BLOCKS
/ 2; ++by
)
234 for (bx
= 0; bx
< MACROBLOCK_WIDTH_IN_BLOCKS
/ 2; ++bx
)
236 const int start
= 16, stop
= 240, range
= stop
- start
;
241 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
) / (float)(INPUT_WIDTH
- 1))),
242 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
+ BLOCK_WIDTH
- 1) / (float)(INPUT_WIDTH
- 1))),
247 blocks
+= BLOCK_SIZE
;
252 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
) / (float)(INPUT_WIDTH
- 1))),
253 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
+ BLOCK_WIDTH
- 1) / (float)(INPUT_WIDTH
- 1))),
258 blocks
+= BLOCK_SIZE
;
262 XSelectInput(display
, window
, ExposureMask
| KeyPressMask
);
263 XMapWindow(display
, window
);
266 /* Test NULL context */
267 assert(XvMCRenderSurface(display
, NULL
, XVMC_FRAME_PICTURE
, &surface
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == XvMCBadContext
);
268 /* Test NULL surface */
269 assert(XvMCRenderSurface(display
, &context
, XVMC_FRAME_PICTURE
, NULL
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == XvMCBadSurface
);
270 /* Test bad picture structure */
271 assert(XvMCRenderSurface(display
, &context
, 0, &surface
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == BadValue
);
272 /* Test valid params */
273 assert(XvMCRenderSurface(display
, &context
, XVMC_FRAME_PICTURE
, &surface
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == Success
);
275 /* Test NULL surface */
276 assert(XvMCPutSurface(display
, NULL
, window
, 0, 0, INPUT_WIDTH
, INPUT_HEIGHT
, 0, 0, output_width
, output_height
, XVMC_FRAME_PICTURE
) == XvMCBadSurface
);
277 /* Test bad window */
278 /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
279 /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
283 puts("Press any button to quit...");
287 if (XPending(display
) > 0)
291 XNextEvent(display
, &event
);
297 /* Test valid params */
302 display
, &surface
, window
,
303 0, 0, INPUT_WIDTH
, INPUT_HEIGHT
,
304 0, 0, output_width
, output_height
,
320 assert(XvMCDestroyBlocks(display
, &block_array
) == Success
);
321 assert(XvMCDestroyMacroBlocks(display
, &mb_array
) == Success
);
322 assert(XvMCDestroySurface(display
, &surface
) == Success
);
323 assert(XvMCDestroyContext(display
, &context
) == Success
);
325 XvUngrabPort(display
, port_num
, CurrentTime
);
326 XDestroyWindow(display
, window
);
327 XCloseDisplay(display
);