1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2009 Younes Manton.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/* Force assertions, even on release builds. */
29bf215546Sopenharmony_ci#undef NDEBUG
30bf215546Sopenharmony_ci#include <assert.h>
31bf215546Sopenharmony_ci#include <stdio.h>
32bf215546Sopenharmony_ci#include <string.h>
33bf215546Sopenharmony_ci#include <stdlib.h>
34bf215546Sopenharmony_ci#include <sys/time.h>
35bf215546Sopenharmony_ci#include "testlib.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#define MACROBLOCK_WIDTH		16
38bf215546Sopenharmony_ci#define MACROBLOCK_HEIGHT		16
39bf215546Sopenharmony_ci#define BLOCKS_PER_MACROBLOCK		6
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#define DEFAULT_INPUT_WIDTH		720
42bf215546Sopenharmony_ci#define DEFAULT_INPUT_HEIGHT		480
43bf215546Sopenharmony_ci#define DEFAULT_REPS			100
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#define PIPELINE_STEP_MC		1
46bf215546Sopenharmony_ci#define PIPELINE_STEP_CSC		2
47bf215546Sopenharmony_ci#define PIPELINE_STEP_SWAP		4
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci#define MB_TYPE_I			1
50bf215546Sopenharmony_ci#define MB_TYPE_P			2
51bf215546Sopenharmony_ci#define MB_TYPE_B			4
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cistruct Config
54bf215546Sopenharmony_ci{
55bf215546Sopenharmony_ci	unsigned int input_width;
56bf215546Sopenharmony_ci	unsigned int input_height;
57bf215546Sopenharmony_ci	unsigned int output_width;
58bf215546Sopenharmony_ci	unsigned int output_height;
59bf215546Sopenharmony_ci	unsigned int pipeline;
60bf215546Sopenharmony_ci	unsigned int mb_types;
61bf215546Sopenharmony_ci	unsigned int reps;
62bf215546Sopenharmony_ci};
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_civoid ParseArgs(int argc, char **argv, struct Config *config);
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_civoid ParseArgs(int argc, char **argv, struct Config *config)
67bf215546Sopenharmony_ci{
68bf215546Sopenharmony_ci	int fail = 0;
69bf215546Sopenharmony_ci	int i;
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci	config->input_width = DEFAULT_INPUT_WIDTH;
72bf215546Sopenharmony_ci	config->input_height = DEFAULT_INPUT_HEIGHT;
73bf215546Sopenharmony_ci	config->output_width = 0;
74bf215546Sopenharmony_ci	config->output_height = 0;
75bf215546Sopenharmony_ci	config->pipeline = 0;
76bf215546Sopenharmony_ci	config->mb_types = 0;
77bf215546Sopenharmony_ci	config->reps = DEFAULT_REPS;
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci	for (i = 1; i < argc && !fail; ++i)
80bf215546Sopenharmony_ci	{
81bf215546Sopenharmony_ci		if (!strcmp(argv[i], "-iw"))
82bf215546Sopenharmony_ci		{
83bf215546Sopenharmony_ci			if (sscanf(argv[++i], "%u", &config->input_width) != 1)
84bf215546Sopenharmony_ci				fail = 1;
85bf215546Sopenharmony_ci		}
86bf215546Sopenharmony_ci		else if (!strcmp(argv[i], "-ih"))
87bf215546Sopenharmony_ci		{
88bf215546Sopenharmony_ci			if (sscanf(argv[++i], "%u", &config->input_height) != 1)
89bf215546Sopenharmony_ci				fail = 1;
90bf215546Sopenharmony_ci		}
91bf215546Sopenharmony_ci		else if (!strcmp(argv[i], "-ow"))
92bf215546Sopenharmony_ci		{
93bf215546Sopenharmony_ci			if (sscanf(argv[++i], "%u", &config->output_width) != 1)
94bf215546Sopenharmony_ci				fail = 1;
95bf215546Sopenharmony_ci		}
96bf215546Sopenharmony_ci		else if (!strcmp(argv[i], "-oh"))
97bf215546Sopenharmony_ci		{
98bf215546Sopenharmony_ci			if (sscanf(argv[++i], "%u", &config->output_height) != 1)
99bf215546Sopenharmony_ci				fail = 1;
100bf215546Sopenharmony_ci		}
101bf215546Sopenharmony_ci		else if (!strcmp(argv[i], "-p"))
102bf215546Sopenharmony_ci		{
103bf215546Sopenharmony_ci			char *token = strtok(argv[++i], ",");
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci			while (token && !fail)
106bf215546Sopenharmony_ci			{
107bf215546Sopenharmony_ci				if (!strcmp(token, "mc"))
108bf215546Sopenharmony_ci					config->pipeline |= PIPELINE_STEP_MC;
109bf215546Sopenharmony_ci				else if (!strcmp(token, "csc"))
110bf215546Sopenharmony_ci					config->pipeline |= PIPELINE_STEP_CSC;
111bf215546Sopenharmony_ci				else if (!strcmp(token, "swp"))
112bf215546Sopenharmony_ci					config->pipeline |= PIPELINE_STEP_SWAP;
113bf215546Sopenharmony_ci				else
114bf215546Sopenharmony_ci					fail = 1;
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci				if (!fail)
117bf215546Sopenharmony_ci					token = strtok(NULL, ",");
118bf215546Sopenharmony_ci			}
119bf215546Sopenharmony_ci		}
120bf215546Sopenharmony_ci		else if (!strcmp(argv[i], "-mb"))
121bf215546Sopenharmony_ci		{
122bf215546Sopenharmony_ci			char *token = strtok(argv[++i], ",");
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci			while (token && !fail)
125bf215546Sopenharmony_ci			{
126bf215546Sopenharmony_ci				if (strcmp(token, "i") == 0)
127bf215546Sopenharmony_ci					config->mb_types |= MB_TYPE_I;
128bf215546Sopenharmony_ci				else if (strcmp(token, "p") == 0)
129bf215546Sopenharmony_ci					config->mb_types |= MB_TYPE_P;
130bf215546Sopenharmony_ci				else if (strcmp(token, "b") == 0)
131bf215546Sopenharmony_ci					config->mb_types |= MB_TYPE_B;
132bf215546Sopenharmony_ci				else
133bf215546Sopenharmony_ci					fail = 1;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci				if (!fail)
136bf215546Sopenharmony_ci					token = strtok(NULL, ",");
137bf215546Sopenharmony_ci			}
138bf215546Sopenharmony_ci		}
139bf215546Sopenharmony_ci		else if (!strcmp(argv[i], "-r"))
140bf215546Sopenharmony_ci		{
141bf215546Sopenharmony_ci			if (sscanf(argv[++i], "%u", &config->reps) != 1)
142bf215546Sopenharmony_ci				fail = 1;
143bf215546Sopenharmony_ci		}
144bf215546Sopenharmony_ci		else
145bf215546Sopenharmony_ci			fail = 1;
146bf215546Sopenharmony_ci	}
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci	if (fail)
149bf215546Sopenharmony_ci	{
150bf215546Sopenharmony_ci		fprintf(
151bf215546Sopenharmony_ci			stderr,
152bf215546Sopenharmony_ci			"Bad argument.\n"
153bf215546Sopenharmony_ci			"\n"
154bf215546Sopenharmony_ci			"Usage: %s [options]\n"
155bf215546Sopenharmony_ci			"\t-iw <width>\tInput width\n"
156bf215546Sopenharmony_ci			"\t-ih <height>\tInput height\n"
157bf215546Sopenharmony_ci			"\t-ow <width>\tOutput width\n"
158bf215546Sopenharmony_ci			"\t-oh <height>\tOutput height\n"
159bf215546Sopenharmony_ci			"\t-p <pipeline>\tPipeline to test\n"
160bf215546Sopenharmony_ci			"\t-mb <mb type>\tMacroBlock types to use\n"
161bf215546Sopenharmony_ci			"\t-r <reps>\tRepetitions\n\n"
162bf215546Sopenharmony_ci			"\tPipeline steps: mc,csc,swap\n"
163bf215546Sopenharmony_ci			"\tMB types: i,p,b\n",
164bf215546Sopenharmony_ci			argv[0]
165bf215546Sopenharmony_ci		);
166bf215546Sopenharmony_ci		exit(1);
167bf215546Sopenharmony_ci	}
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci	if (config->output_width == 0)
170bf215546Sopenharmony_ci		config->output_width = config->input_width;
171bf215546Sopenharmony_ci	if (config->output_height == 0)
172bf215546Sopenharmony_ci		config->output_height = config->input_height;
173bf215546Sopenharmony_ci	if (!config->pipeline)
174bf215546Sopenharmony_ci		config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP;
175bf215546Sopenharmony_ci	if (!config->mb_types)
176bf215546Sopenharmony_ci		config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B;
177bf215546Sopenharmony_ci}
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ciint main(int argc, char **argv)
180bf215546Sopenharmony_ci{
181bf215546Sopenharmony_ci	struct Config		config;
182bf215546Sopenharmony_ci	Display			*display;
183bf215546Sopenharmony_ci	Window			root, window;
184bf215546Sopenharmony_ci	const unsigned int	mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
185bf215546Sopenharmony_ci	XvPortID		port_num;
186bf215546Sopenharmony_ci	int			surface_type_id;
187bf215546Sopenharmony_ci	unsigned int		is_overlay, intra_unsigned;
188bf215546Sopenharmony_ci	int			colorkey;
189bf215546Sopenharmony_ci	XvMCContext		context;
190bf215546Sopenharmony_ci	XvMCSurface		surface;
191bf215546Sopenharmony_ci	XvMCBlockArray		block_array;
192bf215546Sopenharmony_ci	XvMCMacroBlockArray	mb_array;
193bf215546Sopenharmony_ci	unsigned int		mbw, mbh;
194bf215546Sopenharmony_ci	unsigned int		mbx, mby;
195bf215546Sopenharmony_ci	unsigned int		reps;
196bf215546Sopenharmony_ci	struct timeval		start, stop, diff;
197bf215546Sopenharmony_ci	double			diff_secs;
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci	ParseArgs(argc, argv, &config);
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci	mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
202bf215546Sopenharmony_ci	mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci	display = XOpenDisplay(NULL);
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci	if (!GetPort
207bf215546Sopenharmony_ci	(
208bf215546Sopenharmony_ci		display,
209bf215546Sopenharmony_ci		config.input_width,
210bf215546Sopenharmony_ci		config.input_height,
211bf215546Sopenharmony_ci		XVMC_CHROMA_FORMAT_420,
212bf215546Sopenharmony_ci		mc_types,
213bf215546Sopenharmony_ci		2,
214bf215546Sopenharmony_ci		&port_num,
215bf215546Sopenharmony_ci		&surface_type_id,
216bf215546Sopenharmony_ci		&is_overlay,
217bf215546Sopenharmony_ci		&intra_unsigned
218bf215546Sopenharmony_ci	))
219bf215546Sopenharmony_ci	{
220bf215546Sopenharmony_ci		XCloseDisplay(display);
221bf215546Sopenharmony_ci		fprintf(stderr, "Error, unable to find a good port.\n");
222bf215546Sopenharmony_ci		exit(1);
223bf215546Sopenharmony_ci	}
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci	if (is_overlay)
226bf215546Sopenharmony_ci	{
227bf215546Sopenharmony_ci		Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
228bf215546Sopenharmony_ci		XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
229bf215546Sopenharmony_ci	}
230bf215546Sopenharmony_ci	else
231bf215546Sopenharmony_ci	{
232bf215546Sopenharmony_ci		colorkey = 0;
233bf215546Sopenharmony_ci	}
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci	root = XDefaultRootWindow(display);
236bf215546Sopenharmony_ci	window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey);
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci	assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success);
239bf215546Sopenharmony_ci	assert(XvMCCreateSurface(display, &context, &surface) == Success);
240bf215546Sopenharmony_ci	assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
241bf215546Sopenharmony_ci	assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success);
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci	for (mby = 0; mby < mbh; ++mby)
244bf215546Sopenharmony_ci		for (mbx = 0; mbx < mbw; ++mbx)
245bf215546Sopenharmony_ci		{
246bf215546Sopenharmony_ci			mb_array.macro_blocks[mby * mbw + mbx].x = mbx;
247bf215546Sopenharmony_ci			mb_array.macro_blocks[mby * mbw + mbx].y = mby;
248bf215546Sopenharmony_ci			mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA;
249bf215546Sopenharmony_ci			/*mb->motion_type = ;*/
250bf215546Sopenharmony_ci			/*mb->motion_vertical_field_select = ;*/
251bf215546Sopenharmony_ci			mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME;
252bf215546Sopenharmony_ci			/*mb->PMV[0][0][0] = ;
253bf215546Sopenharmony_ci			mb->PMV[0][0][1] = ;
254bf215546Sopenharmony_ci			mb->PMV[0][1][0] = ;
255bf215546Sopenharmony_ci			mb->PMV[0][1][1] = ;
256bf215546Sopenharmony_ci			mb->PMV[1][0][0] = ;
257bf215546Sopenharmony_ci			mb->PMV[1][0][1] = ;
258bf215546Sopenharmony_ci			mb->PMV[1][1][0] = ;
259bf215546Sopenharmony_ci			mb->PMV[1][1][1] = ;*/
260bf215546Sopenharmony_ci			mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK;
261bf215546Sopenharmony_ci			mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F;
262bf215546Sopenharmony_ci		}
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci	XSelectInput(display, window, ExposureMask | KeyPressMask);
265bf215546Sopenharmony_ci	XMapWindow(display, window);
266bf215546Sopenharmony_ci	XSync(display, 0);
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci	gettimeofday(&start, NULL);
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci	for (reps = 0; reps < config.reps; ++reps)
271bf215546Sopenharmony_ci	{
272bf215546Sopenharmony_ci		if (config.pipeline & PIPELINE_STEP_MC)
273bf215546Sopenharmony_ci		{
274bf215546Sopenharmony_ci			assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success);
275bf215546Sopenharmony_ci			assert(XvMCFlushSurface(display, &surface) == Success);
276bf215546Sopenharmony_ci		}
277bf215546Sopenharmony_ci		if (config.pipeline & PIPELINE_STEP_CSC)
278bf215546Sopenharmony_ci			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);
279bf215546Sopenharmony_ci	}
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci	gettimeofday(&stop, NULL);
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci	timeval_subtract(&diff, &stop, &start);
284bf215546Sopenharmony_ci	diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0;
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci	printf("XvMC Benchmark\n");
287bf215546Sopenharmony_ci	printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height);
288bf215546Sopenharmony_ci	printf("Pipeline: ");
289bf215546Sopenharmony_ci	if (config.pipeline & PIPELINE_STEP_MC)
290bf215546Sopenharmony_ci		printf("|mc|");
291bf215546Sopenharmony_ci	if (config.pipeline & PIPELINE_STEP_CSC)
292bf215546Sopenharmony_ci		printf("|csc|");
293bf215546Sopenharmony_ci	if (config.pipeline & PIPELINE_STEP_SWAP)
294bf215546Sopenharmony_ci		printf("|swap|");
295bf215546Sopenharmony_ci	printf("\n");
296bf215546Sopenharmony_ci	printf("Reps: %u\n", config.reps);
297bf215546Sopenharmony_ci	printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs);
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci	assert(XvMCDestroyBlocks(display, &block_array) == Success);
300bf215546Sopenharmony_ci	assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
301bf215546Sopenharmony_ci	assert(XvMCDestroySurface(display, &surface) == Success);
302bf215546Sopenharmony_ci	assert(XvMCDestroyContext(display, &context) == Success);
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci	XvUngrabPort(display, port_num, CurrentTime);
305bf215546Sopenharmony_ci	XDestroyWindow(display, window);
306bf215546Sopenharmony_ci	XCloseDisplay(display);
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci	return 0;
309bf215546Sopenharmony_ci}
310