Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the
  6.  * "Software"), to deal in the Software without restriction, including
  7.  * without limitation the rights to use, copy, modify, merge, publish,
  8.  * distribute, sub license, and/or sell copies of the Software, and to
  9.  * permit persons to whom the Software is furnished to do so, subject to
  10.  * the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the
  13.  * next paragraph) shall be included in all copies or substantial portions
  14.  * of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  19.  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
  20.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  22.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. #define _GNU_SOURCE 1
  26. #include "va.h"
  27. #include "va_backend.h"
  28. #include "va_trace.h"
  29. #include "va_fool.h"
  30.  
  31. #include <assert.h>
  32. #include <stdarg.h>
  33. #include <stdlib.h>
  34. #include <stdio.h>
  35. #include <errno.h>
  36. #include <string.h>
  37. #include <unistd.h>
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <unistd.h>
  41. #include <time.h>
  42. #include <fcntl.h>
  43.  
  44. /*
  45.  * Do dummy decode/encode, ignore the input data
  46.  * In order to debug memory leak or low performance issues, we need to isolate driver problems
  47.  * We export env "VA_FOOL", with which, we can do fake decode/encode:
  48.  *
  49.  * LIBVA_FOOL_DECODE:
  50.  * . if set, decode does nothing
  51.  * LIBVA_FOOL_ENCODE=<framename>:
  52.  * . if set, encode does nothing, but fill in the coded buffer from the content of files with
  53.  *   name framename.0,framename.1,..., framename.N, framename.0,..., framename.N,...repeatly
  54.  *   Use file name to determine h264 or vp8
  55.  * LIBVA_FOOL_JPEG=<framename>:fill the content of filename to codedbuf for jpeg encoding
  56.  * LIBVA_FOOL_POSTP:
  57.  * . if set, do nothing for vaPutSurface
  58.  */
  59.  
  60.  
  61. /* global settings */
  62. int fool_codec = 0;
  63. int fool_postp  = 0;
  64.  
  65. #define FOOL_BUFID_MAGIC   0x12345600
  66. #define FOOL_BUFID_MASK    0xffffff00
  67.  
  68. struct fool_context {
  69.     int enabled; /* fool_codec is global, and it is for concurent encode/decode */
  70.     char *fn_enc;/* file pattern with codedbuf content for encode */
  71.     char *segbuf_enc; /* the segment buffer of coded buffer, load frome fn_enc */
  72.     int file_count;
  73.  
  74.     char *fn_jpg;/* file name of JPEG fool with codedbuf content */
  75.     char *segbuf_jpg; /* the segment buffer of coded buffer, load frome fn_jpg */
  76.  
  77.     VAEntrypoint entrypoint; /* current entrypoint */
  78.  
  79.     /* all buffers with same type share one malloc-ed memory
  80.      * bufferID = (buffer numbers with the same type << 8) || type
  81.      * the malloc-ed memory can be find by fool_buf[bufferID & 0xff]
  82.      * the size is ignored here
  83.      */
  84.     char *fool_buf[VABufferTypeMax]; /* memory of fool buffers */
  85.     unsigned int fool_buf_size[VABufferTypeMax]; /* size of memory of fool buffers */
  86.     unsigned int fool_buf_element[VABufferTypeMax]; /* element count of created buffers */
  87.     unsigned int fool_buf_count[VABufferTypeMax]; /* count of created buffers */
  88.     VAContextID context;
  89. };
  90.  
  91. #define FOOL_CTX(dpy) ((struct fool_context *)((VADisplayContextP)dpy)->vafool)
  92.  
  93. #define DPY2FOOLCTX(dpy)                                 \
  94.     struct fool_context *fool_ctx = FOOL_CTX(dpy);       \
  95.     if (fool_ctx == NULL)                                \
  96.         return 0; /* no fool for the context */          \
  97.  
  98. #define DPY2FOOLCTX_CHK(dpy)                             \
  99.     struct fool_context *fool_ctx = FOOL_CTX(dpy);       \
  100.     if ((fool_ctx == NULL) || (fool_ctx->enabled == 0))  \
  101.         return 0; /* no fool for the context */          \
  102.  
  103. /* Prototype declarations (functions defined in va.c) */
  104.  
  105. void va_errorMessage(const char *msg, ...);
  106. void va_infoMessage(const char *msg, ...);
  107.  
  108. int  va_parseConfig(char *env, char *env_value);
  109.  
  110. void va_FoolInit(VADisplay dpy)
  111. {
  112.     char env_value[1024];
  113.  
  114.     struct fool_context *fool_ctx = calloc(sizeof(struct fool_context), 1);
  115.  
  116.     if (fool_ctx == NULL)
  117.         return;
  118.  
  119.     if (va_parseConfig("LIBVA_FOOL_POSTP", NULL) == 0) {
  120.         fool_postp = 1;
  121.         va_infoMessage("LIBVA_FOOL_POSTP is on, dummy vaPutSurface\n");
  122.     }
  123.  
  124.     if (va_parseConfig("LIBVA_FOOL_DECODE", NULL) == 0) {
  125.         fool_codec  |= VA_FOOL_FLAG_DECODE;
  126.         va_infoMessage("LIBVA_FOOL_DECODE is on, dummy decode\n");
  127.     }
  128.     if (va_parseConfig("LIBVA_FOOL_ENCODE", &env_value[0]) == 0) {
  129.         fool_codec  |= VA_FOOL_FLAG_ENCODE;
  130.         fool_ctx->fn_enc = strdup(env_value);
  131.         va_infoMessage("LIBVA_FOOL_ENCODE is on, load encode data from file with patten %s\n",
  132.                        fool_ctx->fn_enc);
  133.     }
  134.     if (va_parseConfig("LIBVA_FOOL_JPEG", &env_value[0]) == 0) {
  135.         fool_codec  |= VA_FOOL_FLAG_JPEG;
  136.         fool_ctx->fn_jpg = strdup(env_value);
  137.         va_infoMessage("LIBVA_FOOL_JPEG is on, load encode data from file with patten %s\n",
  138.                        fool_ctx->fn_jpg);
  139.     }
  140.  
  141.     ((VADisplayContextP)dpy)->vafool = fool_ctx;
  142. }
  143.  
  144.  
  145. int va_FoolEnd(VADisplay dpy)
  146. {
  147.     int i;
  148.     DPY2FOOLCTX(dpy);
  149.  
  150.     for (i = 0; i < VABufferTypeMax; i++) {/* free memory */
  151.         if (fool_ctx->fool_buf[i])
  152.             free(fool_ctx->fool_buf[i]);
  153.     }
  154.     if (fool_ctx->segbuf_enc)
  155.         free(fool_ctx->segbuf_enc);
  156.     if (fool_ctx->segbuf_jpg)
  157.         free(fool_ctx->segbuf_jpg);
  158.     if (fool_ctx->fn_enc)
  159.         free(fool_ctx->fn_enc);
  160.     if (fool_ctx->fn_jpg)
  161.         free(fool_ctx->fn_jpg);
  162.  
  163.     free(fool_ctx);
  164.     ((VADisplayContextP)dpy)->vafool = NULL;
  165.  
  166.     return 0;
  167. }
  168.  
  169. int va_FoolCreateConfig(
  170.         VADisplay dpy,
  171.         VAProfile profile,
  172.         VAEntrypoint entrypoint,
  173.         VAConfigAttrib *attrib_list,
  174.         int num_attribs,
  175.         VAConfigID *config_id /* out */
  176. )
  177. {
  178.     DPY2FOOLCTX(dpy);
  179.  
  180.     fool_ctx->entrypoint = entrypoint;
  181.  
  182.     /*
  183.      * check fool_codec to align with current context
  184.      * e.g. fool_codec = decode then for encode, the
  185.      * vaBegin/vaRender/vaEnd also run into fool path
  186.      * which is not desired
  187.      */
  188.     if (((fool_codec & VA_FOOL_FLAG_DECODE) && (entrypoint == VAEntrypointVLD)) ||
  189.         ((fool_codec & VA_FOOL_FLAG_JPEG) && (entrypoint == VAEntrypointEncPicture)))
  190.         fool_ctx->enabled = 1;
  191.     else if ((fool_codec & VA_FOOL_FLAG_ENCODE) && (entrypoint == VAEntrypointEncSlice)) {
  192.         /* H264 is desired */
  193.         if (((profile == VAProfileH264Baseline ||
  194.               profile == VAProfileH264Main ||
  195.               profile == VAProfileH264High ||
  196.               profile == VAProfileH264ConstrainedBaseline)) &&
  197.             strstr(fool_ctx->fn_enc, "h264"))
  198.             fool_ctx->enabled = 1;
  199.  
  200.         /* vp8 is desired */
  201.         if ((profile == VAProfileVP8Version0_3) &&
  202.             strstr(fool_ctx->fn_enc, "vp8"))
  203.             fool_ctx->enabled = 1;
  204.     }
  205.     if (fool_ctx->enabled)
  206.         va_infoMessage("FOOL is enabled for this context\n");
  207.     else
  208.         va_infoMessage("FOOL is not enabled for this context\n");
  209.  
  210.    
  211.     return 0; /* continue */
  212. }
  213.  
  214.  
  215. VAStatus va_FoolCreateBuffer(
  216.     VADisplay dpy,
  217.     VAContextID context,        /* in */
  218.     VABufferType type,          /* in */
  219.     unsigned int size,          /* in */
  220.     unsigned int num_elements,  /* in */
  221.     void *data,                 /* in */
  222.     VABufferID *buf_id          /* out */
  223. )
  224. {
  225.     unsigned int new_size = size * num_elements;
  226.     unsigned int old_size;
  227.     DPY2FOOLCTX_CHK(dpy);
  228.  
  229.     old_size = fool_ctx->fool_buf_size[type] * fool_ctx->fool_buf_element[type];
  230.  
  231.     if (old_size < new_size)
  232.         fool_ctx->fool_buf[type] = realloc(fool_ctx->fool_buf[type], new_size);
  233.    
  234.     fool_ctx->fool_buf_size[type] = size;
  235.     fool_ctx->fool_buf_element[type] = num_elements;
  236.     fool_ctx->fool_buf_count[type]++;
  237.     /* because we ignore the vaRenderPicture,
  238.      * all buffers with same type share same real memory
  239.      * bufferID = (magic number) | type
  240.      */
  241.     *buf_id = FOOL_BUFID_MAGIC | type;
  242.  
  243.     return 1; /* don't call into driver */
  244. }
  245.  
  246. VAStatus va_FoolBufferInfo(
  247.     VADisplay dpy,
  248.     VABufferID buf_id,  /* in */
  249.     VABufferType *type, /* out */
  250.     unsigned int *size,         /* out */
  251.     unsigned int *num_elements /* out */
  252. )
  253. {
  254.     unsigned int magic;
  255.    
  256.     DPY2FOOLCTX_CHK(dpy);
  257.  
  258.     magic = buf_id & FOOL_BUFID_MASK;
  259.     if (magic != FOOL_BUFID_MAGIC)
  260.         return 0; /* could be VAImageBufferType from vaDeriveImage */
  261.    
  262.     *type = buf_id & 0xff;
  263.     *size = fool_ctx->fool_buf_size[*type];
  264.     *num_elements = fool_ctx->fool_buf_element[*type];;
  265.    
  266.     return 1; /* fool is valid */
  267. }
  268.  
  269. static int va_FoolFillCodedBufEnc(struct fool_context *fool_ctx)
  270. {
  271.     char file_name[1024];
  272.     struct stat file_stat = {0};
  273.     VACodedBufferSegment *codedbuf;
  274.     int i, fd = -1;
  275.  
  276.     /* try file_name.file_count, if fail, try file_name.file_count-- */
  277.     for (i=0; i<=1; i++) {
  278.         snprintf(file_name, 1024, "%s.%d",
  279.                  fool_ctx->fn_enc,
  280.                  fool_ctx->file_count);
  281.  
  282.         if ((fd = open(file_name, O_RDONLY)) != -1) {
  283.             fstat(fd, &file_stat);
  284.             fool_ctx->file_count++; /* open next file */
  285.             break;
  286.         } else /* fall back to the first file file */
  287.             fool_ctx->file_count = 0;
  288.     }
  289.     if (fd != -1) {
  290.         fool_ctx->segbuf_enc = realloc(fool_ctx->segbuf_enc, file_stat.st_size);
  291.         read(fd, fool_ctx->segbuf_enc, file_stat.st_size);
  292.         close(fd);
  293.     } else
  294.         va_errorMessage("Open file %s failed:%s\n", file_name, strerror(errno));
  295.  
  296.     codedbuf = (VACodedBufferSegment *)fool_ctx->fool_buf[VAEncCodedBufferType];
  297.     codedbuf->size = file_stat.st_size;
  298.     codedbuf->bit_offset = 0;
  299.     codedbuf->status = 0;
  300.     codedbuf->reserved = 0;
  301.     codedbuf->buf = fool_ctx->segbuf_enc;
  302.     codedbuf->next = NULL;
  303.  
  304.     return 0;
  305. }
  306.  
  307. static int va_FoolFillCodedBufJPG(struct fool_context *fool_ctx)
  308. {
  309.     struct stat file_stat = {0};
  310.     VACodedBufferSegment *codedbuf;
  311.     int fd = -1;
  312.  
  313.     if ((fd = open(fool_ctx->fn_jpg, O_RDONLY)) != -1) {
  314.         fstat(fd, &file_stat);
  315.         fool_ctx->segbuf_jpg = realloc(fool_ctx->segbuf_jpg, file_stat.st_size);
  316.         read(fd, fool_ctx->segbuf_jpg, file_stat.st_size);
  317.         close(fd);
  318.     } else
  319.         va_errorMessage("Open file %s failed:%s\n", fool_ctx->fn_jpg, strerror(errno));
  320.  
  321.     codedbuf = (VACodedBufferSegment *)fool_ctx->fool_buf[VAEncCodedBufferType];
  322.     codedbuf->size = file_stat.st_size;
  323.     codedbuf->bit_offset = 0;
  324.     codedbuf->status = 0;
  325.     codedbuf->reserved = 0;
  326.     codedbuf->buf = fool_ctx->segbuf_jpg;
  327.     codedbuf->next = NULL;
  328.  
  329.     return 0;
  330. }
  331.  
  332.  
  333. static int va_FoolFillCodedBuf(struct fool_context *fool_ctx)
  334. {
  335.     if (fool_ctx->entrypoint == VAEntrypointEncSlice)
  336.         va_FoolFillCodedBufEnc(fool_ctx);
  337.     else if (fool_ctx->entrypoint == VAEntrypointEncPicture)
  338.         va_FoolFillCodedBufJPG(fool_ctx);
  339.        
  340.     return 0;
  341. }
  342.  
  343.  
  344. VAStatus va_FoolMapBuffer(
  345.     VADisplay dpy,
  346.     VABufferID buf_id,  /* in */
  347.     void **pbuf         /* out */
  348. )
  349. {
  350.     unsigned int magic, buftype;
  351.     DPY2FOOLCTX_CHK(dpy);
  352.  
  353.     magic = buf_id & FOOL_BUFID_MASK;
  354.     if (magic != FOOL_BUFID_MAGIC)
  355.         return 0; /* could be VAImageBufferType from vaDeriveImage */
  356.    
  357.     buftype = buf_id & 0xff;
  358.     *pbuf = fool_ctx->fool_buf[buftype];
  359.  
  360.     /* it is coded buffer, fill coded segment from file */
  361.     if (*pbuf && (buftype == VAEncCodedBufferType))
  362.         va_FoolFillCodedBuf(fool_ctx);
  363.    
  364.     return 1; /* fool is valid */
  365. }
  366.  
  367. VAStatus va_FoolCheckContinuity(VADisplay dpy)
  368. {
  369.     DPY2FOOLCTX_CHK(dpy);
  370.  
  371.     return 1; /* fool is valid */
  372. }
  373.  
  374.