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 <ruijing.dong@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24361>
This commit is contained in:
David Rosca 2023-07-28 18:14:10 +02:00 committed by Marge Bot
parent 578e10e157
commit 0ee4506c3a

View file

@ -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);