diff --git a/src/gallium/frontends/va/buffer.c b/src/gallium/frontends/va/buffer.c index 5ab90186a1a..d1c00f4b8e8 100644 --- a/src/gallium/frontends/va/buffer.c +++ b/src/gallium/frontends/va/buffer.c @@ -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); diff --git a/src/gallium/frontends/va/image.c b/src/gallium/frontends/va/image.c index bda08ae4314..3d6e0919132 100644 --- a/src/gallium/frontends/va/image.c +++ b/src/gallium/frontends/va/image.c @@ -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); diff --git a/src/gallium/frontends/va/va_private.h b/src/gallium/frontends/va/va_private.h index e3a9790103b..b80eea5b263 100644 --- a/src/gallium/frontends/va/va_private.h +++ b/src/gallium/frontends/va/va_private.h @@ -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 {