From: Julien Isorce <julien.iso...@gmail.com> In general max_references cannot be based on num_render_targets.
This patch allow to allocate accurate sizes for buffers. For other codecs it is a fixed value to 2. This is similar behaviour as vaapi/vdpau-driver. XXX: do the same for HEVC Signed-off-by: Julien Isorce <j.iso...@samsung.com> --- src/gallium/state_trackers/va/context.c | 41 ++++++++++++++-------------- src/gallium/state_trackers/va/picture.c | 37 ++++++++++++++++++------- src/gallium/state_trackers/va/picture_h264.c | 29 +++++++++++++++++++- src/gallium/state_trackers/va/va_private.h | 4 +-- 4 files changed, 78 insertions(+), 33 deletions(-) diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c index f0051e5..985007b 100644 --- a/src/gallium/state_trackers/va/context.c +++ b/src/gallium/state_trackers/va/context.c @@ -187,7 +187,6 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, int picture_height, int flag, VASurfaceID *render_targets, int num_render_targets, VAContextID *context_id) { - struct pipe_video_codec templat = {}; vlVaDriver *drv; vlVaContext *context; int is_vpp; @@ -213,27 +212,28 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, return VA_STATUS_ERROR_INVALID_CONTEXT; } } else { - templat.profile = config_id; - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = picture_width; - templat.height = picture_height; - templat.max_references = num_render_targets; - templat.expect_chunked_decode = true; - - if (u_reduce_video_profile(templat.profile) == - PIPE_VIDEO_FORMAT_MPEG4_AVC) - templat.level = u_get_h264_level(templat.width, templat.height, - &templat.max_references); - - context->decoder = drv->pipe->create_video_codec(drv->pipe, &templat); - if (!context->decoder) { - FREE(context); - return VA_STATUS_ERROR_ALLOCATION_FAILED; + context->templat.profile = config_id; + context->templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + context->templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + context->templat.width = picture_width; + context->templat.height = picture_height; + context->templat.max_references = 2; + context->templat.expect_chunked_decode = true; + + /* Can only create decoders for which max_references is known. */ + if (u_reduce_video_profile(context->templat.profile) != + PIPE_VIDEO_FORMAT_MPEG4_AVC) { + context->decoder = drv->pipe->create_video_codec(drv->pipe, + &context->templat); + if (!context->decoder) { + FREE(context); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } } - if (u_reduce_video_profile(context->decoder->profile) == + if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { + context->templat.max_references = 0; context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps); if (!context->desc.h264.pps) { FREE(context); @@ -247,8 +247,9 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, } } - if (u_reduce_video_profile(context->decoder->profile) == + if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC) { + context->templat.max_references = num_render_targets; context->desc.h265.pps = CALLOC_STRUCT(pipe_h265_pps); if (!context->desc.h265.pps) { FREE(context); diff --git a/src/gallium/state_trackers/va/picture.c b/src/gallium/state_trackers/va/picture.c index 25d2940..e80873b 100644 --- a/src/gallium/state_trackers/va/picture.c +++ b/src/gallium/state_trackers/va/picture.c @@ -60,6 +60,12 @@ vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID rende context->target = surf->buffer; if (!context->decoder) { + /* Decoder creation is delayed until max_references is set. */ + if (u_reduce_video_profile(context->templat.profile) == + PIPE_VIDEO_FORMAT_MPEG4_AVC) + return context->templat.max_references == 0 ? + VA_STATUS_SUCCESS : VA_STATUS_ERROR_INVALID_CONTEXT; + /* VPP */ if ((context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM && context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM && @@ -67,6 +73,7 @@ vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID rende context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM) || context->target->interlaced) return VA_STATUS_ERROR_UNIMPLEMENTED; + return VA_STATUS_SUCCESS; } @@ -86,16 +93,18 @@ vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, *ref_frame = NULL; } -static void +static VAStatus handlePictureParameterBuffer(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) { - switch (u_reduce_video_profile(context->decoder->profile)) { + VAStatus vaStatus = VA_STATUS_SUCCESS; + + switch (u_reduce_video_profile(context->templat.profile)) { case PIPE_VIDEO_FORMAT_MPEG12: vlVaHandlePictureParameterBufferMPEG12(drv, context, buf); break; case PIPE_VIDEO_FORMAT_MPEG4_AVC: - vlVaHandlePictureParameterBufferH264(drv, context, buf); + vaStatus = vlVaHandlePictureParameterBufferH264(drv, context, buf); break; case PIPE_VIDEO_FORMAT_VC1: @@ -113,12 +122,14 @@ handlePictureParameterBuffer(vlVaDriver *drv, vlVaContext *context, vlVaBuffer * default: break; } + + return vaStatus; } static void handleIQMatrixBuffer(vlVaContext *context, vlVaBuffer *buf) { - switch (u_reduce_video_profile(context->decoder->profile)) { + switch (u_reduce_video_profile(context->templat.profile)) { case PIPE_VIDEO_FORMAT_MPEG12: vlVaHandleIQMatrixBufferMPEG12(context, buf); break; @@ -142,7 +153,7 @@ handleIQMatrixBuffer(vlVaContext *context, vlVaBuffer *buf) static void handleSliceParameterBuffer(vlVaContext *context, vlVaBuffer *buf) { - switch (u_reduce_video_profile(context->decoder->profile)) { + switch (u_reduce_video_profile(context->templat.profile)) { case PIPE_VIDEO_FORMAT_MPEG4_AVC: vlVaHandleSliceParameterBufferH264(context, buf); break; @@ -178,8 +189,8 @@ bufHasStartcode(vlVaBuffer *buf, unsigned int code, unsigned int bits) return 0; } -static void -handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) +static VAStatus +handleVASliceDataBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) { enum pipe_video_format format; unsigned num_buffers = 0; @@ -189,7 +200,7 @@ handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) static const uint8_t start_code_h265[] = { 0x00, 0x00, 0x01 }; static const uint8_t start_code_vc1[] = { 0x00, 0x00, 0x01, 0x0d }; - format = u_reduce_video_profile(context->decoder->profile); + format = u_reduce_video_profile(context->templat.profile); switch (format) { case PIPE_VIDEO_FORMAT_MPEG4_AVC: if (bufHasStartcode(buf, 0x000001, 24)) @@ -232,6 +243,8 @@ handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) ++num_buffers; context->decoder->decode_bitstream(context->decoder, context->target, &context->desc.base, num_buffers, (const void * const*)buffers, sizes); + + return VA_STATUS_SUCCESS; } VAStatus @@ -261,7 +274,7 @@ vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buff switch (buf->type) { case VAPictureParameterBufferType: - handlePictureParameterBuffer(drv, context, buf); + vaStatus = handlePictureParameterBuffer(drv, context, buf); break; case VAIQMatrixBufferType: @@ -273,7 +286,7 @@ vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buff break; case VASliceDataBufferType: - handleVASliceDataBufferType(context, buf); + vaStatus = handleVASliceDataBufferType(drv, context, buf); break; case VAProcPipelineParameterBufferType: vaStatus = vlVaHandleVAProcPipelineParameterBufferType(drv, context, buf); @@ -305,6 +318,10 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id) return VA_STATUS_ERROR_INVALID_CONTEXT; if (!context->decoder) { + if (u_reduce_video_profile(context->templat.profile) == + PIPE_VIDEO_FORMAT_MPEG4_AVC) + return VA_STATUS_ERROR_INVALID_CONTEXT; + /* VPP */ return VA_STATUS_SUCCESS; } diff --git a/src/gallium/state_trackers/va/picture_h264.c b/src/gallium/state_trackers/va/picture_h264.c index bd6c8a0..e9a8825 100644 --- a/src/gallium/state_trackers/va/picture_h264.c +++ b/src/gallium/state_trackers/va/picture_h264.c @@ -26,9 +26,10 @@ * **************************************************************************/ +#include "util/u_video.h" #include "va_private.h" -void vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +VAStatus vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) { VAPictureParameterBufferH264 *h264 = buf->data; @@ -90,6 +91,32 @@ void vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context, h264->pic_fields.bits.redundant_pic_cnt_present_flag; /*reference_pic_flag*/ context->desc.h264.frame_num = h264->frame_num; + + if (!context->decoder && context->desc.h264.num_ref_frames > 0) + context->templat.max_references = MIN2(context->desc.h264.num_ref_frames, 16); + + /* Create the decoder once max_references is known. */ + if (!context->decoder) { + if (!context->target) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (context->templat.max_references == 0) + return VA_STATUS_ERROR_INVALID_BUFFER; + + context->templat.level = u_get_h264_level(context->templat.width, + context->templat.height, &context->templat.max_references); + + context->decoder = drv->pipe->create_video_codec(drv->pipe, + &context->templat); + + if (!context->decoder) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + context->decoder->begin_frame(context->decoder, context->target, + &context->desc.base); + } + + return VA_STATUS_SUCCESS; } void vlVaHandleIQMatrixBufferH264(vlVaContext *context, vlVaBuffer *buf) diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h index ff1b9bd..cf9b29d 100644 --- a/src/gallium/state_trackers/va/va_private.h +++ b/src/gallium/state_trackers/va/va_private.h @@ -215,7 +215,7 @@ typedef struct { } vlVaSubpicture; typedef struct { - struct pipe_video_codec *decoder; + struct pipe_video_codec templat, *decoder; struct pipe_video_buffer *target; union { struct pipe_picture_desc base; @@ -353,7 +353,7 @@ VAStatus vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContex void vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, struct pipe_video_buffer **ref_frame); void vlVaHandlePictureParameterBufferMPEG12(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); void vlVaHandleIQMatrixBufferMPEG12(vlVaContext *context, vlVaBuffer *buf); -void vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); +VAStatus vlVaHandlePictureParameterBufferH264(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); void vlVaHandleIQMatrixBufferH264(vlVaContext *context, vlVaBuffer *buf); void vlVaHandleSliceParameterBufferH264(vlVaContext *context, vlVaBuffer *buf); void vlVaHandlePictureParameterBufferVC1(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -- 1.9.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev