frontends/va: add encoder format conversion (EFC) support
authorThong Thai <thong.thai@amd.com>
Mon, 28 Feb 2022 20:23:17 +0000 (15:23 -0500)
committerMarge Bot <emma+marge@anholt.net>
Fri, 11 Mar 2022 14:10:08 +0000 (14:10 +0000)
Signed-off-by: Thong Thai <thong.thai@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15196>

src/gallium/frontends/va/picture.c
src/gallium/frontends/va/postproc.c
src/gallium/frontends/va/va_private.h

index ba8f9de..6c13217 100644 (file)
@@ -785,6 +785,10 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id)
          context->desc.h264enc.frame_num_cnt++;
       } else if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_HEVC)
          getEncParamPresetH265(context);
+
+      context->desc.base.input_format = surf->buffer->buffer_format;
+      context->desc.base.output_format = surf->encoder_format;
+
       context->decoder->begin_frame(context->decoder, context->target, &context->desc.base);
       context->decoder->encode_bitstream(context->decoder, context->target,
                                          coded_buf->derived_surface.resource, &feedback);
index 88d7d81..1201eb0 100644 (file)
@@ -32,6 +32,7 @@
 #include "vl/vl_defines.h"
 #include "vl/vl_video_buffer.h"
 #include "vl/vl_deint_filter.h"
+#include "vl/vl_winsys.h"
 
 #include "va_private.h"
 
@@ -124,9 +125,12 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
    bool scale = false;
    bool grab = false;
    unsigned i;
+   struct pipe_screen *pscreen = drv->vscreen->pscreen;
 
-   if ((src->buffer_format == PIPE_FORMAT_B8G8R8A8_UNORM ||
-        src->buffer_format == PIPE_FORMAT_B8G8R8X8_UNORM) &&
+   if ((src->buffer_format == PIPE_FORMAT_B8G8R8X8_UNORM ||
+        src->buffer_format == PIPE_FORMAT_B8G8R8A8_UNORM ||
+        src->buffer_format == PIPE_FORMAT_R8G8B8X8_UNORM ||
+        src->buffer_format == PIPE_FORMAT_R8G8B8A8_UNORM) &&
        !src->interlaced)
       grab = true;
 
@@ -165,7 +169,9 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
    dst_rect.x1 = dst_region->x + dst_region->width;
    dst_rect.y1 = dst_region->y + dst_region->height;
 
-   if (grab) {
+   if (grab && !pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN,
+                                         PIPE_VIDEO_ENTRYPOINT_ENCODE,
+                                         PIPE_VIDEO_CAP_EFC_SUPPORTED)) {
       vl_compositor_convert_rgb_to_yuv(&drv->cstate, &drv->compositor, 0,
                                        ((struct vl_video_buffer *)src)->resources[0],
                                        dst, &src_rect, &dst_rect);
@@ -220,7 +226,7 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context,
       blit.mask = PIPE_MASK_RGBA;
       blit.filter = PIPE_TEX_MIPFILTER_LINEAR;
 
-      if (drv->pipe->screen->get_param(drv->pipe->screen,
+      if (!grab && drv->pipe->screen->get_param(drv->pipe->screen,
                                        PIPE_CAP_PREFER_COMPUTE_FOR_MULTIMEDIA))
          util_compute_blit(drv->pipe, &blit, &context->blit_cs, !drv->compositor.deinterlace);
       else
@@ -288,6 +294,7 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
    struct pipe_video_buffer *src, *dst;
    vlVaSurface *src_surface, *dst_surface;
    unsigned i;
+   struct pipe_screen *pscreen;
 
    if (!drv || !context)
       return VA_STATUS_ERROR_INVALID_CONTEXT;
@@ -303,6 +310,27 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
    src_surface = handle_table_get(drv->htab, param->surface);
    dst_surface = handle_table_get(drv->htab, context->target_id);
 
+   pscreen = drv->vscreen->pscreen;
+
+   if (src_surface->buffer->buffer_format != dst_surface->buffer->buffer_format &&
+       pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN, PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_EFC_SUPPORTED)) {
+
+      // EFC will convert the buffer to a format the encoder accepts
+      dst_surface->encoder_format = dst_surface->buffer->buffer_format;
+
+      vlVaSurface *surf;
+
+      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;
+
+      context->target = surf->buffer;
+   }
+
    if (!src_surface || !src_surface->buffer)
       return VA_STATUS_ERROR_INVALID_SURFACE;
 
@@ -369,7 +397,11 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
 
    if (context->target->buffer_format != PIPE_FORMAT_NV12 &&
        context->target->buffer_format != PIPE_FORMAT_P010 &&
-       context->target->buffer_format != PIPE_FORMAT_P016)
+       context->target->buffer_format != PIPE_FORMAT_P016 &&
+       context->target->buffer_format != PIPE_FORMAT_B8G8R8X8_UNORM &&
+       context->target->buffer_format != PIPE_FORMAT_B8G8R8A8_UNORM &&
+       context->target->buffer_format != PIPE_FORMAT_R8G8B8X8_UNORM &&
+       context->target->buffer_format != PIPE_FORMAT_R8G8B8A8_UNORM)
       return vlVaPostProcCompositor(drv, context, src_region, dst_region,
                                     src, context->target, deinterlace);
    else
index d511686..149cfa2 100755 (executable)
@@ -337,6 +337,7 @@ typedef struct {
    unsigned int frame_num_cnt;
    bool force_flushed;
    struct pipe_video_buffer *obsolete_buf;
+   enum pipe_format encoder_format;
 } vlVaSurface;
 
 // Public functions: