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 <stdlib.h>
  32. #include <sys/time.h>
  33. #include "testlib.h"
  34.  
  35. #define MACROBLOCK_WIDTH                16
  36. #define MACROBLOCK_HEIGHT               16
  37. #define BLOCKS_PER_MACROBLOCK           6
  38.  
  39. #define DEFAULT_INPUT_WIDTH             720
  40. #define DEFAULT_INPUT_HEIGHT            480
  41. #define DEFAULT_REPS                    100
  42.  
  43. #define PIPELINE_STEP_MC                1
  44. #define PIPELINE_STEP_CSC               2
  45. #define PIPELINE_STEP_SWAP              4
  46.  
  47. #define MB_TYPE_I                       1
  48. #define MB_TYPE_P                       2
  49. #define MB_TYPE_B                       4
  50.  
  51. struct Config
  52. {
  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;
  59.         unsigned int reps;
  60. };
  61.  
  62. void ParseArgs(int argc, char **argv, struct Config *config);
  63.  
  64. void ParseArgs(int argc, char **argv, struct Config *config)
  65. {
  66.         int fail = 0;
  67.         int i;
  68.  
  69.         config->input_width = DEFAULT_INPUT_WIDTH;
  70.         config->input_height = DEFAULT_INPUT_HEIGHT;
  71.         config->output_width = 0;
  72.         config->output_height = 0;
  73.         config->pipeline = 0;
  74.         config->mb_types = 0;
  75.         config->reps = DEFAULT_REPS;
  76.  
  77.         for (i = 1; i < argc && !fail; ++i)
  78.         {
  79.                 if (!strcmp(argv[i], "-iw"))
  80.                 {
  81.                         if (sscanf(argv[++i], "%u", &config->input_width) != 1)
  82.                                 fail = 1;
  83.                 }
  84.                 else if (!strcmp(argv[i], "-ih"))
  85.                 {
  86.                         if (sscanf(argv[++i], "%u", &config->input_height) != 1)
  87.                                 fail = 1;
  88.                 }
  89.                 else if (!strcmp(argv[i], "-ow"))
  90.                 {
  91.                         if (sscanf(argv[++i], "%u", &config->output_width) != 1)
  92.                                 fail = 1;
  93.                 }
  94.                 else if (!strcmp(argv[i], "-oh"))
  95.                 {
  96.                         if (sscanf(argv[++i], "%u", &config->output_height) != 1)
  97.                                 fail = 1;
  98.                 }
  99.                 else if (!strcmp(argv[i], "-p"))
  100.                 {
  101.                         char *token = strtok(argv[++i], ",");
  102.  
  103.                         while (token && !fail)
  104.                         {
  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;
  111.                                 else
  112.                                         fail = 1;
  113.  
  114.                                 if (!fail)
  115.                                         token = strtok(NULL, ",");
  116.                         }
  117.                 }
  118.                 else if (!strcmp(argv[i], "-mb"))
  119.                 {
  120.                         char *token = strtok(argv[++i], ",");
  121.  
  122.                         while (token && !fail)
  123.                         {
  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;
  130.                                 else
  131.                                         fail = 1;
  132.  
  133.                                 if (!fail)
  134.                                         token = strtok(NULL, ",");
  135.                         }
  136.                 }
  137.                 else if (!strcmp(argv[i], "-r"))
  138.                 {
  139.                         if (sscanf(argv[++i], "%u", &config->reps) != 1)
  140.                                 fail = 1;
  141.                 }
  142.                 else
  143.                         fail = 1;
  144.         }
  145.  
  146.         if (fail)
  147.         {
  148.                 fprintf(
  149.                         stderr,
  150.                         "Bad argument.\n"
  151.                         "\n"
  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",
  162.                         argv[0]
  163.                 );
  164.                 exit(1);
  165.         }
  166.  
  167.         if (config->output_width == 0)
  168.                 config->output_width = config->input_width;
  169.         if (config->output_height == 0)
  170.                 config->output_height = config->input_height;
  171.         if (!config->pipeline)
  172.                 config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP;
  173.         if (!config->mb_types)
  174.                 config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B;
  175. }
  176.  
  177. int main(int argc, char **argv)
  178. {
  179.         struct Config           config;
  180.         Display                 *display;
  181.         Window                  root, window;
  182.         const unsigned int      mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
  183.         XvPortID                port_num;
  184.         int                     surface_type_id;
  185.         unsigned int            is_overlay, intra_unsigned;
  186.         int                     colorkey;
  187.         XvMCContext             context;
  188.         XvMCSurface             surface;
  189.         XvMCBlockArray          block_array;
  190.         XvMCMacroBlockArray     mb_array;
  191.         unsigned int            mbw, mbh;
  192.         unsigned int            mbx, mby;
  193.         unsigned int            reps;
  194.         struct timeval          start, stop, diff;
  195.         double                  diff_secs;
  196.  
  197.         ParseArgs(argc, argv, &config);
  198.  
  199.         mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
  200.         mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
  201.  
  202.         display = XOpenDisplay(NULL);
  203.  
  204.         if (!GetPort
  205.         (
  206.                 display,
  207.                 config.input_width,
  208.                 config.input_height,
  209.                 XVMC_CHROMA_FORMAT_420,
  210.                 mc_types,
  211.                 2,
  212.                 &port_num,
  213.                 &surface_type_id,
  214.                 &is_overlay,
  215.                 &intra_unsigned
  216.         ))
  217.         {
  218.                 XCloseDisplay(display);
  219.                 fprintf(stderr, "Error, unable to find a good port.\n");
  220.                 exit(1);
  221.         }
  222.  
  223.         if (is_overlay)
  224.         {
  225.                 Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
  226.                 XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
  227.         }
  228.         else
  229.         {
  230.                 colorkey = 0;
  231.         }
  232.  
  233.         root = XDefaultRootWindow(display);
  234.         window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey);
  235.  
  236.         assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success);
  237.         assert(XvMCCreateSurface(display, &context, &surface) == Success);
  238.         assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success);
  239.         assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success);
  240.  
  241.         for (mby = 0; mby < mbh; ++mby)
  242.                 for (mbx = 0; mbx < mbw; ++mbx)
  243.                 {
  244.                         mb_array.macro_blocks[mby * mbw + mbx].x = mbx;
  245.                         mb_array.macro_blocks[mby * mbw + mbx].y = mby;
  246.                         mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA;
  247.                         /*mb->motion_type = ;*/
  248.                         /*mb->motion_vertical_field_select = ;*/
  249.                         mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME;
  250.                         /*mb->PMV[0][0][0] = ;
  251.                         mb->PMV[0][0][1] = ;
  252.                         mb->PMV[0][1][0] = ;
  253.                         mb->PMV[0][1][1] = ;
  254.                         mb->PMV[1][0][0] = ;
  255.                         mb->PMV[1][0][1] = ;
  256.                         mb->PMV[1][1][0] = ;
  257.                         mb->PMV[1][1][1] = ;*/
  258.                         mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK;
  259.                         mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F;
  260.                 }
  261.  
  262.         XSelectInput(display, window, ExposureMask | KeyPressMask);
  263.         XMapWindow(display, window);
  264.         XSync(display, 0);
  265.  
  266.         gettimeofday(&start, NULL);
  267.  
  268.         for (reps = 0; reps < config.reps; ++reps)
  269.         {
  270.                 if (config.pipeline & PIPELINE_STEP_MC)
  271.                 {
  272.                         assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success);
  273.                         assert(XvMCFlushSurface(display, &surface) == Success);
  274.                 }
  275.                 if (config.pipeline & PIPELINE_STEP_CSC)
  276.                         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);
  277.         }
  278.  
  279.         gettimeofday(&stop, NULL);
  280.  
  281.         timeval_subtract(&diff, &stop, &start);
  282.         diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0;
  283.  
  284.         printf("XvMC Benchmark\n");
  285.         printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height);
  286.         printf("Pipeline: ");
  287.         if (config.pipeline & PIPELINE_STEP_MC)
  288.                 printf("|mc|");
  289.         if (config.pipeline & PIPELINE_STEP_CSC)
  290.                 printf("|csc|");
  291.         if (config.pipeline & PIPELINE_STEP_SWAP)
  292.                 printf("|swap|");
  293.         printf("\n");
  294.         printf("Reps: %u\n", config.reps);
  295.         printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs);
  296.  
  297.         assert(XvMCDestroyBlocks(display, &block_array) == Success);
  298.         assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success);
  299.         assert(XvMCDestroySurface(display, &surface) == Success);
  300.         assert(XvMCDestroyContext(display, &context) == Success);
  301.  
  302.         XvUngrabPort(display, port_num, CurrentTime);
  303.         XDestroyWindow(display, window);
  304.         XCloseDisplay(display);
  305.  
  306.         return 0;
  307. }
  308.