[FFmpeg-devel] [PATCH v2] lavc/vaapi_h264: Fix merging fields in DPB with missing references

Xiang, Haihao haihao.xiang at intel.com
Mon May 27 10:39:45 EEST 2024


On Wo, 2024-05-08 at 17:41 +0200, David Rosca wrote:
> If there are missing references, h264 decode does error concealment
> by copying previous refs which means there will be duplicated surfaces.
> Check long_ref and frame_idx in addition to surface when looking for
> the other field to avoid trying to merge with wrong picture.
> Also allow to merge with multiple pictures in case there are duplicates
> of the other field.
> ---
> v2: Check long_ref/frame_idx + multiple merge
> 
>  libavcodec/vaapi_h264.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c
> index b47531ce1c..398e92568c 100644
> --- a/libavcodec/vaapi_h264.c
> +++ b/libavcodec/vaapi_h264.c
> @@ -93,14 +93,19 @@ typedef struct DPB {
>   */
>  static int dpb_add(DPB *dpb, const H264Picture *pic)
>  {
> -    int i;
> +    int i, pic_frame_idx, merged = 0;
>  
>      if (dpb->size >= dpb->max_size)
>          return -1;
>  
> +    pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num;
> +
>      for (i = 0; i < dpb->size; i++) {
>          VAPictureH264 * const va_pic = &dpb->va_pics[i];
> -        if (va_pic->picture_id == ff_vaapi_get_surface_id(pic->f)) {
> +        int va_pic_long_ref = !!(va_pic->flags &
> VA_PICTURE_H264_LONG_TERM_REFERENCE);
> +        if (va_pic->picture_id == ff_vaapi_get_surface_id(pic->f) &&
> +            va_pic_long_ref == pic->long_ref &&
> +            va_pic->frame_idx == pic_frame_idx) {
>              VAPictureH264 temp_va_pic;
>              fill_vaapi_pic(&temp_va_pic, pic, 0);
>  
> @@ -112,11 +117,14 @@ static int dpb_add(DPB *dpb, const H264Picture *pic)
>                  } else {
>                      va_pic->BottomFieldOrderCnt =
> temp_va_pic.BottomFieldOrderCnt;
>                  }
> +                merged = 1;
>              }
> -            return 0;
>          }
>      }
>  
> +    if (merged)
> +        return 0;
> +
>      fill_vaapi_pic(&dpb->va_pics[dpb->size++], pic, 0);
>      return 0;
>  }

LGTM, will apply

Thanks
Haihao




More information about the ffmpeg-devel mailing list