Module: Mesa
Branch: main
Commit: 0ee4506c3aaf4e024748c91fbda9ea77c215bc4a
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=0ee4506c3aaf4e024748c91fbda9ea77c215bc4a

Author: David Rosca <[email protected]>
Date:   Fri Jul 28 18:14:10 2023 +0200

frontends/vdpau: Alloc interlaced surface for interlaced pics

When decoding interlaced pics, the output surface should
also be allocated as interlaced to make the deinterlace
postproc filter work correctly.

Reviewed-by: Ruijing Dong <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24361>

---

 src/gallium/frontends/vdpau/decode.c | 85 +++++++++++++++++++++---------------
 1 file changed, 49 insertions(+), 36 deletions(-)

diff --git a/src/gallium/frontends/vdpau/decode.c 
b/src/gallium/frontends/vdpau/decode.c
index 4b262df6ca0..bd58f8e5d31 100644
--- a/src/gallium/frontends/vdpau/decode.c
+++ b/src/gallium/frontends/vdpau/decode.c
@@ -552,6 +552,16 @@ vlVdpDecoderFixVC1Startcode(uint32_t *num_buffers, const 
void *buffers[], unsign
    sizes[0] = 4;
 }
 
+static bool
+vlVdpQueryInterlacedH264(struct pipe_h264_picture_desc *h264)
+{
+   if (h264->pps->sps->frame_mbs_only_flag)
+      return false;
+
+   return h264->field_pic_flag || /* PAFF */
+      h264->pps->sps->mb_adaptive_frame_field_flag; /* MBAFF */
+}
+
 /**
  * Decode a compressed field/frame and render the result into a 
VdpVideoSurface.
  */
@@ -583,6 +593,7 @@ vlVdpDecoderRender(VdpDecoder decoder,
       struct pipe_h264_picture_desc h264;
       struct pipe_h265_picture_desc h265;
    } desc;
+   bool picture_interlaced = false;
 
    if (!(picture_info && bitstream_buffers))
       return VDP_STATUS_INVALID_POINTER;
@@ -605,42 +616,6 @@ vlVdpDecoderRender(VdpDecoder decoder,
       // TODO: Recreate decoder with correct chroma
       return VDP_STATUS_INVALID_CHROMA_TYPE;
 
-   buffer_support[0] = screen->get_video_param(screen, dec->profile, 
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
-                                               
PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE);
-   buffer_support[1] = screen->get_video_param(screen, dec->profile, 
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
-                                               
PIPE_VIDEO_CAP_SUPPORTS_INTERLACED);
-
-   if (vlsurf->video_buffer == NULL ||
-       !screen->is_video_format_supported(screen, 
vlsurf->video_buffer->buffer_format,
-                                          dec->profile, 
PIPE_VIDEO_ENTRYPOINT_BITSTREAM) ||
-       !buffer_support[vlsurf->video_buffer->interlaced]) {
-
-      mtx_lock(&vlsurf->device->mutex);
-
-      /* destroy the old one */
-      if (vlsurf->video_buffer)
-         vlsurf->video_buffer->destroy(vlsurf->video_buffer);
-
-      /* set the buffer format to the prefered one */
-      vlsurf->templat.buffer_format = screen->get_video_param(screen, 
dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
-                                                              
PIPE_VIDEO_CAP_PREFERED_FORMAT);
-
-      /* also set interlacing to decoders preferences */
-      vlsurf->templat.interlaced = screen->get_video_param(screen, 
dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
-                                                           
PIPE_VIDEO_CAP_PREFERS_INTERLACED);
-
-      /* and recreate the video buffer */
-      vlsurf->video_buffer = dec->context->create_video_buffer(dec->context, 
&vlsurf->templat);
-
-      /* still no luck? get me out of here... */
-      if (!vlsurf->video_buffer) {
-         mtx_unlock(&vlsurf->device->mutex);
-         return VDP_STATUS_NO_IMPLEMENTATION;
-      }
-      vlVdpVideoSurfaceClear(vlsurf);
-      mtx_unlock(&vlsurf->device->mutex);
-   }
-
    for (i = 0; i < bitstream_buffer_count; ++i) {
       buffers[i] = bitstream_buffers[i].bitstream;
       sizes[i] = bitstream_buffers[i].bitstream_bytes;
@@ -663,6 +638,7 @@ vlVdpDecoderRender(VdpDecoder decoder,
    case PIPE_VIDEO_FORMAT_MPEG4_AVC:
       desc.h264.pps = &pps_h264;
       ret = vlVdpDecoderRenderH264(&desc.h264, (VdpPictureInfoH264 
*)picture_info, dec->level);
+      picture_interlaced = vlVdpQueryInterlacedH264(&desc.h264);
       break;
    case PIPE_VIDEO_FORMAT_HEVC:
       desc.h265.pps = &pps_h265;
@@ -675,6 +651,43 @@ vlVdpDecoderRender(VdpDecoder decoder,
    if (ret != VDP_STATUS_OK)
       return ret;
 
+   buffer_support[0] = screen->get_video_param(screen, dec->profile, 
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
+                                               
PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE);
+   buffer_support[1] = screen->get_video_param(screen, dec->profile, 
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
+                                               
PIPE_VIDEO_CAP_SUPPORTS_INTERLACED);
+
+   if (vlsurf->video_buffer == NULL ||
+       !screen->is_video_format_supported(screen, 
vlsurf->video_buffer->buffer_format,
+                                          dec->profile, 
PIPE_VIDEO_ENTRYPOINT_BITSTREAM) ||
+       !buffer_support[vlsurf->video_buffer->interlaced] ||
+       (picture_interlaced && !vlsurf->video_buffer->interlaced && 
buffer_support[1])) {
+
+      mtx_lock(&vlsurf->device->mutex);
+
+      /* destroy the old one */
+      if (vlsurf->video_buffer)
+         vlsurf->video_buffer->destroy(vlsurf->video_buffer);
+
+      /* set the buffer format to the prefered one */
+      vlsurf->templat.buffer_format = screen->get_video_param(screen, 
dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
+                                                              
PIPE_VIDEO_CAP_PREFERED_FORMAT);
+
+      /* also set interlacing to decoders preferences */
+      vlsurf->templat.interlaced = screen->get_video_param(screen, 
dec->profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
+                                                           
PIPE_VIDEO_CAP_PREFERS_INTERLACED) || picture_interlaced;
+
+      /* and recreate the video buffer */
+      vlsurf->video_buffer = dec->context->create_video_buffer(dec->context, 
&vlsurf->templat);
+
+      /* still no luck? get me out of here... */
+      if (!vlsurf->video_buffer) {
+         mtx_unlock(&vlsurf->device->mutex);
+         return VDP_STATUS_NO_IMPLEMENTATION;
+      }
+      vlVdpVideoSurfaceClear(vlsurf);
+      mtx_unlock(&vlsurf->device->mutex);
+   }
+
    mtx_lock(&vldecoder->mutex);
    dec->begin_frame(dec, vlsurf->video_buffer, &desc.base);
    dec->decode_bitstream(dec, vlsurf->video_buffer, &desc.base, 
bitstream_buffer_count, buffers, sizes);

Reply via email to