| Index: third_party/libva/va/va_fool.c
|
| diff --git a/third_party/libva/va/va_fool.c b/third_party/libva/va/va_fool.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..807307e84d92dc16d9af8e6a854fa628d8ca6ccb
|
| --- /dev/null
|
| +++ b/third_party/libva/va/va_fool.c
|
| @@ -0,0 +1,367 @@
|
| +/*
|
| + * Copyright (c) 2009 Intel Corporation. All Rights Reserved.
|
| + *
|
| + * Permission is hereby granted, free of charge, to any person obtaining a
|
| + * copy of this software and associated documentation files (the
|
| + * "Software"), to deal in the Software without restriction, including
|
| + * without limitation the rights to use, copy, modify, merge, publish,
|
| + * distribute, sub license, and/or sell copies of the Software, and to
|
| + * permit persons to whom the Software is furnished to do so, subject to
|
| + * the following conditions:
|
| + *
|
| + * The above copyright notice and this permission notice (including the
|
| + * next paragraph) shall be included in all copies or substantial portions
|
| + * of the Software.
|
| + *
|
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
| + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
| + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
| + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
|
| + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
| + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
| + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
| + */
|
| +
|
| +#define _GNU_SOURCE 1
|
| +#include "va.h"
|
| +#include "va_backend.h"
|
| +#include "va_trace.h"
|
| +#include "va_fool.h"
|
| +
|
| +#include <assert.h>
|
| +#include <stdarg.h>
|
| +#include <stdlib.h>
|
| +#include <stdio.h>
|
| +#include <string.h>
|
| +#include <dlfcn.h>
|
| +#include <unistd.h>
|
| +#include <sys/types.h>
|
| +#include <sys/stat.h>
|
| +#include <unistd.h>
|
| +#include <time.h>
|
| +#include <fcntl.h>
|
| +
|
| +/*
|
| + * Do dummy decode/encode, ignore the input data
|
| + * In order to debug memory leak or low performance issues, we need to isolate driver problems
|
| + * We export env "VA_FOOL", with which, we can do fake decode/encode:
|
| + *
|
| + * LIBVA_FOOL_DECODE:
|
| + * . if set, decode does nothing
|
| + * LIBVA_FOOL_ENCODE=<framename>:
|
| + * . if set, encode does nothing, but fill in the coded buffer from the content of files with
|
| + * name framename.0,framename.1,framename.2, ..., framename.N, framename.N,framename.N,...
|
| + * LIBVA_FOOL_JPEG=<framename>:fill the content of filename to codedbuf for jpeg encoding
|
| + * LIBVA_FOOL_POSTP:
|
| + * . if set, do nothing for vaPutSurface
|
| + */
|
| +
|
| +
|
| +/* global settings */
|
| +int fool_codec = 0;
|
| +int fool_postp = 0;
|
| +
|
| +#define FOOL_CONTEXT_MAX 4
|
| +
|
| +#define FOOL_BUFID_MAGIC 0x12345600
|
| +#define FOOL_BUFID_MASK 0xffffff00
|
| +/* per context settings */
|
| +static struct _fool_context {
|
| + VADisplay dpy; /* should use context as the key */
|
| +
|
| + char *fn_enc;/* file pattern with codedbuf content for encode */
|
| + char *segbuf_enc; /* the segment buffer of coded buffer, load frome fn_enc */
|
| + int file_count;
|
| +
|
| + char *fn_jpg;/* file name of JPEG fool with codedbuf content */
|
| + char *segbuf_jpg; /* the segment buffer of coded buffer, load frome fn_jpg */
|
| +
|
| + VAEntrypoint entrypoint; /* current entrypoint */
|
| +
|
| + /* all buffers with same type share one malloc-ed memory
|
| + * bufferID = (buffer numbers with the same type << 8) || type
|
| + * the malloc-ed memory can be find by fool_buf[bufferID & 0xff]
|
| + * the size is ignored here
|
| + */
|
| + char *fool_buf[VABufferTypeMax]; /* memory of fool buffers */
|
| + unsigned int fool_buf_size[VABufferTypeMax]; /* size of memory of fool buffers */
|
| + unsigned int fool_buf_element[VABufferTypeMax]; /* element count of created buffers */
|
| + unsigned int fool_buf_count[VABufferTypeMax]; /* count of created buffers */
|
| + VAContextID context;
|
| +} fool_context[FOOL_CONTEXT_MAX]; /* trace five context at the same time */
|
| +
|
| +#define DPY2INDEX(dpy) \
|
| + int idx; \
|
| + \
|
| + for (idx = 0; idx < FOOL_CONTEXT_MAX; idx++) \
|
| + if (fool_context[idx].dpy == dpy) \
|
| + break; \
|
| + \
|
| + if (idx == FOOL_CONTEXT_MAX) \
|
| + return 0; /* let driver go */
|
| +
|
| +/* Prototype declarations (functions defined in va.c) */
|
| +
|
| +void va_errorMessage(const char *msg, ...);
|
| +void va_infoMessage(const char *msg, ...);
|
| +
|
| +int va_parseConfig(char *env, char *env_value);
|
| +
|
| +void va_FoolInit(VADisplay dpy)
|
| +{
|
| + char env_value[1024];
|
| + int fool_index = 0;
|
| +
|
| + for (fool_index = 0; fool_index < FOOL_CONTEXT_MAX; fool_index++)
|
| + if (fool_context[fool_index].dpy == 0)
|
| + break;
|
| +
|
| + if (fool_index == FOOL_CONTEXT_MAX)
|
| + return;
|
| +
|
| + memset(&fool_context[fool_index], 0, sizeof(struct _fool_context));
|
| + if (va_parseConfig("LIBVA_FOOL_POSTP", NULL) == 0) {
|
| + fool_postp = 1;
|
| + va_infoMessage("LIBVA_FOOL_POSTP is on, dummy vaPutSurface\n");
|
| + }
|
| +
|
| + if (va_parseConfig("LIBVA_FOOL_DECODE", NULL) == 0) {
|
| + fool_codec |= VA_FOOL_FLAG_DECODE;
|
| + va_infoMessage("LIBVA_FOOL_DECODE is on, dummy decode\n");
|
| + }
|
| + if (va_parseConfig("LIBVA_FOOL_ENCODE", &env_value[0]) == 0) {
|
| + fool_codec |= VA_FOOL_FLAG_ENCODE;
|
| + fool_context[fool_index].fn_enc = strdup(env_value);
|
| + va_infoMessage("LIBVA_FOOL_ENCODE is on, load encode data from file with patten %s\n",
|
| + fool_context[fool_index].fn_enc);
|
| + }
|
| + if (va_parseConfig("LIBVA_FOOL_JPEG", &env_value[0]) == 0) {
|
| + fool_codec |= VA_FOOL_FLAG_JPEG;
|
| + fool_context[fool_index].fn_jpg = strdup(env_value);
|
| + va_infoMessage("LIBVA_FOOL_JPEG is on, load encode data from file with patten %s\n",
|
| + fool_context[fool_index].fn_jpg);
|
| + }
|
| +
|
| + if (fool_codec)
|
| + fool_context[fool_index].dpy = dpy;
|
| +}
|
| +
|
| +
|
| +int va_FoolEnd(VADisplay dpy)
|
| +{
|
| + int i;
|
| + DPY2INDEX(dpy);
|
| +
|
| + for (i = 0; i < VABufferTypeMax; i++) {/* free memory */
|
| + if (fool_context[idx].fool_buf[i])
|
| + free(fool_context[idx].fool_buf[i]);
|
| + }
|
| + if (fool_context[idx].segbuf_enc)
|
| + free(fool_context[idx].segbuf_enc);
|
| + if (fool_context[idx].segbuf_jpg)
|
| + free(fool_context[idx].segbuf_jpg);
|
| + if (fool_context[idx].fn_enc)
|
| + free(fool_context[idx].fn_enc);
|
| + if (fool_context[idx].fn_jpg)
|
| + free(fool_context[idx].fn_jpg);
|
| +
|
| + memset(&fool_context[idx], 0, sizeof(struct _fool_context));
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +
|
| +int va_FoolCreateConfig(
|
| + VADisplay dpy,
|
| + VAProfile profile,
|
| + VAEntrypoint entrypoint,
|
| + VAConfigAttrib *attrib_list,
|
| + int num_attribs,
|
| + VAConfigID *config_id /* out */
|
| +)
|
| +{
|
| + DPY2INDEX(dpy);
|
| +
|
| + fool_context[idx].entrypoint = entrypoint;
|
| +
|
| + /*
|
| + * check fool_codec to align with current context
|
| + * e.g. fool_codec = decode then for encode, the
|
| + * vaBegin/vaRender/vaEnd also run into fool path
|
| + * which is not desired
|
| + */
|
| + if (((fool_codec & VA_FOOL_FLAG_DECODE) && (entrypoint == VAEntrypointVLD)) ||
|
| + ((fool_codec & VA_FOOL_FLAG_ENCODE) && (entrypoint == VAEntrypointEncSlice)) ||
|
| + ((fool_codec & VA_FOOL_FLAG_JPEG) && (entrypoint == VAEntrypointEncPicture)))
|
| + ; /* the fool_codec is meaningful */
|
| + else
|
| + fool_codec = 0;
|
| +
|
| + return 0; /* driver continue */
|
| +}
|
| +
|
| +
|
| +VAStatus va_FoolCreateBuffer(
|
| + VADisplay dpy,
|
| + VAContextID context, /* in */
|
| + VABufferType type, /* in */
|
| + unsigned int size, /* in */
|
| + unsigned int num_elements, /* in */
|
| + void *data, /* in */
|
| + VABufferID *buf_id /* out */
|
| +)
|
| +{
|
| + unsigned int new_size = size * num_elements;
|
| + unsigned int old_size;
|
| + DPY2INDEX(dpy);
|
| +
|
| + old_size = fool_context[idx].fool_buf_size[type] * fool_context[idx].fool_buf_element[type];
|
| +
|
| + if (old_size < new_size)
|
| + fool_context[idx].fool_buf[type] = realloc(fool_context[idx].fool_buf[type], new_size);
|
| +
|
| + fool_context[idx].fool_buf_size[type] = size;
|
| + fool_context[idx].fool_buf_element[type] = num_elements;
|
| + fool_context[idx].fool_buf_count[type]++;
|
| + /* because we ignore the vaRenderPicture,
|
| + * all buffers with same type share same real memory
|
| + * bufferID = (magic number) | type
|
| + */
|
| + *buf_id = FOOL_BUFID_MAGIC | type;
|
| +
|
| + return 1; /* don't call into driver */
|
| +}
|
| +
|
| +VAStatus va_FoolBufferInfo(
|
| + VADisplay dpy,
|
| + VABufferID buf_id, /* in */
|
| + VABufferType *type, /* out */
|
| + unsigned int *size, /* out */
|
| + unsigned int *num_elements /* out */
|
| +)
|
| +{
|
| + unsigned int magic = buf_id & FOOL_BUFID_MASK;
|
| + DPY2INDEX(dpy);
|
| +
|
| + if (magic != FOOL_BUFID_MAGIC)
|
| + return 0;
|
| +
|
| + *type = buf_id & 0xff;
|
| + *size = fool_context[idx].fool_buf_size[*type];
|
| + *num_elements = fool_context[idx].fool_buf_element[*type];;
|
| +
|
| + return 1; /* don't call into driver */
|
| +}
|
| +
|
| +static int va_FoolFillCodedBufEnc(int idx)
|
| +{
|
| + char file_name[1024];
|
| + struct stat file_stat;
|
| + VACodedBufferSegment *codedbuf;
|
| + int i, fd = -1;
|
| +
|
| + /* try file_name.file_count, if fail, try file_name.file_count-- */
|
| + for (i=0; i<=1; i++) {
|
| + sprintf(file_name, "%s.%d",
|
| + fool_context[idx].fn_enc,
|
| + fool_context[idx].file_count);
|
| +
|
| + if ((fd = open(file_name, O_RDONLY)) != -1) {
|
| + fstat(fd, &file_stat);
|
| + fool_context[idx].file_count++; /* open next file */
|
| + break;
|
| + }
|
| +
|
| + fool_context[idx].file_count--; /* fall back to previous file */
|
| + if (fool_context[idx].file_count < 0)
|
| + fool_context[idx].file_count = 0;
|
| + }
|
| + if (fd != -1) {
|
| + fool_context[idx].segbuf_enc = realloc(fool_context[idx].segbuf_enc, file_stat.st_size);
|
| + read(fd, fool_context[idx].segbuf_enc, file_stat.st_size);
|
| + close(fd);
|
| + }
|
| + codedbuf = (VACodedBufferSegment *)fool_context[idx].fool_buf[VAEncCodedBufferType];
|
| + codedbuf->size = file_stat.st_size;
|
| + codedbuf->bit_offset = 0;
|
| + codedbuf->status = 0;
|
| + codedbuf->reserved = 0;
|
| + codedbuf->buf = fool_context[idx].segbuf_enc;
|
| + codedbuf->next = NULL;
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +
|
| +static int va_FoolFillCodedBufJPG(int idx)
|
| +{
|
| + struct stat file_stat;
|
| + VACodedBufferSegment *codedbuf;
|
| + int i, fd = -1;
|
| +
|
| + if ((fd = open(fool_context[idx].fn_jpg, O_RDONLY)) != -1)
|
| + fstat(fd, &file_stat);
|
| +
|
| + if (fd != -1) {
|
| + fool_context[idx].segbuf_jpg = realloc(fool_context[idx].segbuf_jpg, file_stat.st_size);
|
| + read(fd, fool_context[idx].segbuf_jpg, file_stat.st_size);
|
| + close(fd);
|
| + }
|
| + codedbuf = (VACodedBufferSegment *)fool_context[idx].fool_buf[VAEncCodedBufferType];
|
| + codedbuf->size = file_stat.st_size;
|
| + codedbuf->bit_offset = 0;
|
| + codedbuf->status = 0;
|
| + codedbuf->reserved = 0;
|
| + codedbuf->buf = fool_context[idx].segbuf_jpg;
|
| + codedbuf->next = NULL;
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +
|
| +static int va_FoolFillCodedBuf(int idx)
|
| +{
|
| + if (fool_context[idx].entrypoint == VAEntrypointEncSlice)
|
| + va_FoolFillCodedBufEnc(idx);
|
| + else if (fool_context[idx].entrypoint == VAEntrypointEncPicture)
|
| + va_FoolFillCodedBufJPG(idx);
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +
|
| +VAStatus va_FoolMapBuffer(
|
| + VADisplay dpy,
|
| + VABufferID buf_id, /* in */
|
| + void **pbuf /* out */
|
| +)
|
| +{
|
| + unsigned int buftype = buf_id & 0xff;
|
| + unsigned int magic = buf_id & FOOL_BUFID_MASK;
|
| + DPY2INDEX(dpy);
|
| +
|
| + if (magic != FOOL_BUFID_MAGIC)
|
| + return 0;
|
| +
|
| + /* buf_id is the buffer type */
|
| + *pbuf = fool_context[idx].fool_buf[buftype];
|
| +
|
| + /* it is coded buffer, fill the fake segment buf from file */
|
| + if (*pbuf && (buftype == VAEncCodedBufferType))
|
| + va_FoolFillCodedBuf(idx);
|
| +
|
| + return 1; /* don't call into driver */
|
| +}
|
| +
|
| +VAStatus va_FoolUnmapBuffer(
|
| + VADisplay dpy,
|
| + VABufferID buf_id /* in */
|
| +)
|
| +{
|
| + unsigned int magic = buf_id & FOOL_BUFID_MASK;
|
| +
|
| + if (magic != FOOL_BUFID_MAGIC)
|
| + return 0;
|
| +
|
| + return 1;
|
| +}
|
|
|