[FFmpeg-trac] #3391(undetermined:new): Gaps in input timestamps cause invalid Ogg Opus output
FFmpeg
trac at avcodec.org
Mon Feb 17 10:42:31 CET 2014
#3391: Gaps in input timestamps cause invalid Ogg Opus output
-------------------------------------+-------------------------------------
Reporter: MarkZV | Type: defect
Status: new | Priority: normal
Component: | Version: git-
undetermined | master
Keywords: | Blocked By:
Blocking: | Reproduced by developer: 0
Analyzed by developer: 0 |
-------------------------------------+-------------------------------------
When transcoding to Ogg Opus from a format with per-packet timestamps,
such as mp4 audio, if the input contains a gap in packet timestamps (e.g.
due to a lost/corrupted packet), FFmpeg writes invalid Ogg Opus output.
Specifically, the Ogg granule position written by FFmpeg increments by
more than the number of samples contained in packets that complete on the
page.
This violates [https://tools.ietf.org/html/draft-ietf-codec-
oggopus-03#section-4 section 4 of the specification] and may cause
synchronization problems.
Because the Ogg container does not have explicit per-frame or per-packet
timestamps, Ogg Opus does not allow gaps in the audio. Instead, an equal
duration of silence or predicted samples may be substituted for the
missing samples when encoding. If pre-encoded Opus is being copied to Ogg
without encoding, any missing Opus packets may be replaced with Opus PLC
(packet loss concealment) packets as described in
[https://tools.ietf.org/html/draft-ietf-codec-oggopus-03#section-4.1
section 4.1 of the specification].
{{{
$ ffmpeg -v 9 -loglevel 99 -i lostpacket.m4a out.opus
ffmpeg version N-60696-g38a08e0 Copyright (c) 2000-2014 the FFmpeg
developers
built on Feb 17 2014 01:24:12 with gcc 4.8.2 (MacPots gcc48 4.8.2_0)
configuration: --enable-debug --assert-level=2 --prefix=/opt/local
--enable-swscale --enable-avfilter --enable-avresample --enable-libmp3lame
--enable-libvorbis --enable-libopus --enable-libtheora --enable-
libschroedinger --enable-libopenjpeg --enable-libmodplug --enable-libvpx
--enable-libspeex --enable-libass --enable-libbluray --enable-gnutls
--enable-fontconfig --enable-libfreetype --mandir=/opt/local/share/man
--enable-pthreads --cc=/opt/local/bin/gcc-mp-4.8 --arch=x86_64 --enable-
yasm --enable-gpl --enable-postproc --enable-libx264 --enable-libxvid
--enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb
--enable-nonfree --enable-libfdk-aac --enable-libfaac
libavutil 52. 64.100 / 52. 64.100
libavcodec 55. 52.102 / 55. 52.102
libavformat 55. 33.100 / 55. 33.100
libavdevice 55. 10.100 / 55. 10.100
libavfilter 4. 1.102 / 4. 1.102
libavresample 1. 1. 0 / 1. 1. 0
libswscale 2. 5.101 / 2. 5.101
libswresample 0. 17.104 / 0. 17.104
libpostproc 52. 3.100 / 52. 3.100
Splitting the commandline.
Reading option '-v' ... matched as option 'v' (set logging level) with
argument '9'.
Reading option '-loglevel' ... matched as option 'loglevel' (set logging
level) with argument '99'.
Reading option '-i' ... matched as input file with argument
'lostpacket.m4a'.
Reading option 'out.opus' ... matched as output file.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option v (set logging level) with argument 9.
Successfully parsed a group of options.
Parsing a group of options: input file lostpacket.m4a.
Successfully parsed a group of options.
Opening an input file: lostpacket.m4a.
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x103009800] Format mov,mp4,m4a,3gp,3g2,mj2
probed with size=2048 and score=100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x103009800] ISO: File Type Major Brand: M4A
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x103009800] Before avformat_find_stream_info()
pos: 28861 bytes read:28861 seeks:0
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x103009800] All info found
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x103009800] After avformat_find_stream_info()
pos: 48 bytes read:28861 seeks:0 frames:1
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'lostpacket.m4a':
Metadata:
major_brand : M4A
minor_version : 512
compatible_brands: isomiso2
encoder : Lavf55.32.101
Duration: 00:00:03.54, start: 0.042667, bitrate: 65 kb/s
Stream #0:0(und), 1, 1/48000: Audio: aac (mp4a / 0x6134706D), 48000
Hz, stereo, fltp, 61 kb/s (default)
Metadata:
handler_name : SoundHandler
Successfully opened the file.
Parsing a group of options: output file out.opus.
Successfully parsed a group of options.
Opening an output file: out.opus.
Successfully opened the file.
detected 4 logical cores
[graph 0 input from stream 0:0 @ 0x102a12fc0] Setting 'time_base' to value
'1/48000'
[graph 0 input from stream 0:0 @ 0x102a12fc0] Setting 'sample_rate' to
value '48000'
[graph 0 input from stream 0:0 @ 0x102a12fc0] Setting 'sample_fmt' to
value 'fltp'
[graph 0 input from stream 0:0 @ 0x102a12fc0] Setting 'channel_layout' to
value '0x3'
[graph 0 input from stream 0:0 @ 0x102a12fc0] tb:1/48000 samplefmt:fltp
samplerate:48000 chlayout:0x3
[audio format for output stream 0:0 @ 0x102a138a0] Setting 'sample_fmts'
to value 's16|flt'
[audio format for output stream 0:0 @ 0x102a138a0] Setting 'sample_rates'
to value '48000|24000|16000|12000|8000'
[audio format for output stream 0:0 @ 0x102a138a0] Setting
'channel_layouts' to value '0x4|0x3|0x7|0x33|0x37|0x3f|0x70f|0x63f'
[audio format for output stream 0:0 @ 0x102a138a0] auto-inserting filter
'auto-inserted resampler 0' between the filter 'Parsed_anull_0' and the
filter 'audio format for output stream 0:0'
[AVFilterGraph @ 0x102a11be0] query_formats: 4 queried, 6 merged, 3
already done, 0 delayed
[auto-inserted resampler 0 @ 0x102a14080] ch:2 chl:stereo fmt:fltp
r:48000Hz -> ch:2 chl:stereo fmt:flt r:48000Hz
[libopus @ 0x10300f800] No bit rate set. Defaulting to 96000 bps.
Output #0, opus, to 'out.opus':
Metadata:
major_brand : M4A
minor_version : 512
compatible_brands: isomiso2
encoder : Lavf55.33.100
Stream #0:0(und), 0, 1/48000: Audio: opus (libopus), 48000 Hz, stereo,
flt, 96 kb/s (default)
Metadata:
handler_name : SoundHandler
major_brand : M4A
minor_version : 512
compatible_brands: isomiso2
encoder : Lavf55.33.100
Stream mapping:
Stream #0:0 -> #0:0 (aac -> libopus)
Press [q] to stop, [?] for help
[libopus @ 0x10300f800] Trying to remove 584 more samples than there are
in the queue
[output stream 0:0 @ 0x102a13300] EOF on sink link output stream
0:0:default.
No more output streams to write to, finishing.
size= 49kB time=00:00:03.57 bitrate= 112.8kbits/s
video:0kB audio:49kB subtitle:0 data:0 global headers:0kB muxing overhead
1.290400%
166 frames successfully decoded, 0 decoding errors
[AVIOContext @ 0x102a12c80] Statistics: 0 seeks, 6 writeouts
[AVIOContext @ 0x102a11dc0] Statistics: 28861 bytes read, 0 seeks
$
}}}
The incorrect Ogg Opus file produces warnings from the opusinfo tool (part
of [http://www.opus-codec.org/downloads/ opus-tools]); "Sample count
behind granule":
{{{
$ opusinfo out.opus
Processing file "out.opus"...
New logical stream (#1, serial: f039efde): type opus
Encoded with Lavf55.33.100
User comments section follows...
language=und
handler_name=SoundHandler
major_brand=M4A
minor_version=512
compatible_brands=isomiso2
encoder=Lavf55.33.100
WARNING: Sample count behind granule (95040>96064) in stream 1
WARNING: Sample count behind granule (143040>144064) in stream 1
WARNING: Sample count behind granule (170880>171320) in stream 1
Opus stream 1:
Pre-skip: 312
Playback gain: 0 dB
Channels: 2
Original sample rate: 48000Hz
Packet duration: 20.0ms (max), 20.0ms (avg), 20.0ms (min)
Page duration: 1000.0ms (max), 890.0ms (avg), 580.0ms (min)
Total data length: 50394 bytes (overhead: 1.31%)
Playback length: 0m:03.562s
Average bitrate: 113.2 kb/s, w/o overhead: 111.7 kb/s
Logical stream 1 ended
$
}}}
It is expected that FFmpeg would produce a valid Ogg Opus file, in this
case by inserting silence or predicted samples in place of the missing
samples before encoding.
--
Ticket URL: <https://trac.ffmpeg.org/ticket/3391>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker
More information about the FFmpeg-trac
mailing list