/* * 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 #include #include #include #include #include #include #include #include #include #include #include "va_fool_264.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, but fill in some YUV data * LIBVA_FOOL_ENCODE: * . if set, encode does nothing, but fill in a hard-coded 720P clip into coded buffer. * . VA CONTEXT/CONFIG/SURFACE will call into drivers, but VA Buffer creation is done in here * . Bypass all ~SvaBeginPic/vaRenderPic/vaEndPic~T * LIBVA_FOOL_POSTP: * . if set, do nothing for vaPutSurface */ /* global settings */ /* LIBVA_FOOL_DECODE/LIBVA_FOOL_ENCODE/LIBVA_FOOL_POSTP */ static int fool_decode = 0; static int fool_encode = 0; int fool_postp = 0; #define FOOL_CONTEXT_MAX 4 /* per context settings */ static struct _fool_context { VADisplay dpy; /* should use context as the key */ VAProfile fool_profile; /* current profile for buffers */ VAEntrypoint fool_entrypoint; /* current entrypoint */ FILE *fool_fp_codedclip; /* load a clip from disk for fooling encode*/ /* 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_count[VABufferTypeMax]; /* count of created buffers */ VAContextID context; } fool_context[FOOL_CONTEXT_MAX] = { {0} }; /* trace five context at the same time */ #define FOOL_DECODE(idx) (fool_decode && (fool_context[idx].fool_entrypoint == VAEntrypointVLD)) #define FOOL_ENCODE(idx) \ (fool_encode \ && (fool_context[idx].fool_entrypoint == VAEntrypointEncSlice) \ && (fool_context[idx].fool_profile >= VAProfileH264Baseline) \ && (fool_context[idx].fool_profile <= VAProfileH264High)) #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); VAStatus vaBufferInfo( VADisplay dpy, VAContextID context, /* in */ VABufferID buf_id, /* in */ VABufferType *type, /* out */ unsigned int *size, /* out */ unsigned int *num_elements /* out */ ); VAStatus vaLockSurface(VADisplay dpy, VASurfaceID surface, unsigned int *fourcc, /* following are output argument */ unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, unsigned int *buffer_name, void **buffer ); VAStatus vaUnlockSurface(VADisplay dpy, VASurfaceID surface ); 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; 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_decode = 1; va_infoMessage("LIBVA_FOOL_DECODE is on, dummy decode\n"); } if (va_parseConfig("LIBVA_FOOL_ENCODE", &env_value[0]) == 0) { FILE *tmp = fopen(env_value, "r"); if (tmp) fool_context[fool_index].fool_fp_codedclip = tmp; fool_encode = 1; va_infoMessage("LIBVA_FOOL_ENCODE is on, dummy encode\n"); } if (fool_encode || fool_decode) 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]); memset(&fool_context[idx], sizeof(struct _fool_context), 0); return 0; } int va_FoolCodedBuf(VADisplay dpy) { /* do nothing */ return 0; } int va_FoolCreateConfig( VADisplay dpy, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id /* out */ ) { DPY2INDEX(dpy); /* call into driver level to allocate real context/surface/buffers, etc */ fool_context[idx].fool_profile = profile; fool_context[idx].fool_entrypoint = entrypoint; return 0; } static int yuvgen_planar( int width, int height, unsigned char *Y_start, int Y_pitch, unsigned char *U_start, int U_pitch, unsigned char *V_start, int V_pitch, int UV_interleave, int box_width, int row_shift, int field ) { int row; /* copy Y plane */ for (row=0;row