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 MACROBLOCK_WIDTH 16
38 #define MACROBLOCK_HEIGHT 16
39 #define BLOCKS_PER_MACROBLOCK 6
41 #define DEFAULT_INPUT_WIDTH 720
42 #define DEFAULT_INPUT_HEIGHT 480
43 #define DEFAULT_REPS 100
45 #define PIPELINE_STEP_MC 1
46 #define PIPELINE_STEP_CSC 2
47 #define PIPELINE_STEP_SWAP 4
55 unsigned int input_width
;
56 unsigned int input_height
;
57 unsigned int output_width
;
58 unsigned int output_height
;
59 unsigned int pipeline
;
60 unsigned int mb_types
;
64 void ParseArgs(int argc
, char **argv
, struct Config
*config
);
66 void ParseArgs(int argc
, char **argv
, struct Config
*config
)
71 config
->input_width
= DEFAULT_INPUT_WIDTH
;
72 config
->input_height
= DEFAULT_INPUT_HEIGHT
;
73 config
->output_width
= 0;
74 config
->output_height
= 0;
77 config
->reps
= DEFAULT_REPS
;
79 for (i
= 1; i
< argc
&& !fail
; ++i
)
81 if (!strcmp(argv
[i
], "-iw"))
83 if (sscanf(argv
[++i
], "%u", &config
->input_width
) != 1)
86 else if (!strcmp(argv
[i
], "-ih"))
88 if (sscanf(argv
[++i
], "%u", &config
->input_height
) != 1)
91 else if (!strcmp(argv
[i
], "-ow"))
93 if (sscanf(argv
[++i
], "%u", &config
->output_width
) != 1)
96 else if (!strcmp(argv
[i
], "-oh"))
98 if (sscanf(argv
[++i
], "%u", &config
->output_height
) != 1)
101 else if (!strcmp(argv
[i
], "-p"))
103 char *token
= strtok(argv
[++i
], ",");
105 while (token
&& !fail
)
107 if (!strcmp(token
, "mc"))
108 config
->pipeline
|= PIPELINE_STEP_MC
;
109 else if (!strcmp(token
, "csc"))
110 config
->pipeline
|= PIPELINE_STEP_CSC
;
111 else if (!strcmp(token
, "swp"))
112 config
->pipeline
|= PIPELINE_STEP_SWAP
;
117 token
= strtok(NULL
, ",");
120 else if (!strcmp(argv
[i
], "-mb"))
122 char *token
= strtok(argv
[++i
], ",");
124 while (token
&& !fail
)
126 if (strcmp(token
, "i") == 0)
127 config
->mb_types
|= MB_TYPE_I
;
128 else if (strcmp(token
, "p") == 0)
129 config
->mb_types
|= MB_TYPE_P
;
130 else if (strcmp(token
, "b") == 0)
131 config
->mb_types
|= MB_TYPE_B
;
136 token
= strtok(NULL
, ",");
139 else if (!strcmp(argv
[i
], "-r"))
141 if (sscanf(argv
[++i
], "%u", &config
->reps
) != 1)
154 "Usage: %s [options]\n"
155 "\t-iw <width>\tInput width\n"
156 "\t-ih <height>\tInput height\n"
157 "\t-ow <width>\tOutput width\n"
158 "\t-oh <height>\tOutput height\n"
159 "\t-p <pipeline>\tPipeline to test\n"
160 "\t-mb <mb type>\tMacroBlock types to use\n"
161 "\t-r <reps>\tRepetitions\n\n"
162 "\tPipeline steps: mc,csc,swap\n"
163 "\tMB types: i,p,b\n",
169 if (config
->output_width
== 0)
170 config
->output_width
= config
->input_width
;
171 if (config
->output_height
== 0)
172 config
->output_height
= config
->input_height
;
173 if (!config
->pipeline
)
174 config
->pipeline
= PIPELINE_STEP_MC
| PIPELINE_STEP_CSC
| PIPELINE_STEP_SWAP
;
175 if (!config
->mb_types
)
176 config
->mb_types
= MB_TYPE_I
| MB_TYPE_P
| MB_TYPE_B
;
179 int main(int argc
, char **argv
)
181 struct Config config
;
184 const unsigned int mc_types
[2] = {XVMC_MOCOMP
| XVMC_MPEG_2
, XVMC_IDCT
| XVMC_MPEG_2
};
187 unsigned int is_overlay
, intra_unsigned
;
191 XvMCBlockArray block_array
;
192 XvMCMacroBlockArray mb_array
;
193 unsigned int mbw
, mbh
;
194 unsigned int mbx
, mby
;
196 struct timeval start
, stop
, diff
;
199 ParseArgs(argc
, argv
, &config
);
201 mbw
= align(config
.input_width
, MACROBLOCK_WIDTH
) / MACROBLOCK_WIDTH
;
202 mbh
= align(config
.input_height
, MACROBLOCK_HEIGHT
) / MACROBLOCK_HEIGHT
;
204 display
= XOpenDisplay(NULL
);
211 XVMC_CHROMA_FORMAT_420
,
220 XCloseDisplay(display
);
221 fprintf(stderr
, "Error, unable to find a good port.\n");
227 Atom xv_colorkey
= XInternAtom(display
, "XV_COLORKEY", 0);
228 XvGetPortAttribute(display
, port_num
, xv_colorkey
, &colorkey
);
235 root
= XDefaultRootWindow(display
);
236 window
= XCreateSimpleWindow(display
, root
, 0, 0, config
.output_width
, config
.output_height
, 0, 0, colorkey
);
238 assert(XvMCCreateContext(display
, port_num
, surface_type_id
, config
.input_width
, config
.input_height
, XVMC_DIRECT
, &context
) == Success
);
239 assert(XvMCCreateSurface(display
, &context
, &surface
) == Success
);
240 assert(XvMCCreateBlocks(display
, &context
, mbw
* mbh
* BLOCKS_PER_MACROBLOCK
, &block_array
) == Success
);
241 assert(XvMCCreateMacroBlocks(display
, &context
, mbw
* mbh
, &mb_array
) == Success
);
243 for (mby
= 0; mby
< mbh
; ++mby
)
244 for (mbx
= 0; mbx
< mbw
; ++mbx
)
246 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].x
= mbx
;
247 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].y
= mby
;
248 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].macroblock_type
= XVMC_MB_TYPE_INTRA
;
249 /*mb->motion_type = ;*/
250 /*mb->motion_vertical_field_select = ;*/
251 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].dct_type
= XVMC_DCT_TYPE_FRAME
;
252 /*mb->PMV[0][0][0] = ;
259 mb->PMV[1][1][1] = ;*/
260 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].index
= (mby
* mbw
+ mbx
) * BLOCKS_PER_MACROBLOCK
;
261 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].coded_block_pattern
= 0x3F;
264 XSelectInput(display
, window
, ExposureMask
| KeyPressMask
);
265 XMapWindow(display
, window
);
268 gettimeofday(&start
, NULL
);
270 for (reps
= 0; reps
< config
.reps
; ++reps
)
272 if (config
.pipeline
& PIPELINE_STEP_MC
)
274 assert(XvMCRenderSurface(display
, &context
, XVMC_FRAME_PICTURE
, &surface
, NULL
, NULL
, 0, mbw
* mbh
, 0, &mb_array
, &block_array
) == Success
);
275 assert(XvMCFlushSurface(display
, &surface
) == Success
);
277 if (config
.pipeline
& PIPELINE_STEP_CSC
)
278 assert(XvMCPutSurface(display
, &surface
, window
, 0, 0, config
.input_width
, config
.input_height
, 0, 0, config
.output_width
, config
.output_height
, XVMC_FRAME_PICTURE
) == Success
);
281 gettimeofday(&stop
, NULL
);
283 timeval_subtract(&diff
, &stop
, &start
);
284 diff_secs
= (double)diff
.tv_sec
+ (double)diff
.tv_usec
/ 1000000.0;
286 printf("XvMC Benchmark\n");
287 printf("Input: %u,%u\nOutput: %u,%u\n", config
.input_width
, config
.input_height
, config
.output_width
, config
.output_height
);
288 printf("Pipeline: ");
289 if (config
.pipeline
& PIPELINE_STEP_MC
)
291 if (config
.pipeline
& PIPELINE_STEP_CSC
)
293 if (config
.pipeline
& PIPELINE_STEP_SWAP
)
296 printf("Reps: %u\n", config
.reps
);
297 printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs
, config
.reps
/ diff_secs
);
299 assert(XvMCDestroyBlocks(display
, &block_array
) == Success
);
300 assert(XvMCDestroyMacroBlocks(display
, &mb_array
) == Success
);
301 assert(XvMCDestroySurface(display
, &surface
) == Success
);
302 assert(XvMCDestroyContext(display
, &context
) == Success
);
304 XvUngrabPort(display
, port_num
, CurrentTime
);
305 XDestroyWindow(display
, window
);
306 XCloseDisplay(display
);