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 **************************************************************************/
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 64
44 #define INPUT_HEIGHT 64
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 static void ParseArgs(int argc
, char **argv
, unsigned int *output_width
, unsigned int *output_height
, double *acceptable_error
, int *prompt
)
58 *output_width
= DEFAULT_OUTPUT_WIDTH
;
59 *output_height
= DEFAULT_OUTPUT_HEIGHT
;
60 *acceptable_error
= DEFAULT_ACCEPTABLE_ERR
;
63 for (i
= 1; i
< argc
&& !fail
; ++i
)
65 if (!strcmp(argv
[i
], "-w"))
67 if (sscanf(argv
[++i
], "%u", output_width
) != 1)
70 else if (!strcmp(argv
[i
], "-h"))
72 if (sscanf(argv
[++i
], "%u", output_height
) != 1)
75 else if (!strcmp(argv
[i
], "-e"))
77 if (sscanf(argv
[++i
], "%lf", acceptable_error
) != 1)
80 else if (!strcmp(argv
[i
], "-p"))
92 "Usage: %s [options]\n"
93 "\t-w <width>\tOutput width\n"
94 "\t-h <height>\tOutput height\n"
95 "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
96 "\t-p\tPrompt for quit\n",
101 static void Gradient(short *block
, unsigned int start
, unsigned int stop
, int horizontal
, unsigned int intra_unsigned
)
104 unsigned int range
= stop
- start
;
108 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
109 for (x
= 0; x
< BLOCK_WIDTH
; ++x
) {
110 *block
= (short)(start
+ range
* (x
/ (float)(BLOCK_WIDTH
- 1)));
118 for (y
= 0; y
< BLOCK_HEIGHT
; ++y
)
119 for (x
= 0; x
< BLOCK_WIDTH
; ++x
) {
120 *block
= (short)(start
+ range
* (y
/ (float)(BLOCK_WIDTH
- 1)));
128 int main(int argc
, char **argv
)
130 unsigned int output_width
;
131 unsigned int output_height
;
132 double acceptable_error
;
136 const unsigned int mc_types
[] = {XVMC_MOCOMP
| XVMC_MPEG_2
};
139 unsigned int is_overlay
, intra_unsigned
;
143 XvMCBlockArray block_array
;
144 XvMCMacroBlockArray mb_array
;
145 int mbx
, mby
, bx
, by
;
150 ParseArgs(argc
, argv
, &output_width
, &output_height
, &acceptable_error
, &prompt
);
152 display
= XOpenDisplay(NULL
);
159 XVMC_CHROMA_FORMAT_420
,
161 sizeof(mc_types
)/sizeof(*mc_types
),
168 XCloseDisplay(display
);
169 error(1, 0, "Error, unable to find a good port.\n");
174 Atom xv_colorkey
= XInternAtom(display
, "XV_COLORKEY", 0);
175 XvGetPortAttribute(display
, port_num
, xv_colorkey
, &colorkey
);
178 root
= XDefaultRootWindow(display
);
179 window
= XCreateSimpleWindow(display
, root
, 0, 0, output_width
, output_height
, 0, 0, colorkey
);
181 assert(XvMCCreateContext(display
, port_num
, surface_type_id
, INPUT_WIDTH
, INPUT_HEIGHT
, XVMC_DIRECT
, &context
) == Success
);
182 assert(XvMCCreateSurface(display
, &context
, &surface
) == Success
);
183 assert(XvMCCreateBlocks(display
, &context
, NUM_MACROBLOCKS
* BLOCKS_PER_MACROBLOCK
, &block_array
) == Success
);
184 assert(XvMCCreateMacroBlocks(display
, &context
, NUM_MACROBLOCKS
, &mb_array
) == Success
);
186 mb
= mb_array
.macro_blocks
;
187 blocks
= block_array
.blocks
;
189 for (mby
= 0; mby
< INPUT_HEIGHT_IN_MACROBLOCKS
; ++mby
)
190 for (mbx
= 0; mbx
< INPUT_WIDTH_IN_MACROBLOCKS
; ++mbx
)
194 mb
->macroblock_type
= XVMC_MB_TYPE_INTRA
;
195 /*mb->motion_type = ;*/
196 /*mb->motion_vertical_field_select = ;*/
197 mb
->dct_type
= XVMC_DCT_TYPE_FRAME
;
198 /*mb->PMV[0][0][0] = ;
205 mb->PMV[1][1][1] = ;*/
206 mb
->index
= (mby
* INPUT_WIDTH_IN_MACROBLOCKS
+ mbx
) * BLOCKS_PER_MACROBLOCK
;
207 mb
->coded_block_pattern
= 0x3F;
211 for (by
= 0; by
< MACROBLOCK_HEIGHT_IN_BLOCKS
; ++by
)
212 for (bx
= 0; bx
< MACROBLOCK_WIDTH_IN_BLOCKS
; ++bx
)
214 const int start
= 16, stop
= 235, range
= stop
- start
;
219 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
) / (float)(INPUT_WIDTH
- 1))),
220 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
+ BLOCK_WIDTH
- 1) / (float)(INPUT_WIDTH
- 1))),
225 blocks
+= BLOCK_SIZE
;
228 for (by
= 0; by
< MACROBLOCK_HEIGHT_IN_BLOCKS
/ 2; ++by
)
229 for (bx
= 0; bx
< MACROBLOCK_WIDTH_IN_BLOCKS
/ 2; ++bx
)
231 const int start
= 16, stop
= 240, range
= stop
- start
;
236 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
) / (float)(INPUT_WIDTH
- 1))),
237 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
+ BLOCK_WIDTH
- 1) / (float)(INPUT_WIDTH
- 1))),
242 blocks
+= BLOCK_SIZE
;
247 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
) / (float)(INPUT_WIDTH
- 1))),
248 (short)(start
+ range
* ((mbx
* MACROBLOCK_WIDTH
+ bx
* BLOCK_WIDTH
+ BLOCK_WIDTH
- 1) / (float)(INPUT_WIDTH
- 1))),
253 blocks
+= BLOCK_SIZE
;
257 XSelectInput(display
, window
, ExposureMask
| KeyPressMask
);
258 XMapWindow(display
, window
);
261 /* Test NULL context */
262 assert(XvMCRenderSurface(display
, NULL
, XVMC_FRAME_PICTURE
, &surface
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == XvMCBadContext
);
263 /* Test NULL surface */
264 assert(XvMCRenderSurface(display
, &context
, XVMC_FRAME_PICTURE
, NULL
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == XvMCBadSurface
);
265 /* Test bad picture structure */
266 assert(XvMCRenderSurface(display
, &context
, 0, &surface
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == BadValue
);
267 /* Test valid params */
268 assert(XvMCRenderSurface(display
, &context
, XVMC_FRAME_PICTURE
, &surface
, NULL
, NULL
, 0, NUM_MACROBLOCKS
, 0, &mb_array
, &block_array
) == Success
);
270 /* Test NULL surface */
271 assert(XvMCPutSurface(display
, NULL
, window
, 0, 0, INPUT_WIDTH
, INPUT_HEIGHT
, 0, 0, output_width
, output_height
, XVMC_FRAME_PICTURE
) == XvMCBadSurface
);
272 /* Test bad window */
273 /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
274 /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
278 puts("Press any button to quit...");
282 if (XPending(display
) > 0)
286 XNextEvent(display
, &event
);
292 /* Test valid params */
297 display
, &surface
, window
,
298 0, 0, INPUT_WIDTH
, INPUT_HEIGHT
,
299 0, 0, output_width
, output_height
,
315 assert(XvMCDestroyBlocks(display
, &block_array
) == Success
);
316 assert(XvMCDestroyMacroBlocks(display
, &mb_array
) == Success
);
317 assert(XvMCDestroySurface(display
, &surface
) == Success
);
318 assert(XvMCDestroyContext(display
, &context
) == Success
);
320 XvUngrabPort(display
, port_num
, CurrentTime
);
321 XDestroyWindow(display
, window
);
322 XCloseDisplay(display
);