#include "va.h"
#include "va_backend.h"
#include "va_trace.h"
+#include "va_fool.h"
#include <assert.h>
#include <stdarg.h>
#include <unistd.h>
#include <time.h>
-#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
*
* 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.
+ * LIBVA_FOOL_ENCODE=<clip name>:
+ * . if set, encode does nothing, but fill in the coded buffer from a H264 clip.
* . VA CONTEXT/CONFIG/SURFACE will call into drivers, but VA Buffer creation is done in here
- * . Bypass all ~SvaBeginPic/vaRenderPic/vaEndPic~T
+ * . Bypass all "vaBeginPic/vaRenderPic/vaEndPic"
* 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_decode = 0;
+int fool_encode = 0;
int fool_postp = 0;
+
+
+#define NAL_BUF_SIZE 65536 // maximum NAL unit size
+#define RING_BUF_SIZE 8192 // input ring buffer size, MUST be a power of two!
+#define MAX_FRAME 16
+#define SLICE_NUM 4
+
#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*/
-
+ char *frame_buf;
+
/* 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]
#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))
+ (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 */
-#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) */
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 */
+ 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
+ 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
+ VASurfaceID surface
);
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");
+ fool_context[fool_index].fool_fp_codedclip = fopen(env_value, "r");
- if (tmp)
- fool_context[fool_index].fool_fp_codedclip = tmp;
-
- fool_encode = 1;
+ if (fool_context[fool_index].fool_fp_codedclip) {
+ fool_encode = 1;
+ } else
+ fool_encode = 0;
- va_infoMessage("LIBVA_FOOL_ENCODE is on, dummy encode\n");
+ if (fool_encode) /* malloc the buffer for fake clip */
+ fool_context[fool_index].frame_buf = malloc(MAX_FRAME*SLICE_NUM*NAL_BUF_SIZE*sizeof(char));
+
+ if (fool_context[fool_index].frame_buf == NULL)
+ fool_encode = 0;
+
+ if (fool_encode)
+ va_infoMessage("LIBVA_FOOL_ENCODE is on, dummy encode\n");
}
if (fool_encode || fool_decode)
int va_FoolEnd(VADisplay dpy)
{
int i;
-
+
DPY2INDEX(dpy);
-
- for (i = 0; i < VABufferTypeMax; i++) /* free memory */
+
+ 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].fool_fp_codedclip)
+ fclose(fool_context[idx].fool_fp_codedclip);
+
+ if (fool_context[idx].frame_buf)
+ free(fool_context[idx].frame_buf);
memset(&fool_context[idx], sizeof(struct _fool_context), 0);
return 0;
int va_FoolCreateConfig(
- VADisplay dpy,
- VAProfile profile,
- VAEntrypoint entrypoint,
- VAConfigAttrib *attrib_list,
- int num_attribs,
- VAConfigID *config_id /* out */
+ 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;
}
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 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;
/* fill garbage data into the other field */
if (((field == VA_TOP_FIELD) && (row &1))
- || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) {
+ || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) {
memset(Y_row, 0xff, width);
continue;
}
-
+
for (jj=0; jj<width; jj++) {
xpos = ((row_shift + jj) / box_width) & 0x1;
-
+
if ((xpos == 0) && (ypos == 0))
Y_row[jj] = 0xeb;
if ((xpos == 1) && (ypos == 1))
Y_row[jj] = 0xeb;
-
+
if ((xpos == 1) && (ypos == 0))
Y_row[jj] = 0x10;
if ((xpos == 0) && (ypos == 1))
Y_row[jj] = 0x10;
}
}
-
+
/* copy UV data */
for( row =0; row < height/2; row++) {
unsigned short value = 0x80;
/* fill garbage data into the other field */
if (((field == VA_TOP_FIELD) && (row &1))
- || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) {
+ || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) {
value = 0xff;
}
} else {
unsigned char *U_row = U_start + row * U_pitch;
unsigned char *V_row = V_start + row * V_pitch;
-
+
memset (U_row,value,width/2);
memset (V_row,value,width/2);
}
int va_FoolCreateSurfaces(
- VADisplay dpy,
- int width,
- int height,
- int format,
- int num_surfaces,
- VASurfaceID *surfaces /* out */
+ VADisplay dpy,
+ int width,
+ int height,
+ int format,
+ int num_surfaces,
+ VASurfaceID *surfaces /* out */
)
{
int i;
int box_width = num_surfaces/2;
int row_shift = 0;
VAStatus va_status;
-
+
DPY2INDEX(dpy);
if (FOOL_DECODE(idx)) {
- /* call into driver level to allocate real context/surface/buffers, etc
- * fill in the YUV data, will be overwrite if it is encode context
- */
- for (i = 0; i < num_surfaces; i++) {
- /* fool decoder: fill with auto-generated YUV data */
- va_status = vaLockSurface(dpy, surfaces[i], &fourcc,
- &luma_stride, &chroma_u_stride, &chroma_v_stride,
- &luma_offset, &chroma_u_offset, &chroma_v_offset,
- &buffer_name, &buffer);
-
- if (va_status != VA_STATUS_SUCCESS)
- return 0;
-
- if (!buffer) {
- vaUnlockSurface(dpy, surfaces[i]);
- return 0;
- }
-
- Y_data = buffer;
-
- /* UV should be same for NV12 */
- U_data = buffer + chroma_u_offset;
- V_data = buffer + chroma_v_offset;
-
- yuvgen_planar(width, height,
- Y_data, luma_stride,
- U_data, chroma_v_stride,
- V_data, chroma_v_stride,
- (fourcc==VA_FOURCC_NV12),
- box_width, row_shift, 0);
-
- vaUnlockSurface(dpy, surfaces[i]);
-
- row_shift++;
- if (row_shift==(2*box_width))
- row_shift= 0;
- }
- return 0; /* the return value is ignored */
+ /* call into driver level to allocate real context/surface/buffers, etc
+ * fill in the YUV data, will be overwrite if it is encode context
+ */
+ for (i = 0; i < num_surfaces; i++) {
+ /* fool decoder: fill with auto-generated YUV data */
+ va_status = vaLockSurface(dpy, surfaces[i], &fourcc,
+ &luma_stride, &chroma_u_stride, &chroma_v_stride,
+ &luma_offset, &chroma_u_offset, &chroma_v_offset,
+ &buffer_name, &buffer);
+
+ if (va_status != VA_STATUS_SUCCESS)
+ return 0;
+
+ if (!buffer) {
+ vaUnlockSurface(dpy, surfaces[i]);
+ return 0;
+ }
+
+ Y_data = buffer;
+
+ /* UV should be same for NV12 */
+ U_data = buffer + chroma_u_offset;
+ V_data = buffer + chroma_v_offset;
+
+ yuvgen_planar(width, height,
+ Y_data, luma_stride,
+ U_data, chroma_v_stride,
+ V_data, chroma_v_stride,
+ (fourcc==VA_FOURCC_NV12),
+ box_width, row_shift, 0);
+
+ vaUnlockSurface(dpy, surfaces[i]);
+
+ row_shift++;
+ if (row_shift==(2*box_width))
+ row_shift= 0;
+ }
+ return 0; /* the return value is ignored */
}
return 0; /* the return value is ignored */
}
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 */
+ VADisplay dpy,
+ VAContextID context, /* in */
+ VABufferType type, /* in */
+ unsigned int size, /* in */
+ unsigned int num_elements, /* in */
+ void *data, /* in */
+ VABufferID *buf_id /* out */
)
{
DPY2INDEX(dpy);
if (FOOL_ENCODE(idx) || FOOL_DECODE(idx)) { /* fool buffer creation */
int new_size = size * num_elements;
-
+
if (type == VAEncCodedBufferType) /* only a VACodedBufferSegment */
new_size = sizeof(VACodedBufferSegment);
-
- if (fool_context[idx].fool_buf_size[type] == 0)
- fool_context[idx].fool_buf[type] = calloc(1, new_size);
- else if (fool_context[idx].fool_buf_size[type] <= new_size)
+
+ if (fool_context[idx].fool_buf_size[type] == 0)
+ fool_context[idx].fool_buf[type] = calloc(1, new_size);
+ else if (fool_context[idx].fool_buf_size[type] <= new_size)
fool_context[idx].fool_buf[type] = realloc(fool_context[idx].fool_buf, new_size);
if (fool_context[idx].fool_buf[type] == NULL) {
*/
fool_context[idx].fool_buf_count[type]++;
*buf_id = (fool_context[idx].fool_buf_count[type] << 8) | type;
-
+
return 1; /* don't call into driver */
}
-
+
return 0; /* let driver go ... */
}
-
VAStatus va_FoolMapBuffer (
- VADisplay dpy,
- VABufferID buf_id, /* in */
- void **pbuf /* out */
+ VADisplay dpy,
+ VABufferID buf_id, /* in */
+ void **pbuf /* out */
)
{
VABufferType type;
if (FOOL_ENCODE(idx) || FOOL_DECODE(idx)) { /* fool buffer creation */
unsigned int buf_idx = buf_id & 0xff;
-
- /*Image buffer?*/
- vaBufferInfo(dpy, fool_context[idx].context, buf_id, &type, &size, &num_elements);
- if (type == VAImageBufferType && FOOL_ENCODE(idx))
- return 0;
+
+ /* Image buffer? */
+ vaBufferInfo(dpy, fool_context[idx].context, buf_id, &type, &size, &num_elements);
+ if (type == VAImageBufferType && FOOL_ENCODE(idx))
+ return 0;
/* buf_id is the buffer type */
if (fool_context[idx].fool_buf[buf_idx] != NULL)
/* expect APP to MapBuffer when get the the coded data */
if (*pbuf && (buf_idx == VAEncCodedBufferType)) { /* it is coded buffer */
- /* should read from a clip, here we use the hardcoded h264_720p_nal */
- memcpy(*pbuf, &h264_720p_nal[h264_720p_nal_idx], sizeof(VACodedBufferSegment));
- h264_720p_nal_idx++;
- if (h264_720p_nal_idx == H264_720P_NAL_NUMBER)
- h264_720p_nal_idx = 0; /* reset to 0 */
+ /* read from a clip */
+ va_FoolGetFrame(fool_context[idx].fool_fp_codedclip,
+ fool_context[idx].frame_buf);
+ *pbuf = fool_context[idx].frame_buf;
}
-
return 1; /* don't call into driver */
}
-
+
return 0; /* let driver go ... */
}
int va_FoolBeginPicture(
- VADisplay dpy,
- VAContextID context,
- VASurfaceID render_target
+ VADisplay dpy,
+ VAContextID context,
+ VASurfaceID render_target
)
{
DPY2INDEX(dpy);
-
- if (FOOL_ENCODE(idx) || FOOL_DECODE(idx))
- {
- if (fool_context[idx].context == 0)
- fool_context[idx].context = context;
+
+ if (FOOL_ENCODE(idx) || FOOL_DECODE(idx)) {
+ if (fool_context[idx].context == 0)
+ fool_context[idx].context = context;
return 1; /* don't call into driver level */
}
-
+
return 0; /* let driver go ... */
}
int va_FoolRenderPicture(
- VADisplay dpy,
- VAContextID context,
- VABufferID *buffers,
- int num_buffers
+ VADisplay dpy,
+ VAContextID context,
+ VABufferID *buffers,
+ int num_buffers
)
{
DPY2INDEX(dpy);
-
+
if (FOOL_ENCODE(idx) || FOOL_DECODE(idx))
return 1; /* don't call into driver level */
int va_FoolEndPicture(
- VADisplay dpy,
- VAContextID context
+ VADisplay dpy,
+ VAContextID context
)
{
DPY2INDEX(dpy);
}
int va_FoolSyncSurface(
- VADisplay dpy,
- VASurfaceID render_target)
+ VADisplay dpy,
+ VASurfaceID render_target
+)
{
DPY2INDEX(dpy);
+
/*Fill in black and white squares. */
if (FOOL_DECODE(idx) || FOOL_DECODE(idx))
- {
- return 1;
- }
+ return 1;
return 0;
}
-VAStatus va_FoolUnmapBuffer (
- VADisplay dpy,
- VABufferID buf_id /* in */
+VAStatus va_FoolUnmapBuffer(
+ VADisplay dpy,
+ VABufferID buf_id /* in */
)
{
DPY2INDEX(dpy);
- if (FOOL_ENCODE(idx) || FOOL_DECODE(idx)) { /* fool buffer creation */
- return 1;
- }
+ if (FOOL_ENCODE(idx) || FOOL_DECODE(idx))
+ return 1; /* fool buffer creation */
+
return 0;
}
-VAStatus va_FoolQuerySubpictureFormats (
- VADisplay dpy,
- VAImageFormat *format_list,
- unsigned int *flags,
- unsigned int *num_formats
+VAStatus va_FoolQuerySubpictureFormats(
+ VADisplay dpy,
+ VAImageFormat *format_list,
+ unsigned int *flags,
+ unsigned int *num_formats
)
{
DPY2INDEX(dpy);
if (FOOL_ENCODE(idx) || FOOL_DECODE(idx)) {
- if (num_formats)
- *num_formats = 0;
- return 1;
+ if (num_formats)
+ *num_formats = 0;
+ return 1;
}
return 0;
}