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 MACROBLOCK_WIDTH 16
36 #define MACROBLOCK_HEIGHT 16
37 #define BLOCKS_PER_MACROBLOCK 6
39 #define DEFAULT_INPUT_WIDTH 720
40 #define DEFAULT_INPUT_HEIGHT 480
41 #define DEFAULT_REPS 100
43 #define PIPELINE_STEP_MC 1
44 #define PIPELINE_STEP_CSC 2
45 #define PIPELINE_STEP_SWAP 4
53 unsigned int input_width
;
54 unsigned int input_height
;
55 unsigned int output_width
;
56 unsigned int output_height
;
57 unsigned int pipeline
;
58 unsigned int mb_types
;
62 void ParseArgs(int argc
, char **argv
, struct Config
*config
);
64 void ParseArgs(int argc
, char **argv
, struct Config
*config
)
69 config
->input_width
= DEFAULT_INPUT_WIDTH
;
70 config
->input_height
= DEFAULT_INPUT_HEIGHT
;
71 config
->output_width
= 0;
72 config
->output_height
= 0;
75 config
->reps
= DEFAULT_REPS
;
77 for (i
= 1; i
< argc
&& !fail
; ++i
)
79 if (!strcmp(argv
[i
], "-iw"))
81 if (sscanf(argv
[++i
], "%u", &config
->input_width
) != 1)
84 else if (!strcmp(argv
[i
], "-ih"))
86 if (sscanf(argv
[++i
], "%u", &config
->input_height
) != 1)
89 else if (!strcmp(argv
[i
], "-ow"))
91 if (sscanf(argv
[++i
], "%u", &config
->output_width
) != 1)
94 else if (!strcmp(argv
[i
], "-oh"))
96 if (sscanf(argv
[++i
], "%u", &config
->output_height
) != 1)
99 else if (!strcmp(argv
[i
], "-p"))
101 char *token
= strtok(argv
[++i
], ",");
103 while (token
&& !fail
)
105 if (!strcmp(token
, "mc"))
106 config
->pipeline
|= PIPELINE_STEP_MC
;
107 else if (!strcmp(token
, "csc"))
108 config
->pipeline
|= PIPELINE_STEP_CSC
;
109 else if (!strcmp(token
, "swp"))
110 config
->pipeline
|= PIPELINE_STEP_SWAP
;
115 token
= strtok(NULL
, ",");
118 else if (!strcmp(argv
[i
], "-mb"))
120 char *token
= strtok(argv
[++i
], ",");
122 while (token
&& !fail
)
124 if (strcmp(token
, "i"))
125 config
->mb_types
|= MB_TYPE_I
;
126 else if (strcmp(token
, "p"))
127 config
->mb_types
|= MB_TYPE_P
;
128 else if (strcmp(token
, "b"))
129 config
->mb_types
|= MB_TYPE_B
;
134 token
= strtok(NULL
, ",");
137 else if (!strcmp(argv
[i
], "-r"))
139 if (sscanf(argv
[++i
], "%u", &config
->reps
) != 1)
152 "Usage: %s [options]\n"
153 "\t-iw <width>\tInput width\n"
154 "\t-ih <height>\tInput height\n"
155 "\t-ow <width>\tOutput width\n"
156 "\t-oh <height>\tOutput height\n"
157 "\t-p <pipeline>\tPipeline to test\n"
158 "\t-mb <mb type>\tMacroBlock types to use\n"
159 "\t-r <reps>\tRepetitions\n\n"
160 "\tPipeline steps: mc,csc,swap\n"
161 "\tMB types: i,p,b\n",
165 if (config
->output_width
== 0)
166 config
->output_width
= config
->input_width
;
167 if (config
->output_height
== 0)
168 config
->output_height
= config
->input_height
;
169 if (!config
->pipeline
)
170 config
->pipeline
= PIPELINE_STEP_MC
| PIPELINE_STEP_CSC
| PIPELINE_STEP_SWAP
;
171 if (!config
->mb_types
)
172 config
->mb_types
= MB_TYPE_I
| MB_TYPE_P
| MB_TYPE_B
;
175 int main(int argc
, char **argv
)
177 struct Config config
;
180 const unsigned int mc_types
[2] = {XVMC_MOCOMP
| XVMC_MPEG_2
, XVMC_IDCT
| XVMC_MPEG_2
};
183 unsigned int is_overlay
, intra_unsigned
;
187 XvMCBlockArray block_array
;
188 XvMCMacroBlockArray mb_array
;
189 unsigned int mbw
, mbh
;
190 unsigned int mbx
, mby
;
192 struct timeval start
, stop
, diff
;
195 ParseArgs(argc
, argv
, &config
);
197 mbw
= align(config
.input_width
, MACROBLOCK_WIDTH
) / MACROBLOCK_WIDTH
;
198 mbh
= align(config
.input_height
, MACROBLOCK_HEIGHT
) / MACROBLOCK_HEIGHT
;
200 display
= XOpenDisplay(NULL
);
207 XVMC_CHROMA_FORMAT_420
,
216 XCloseDisplay(display
);
217 error(1, 0, "Error, unable to find a good port.\n");
222 Atom xv_colorkey
= XInternAtom(display
, "XV_COLORKEY", 0);
223 XvGetPortAttribute(display
, port_num
, xv_colorkey
, &colorkey
);
230 root
= XDefaultRootWindow(display
);
231 window
= XCreateSimpleWindow(display
, root
, 0, 0, config
.output_width
, config
.output_height
, 0, 0, colorkey
);
233 assert(XvMCCreateContext(display
, port_num
, surface_type_id
, config
.input_width
, config
.input_height
, XVMC_DIRECT
, &context
) == Success
);
234 assert(XvMCCreateSurface(display
, &context
, &surface
) == Success
);
235 assert(XvMCCreateBlocks(display
, &context
, mbw
* mbh
* BLOCKS_PER_MACROBLOCK
, &block_array
) == Success
);
236 assert(XvMCCreateMacroBlocks(display
, &context
, mbw
* mbh
, &mb_array
) == Success
);
238 for (mby
= 0; mby
< mbh
; ++mby
)
239 for (mbx
= 0; mbx
< mbw
; ++mbx
)
241 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].x
= mbx
;
242 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].y
= mby
;
243 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].macroblock_type
= XVMC_MB_TYPE_INTRA
;
244 /*mb->motion_type = ;*/
245 /*mb->motion_vertical_field_select = ;*/
246 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].dct_type
= XVMC_DCT_TYPE_FRAME
;
247 /*mb->PMV[0][0][0] = ;
254 mb->PMV[1][1][1] = ;*/
255 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].index
= (mby
* mbw
+ mbx
) * BLOCKS_PER_MACROBLOCK
;
256 mb_array
.macro_blocks
[mby
* mbw
+ mbx
].coded_block_pattern
= 0x3F;
259 XSelectInput(display
, window
, ExposureMask
| KeyPressMask
);
260 XMapWindow(display
, window
);
263 gettimeofday(&start
, NULL
);
265 for (reps
= 0; reps
< config
.reps
; ++reps
)
267 if (config
.pipeline
& PIPELINE_STEP_MC
)
269 assert(XvMCRenderSurface(display
, &context
, XVMC_FRAME_PICTURE
, &surface
, NULL
, NULL
, 0, mbw
* mbh
, 0, &mb_array
, &block_array
) == Success
);
270 assert(XvMCFlushSurface(display
, &surface
) == Success
);
272 if (config
.pipeline
& PIPELINE_STEP_CSC
)
273 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
);
276 gettimeofday(&stop
, NULL
);
278 timeval_subtract(&diff
, &stop
, &start
);
279 diff_secs
= (double)diff
.tv_sec
+ (double)diff
.tv_usec
/ 1000000.0;
281 printf("XvMC Benchmark\n");
282 printf("Input: %u,%u\nOutput: %u,%u\n", config
.input_width
, config
.input_height
, config
.output_width
, config
.output_height
);
283 printf("Pipeline: ");
284 if (config
.pipeline
& PIPELINE_STEP_MC
)
286 if (config
.pipeline
& PIPELINE_STEP_CSC
)
288 if (config
.pipeline
& PIPELINE_STEP_SWAP
)
291 printf("Reps: %u\n", config
.reps
);
292 printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs
, config
.reps
/ diff_secs
);
294 assert(XvMCDestroyBlocks(display
, &block_array
) == Success
);
295 assert(XvMCDestroyMacroBlocks(display
, &mb_array
) == Success
);
296 assert(XvMCDestroySurface(display
, &surface
) == Success
);
297 assert(XvMCDestroyContext(display
, &context
) == Success
);
299 XvUngrabPort(display
, port_num
, CurrentTime
);
300 XDestroyWindow(display
, window
);
301 XCloseDisplay(display
);