Subversion Repositories Kolibri OS

Rev

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 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.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include <assert.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <stdlib.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. static void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt)
  54. {
  55.         int fail = 0;
  56.         int i;
  57.  
  58.         *output_width = DEFAULT_OUTPUT_WIDTH;
  59.         *output_height = DEFAULT_OUTPUT_HEIGHT;
  60.         *acceptable_error = DEFAULT_ACCEPTABLE_ERR;
  61.         *prompt = 0;
  62.  
  63.         for (i = 1; i < argc && !fail; ++i)
  64.         {
  65.                 if (!strcmp(argv[i], "-w"))
  66.                 {
  67.                         if (sscanf(argv[++i], "%u", output_width) != 1)
  68.                                 fail = 1;
  69.                 }
  70.                 else if (!strcmp(argv[i], "-h"))
  71.                 {
  72.                         if (sscanf(argv[++i], "%u", output_height) != 1)
  73.                                 fail = 1;
  74.                 }
  75.                 else if (!strcmp(argv[i], "-e"))
  76.                 {
  77.                         if (sscanf(argv[++i], "%lf", acceptable_error) != 1)
  78.                                 fail = 1;
  79.                 }
  80.                 else if (!strcmp(argv[i], "-p"))
  81.                         *prompt = 1;
  82.                 else
  83.                         fail = 1;
  84.         }
  85.  
  86.         if (fail)
  87.         {
  88.                 fprintf(
  89.                         stderr,
  90.                         "Bad argument.\n"
  91.                         "\n"
  92.                         "Usage: %s [options]\n"
  93.                         "\t-w <width>\tOutput width\n"
  94.                         "\t-h <height>\tOutput height\n"
  95.                         "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n"
  96.                         "\t-p\tPrompt for quit\n",
  97.                         argv[0]
  98.                 );
  99.                 exit(1);
  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.                 fprintf(stderr, "Error, unable to find a good port.\n");
  172.                 exit(1);
  173.         }
  174.  
  175.         if (is_overlay)
  176.         {
  177.                 Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
  178.                 XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
  179.         }
  180.  
  181.         root = XDefaultRootWindow(display);
  182.         window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey);
  183.  
  184.         assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success);
  185.         assert(XvMCCreateSurface(display, &context, &surface) == Success);
  186.         assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
  187.         assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success);
  188.  
  189.         mb = mb_array.macro_blocks;
  190.         blocks = block_array.blocks;
  191.  
  192.         for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby)
  193.                 for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx)
  194.                 {
  195.                         mb->x = mbx;
  196.                         mb->y = mby;
  197.                         mb->macroblock_type = XVMC_MB_TYPE_INTRA;
  198.                         /*mb->motion_type = ;*/
  199.                         /*mb->motion_vertical_field_select = ;*/
  200.                         mb->dct_type = XVMC_DCT_TYPE_FRAME;
  201.                         /*mb->PMV[0][0][0] = ;
  202.                         mb->PMV[0][0][1] = ;
  203.                         mb->PMV[0][1][0] = ;
  204.                         mb->PMV[0][1][1] = ;
  205.                         mb->PMV[1][0][0] = ;
  206.                         mb->PMV[1][0][1] = ;
  207.                         mb->PMV[1][1][0] = ;
  208.                         mb->PMV[1][1][1] = ;*/
  209.                         mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK;
  210.                         mb->coded_block_pattern = 0x3F;
  211.  
  212.                         mb++;
  213.  
  214.                         for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by)
  215.                                 for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx)
  216.                                 {
  217.                                         const int start = 16, stop = 235, range = stop - start;
  218.  
  219.                                         Gradient
  220.                                         (
  221.                                                 blocks,
  222.                                                 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
  223.                                                 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
  224.                                                 1,
  225.                                                 intra_unsigned
  226.                                         );
  227.  
  228.                                         blocks += BLOCK_SIZE;
  229.                                 }
  230.  
  231.                         for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by)
  232.                                 for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx)
  233.                                 {
  234.                                         const int start = 16, stop = 240, range = stop - start;
  235.  
  236.                                         Gradient
  237.                                         (
  238.                                                 blocks,
  239.                                                 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
  240.                                                 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
  241.                                                 1,
  242.                                                 intra_unsigned
  243.                                         );
  244.  
  245.                                         blocks += BLOCK_SIZE;
  246.  
  247.                                         Gradient
  248.                                         (
  249.                                                 blocks,
  250.                                                 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))),
  251.                                                 (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))),
  252.                                                 1,
  253.                                                 intra_unsigned
  254.                                         );
  255.  
  256.                                         blocks += BLOCK_SIZE;
  257.                                 }
  258.                 }
  259.  
  260.         XSelectInput(display, window, ExposureMask | KeyPressMask);
  261.         XMapWindow(display, window);
  262.         XSync(display, 0);
  263.  
  264.         /* Test NULL context */
  265.         assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext);
  266.         /* Test NULL surface */
  267.         assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface);
  268.         /* Test bad picture structure */
  269.         assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue);
  270.         /* Test valid params */
  271.         assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success);
  272.  
  273.         /* Test NULL surface */
  274.         assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface);
  275.         /* Test bad window */
  276.         /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */
  277.         /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/
  278.  
  279.         if (prompt)
  280.         {
  281.                 puts("Press any button to quit...");
  282.  
  283.                 while (!quit)
  284.                 {
  285.                         if (XPending(display) > 0)
  286.                         {
  287.                                 XEvent event;
  288.  
  289.                                 XNextEvent(display, &event);
  290.  
  291.                                 switch (event.type)
  292.                                 {
  293.                                         case Expose:
  294.                                         {
  295.                                                 /* Test valid params */
  296.                                                 assert
  297.                                                 (
  298.                                                         XvMCPutSurface
  299.                                                         (
  300.                                                                 display, &surface, window,
  301.                                                                 0, 0, INPUT_WIDTH, INPUT_HEIGHT,
  302.                                                                 0, 0, output_width, output_height,
  303.                                                                 XVMC_FRAME_PICTURE
  304.                                                         ) == Success
  305.                                                 );
  306.                                                 break;
  307.                                         }
  308.                                         case KeyPress:
  309.                                         {
  310.                                                 quit = 1;
  311.                                                 break;
  312.                                         }
  313.                                 }
  314.                         }
  315.                 }
  316.         }
  317.  
  318.         assert(XvMCDestroyBlocks(display, &block_array) == Success);
  319.         assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
  320.         assert(XvMCDestroySurface(display, &surface) == Success);
  321.         assert(XvMCDestroyContext(display, &context) == Success);
  322.  
  323.         XvUngrabPort(display, port_num, CurrentTime);
  324.         XDestroyWindow(display, window);
  325.         XCloseDisplay(display);
  326.  
  327.         return 0;
  328. }
  329.