frontends/va: Skip processing buffers already converted with EFC

Since the EFC conversion reallocates the dst buffer with new format,
any subsequent VA postproc calls on the same surface will fall back
to vl_compositor conversion.

This is the case in ffmpeg where the postproc filter output
buffers are reused instead of allocated for each frame.

Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24170>
This commit is contained in:
David Rosca 2023-07-15 14:46:53 +02:00 committed by Marge Bot
parent 0e9affd267
commit b5fa9f992d

View File

@ -368,6 +368,27 @@ vlVaApplyDeint(vlVaDriver *drv, vlVaContext *context,
return context->deint->video_buffer;
}
static bool can_convert_with_efc(vlVaSurface *src, vlVaSurface *dst)
{
enum pipe_format src_format, dst_format;
if (src->buffer->interlaced)
return false;
src_format = src->buffer->buffer_format;
if (src_format != PIPE_FORMAT_B8G8R8A8_UNORM &&
src_format != PIPE_FORMAT_R8G8B8A8_UNORM &&
src_format != PIPE_FORMAT_B8G8R8X8_UNORM &&
src_format != PIPE_FORMAT_R8G8B8X8_UNORM)
return false;
dst_format = dst->encoder_format != PIPE_FORMAT_NONE ?
dst->encoder_format : dst->buffer->buffer_format;
return dst_format == PIPE_FORMAT_NV12;
}
VAStatus
vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
{
@ -400,28 +421,25 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
pscreen = drv->vscreen->pscreen;
if (src_surface->buffer->buffer_format != dst_surface->buffer->buffer_format &&
!src_surface->buffer->interlaced &&
(dst_surface->buffer->buffer_format == PIPE_FORMAT_NV12 ||
dst_surface->buffer->buffer_format == PIPE_FORMAT_P010 ||
dst_surface->buffer->buffer_format == PIPE_FORMAT_P016) &&
if (can_convert_with_efc(src_surface, dst_surface) &&
pscreen->get_video_param(pscreen,
PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_ENCODE,
PIPE_VIDEO_CAP_EFC_SUPPORTED)) {
vlVaSurface *surf = dst_surface;
// EFC will convert the buffer to a format the encoder accepts
dst_surface->encoder_format = dst_surface->buffer->buffer_format;
if (src_surface->buffer->buffer_format != surf->buffer->buffer_format) {
surf->encoder_format = surf->buffer->buffer_format;
vlVaSurface *surf;
surf->templat.interlaced = src_surface->templat.interlaced;
surf->templat.buffer_format = src_surface->templat.buffer_format;
surf->buffer->destroy(surf->buffer);
surf = handle_table_get(drv->htab, context->target_id);
surf->templat.interlaced = src_surface->templat.interlaced;
surf->templat.buffer_format = src_surface->templat.buffer_format;
surf->buffer->destroy(surf->buffer);
if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
pipe_resource_reference(&(((struct vl_video_buffer *)(surf->buffer))->resources[0]), ((struct vl_video_buffer *)(src_surface->buffer))->resources[0]);
context->target = surf->buffer;