Improve following functions to support VA_PROFILE_NONE profile (vpp): vlVaQueryConfigProfiles vlVaQueryConfigEntrypoints vlVaCreateConfig vlVaQueryConfigAttributes
Add VADriverVTableVPP and improve following functions to support vpp: vlVaCreateContext vlVaDestroyContext vlVaBeginPicture vlVaRenderPicture vlVaEndPicture Add handleVAProcPipelineParameterBufferType helper. One of the application is: VASurfaceNV12 -> gstvaapipostproc -> VASurfaceRGBA Signed-off-by: Julien Isorce <j.iso...@samsung.com> --- src/gallium/state_trackers/va/config.c | 20 +++++++ src/gallium/state_trackers/va/context.c | 94 +++++++++++++++++++----------- src/gallium/state_trackers/va/picture.c | 89 +++++++++++++++++++++++++++- src/gallium/state_trackers/va/surface.c | 73 +++++++++++++++++++++++ src/gallium/state_trackers/va/va_private.h | 13 ++++- 5 files changed, 254 insertions(+), 35 deletions(-) diff --git a/src/gallium/state_trackers/va/config.c b/src/gallium/state_trackers/va/config.c index cfb0b25..bde6615 100644 --- a/src/gallium/state_trackers/va/config.c +++ b/src/gallium/state_trackers/va/config.c @@ -52,6 +52,9 @@ vlVaQueryConfigProfiles(VADriverContextP ctx, VAProfile *profile_list, int *num_ profile_list[(*num_profiles)++] = vap; } + /* Support postprocessing through vl_compositor */ + profile_list[(*num_profiles)++] = VAProfileNone; + return VA_STATUS_SUCCESS; } @@ -67,6 +70,11 @@ vlVaQueryConfigEntrypoints(VADriverContextP ctx, VAProfile profile, *num_entrypoints = 0; + if (profile == VAProfileNone) { + entrypoint_list[(*num_entrypoints)++] = VAEntrypointVideoProc; + return VA_STATUS_SUCCESS; + } + p = ProfileToPipe(profile); if (p == PIPE_VIDEO_PROFILE_UNKNOWN) return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; @@ -118,6 +126,11 @@ vlVaCreateConfig(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoin if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; + if (profile == VAProfileNone && entrypoint == VAEntrypointVideoProc) { + *config_id = PIPE_VIDEO_PROFILE_UNKNOWN; + return VA_STATUS_SUCCESS; + } + p = ProfileToPipe(profile); if (p == PIPE_VIDEO_PROFILE_UNKNOWN) return VA_STATUS_ERROR_UNSUPPORTED_PROFILE; @@ -151,6 +164,13 @@ vlVaQueryConfigAttributes(VADriverContextP ctx, VAConfigID config_id, VAProfile return VA_STATUS_ERROR_INVALID_CONTEXT; *profile = PipeToProfile(config_id); + + if (config_id == PIPE_VIDEO_PROFILE_UNKNOWN) { + *entrypoint = VAEntrypointVideoProc; + *num_attribs = 0; + return VA_STATUS_SUCCESS; + } + *entrypoint = VAEntrypointVLD; *num_attribs = 1; diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c index 8949d42..ddc863b 100644 --- a/src/gallium/state_trackers/va/context.c +++ b/src/gallium/state_trackers/va/context.c @@ -87,6 +87,14 @@ static struct VADriverVTable vtable = &vlVaQuerySurfaceAttributes }; +static struct VADriverVTableVPP vtable_vpp = +{ + VA_DRIVER_VTABLE_VPP_VERSION, + &vlVaQueryVideoProcFilters, + &vlVaQueryVideoProcFilterCaps, + &vlVaQueryVideoProcPipelineCaps +}; + PUBLIC VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP ctx) { @@ -122,6 +130,7 @@ VA_DRIVER_INIT_FUNC(VADriverContextP ctx) ctx->version_major = 0; ctx->version_minor = 1; *ctx->vtable = vtable; + *ctx->vtable_vpp = vtable_vpp; ctx->max_profiles = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH - PIPE_VIDEO_PROFILE_UNKNOWN; ctx->max_entrypoints = 1; ctx->max_attributes = 1; @@ -151,11 +160,16 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, struct pipe_video_codec templat = {}; vlVaDriver *drv; vlVaContext *context; + int is_vpp = 0; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; - if (!(picture_width && picture_height)) + is_vpp = config_id == PIPE_VIDEO_PROFILE_UNKNOWN && + picture_width == 0 && picture_height == 0 && flag ==0 && !render_targets + && num_render_targets == 0; + + if (!(picture_width && picture_height) && !is_vpp) return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; drv = VL_VA_DRIVER(ctx); @@ -163,38 +177,48 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, if (!context) return VA_STATUS_ERROR_ALLOCATION_FAILED; - 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; - } - - if (u_reduce_video_profile(context->decoder->profile) == - PIPE_VIDEO_FORMAT_MPEG4_AVC) { - context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps); - if (!context->desc.h264.pps) { + if (is_vpp) { + context->decoder = NULL; + if (!drv->compositor.upload) { FREE(context); - return VA_STATUS_ERROR_ALLOCATION_FAILED; + return VA_STATUS_ERROR_INVALID_CONTEXT; } - context->desc.h264.pps->sps = CALLOC_STRUCT(pipe_h264_sps); - if (!context->desc.h264.pps->sps) { - FREE(context->desc.h264.pps); + } 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 = 2; + templat.expect_chunked_decode = true; + + if (u_reduce_video_profile(templat.profile) == + PIPE_VIDEO_FORMAT_MPEG4_AVC) { + templat.max_references = 16; + 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; } + + if (u_reduce_video_profile(context->decoder->profile) == + PIPE_VIDEO_FORMAT_MPEG4_AVC) { + context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps); + if (!context->desc.h264.pps) { + FREE(context); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + context->desc.h264.pps->sps = CALLOC_STRUCT(pipe_h264_sps); + if (!context->desc.h264.pps->sps) { + FREE(context->desc.h264.pps); + FREE(context); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + } } context->desc.base.profile = config_id; @@ -214,12 +238,16 @@ vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id) drv = VL_VA_DRIVER(ctx); context = handle_table_get(drv->htab, context_id); - if (u_reduce_video_profile(context->decoder->profile) == - PIPE_VIDEO_FORMAT_MPEG4_AVC) { - FREE(context->desc.h264.pps->sps); - FREE(context->desc.h264.pps); + + if (context->decoder) { + if (u_reduce_video_profile(context->decoder->profile) == + PIPE_VIDEO_FORMAT_MPEG4_AVC) { + FREE(context->desc.h264.pps->sps); + FREE(context->desc.h264.pps); + } + context->decoder->destroy(context->decoder); } - context->decoder->destroy(context->decoder); + FREE(context); handle_table_remove(drv->htab, context_id); diff --git a/src/gallium/state_trackers/va/picture.c b/src/gallium/state_trackers/va/picture.c index 9b94b39..0b42afe 100644 --- a/src/gallium/state_trackers/va/picture.c +++ b/src/gallium/state_trackers/va/picture.c @@ -32,6 +32,7 @@ #include "util/u_video.h" #include "vl/vl_vlc.h" +#include "vl/vl_winsys.h" #include "va_private.h" @@ -58,6 +59,16 @@ vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID rende return VA_STATUS_ERROR_INVALID_SURFACE; context->target = surf->buffer; + + if (!context->decoder) { + /* VPP */ + if ((context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM && + context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM) || + context->target->interlaced) + return VA_STATUS_ERROR_UNIMPLEMENTED; + return VA_STATUS_SUCCESS; + } + context->decoder->begin_frame(context->decoder, context->target, NULL); return VA_STATUS_SUCCESS; @@ -521,11 +532,79 @@ handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) num_buffers, (const void * const*)buffers, sizes); } +static VAStatus +handleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf) +{ + struct u_rect src_rect = {0}; + struct u_rect dst_rect = {0}; + struct u_rect *dirty_area = NULL; + vlVaSurface *src_surface = NULL; + VAProcPipelineParameterBuffer *pipeline_param = NULL; + struct pipe_surface **surfaces = NULL; + struct pipe_screen *screen = NULL; + struct pipe_surface *psurf = NULL; + + if (!drv || !context) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!buf || !buf->data) + return VA_STATUS_ERROR_INVALID_BUFFER; + + if (!context->target) + return VA_STATUS_ERROR_INVALID_SURFACE; + + pipeline_param = buf->data; // cast + + src_surface = handle_table_get(drv->htab, pipeline_param->surface); + if (!src_surface || !src_surface->buffer) + return VA_STATUS_ERROR_INVALID_SURFACE; + + screen = drv->pipe->screen; + + if(src_surface->fence) { + screen->fence_finish(screen, src_surface->fence, PIPE_TIMEOUT_INFINITE); + screen->fence_reference(screen, &src_surface->fence, NULL); + } + + surfaces = context->target->get_surfaces(context->target); + + if (!surfaces) + return VA_STATUS_ERROR_INVALID_SURFACE; + + psurf = surfaces[0]; + + if (!psurf) + return VA_STATUS_ERROR_INVALID_SURFACE; + + src_rect.x0 = pipeline_param->surface_region->x; + src_rect.y0 = pipeline_param->surface_region->y; + src_rect.x1 = pipeline_param->surface_region->x + pipeline_param->surface_region->width; + src_rect.y1 = pipeline_param->surface_region->y + pipeline_param->surface_region->height; + + dst_rect.x0 = pipeline_param->output_region->x; + dst_rect.y0 = pipeline_param->output_region->y; + dst_rect.x1 = pipeline_param->output_region->x + pipeline_param->output_region->width; + dst_rect.y1 = pipeline_param->output_region->y + pipeline_param->output_region->height; + + dirty_area = vl_screen_get_dirty_area(drv->vscreen); + + vl_compositor_clear_layers(&drv->cstate); + vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, src_surface->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE); + vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect); + vl_compositor_render(&drv->cstate, &drv->compositor, psurf, dirty_area, true); + + screen->fence_reference(screen, &src_surface->fence, NULL); + drv->pipe->flush(drv->pipe, &src_surface->fence, 0); + + return VA_STATUS_SUCCESS; +} + VAStatus vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buffers, int num_buffers) { vlVaDriver *drv; vlVaContext *context; + VAStatus vaStatus = VA_STATUS_SUCCESS; unsigned i; @@ -561,13 +640,16 @@ vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buff case VASliceDataBufferType: handleVASliceDataBufferType(context, buf); break; + case VAProcPipelineParameterBufferType: + vaStatus = handleVAProcPipelineParameterBufferType(drv, context, buf); + break; default: break; } } - return VA_STATUS_SUCCESS; + return vaStatus; } VAStatus @@ -587,6 +669,11 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id) if (!context) return VA_STATUS_ERROR_INVALID_CONTEXT; + if (!context->decoder) { + /* VPP */ + return VA_STATUS_SUCCESS; + } + context->mpeg4.frame_num++; context->decoder->end_frame(context->decoder, context->target, &context->desc.base); diff --git a/src/gallium/state_trackers/va/surface.c b/src/gallium/state_trackers/va/surface.c index eb5b8ca..bfa4803 100644 --- a/src/gallium/state_trackers/va/surface.c +++ b/src/gallium/state_trackers/va/surface.c @@ -625,3 +625,76 @@ no_res: return VA_STATUS_ERROR_ALLOCATION_FAILED; } + +VAStatus +vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, + VAProcFilterType *filters, unsigned int *num_filters) +{ + unsigned int num = 0; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!num_filters || !filters) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + filters[num++] = VAProcFilterNone; + + *num_filters = num; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context, + VAProcFilterType type, void *filter_caps, + unsigned int *num_filter_caps) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +static VAProcColorStandardType vpp_input_color_standards[VAProcColorStandardCount] = { + VAProcColorStandardBT601 +}; + +static VAProcColorStandardType vpp_output_color_standards[VAProcColorStandardCount] = { + VAProcColorStandardBT601 +}; + +VAStatus +vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, + VABufferID *filters, unsigned int num_filters, + VAProcPipelineCaps *pipeline_cap) +{ + unsigned int i = 0; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!pipeline_cap) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + if (num_filters && !filters) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + pipeline_cap->pipeline_flags = 0; + pipeline_cap->filter_flags = 0; + pipeline_cap->num_forward_references = 0; + pipeline_cap->num_backward_references = 0; + pipeline_cap->num_input_color_standards = 1; + pipeline_cap->input_color_standards = vpp_input_color_standards; + pipeline_cap->num_output_color_standards = 1; + pipeline_cap->output_color_standards = vpp_output_color_standards; + + for (i = 0; i < num_filters; i++) { + vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]); + + if (!buf || buf->type >= VABufferTypeMax) + return VA_STATUS_ERROR_INVALID_BUFFER; + } + + return VA_STATUS_SUCCESS; +} diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h index 2cdd787..d3a29bc 100644 --- a/src/gallium/state_trackers/va/va_private.h +++ b/src/gallium/state_trackers/va/va_private.h @@ -33,6 +33,7 @@ #include <va/va.h> #include <va/va_backend.h> +#include <va/va_backend_vpp.h> #include <va/va_drmcommon.h> #include "pipe/p_video_enums.h" @@ -148,7 +149,8 @@ PipeToProfile(enum pipe_video_profile profile) case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: return VAProfileH264High; case PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED: - return VAProfileNone; + case PIPE_VIDEO_PROFILE_UNKNOWN: + return VAProfileNone; default: assert(0); return -1; @@ -179,6 +181,8 @@ ProfileToPipe(VAProfile profile) return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; case VAProfileH264High: return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + case VAProfileNone: + return PIPE_VIDEO_PROFILE_UNKNOWN; default: return PIPE_VIDEO_PROFILE_UNKNOWN; } @@ -320,4 +324,11 @@ VAStatus vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, unsigned unsigned int num_attribs); VAStatus vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config, VASurfaceAttrib *attrib_list, unsigned int *num_attribs); + +VAStatus vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, VAProcFilterType *filters, + unsigned int *num_filters); +VAStatus vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context, VAProcFilterType type, + void *filter_caps, unsigned int *num_filter_caps); +VAStatus vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, VABufferID *filters, + unsigned int num_filters, VAProcPipelineCaps *pipeline_cap); #endif //VA_PRIVATE_H -- 1.9.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev