diff mbox series

[FFmpeg-devel,1/3] avformat/oggparsevorbis: Update end_trimming for the last packet

Message ID 20210707154134.59769-1-gsun@roblox.com
State Accepted
Headers show
Series [FFmpeg-devel,1/3] avformat/oggparsevorbis: Update end_trimming for the last packet | expand

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate fail Make fate failed
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate warning Make fate failed

Commit Message

Guangyu Sun July 7, 2021, 3:41 p.m. UTC
Without end_trimming, the last packet will contain unexpected samples used
for padding.

This commit partially fixes #6367 when the audio length is long enough.

dd if=/dev/zero of=./silence.raw count=20 bs=500
oggenc --raw silence.raw --output=silence.ogg
oggdec --raw --output silence.oggdec.raw silence.ogg
ffmpeg -codec:a libvorbis -i silence.ogg -f s16le -codec:a pcm_s16le silence.libvorbis.ffmpeg.raw
ffmpeg -i silence.ogg -f s16le -codec:a pcm_s16le silence.native.ffmpeg.raw
ls -l *.raw

The original test case in #6367 is still not fixed due to a remaining issue.

The remaining issue is that ogg_stream->private is not kept during
ogg_save()/ogg_restore(). Field final_duration in the private data is
important to calculate end_trimming.

Some common operations such as avformat_open_input() and
avformat_find_stream_info() before reading packet will trigger ogg_save()
and ogg_restore().

Luckily, final_duration will not get updated until the last ogg page. The
save/restore mentioned above will not change final_duration most of the
time. But if the audio length is short, those reads may be performed on
the last ogg page, causing trouble keeping the correct value of
final_duration. We probably need a more complicated patch to address this
issue.

Signed-off-by: Guangyu Sun <gsun@roblox.com>
---
 libavformat/oggparsevorbis.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index 0e8c25c030..c48658ceda 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -492,8 +492,12 @@  static int vorbis_packet(AVFormatContext *s, int idx)
             priv->final_pts      = os->lastpts;
             priv->final_duration = 0;
         }
-        if (os->segp == os->nsegs)
+        if (os->segp == os->nsegs) {
+            int64_t skip = priv->final_pts + priv->final_duration + os->pduration - os->granule;
+            if (skip > 0)
+                os->end_trimming = skip;
             os->pduration = os->granule - priv->final_pts - priv->final_duration;
+        }
         priv->final_duration += os->pduration;
     }