From 6e911cf252e16d8c76659a60ea7c60315910ce7f Mon Sep 17 00:00:00 2001 From: David Rosca Date: Fri, 20 Dec 2024 08:55:00 +0100 Subject: [PATCH] frontends/va: Fix decoding VC1 interlaced video VC1 has different start code for FRAME and FIELD, so we need to use FIELD start code for second field. Also simplify start code search to only look for 00 00 01. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/2347 Cc: mesa-stable Reviewed-by: David (Ming Qiang) Wu Part-of: --- src/gallium/frontends/va/picture.c | 13 +++++++------ src/gallium/frontends/va/picture_vc1.c | 1 + src/gallium/include/pipe/p_video_state.h | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/gallium/frontends/va/picture.c b/src/gallium/frontends/va/picture.c index 3dd7df0fa1f..9d0d705a711 100644 --- a/src/gallium/frontends/va/picture.c +++ b/src/gallium/frontends/va/picture.c @@ -407,7 +407,8 @@ handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) enum pipe_video_format format = u_reduce_video_profile(context->templat.profile); static const uint8_t start_code_h264[] = { 0x00, 0x00, 0x01 }; static const uint8_t start_code_h265[] = { 0x00, 0x00, 0x01 }; - static const uint8_t start_code_vc1[] = { 0x00, 0x00, 0x01, 0x0d }; + static const uint8_t start_code_vc1_frame[] = { 0x00, 0x00, 0x01, 0x0d }; + static const uint8_t start_code_vc1_field[] = { 0x00, 0x00, 0x01, 0x0c }; static const uint8_t eoi_jpeg[] = { 0xff, 0xd9 }; if (!context->decoder) @@ -441,14 +442,14 @@ handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf) context->bs.sizes[context->bs.num_buffers++] = sizeof(start_code_h265); break; case PIPE_VIDEO_FORMAT_VC1: - if (bufHasStartcode(buf, 0x0000010d, 32) || - bufHasStartcode(buf, 0x0000010c, 32) || - bufHasStartcode(buf, 0x0000010b, 32)) + if (bufHasStartcode(buf, 0x000001, 24)) break; if (context->decoder->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) { - context->bs.buffers[context->bs.num_buffers] = (void *const)&start_code_vc1; - context->bs.sizes[context->bs.num_buffers++] = sizeof(start_code_vc1); + const uint8_t *start_code = + context->desc.vc1.is_first_field ? start_code_vc1_frame : start_code_vc1_field; + context->bs.buffers[context->bs.num_buffers] = (void *const)start_code; + context->bs.sizes[context->bs.num_buffers++] = sizeof(start_code_vc1_frame); } break; case PIPE_VIDEO_FORMAT_MPEG4: diff --git a/src/gallium/frontends/va/picture_vc1.c b/src/gallium/frontends/va/picture_vc1.c index 6ad1571ca96..15d0f4b564d 100644 --- a/src/gallium/frontends/va/picture_vc1.c +++ b/src/gallium/frontends/va/picture_vc1.c @@ -37,6 +37,7 @@ void vlVaHandlePictureParameterBufferVC1(vlVaDriver *drv, vlVaContext *context, vlVaGetReferenceFrame(drv, vc1->backward_reference_picture, &context->desc.vc1.ref[1]); context->desc.vc1.picture_type = vc1->picture_fields.bits.picture_type; context->desc.vc1.frame_coding_mode = vc1->picture_fields.bits.frame_coding_mode; + context->desc.vc1.is_first_field = vc1->picture_fields.bits.is_first_field; context->desc.vc1.postprocflag = vc1->post_processing != 0; context->desc.vc1.pulldown = vc1->sequence_fields.bits.pulldown; context->desc.vc1.interlace = vc1->sequence_fields.bits.interlace; diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h index 05fdd3a2dbf..259410fe6ee 100644 --- a/src/gallium/include/pipe/p_video_state.h +++ b/src/gallium/include/pipe/p_video_state.h @@ -344,6 +344,7 @@ struct pipe_vc1_picture_desc uint32_t slice_count; uint8_t picture_type; uint8_t frame_coding_mode; + uint8_t is_first_field; uint8_t postprocflag; uint8_t pulldown; uint8_t interlace;