GNOME Bugzilla – Bug 796495
vaapi{h264,h265}enc: Missing frames when encode with B frames from YUV file and num-buffers specified
Last modified: 2018-11-03 15:54:43 UTC
When filesrc num-buffers=N is specified in encode pipeline for vaapi encode and max-bframes > 0, the resulting encoded video does not contain N frames. 1. Generate 100-frame YUV file: $ gst-launch-1.0 videotestsrc num-buffers=100 ! video/x-raw,format=NV12,width=1920,height=1080 ! filesink location=./test.yuv 2. Encode 90 frames from previous YUV output file: $ gst-launch-1.0 filesrc location=test.yuv num-buffers=90 ! rawvideoparse format=nv12 width=1920 height=1080 ! vaapih264enc rate-control=cbr bitrate=5000 keyframe-period=30 num-slices=4 max-bframes=2 ! h264parse ! filesink location=./test.h264 ...the resulting file, test.h264 only contains 88 frames, which is NOT expected. 3. If we switch the encoder to msdkh264enc: gst-launch-1.0 filesrc location=test.yuv num-buffers=90 ! rawvideoparse format=nv12 width=1920 height=1080 ! msdkh264enc rate-control=cbr bitrate=5000 gop-size=30 num-slices=4 b-frames=2 ! h264parse ! filesink location=./test.h264 ...the resulting file contains the requested 90 frames, which is expected. Other encoders like ffmpeg and yami output the correct number of frames. Thus, only gstreamer-vaapi encoders (all encoders that support b-frames) exhibit the incorrect number of frames in encoded output.
FWIW: gst-launch-1.0 filesrc location=test.yuv num-buffers=90 ! rawvideoparse format=nv12 width=1920 height=1080 ! checksumsink ...outputs 90 values
Looks like is the b-frames setting that impact the results here, a simpler way to reproduce the issue: gst-launch-1.0 videotestsrc num-buffers=90 ! vaapih264enc max-bframes=4 ! h264parse ! multifilesink If you move it back to 0 bframes, there it's good. I'm confirming this issue.
@Victor, I see you changed the subject. Please not that this happens with vaapih265enc too!
(In reply to U. Artie Eoff from comment #3) > @Victor, I see you changed the subject. Please not that this happens with > vaapih265enc too! /not/note/
Take a example, if set max-bframes as 4, then encoder need 4 frames in a list together to encode the 4 B frames per time. If the total frame number can not divide by 4, then there will be less than 4 frames in list in the end. And the list will be release and the frames will be drop in it during flush. So one solution is to change B frame into P frame in flush and re-encode all the remind frames instead of drop them. But seems it is hard to implement because encode/flush are called in video encode base class. Any suggestion on this?
I can't comment on the solution, I would have to check what other encoders do by parsing the results, but it seems fair. The base class will signal the moment you should do that on finish() virtual function. It's of course harder than usual, as we are implementing a part of the encoder.
-- GitLab Migration Automatic Message -- This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/issues/97.