From 0ee4506c3aaf4e024748c91fbda9ea77c215bc4a Mon Sep 17 00:00:00 2001 From: David Rosca Date: Fri, 28 Jul 2023 18:14:10 +0200 Subject: [PATCH] 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 Part-of: --- 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 4b262df..bd58f8e 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); -- 2.7.4