From d2e4f9b2a5e144081223c905304a1b97fa51eb91 Mon Sep 17 00:00:00 2001 From: Waldo Bastian Date: Wed, 7 Nov 2007 10:47:56 -0800 Subject: [PATCH] Update to VA API 0.26 - Combine vaCreateBuffer and vaBufferData --- configure.ac | 2 +- dummy_drv_video/dummy_drv_video.c | 72 +++++++++++++++++++-------------------- src/Makefile.am | 2 +- src/va.c | 28 +++++---------- src/va.h | 45 +++++++++++------------- src/va_backend.h | 14 +++----- test/test_10.c | 55 +++++++++++++++++++++++++++++- test/test_11.c | 67 +++++++++++++++++++++++++++++++----- 8 files changed, 183 insertions(+), 102 deletions(-) diff --git a/configure.ac b/configure.ac index 100ebf9..eac1988 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libva], 0.25, [waldo.bastian@intel.com], libva) +AC_INIT([libva], 0.26, [waldo.bastian@intel.com], libva) AC_CONFIG_SRCDIR([Makefile.am]) AM_INIT_AUTOMAKE([dist-bzip2]) diff --git a/dummy_drv_video/dummy_drv_video.c b/dummy_drv_video/dummy_drv_video.c index bc86a7b..7cf1a50 100644 --- a/dummy_drv_video/dummy_drv_video.c +++ b/dummy_drv_video/dummy_drv_video.c @@ -734,11 +734,28 @@ VAStatus dummy_DestroyContext( } + +static VAStatus dummy__allocate_buffer(object_buffer_p obj_buffer, int size) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + + obj_buffer->buffer_data = realloc(obj_buffer->buffer_data, size); + if (NULL == obj_buffer->buffer_data) + { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + } + return vaStatus; +} + VAStatus dummy_CreateBuffer( VADriverContextP ctx, - VABufferType type, /* in */ - VABufferID *buf_desc /* out */ - ) + VAContextID context, /* in */ + VABufferType type, /* in */ + unsigned int size, /* in */ + unsigned int num_elements, /* in */ + void *data, /* in */ + VABufferID *buf_id /* out */ +) { INIT_DRIVER_DATA VAStatus vaStatus = VA_STATUS_SUCCESS; @@ -775,36 +792,6 @@ VAStatus dummy_CreateBuffer( obj_buffer->buffer_data = NULL; - *buf_desc = bufferID; - - return vaStatus; -} - -static VAStatus dummy__allocate_buffer(object_buffer_p obj_buffer, int size) -{ - VAStatus vaStatus = VA_STATUS_SUCCESS; - - obj_buffer->buffer_data = realloc(obj_buffer->buffer_data, size); - if (NULL == obj_buffer->buffer_data) - { - vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; - } - return vaStatus; -} - -VAStatus dummy_BufferData( - VADriverContextP ctx, - VABufferID buf_id, /* in */ - unsigned int size, /* in */ - unsigned int num_elements, /* in */ - void *data /* in */ - ) -{ - INIT_DRIVER_DATA - VAStatus vaStatus = VA_STATUS_SUCCESS; - object_buffer_p obj_buffer = BUFFER(buf_id); - ASSERT(obj_buffer); - vaStatus = dummy__allocate_buffer(obj_buffer, size * num_elements); if (VA_STATUS_SUCCESS == vaStatus) { @@ -816,9 +803,15 @@ VAStatus dummy_BufferData( } } + if (VA_STATUS_SUCCESS == vaStatus) + { + *buf_id = bufferID; + } + return vaStatus; } + VAStatus dummy_BufferSetNumElements( VADriverContextP ctx, VABufferID buf_id, /* in */ @@ -951,6 +944,14 @@ VAStatus dummy_RenderPicture( break; } } + + /* Release buffers */ + for(i = 0; i < num_buffers; i++) + { + object_buffer_p obj_buffer = BUFFER(buffers[i]); + ASSERT(obj_buffer); + dummy__destroy_buffer(driver_data, obj_buffer); + } return vaStatus; } @@ -1140,7 +1141,7 @@ VAStatus dummy_Terminate( VADriverContextP ctx ) return VA_STATUS_SUCCESS; } -VAStatus __vaDriverInit_0_25( VADriverContextP ctx ) +VAStatus __vaDriverInit_0_26( VADriverContextP ctx ) { object_base_p obj; int result; @@ -1148,7 +1149,7 @@ VAStatus __vaDriverInit_0_25( VADriverContextP ctx ) int i; ctx->version_major = 0; - ctx->version_minor = 25; + ctx->version_minor = 26; ctx->max_profiles = DUMMY_MAX_PROFILES; ctx->max_entrypoints = DUMMY_MAX_ENTRYPOINTS; ctx->max_attributes = DUMMY_MAX_CONFIG_ATTRIBUTES; @@ -1170,7 +1171,6 @@ VAStatus __vaDriverInit_0_25( VADriverContextP ctx ) ctx->vtable.vaCreateContext = dummy_CreateContext; ctx->vtable.vaDestroyContext = dummy_DestroyContext; ctx->vtable.vaCreateBuffer = dummy_CreateBuffer; - ctx->vtable.vaBufferData = dummy_BufferData; ctx->vtable.vaBufferSetNumElements = dummy_BufferSetNumElements; ctx->vtable.vaMapBuffer = dummy_MapBuffer; ctx->vtable.vaUnmapBuffer = dummy_UnmapBuffer; diff --git a/src/Makefile.am b/src/Makefile.am index 755799d..1eed0c6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,7 +22,7 @@ libva_la_LTLIBRARIES = libva.la libva_ladir = $(libdir) -libva_la_LDFLAGS = -version-number 0:25:0 -no-undefined +libva_la_LDFLAGS = -version-number 0:26:0 -no-undefined libva_la_LIBADD = -ldl -lX11 -lXext libva_la_SOURCES = va_dri.c va.c va_dristr.h diff --git a/src/va.c b/src/va.c index 2e4fd5e..8b9b73b 100644 --- a/src/va.c +++ b/src/va.c @@ -36,7 +36,7 @@ #define DEFAULT_DRIVER_DIR "/usr/X11R6/lib/modules/dri" #define DRIVER_EXTENSION "_drv_video.so" -#define DRIVER_INIT_FUNC "__vaDriverInit_0_25" +#define DRIVER_INIT_FUNC "__vaDriverInit_0_26" #define CTX(dpy) ((VADriverContextP) dpy ); #define CHECK_CONTEXT(dpy) if( !vaContextIsValid(dpy) ) { return VA_STATUS_ERROR_INVALID_DISPLAY; } @@ -279,7 +279,6 @@ static VAStatus va_openDriver(VADriverContextP ctx, char *driver_name) CHECK_VTABLE(vaStatus, ctx, CreateContext); CHECK_VTABLE(vaStatus, ctx, DestroyContext); CHECK_VTABLE(vaStatus, ctx, CreateBuffer); - CHECK_VTABLE(vaStatus, ctx, BufferData); CHECK_VTABLE(vaStatus, ctx, BufferSetNumElements); CHECK_VTABLE(vaStatus, ctx, MapBuffer); CHECK_VTABLE(vaStatus, ctx, UnmapBuffer); @@ -656,30 +655,19 @@ VAStatus vaDestroyContext ( VAStatus vaCreateBuffer ( VADisplay dpy, - VABufferType type, /* in */ - VABufferID *buf_id /* out */ + VAContextID context, /* in */ + VABufferType type, /* in */ + unsigned int size, /* in */ + unsigned int num_elements, /* in */ + void *data, /* in */ + VABufferID *buf_id /* out */ ) { VADriverContextP ctx = CTX(dpy); CHECK_CONTEXT(ctx); TRACE(vaCreateBuffer); - return ctx->vtable.vaCreateBuffer( ctx, type, buf_id); -} - -VAStatus vaBufferData ( - VADisplay dpy, - VABufferID buf_id, /* in */ - unsigned int size, /* in */ - unsigned int num_elements, /* in */ - void *data /* in */ -) -{ - VADriverContextP ctx = CTX(dpy); - CHECK_CONTEXT(ctx); - - TRACE(vaBufferData); - return ctx->vtable.vaBufferData( ctx, buf_id, size, num_elements, data); + return ctx->vtable.vaCreateBuffer( ctx, context, type, size, num_elements, data, buf_id); } VAStatus vaBufferSetNumElements ( diff --git a/src/va.h b/src/va.h index 449ebdd..49c26bd 100755 --- a/src/va.h +++ b/src/va.h @@ -45,6 +45,7 @@ * rev 0.23 (09/11/2007 Jonathan Bian) - Fixed some issues with images and subpictures. * rev 0.24 (09/18/2007 Jonathan Bian) - Added display attributes. * rev 0.25 (10/18/2007 Jonathan Bian) - Changed to use IDs only for some types. + * rev 0.26 (11/07/2007 Waldo Bastian) - Change vaCreateBuffer semantics * * Acknowledgements: * Some concepts borrowed from XvMC and XvImage. @@ -939,33 +940,27 @@ typedef struct _VASliceParameterBufferH264 /* Buffer functions */ /* - * Creates a buffer for storing a certain type of data, no data store allocated - * Note: image buffers are created by the library, not the client. Please see - * vaCreateImage on how image buffers are managed. - */ -VAStatus vaCreateBuffer ( - VADisplay dpy, - VABufferType type, /* in */ - VABufferID *buf_id /* out */ -); - -/* - * Create data store for the buffer and initalize with "data". + * Creates a buffer for "num_elements" elements of "size" bytes and + * initalize with "data". * if "data" is null, then the contents of the buffer data store * are undefined. * Basically there are two ways to get buffer data to the server side. One is - * to call vaBufferData() with a non-null "data", which results the data being + * to call vaCreateBuffer() with a non-null "data", which results the data being * copied to the data store on the server side. A different method that - * eliminates this copy is to pass null as "data" when calling vaBufferData(), + * eliminates this copy is to pass null as "data" when calling vaCreateBuffer(), * and then use vaMapBuffer() to map the data store from the server side to the * client address space for access. + * Note: image buffers are created by the library, not the client. Please see + * vaCreateImage on how image buffers are managed. */ -VAStatus vaBufferData ( +VAStatus vaCreateBuffer ( VADisplay dpy, - VABufferID buf_id, /* in */ + VAContextID context, + VABufferType type, /* in */ unsigned int size, /* in */ unsigned int num_elements, /* in */ - void *data /* in */ + void *data, /* in */ + VABufferID *buf_id /* out */ ); /* @@ -982,7 +977,7 @@ VAStatus vaBufferSetNumElements ( /* * Map data store of the buffer into the client's address space - * vaBufferData() needs to be called with "data" set to NULL before + * vaCreateBuffer() needs to be called with "data" set to NULL before * calling vaMapBuffer() */ VAStatus vaMapBuffer ( @@ -1003,6 +998,7 @@ VAStatus vaUnmapBuffer ( /* * After this call, the buffer is deleted and this buffer_id is no longer valid + * Only call this if the buffer is not going to be passed to vaRenderBuffer */ VAStatus vaDestroyBuffer ( VADisplay dpy, @@ -1028,6 +1024,7 @@ VAStatus vaBeginPicture ( /* * Send decode buffers to the server. + * Buffers are automatically destroyed afterwards */ VAStatus vaRenderPicture ( VADisplay dpy, @@ -1552,8 +1549,7 @@ Mostly to demonstrate program flow with no error handling ... /* Create a picture parameter buffer for this frame */ VABufferID picture_buf; VAPictureParameterBufferMPEG2 *picture_param; - vaCreateBuffer(dpy, VAPictureParameterBufferType, &picture_buf); - vaBufferData(dpy, picture_buf, sizeof(VAPictureParameterBufferMPEG2), NULL); + vaCreateBuffer(dpy, context, VAPictureParameterBufferType, sizeof(VAPictureParameterBufferMPEG2), 1, NULL, &picture_buf); vaMapBuffer(dpy, picture_buf, &picture_param); picture_param->horizontal_size = 720; picture_param->vertical_size = 480; @@ -1564,8 +1560,7 @@ Mostly to demonstrate program flow with no error handling ... /* Create an IQ matrix buffer for this frame */ VABufferID iq_buf; VAIQMatrixBufferMPEG2 *iq_matrix; - vaCreateBuffer(dpy, VAIQMatrixBufferType, &iq_buf); - vaBufferData(dpy, iq_buf, sizeof(VAIQMatrixBufferMPEG2), NULL); + vaCreateBuffer(dpy, context, VAIQMatrixBufferType, sizeof(VAIQMatrixBufferMPEG2), 1, NULL, &iq_buf); vaMapBuffer(dpy, iq_buf, &iq_matrix); /* fill values for IQ_matrix here */ vaUnmapBuffer(dpy, iq_buf); @@ -1586,8 +1581,7 @@ Mostly to demonstrate program flow with no error handling ... /* Create a slice parameter buffer */ VABufferID slice_param_buf; VASliceParameterBufferMPEG2 *slice_param; - vaCreateBuffer(dpy, VASliceParameterBufferType, &slice_param_buf); - vaBufferData(dpy, slice_param_buf, sizeof(VASliceParameterBufferMPEG2), NULL); + vaCreateBuffer(dpy, context, VASliceParameterBufferType, sizeof(VASliceParameterBufferMPEG2), 1, NULL, &slice_param_buf); vaMapBuffer(dpy, slice_param_buf, &slice_param); slice_param->slice_data_offset = 0; /* Let's say all slices in this bit-stream has 64-bit header */ @@ -1602,8 +1596,7 @@ Mostly to demonstrate program flow with no error handling ... /* Create a slice data buffer */ unsigned char *slice_data; VABufferID slice_data_buf; - vaCreateBuffer(dpy, VASliceDataBufferType, slice_data_buf); - vaBufferData(dpy, slice_data_buf, x /* decoder figure out how big */, NULL); + vaCreateBuffer(dpy, context, VASliceDataBufferType, x /* decoder figure out how big */, 1, NULL, &slice_data_buf); vaMapBuffer(dpy, slice_data_buf, &slice_data); /* decoder fill in slice_data */ vaUnmapBuffer(dpy, slice_data_buf); diff --git a/src/va_backend.h b/src/va_backend.h index 890b07e..9304088 100755 --- a/src/va_backend.h +++ b/src/va_backend.h @@ -118,16 +118,12 @@ struct VADriverVTable VAStatus (*vaCreateBuffer) ( VADriverContextP ctx, - VABufferType type, /* in */ - VABufferID *buf_desc /* out */ - ); - - VAStatus (*vaBufferData) ( - VADriverContextP ctx, - VABufferID buf_id, /* in */ - unsigned int size, /* in */ + VAContextID context, /* in */ + VABufferType type, /* in */ + unsigned int size, /* in */ unsigned int num_elements, /* in */ - void *data /* in */ + void *data, /* in */ + VABufferID *buf_id /* out */ ); VAStatus (*vaBufferSetNumElements) ( diff --git a/test/test_10.c b/test/test_10.c index 3158184..c84211c 100644 --- a/test/test_10.c +++ b/test/test_10.c @@ -26,9 +26,34 @@ #include "test_common.c" +VAConfigID config; +VAContextID context; +VASurfaceID *surfaces; +int total_surfaces; + void pre() { test_init(); + + va_status = vaCreateConfig(va_dpy, VAProfileMPEG2Main, VAEntrypointVLD, NULL, 0, &config); + ASSERT( VA_STATUS_SUCCESS == va_status ); + status("vaCreateConfig returns %08x\n", config); + + int width = 352; + int height = 288; + int surface_count = 4; + total_surfaces = surface_count; + + surfaces = malloc(total_surfaces * sizeof(VASurfaceID)); + + // TODO: Don't assume VA_RT_FORMAT_YUV420 is supported / needed for each config + va_status = vaCreateSurfaces(va_dpy, width, height, VA_RT_FORMAT_YUV420, total_surfaces, surfaces); + ASSERT( VA_STATUS_SUCCESS == va_status ); + + status("vaCreateContext with config %08x\n", config); + int flags = 0; + va_status = vaCreateContext( va_dpy, config, width, height, flags, surfaces, surface_count, &context ); + ASSERT( VA_STATUS_SUCCESS == va_status ); } void test_unique_buffers(VABufferID *buffer_list, int buffer_count) @@ -58,6 +83,21 @@ VABufferType buffer_types[] = VAImageBufferType }; +unsigned int buffer_sizes[] = +{ + sizeof(VAPictureParameterBufferMPEG4), + sizeof(VAIQMatrixBufferH264), + 32*1024, + 48*1024, + sizeof(VASliceParameterBufferMPEG2), + 128*1024, + sizeof(VAMacroblockParameterBufferMPEG2), + 32*1024, + 15*1024, + 32*1024, +}; + + #define NUM_BUFFER_TYPES (sizeof(buffer_types) / sizeof(VABufferType)) #define DEAD_BUFFER_ID ((VABufferID) 0x1234ffff) @@ -70,7 +110,7 @@ void test() for(i=0; i < NUM_BUFFER_TYPES; i++) { buffer_ids[i+1] = DEAD_BUFFER_ID; - va_status = vaCreateBuffer(va_dpy, buffer_types[i], &buffer_ids[i]); + va_status = vaCreateBuffer(va_dpy, context, buffer_types[i], buffer_sizes[i], 1, NULL, &buffer_ids[i]); ASSERT( VA_STATUS_SUCCESS == va_status ); ASSERT( DEAD_BUFFER_ID == buffer_ids[i+1] ); /* Bounds check */ } @@ -85,5 +125,18 @@ void test() void post() { + status("vaDestroyContext for context %08x\n", context); + va_status = vaDestroyContext( va_dpy, context ); + ASSERT( VA_STATUS_SUCCESS == va_status ); + + status("vaDestroyConfig for config %08x\n", config); + va_status = vaDestroyConfig( va_dpy, config ); + ASSERT( VA_STATUS_SUCCESS == va_status ); + + va_status = vaDestroySurfaces(va_dpy, surfaces, total_surfaces); + ASSERT( VA_STATUS_SUCCESS == va_status ); + + free(surfaces); + test_terminate(); } diff --git a/test/test_11.c b/test/test_11.c index 53a1bd5..7535613 100644 --- a/test/test_11.c +++ b/test/test_11.c @@ -26,9 +26,47 @@ #include "test_common.c" +VAConfigID config; +VAContextID context; +VASurfaceID *surfaces; +int total_surfaces; + void pre() { test_init(); + + va_status = vaCreateConfig(va_dpy, VAProfileMPEG2Main, VAEntrypointVLD, NULL, 0, &config); + ASSERT( VA_STATUS_SUCCESS == va_status ); + status("vaCreateConfig returns %08x\n", config); + + int width = 352; + int height = 288; + int surface_count = 4; + total_surfaces = surface_count; + + surfaces = malloc(total_surfaces * sizeof(VASurfaceID)); + + // TODO: Don't assume VA_RT_FORMAT_YUV420 is supported / needed for each config + va_status = vaCreateSurfaces(va_dpy, width, height, VA_RT_FORMAT_YUV420, total_surfaces, surfaces); + ASSERT( VA_STATUS_SUCCESS == va_status ); + + status("vaCreateContext with config %08x\n", config); + int flags = 0; + va_status = vaCreateContext( va_dpy, config, width, height, flags, surfaces, surface_count, &context ); + ASSERT( VA_STATUS_SUCCESS == va_status ); +} + +void test_unique_buffers(VABufferID *buffer_list, int buffer_count) +{ + int i,j; + + for(i = 0; i < buffer_count; i++) + { + for(j = 0; j < i; j++) + { + ASSERT(buffer_list[i] != buffer_list[j]); + } + } } VABufferType buffer_types[] = @@ -59,8 +97,11 @@ unsigned int buffer_sizes[] = 32*1024, }; + #define NUM_BUFFER_TYPES (sizeof(buffer_types) / sizeof(VABufferType)) +#define DEAD_BUFFER_ID ((VABufferID) 0x1234ffff) + void test() { VABufferID buffer_ids[NUM_BUFFER_TYPES+1]; @@ -70,9 +111,6 @@ void test() for(i=0; i < NUM_BUFFER_TYPES; i++) { uint32_t *data; - va_status = vaCreateBuffer(va_dpy, buffer_types[i], &buffer_ids[i]); - ASSERT( VA_STATUS_SUCCESS == va_status ); - status("vaCreateBuffer created buffer %08x of type %d\n", buffer_ids[i], buffer_types[i]); input_data[i] = malloc(buffer_sizes[i]+4); ASSERT(input_data[i]); @@ -88,9 +126,10 @@ void test() ASSERT(data); memcpy(data, input_data[i], buffer_sizes[i]); - /* Send to VA Buffer */ - va_status = vaBufferData(va_dpy, buffer_ids[i], buffer_sizes[i], 1, data); + /* Create buffer and fill with data */ + va_status = vaCreateBuffer(va_dpy, context, buffer_types[i], buffer_sizes[i], 1, data, &buffer_ids[i]); ASSERT( VA_STATUS_SUCCESS == va_status ); + status("vaCreateBuffer created buffer %08x of type %d\n", buffer_ids[i], buffer_types[i]); /* Wipe secondary buffer */ memset(data, 0, buffer_sizes[i]); @@ -101,9 +140,6 @@ void test() { void *data = NULL; /* Fetch VA Buffer */ - va_status = vaBufferData(va_dpy, buffer_ids[i], buffer_sizes[i], 1, NULL); - ASSERT( VA_STATUS_SUCCESS == va_status ); - va_status = vaMapBuffer(va_dpy, buffer_ids[i], &data); ASSERT( VA_STATUS_SUCCESS == va_status ); status("vaMapBuffer mapped buffer %08x\n", buffer_ids[i]); @@ -124,7 +160,22 @@ void test() } } + + void post() { + status("vaDestroyContext for context %08x\n", context); + va_status = vaDestroyContext( va_dpy, context ); + ASSERT( VA_STATUS_SUCCESS == va_status ); + + status("vaDestroyConfig for config %08x\n", config); + va_status = vaDestroyConfig( va_dpy, config ); + ASSERT( VA_STATUS_SUCCESS == va_status ); + + va_status = vaDestroySurfaces(va_dpy, surfaces, total_surfaces); + ASSERT( VA_STATUS_SUCCESS == va_status ); + + free(surfaces); + test_terminate(); } -- 2.7.4