[FFmpeg-devel] [PATCH] lavc/vaapi_h264: Don't try to merge fields in DPB for non-field pics

David Rosca nowrep at gmail.com
Tue May 7 09:02:48 EEST 2024


On Mon, May 6, 2024 at 9:55 PM Mark Thompson <sw at jkqxz.net> wrote:
>
> On 05/05/2024 17:36, David Rosca wrote:
> > This path can be hit when there are missing references while decoding
> > progressive stream and would completely break the DPB contents.
> > ---
> >  libavcodec/vaapi_h264.c | 30 ++++++++++++++++--------------
> >  1 file changed, 16 insertions(+), 14 deletions(-)
>
> Can you share a stream which does this in a progressive case?

https://github.com/nowrep/chiaki4deck/raw/samples/samples/missingframes.h264

>
> My understanding of this (though I suspect I am missing something) is that we are filling from the short/long DPB lists which should not contain duplicates (not RefPicListX, which can), so I'm not seeing how this case could be triggered.
>
> If you do have two DPB entries which are different frames but refer to the same surface then that seems like a bug elsewhere.

It comes from the error concealment in h264dec which copies previous
ref for missing refs. It can actually also happen for interlaced
streams. I've sent a new patch that should fix it for both progressive
and interlaced.

https://github.com/FFmpeg/FFmpeg/blob/b1037d4ebe7b7f9548ce1ed24a2929aedbe9a27a/libavcodec/h264_slice.c#L1520-L1559

Thanks,
David

>
> Thanks,
>
> - Mark
>
>
> > diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c
> > index b47531ce1c..ca0076f57a 100644
> > --- a/libavcodec/vaapi_h264.c
> > +++ b/libavcodec/vaapi_h264.c
> > @@ -98,22 +98,24 @@ static int dpb_add(DPB *dpb, const H264Picture *pic)
> >      if (dpb->size >= dpb->max_size)
> >          return -1;
> >
> > -    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)) {
> > -            VAPictureH264 temp_va_pic;
> > -            fill_vaapi_pic(&temp_va_pic, pic, 0);
> > -
> > -            if ((temp_va_pic.flags ^ va_pic->flags) & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD)) {
> > -                va_pic->flags |= temp_va_pic.flags & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD);
> > -                /* Merge second field */
> > -                if (temp_va_pic.flags & VA_PICTURE_H264_TOP_FIELD) {
> > -                    va_pic->TopFieldOrderCnt    = temp_va_pic.TopFieldOrderCnt;
> > -                } else {
> > -                    va_pic->BottomFieldOrderCnt = temp_va_pic.BottomFieldOrderCnt;
> > +    if (pic->field_picture) {
> > +        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)) {
> > +                VAPictureH264 temp_va_pic;
> > +                fill_vaapi_pic(&temp_va_pic, pic, 0);
> > +
> > +                if ((temp_va_pic.flags ^ va_pic->flags) & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD)) {
> > +                    va_pic->flags |= temp_va_pic.flags & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD);
> > +                    /* Merge second field */
> > +                    if (temp_va_pic.flags & VA_PICTURE_H264_TOP_FIELD) {
> > +                        va_pic->TopFieldOrderCnt    = temp_va_pic.TopFieldOrderCnt;
> > +                    } else {
> > +                        va_pic->BottomFieldOrderCnt = temp_va_pic.BottomFieldOrderCnt;
> > +                    }
> >                  }
> > +                return 0;
> >              }
> > -            return 0;
> >          }
> >      }
> >
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".


More information about the ffmpeg-devel mailing list