frontends/va: Derive image from interlaced buffers
authorThong Thai <thong.thai@amd.com>
Thu, 16 Jul 2020 20:57:54 +0000 (16:57 -0400)
committerMarge Bot <eric+marge@anholt.net>
Tue, 15 Sep 2020 14:58:26 +0000 (14:58 +0000)
Allow vaDriveImage to derive a vaImage from interlaced buffers
by creating a new progressive buffer.

v2: Keeps the surface used by DeriveImage untouched (Pierre-Eric)
v3: Fixed a segfault reported by Roman Elshin

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/1428
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/5942>

src/gallium/frontends/va/buffer.c
src/gallium/frontends/va/image.c
src/gallium/frontends/va/va_private.h

index 5ab9018..d1c00f4 100644 (file)
@@ -204,9 +204,13 @@ vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id)
       return VA_STATUS_ERROR_INVALID_BUFFER;
    }
 
-   if (buf->derived_surface.resource)
+   if (buf->derived_surface.resource) {
       pipe_resource_reference(&buf->derived_surface.resource, NULL);
 
+      if (buf->derived_image_buffer)
+         buf->derived_image_buffer->destroy(buf->derived_image_buffer);
+   }
+
    FREE(buf->data);
    FREE(buf);
    handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id);
index bda08ae..3d6e091 100644 (file)
@@ -201,6 +201,7 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
    VAImage *img;
    struct pipe_screen *screen;
    struct pipe_surface **surfaces;
+   struct pipe_video_buffer *new_buffer = NULL;
    int w;
    int h;
    int i;
@@ -225,9 +226,6 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
    if (!surf || !surf->buffer)
       return VA_STATUS_ERROR_INVALID_SURFACE;
 
-   if (surf->buffer->interlaced)
-     return VA_STATUS_ERROR_OPERATION_FAILED;
-
    surfaces = surf->buffer->get_surfaces(surf->buffer);
    if (!surfaces || !surfaces[0]->texture)
       return VA_STATUS_ERROR_ALLOCATION_FAILED;
@@ -285,6 +283,38 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
    case VA_FOURCC('N','V','1','2'):
    case VA_FOURCC('P','0','1','0'):
    case VA_FOURCC('P','0','1','6'):
+      if (surf->buffer->interlaced) {
+         struct u_rect src_rect, dst_rect;
+         struct pipe_video_buffer new_template;
+
+         new_template = surf->templat;
+         new_template.interlaced = false;
+         new_buffer = drv->pipe->create_video_buffer(drv->pipe, &new_template);
+
+         /* convert the interlaced to the progressive */
+         src_rect.x0 = dst_rect.x0 = 0;
+         src_rect.x1 = dst_rect.x1 = surf->templat.width;
+         src_rect.y0 = dst_rect.y0 = 0;
+         src_rect.y1 = dst_rect.y1 = surf->templat.height;
+
+         vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
+                           surf->buffer, new_buffer,
+                           &src_rect, &dst_rect,
+                           VL_COMPOSITOR_WEAVE);
+
+         /* recalculate the values now that we have a new surface */
+         surfaces = surf->buffer->get_surfaces(new_buffer);
+         if (screen->resource_get_info) {
+            screen->resource_get_info(screen, surfaces[0]->texture, &stride,
+                                    &offset);
+            if (!stride)
+               offset = 0;
+         }
+
+         w = align(new_buffer->width, 2);
+         h = align(new_buffer->height, 2);
+      }
+
       img->num_planes = 2;
       img->pitches[0] = stride > 0 ? stride : w;
       img->pitches[1] = stride > 0 ? stride : w;
@@ -314,6 +344,7 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
    img_buf->num_elements = 1;
 
    pipe_resource_reference(&img_buf->derived_surface.resource, surfaces[0]->texture);
+   img_buf->derived_image_buffer = new_buffer;
 
    img->buf = handle_table_add(VL_VA_DRIVER(ctx)->htab, img_buf);
    mtx_unlock(&drv->mutex);
index e3a9790..b80eea5 100644 (file)
@@ -267,6 +267,7 @@ typedef struct {
    unsigned int export_refcount;
    VABufferInfo export_state;
    unsigned int coded_size;
+   struct pipe_video_buffer *derived_image_buffer;
 } vlVaBuffer;
 
 typedef struct {