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 "testlib.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#define BLOCK_WIDTH 8 37bf215546Sopenharmony_ci#define BLOCK_HEIGHT 8 38bf215546Sopenharmony_ci#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT) 39bf215546Sopenharmony_ci#define MACROBLOCK_WIDTH 16 40bf215546Sopenharmony_ci#define MACROBLOCK_HEIGHT 16 41bf215546Sopenharmony_ci#define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH) 42bf215546Sopenharmony_ci#define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT) 43bf215546Sopenharmony_ci#define BLOCKS_PER_MACROBLOCK 6 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci#define INPUT_WIDTH 64 46bf215546Sopenharmony_ci#define INPUT_HEIGHT 64 47bf215546Sopenharmony_ci#define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH) 48bf215546Sopenharmony_ci#define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT) 49bf215546Sopenharmony_ci#define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS) 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci#define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH 52bf215546Sopenharmony_ci#define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT 53bf215546Sopenharmony_ci#define DEFAULT_ACCEPTABLE_ERR 0.01 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_cistatic void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt) 56bf215546Sopenharmony_ci{ 57bf215546Sopenharmony_ci int fail = 0; 58bf215546Sopenharmony_ci int i; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci *output_width = DEFAULT_OUTPUT_WIDTH; 61bf215546Sopenharmony_ci *output_height = DEFAULT_OUTPUT_HEIGHT; 62bf215546Sopenharmony_ci *acceptable_error = DEFAULT_ACCEPTABLE_ERR; 63bf215546Sopenharmony_ci *prompt = 0; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci for (i = 1; i < argc && !fail; ++i) 66bf215546Sopenharmony_ci { 67bf215546Sopenharmony_ci if (!strcmp(argv[i], "-w")) 68bf215546Sopenharmony_ci { 69bf215546Sopenharmony_ci if (sscanf(argv[++i], "%u", output_width) != 1) 70bf215546Sopenharmony_ci fail = 1; 71bf215546Sopenharmony_ci } 72bf215546Sopenharmony_ci else if (!strcmp(argv[i], "-h")) 73bf215546Sopenharmony_ci { 74bf215546Sopenharmony_ci if (sscanf(argv[++i], "%u", output_height) != 1) 75bf215546Sopenharmony_ci fail = 1; 76bf215546Sopenharmony_ci } 77bf215546Sopenharmony_ci else if (!strcmp(argv[i], "-e")) 78bf215546Sopenharmony_ci { 79bf215546Sopenharmony_ci if (sscanf(argv[++i], "%lf", acceptable_error) != 1) 80bf215546Sopenharmony_ci fail = 1; 81bf215546Sopenharmony_ci } 82bf215546Sopenharmony_ci else if (!strcmp(argv[i], "-p")) 83bf215546Sopenharmony_ci *prompt = 1; 84bf215546Sopenharmony_ci else 85bf215546Sopenharmony_ci fail = 1; 86bf215546Sopenharmony_ci } 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci if (fail) 89bf215546Sopenharmony_ci { 90bf215546Sopenharmony_ci fprintf( 91bf215546Sopenharmony_ci stderr, 92bf215546Sopenharmony_ci "Bad argument.\n" 93bf215546Sopenharmony_ci "\n" 94bf215546Sopenharmony_ci "Usage: %s [options]\n" 95bf215546Sopenharmony_ci "\t-w <width>\tOutput width\n" 96bf215546Sopenharmony_ci "\t-h <height>\tOutput height\n" 97bf215546Sopenharmony_ci "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n" 98bf215546Sopenharmony_ci "\t-p\tPrompt for quit\n", 99bf215546Sopenharmony_ci argv[0] 100bf215546Sopenharmony_ci ); 101bf215546Sopenharmony_ci exit(1); 102bf215546Sopenharmony_ci } 103bf215546Sopenharmony_ci} 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_cistatic void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal, unsigned int intra_unsigned) 106bf215546Sopenharmony_ci{ 107bf215546Sopenharmony_ci unsigned int x, y; 108bf215546Sopenharmony_ci unsigned int range = stop - start; 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci if (horizontal) 111bf215546Sopenharmony_ci { 112bf215546Sopenharmony_ci for (y = 0; y < BLOCK_HEIGHT; ++y) 113bf215546Sopenharmony_ci for (x = 0; x < BLOCK_WIDTH; ++x) { 114bf215546Sopenharmony_ci *block = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1))); 115bf215546Sopenharmony_ci if (intra_unsigned) 116bf215546Sopenharmony_ci *block += 1 << 10; 117bf215546Sopenharmony_ci block++; 118bf215546Sopenharmony_ci } 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci else 121bf215546Sopenharmony_ci { 122bf215546Sopenharmony_ci for (y = 0; y < BLOCK_HEIGHT; ++y) 123bf215546Sopenharmony_ci for (x = 0; x < BLOCK_WIDTH; ++x) { 124bf215546Sopenharmony_ci *block = (short)(start + range * (y / (float)(BLOCK_WIDTH - 1))); 125bf215546Sopenharmony_ci if (intra_unsigned) 126bf215546Sopenharmony_ci *block += 1 << 10; 127bf215546Sopenharmony_ci block++; 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci } 130bf215546Sopenharmony_ci} 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ciint main(int argc, char **argv) 133bf215546Sopenharmony_ci{ 134bf215546Sopenharmony_ci unsigned int output_width; 135bf215546Sopenharmony_ci unsigned int output_height; 136bf215546Sopenharmony_ci double acceptable_error; 137bf215546Sopenharmony_ci int prompt; 138bf215546Sopenharmony_ci Display *display; 139bf215546Sopenharmony_ci Window root, window; 140bf215546Sopenharmony_ci const unsigned int mc_types[] = {XVMC_MOCOMP | XVMC_MPEG_2}; 141bf215546Sopenharmony_ci XvPortID port_num; 142bf215546Sopenharmony_ci int surface_type_id; 143bf215546Sopenharmony_ci unsigned int is_overlay, intra_unsigned; 144bf215546Sopenharmony_ci int colorkey; 145bf215546Sopenharmony_ci XvMCContext context; 146bf215546Sopenharmony_ci XvMCSurface surface; 147bf215546Sopenharmony_ci XvMCBlockArray block_array; 148bf215546Sopenharmony_ci XvMCMacroBlockArray mb_array; 149bf215546Sopenharmony_ci int mbx, mby, bx, by; 150bf215546Sopenharmony_ci XvMCMacroBlock *mb; 151bf215546Sopenharmony_ci short *blocks; 152bf215546Sopenharmony_ci int quit = 0; 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt); 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci display = XOpenDisplay(NULL); 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci if (!GetPort 159bf215546Sopenharmony_ci ( 160bf215546Sopenharmony_ci display, 161bf215546Sopenharmony_ci INPUT_WIDTH, 162bf215546Sopenharmony_ci INPUT_HEIGHT, 163bf215546Sopenharmony_ci XVMC_CHROMA_FORMAT_420, 164bf215546Sopenharmony_ci mc_types, 165bf215546Sopenharmony_ci sizeof(mc_types)/sizeof(*mc_types), 166bf215546Sopenharmony_ci &port_num, 167bf215546Sopenharmony_ci &surface_type_id, 168bf215546Sopenharmony_ci &is_overlay, 169bf215546Sopenharmony_ci &intra_unsigned 170bf215546Sopenharmony_ci )) 171bf215546Sopenharmony_ci { 172bf215546Sopenharmony_ci XCloseDisplay(display); 173bf215546Sopenharmony_ci fprintf(stderr, "Error, unable to find a good port.\n"); 174bf215546Sopenharmony_ci exit(1); 175bf215546Sopenharmony_ci } 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci if (is_overlay) 178bf215546Sopenharmony_ci { 179bf215546Sopenharmony_ci Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); 180bf215546Sopenharmony_ci XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); 181bf215546Sopenharmony_ci } 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci root = XDefaultRootWindow(display); 184bf215546Sopenharmony_ci window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey); 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success); 187bf215546Sopenharmony_ci assert(XvMCCreateSurface(display, &context, &surface) == Success); 188bf215546Sopenharmony_ci assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success); 189bf215546Sopenharmony_ci assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success); 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci mb = mb_array.macro_blocks; 192bf215546Sopenharmony_ci blocks = block_array.blocks; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby) 195bf215546Sopenharmony_ci for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx) 196bf215546Sopenharmony_ci { 197bf215546Sopenharmony_ci mb->x = mbx; 198bf215546Sopenharmony_ci mb->y = mby; 199bf215546Sopenharmony_ci mb->macroblock_type = XVMC_MB_TYPE_INTRA; 200bf215546Sopenharmony_ci /*mb->motion_type = ;*/ 201bf215546Sopenharmony_ci /*mb->motion_vertical_field_select = ;*/ 202bf215546Sopenharmony_ci mb->dct_type = XVMC_DCT_TYPE_FRAME; 203bf215546Sopenharmony_ci /*mb->PMV[0][0][0] = ; 204bf215546Sopenharmony_ci mb->PMV[0][0][1] = ; 205bf215546Sopenharmony_ci mb->PMV[0][1][0] = ; 206bf215546Sopenharmony_ci mb->PMV[0][1][1] = ; 207bf215546Sopenharmony_ci mb->PMV[1][0][0] = ; 208bf215546Sopenharmony_ci mb->PMV[1][0][1] = ; 209bf215546Sopenharmony_ci mb->PMV[1][1][0] = ; 210bf215546Sopenharmony_ci mb->PMV[1][1][1] = ;*/ 211bf215546Sopenharmony_ci mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK; 212bf215546Sopenharmony_ci mb->coded_block_pattern = 0x3F; 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci mb++; 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by) 217bf215546Sopenharmony_ci for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx) 218bf215546Sopenharmony_ci { 219bf215546Sopenharmony_ci const int start = 16, stop = 235, range = stop - start; 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci Gradient 222bf215546Sopenharmony_ci ( 223bf215546Sopenharmony_ci blocks, 224bf215546Sopenharmony_ci (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), 225bf215546Sopenharmony_ci (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), 226bf215546Sopenharmony_ci 1, 227bf215546Sopenharmony_ci intra_unsigned 228bf215546Sopenharmony_ci ); 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci blocks += BLOCK_SIZE; 231bf215546Sopenharmony_ci } 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by) 234bf215546Sopenharmony_ci for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx) 235bf215546Sopenharmony_ci { 236bf215546Sopenharmony_ci const int start = 16, stop = 240, range = stop - start; 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci Gradient 239bf215546Sopenharmony_ci ( 240bf215546Sopenharmony_ci blocks, 241bf215546Sopenharmony_ci (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), 242bf215546Sopenharmony_ci (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), 243bf215546Sopenharmony_ci 1, 244bf215546Sopenharmony_ci intra_unsigned 245bf215546Sopenharmony_ci ); 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci blocks += BLOCK_SIZE; 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci Gradient 250bf215546Sopenharmony_ci ( 251bf215546Sopenharmony_ci blocks, 252bf215546Sopenharmony_ci (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), 253bf215546Sopenharmony_ci (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), 254bf215546Sopenharmony_ci 1, 255bf215546Sopenharmony_ci intra_unsigned 256bf215546Sopenharmony_ci ); 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci blocks += BLOCK_SIZE; 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci } 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci XSelectInput(display, window, ExposureMask | KeyPressMask); 263bf215546Sopenharmony_ci XMapWindow(display, window); 264bf215546Sopenharmony_ci XSync(display, 0); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci /* Test NULL context */ 267bf215546Sopenharmony_ci assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext); 268bf215546Sopenharmony_ci /* Test NULL surface */ 269bf215546Sopenharmony_ci assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface); 270bf215546Sopenharmony_ci /* Test bad picture structure */ 271bf215546Sopenharmony_ci assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue); 272bf215546Sopenharmony_ci /* Test valid params */ 273bf215546Sopenharmony_ci assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success); 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci /* Test NULL surface */ 276bf215546Sopenharmony_ci assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface); 277bf215546Sopenharmony_ci /* Test bad window */ 278bf215546Sopenharmony_ci /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */ 279bf215546Sopenharmony_ci /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/ 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci if (prompt) 282bf215546Sopenharmony_ci { 283bf215546Sopenharmony_ci puts("Press any button to quit..."); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci while (!quit) 286bf215546Sopenharmony_ci { 287bf215546Sopenharmony_ci if (XPending(display) > 0) 288bf215546Sopenharmony_ci { 289bf215546Sopenharmony_ci XEvent event; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci XNextEvent(display, &event); 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci switch (event.type) 294bf215546Sopenharmony_ci { 295bf215546Sopenharmony_ci case Expose: 296bf215546Sopenharmony_ci { 297bf215546Sopenharmony_ci /* Test valid params */ 298bf215546Sopenharmony_ci assert 299bf215546Sopenharmony_ci ( 300bf215546Sopenharmony_ci XvMCPutSurface 301bf215546Sopenharmony_ci ( 302bf215546Sopenharmony_ci display, &surface, window, 303bf215546Sopenharmony_ci 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 304bf215546Sopenharmony_ci 0, 0, output_width, output_height, 305bf215546Sopenharmony_ci XVMC_FRAME_PICTURE 306bf215546Sopenharmony_ci ) == Success 307bf215546Sopenharmony_ci ); 308bf215546Sopenharmony_ci break; 309bf215546Sopenharmony_ci } 310bf215546Sopenharmony_ci case KeyPress: 311bf215546Sopenharmony_ci { 312bf215546Sopenharmony_ci quit = 1; 313bf215546Sopenharmony_ci break; 314bf215546Sopenharmony_ci } 315bf215546Sopenharmony_ci } 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci } 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci assert(XvMCDestroyBlocks(display, &block_array) == Success); 321bf215546Sopenharmony_ci assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); 322bf215546Sopenharmony_ci assert(XvMCDestroySurface(display, &surface) == Success); 323bf215546Sopenharmony_ci assert(XvMCDestroyContext(display, &context) == Success); 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci XvUngrabPort(display, port_num, CurrentTime); 326bf215546Sopenharmony_ci XDestroyWindow(display, window); 327bf215546Sopenharmony_ci XCloseDisplay(display); 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci return 0; 330bf215546Sopenharmony_ci} 331