Blame va/va_fool.c

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