Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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