mpv/DOCS/man
wm4 204a7725de demux_lavf: implement bad hack for backward playback of wav
This commit generally fixes backward playing in wav, at least in most
PCM cases.

libavformat's wav demuxer (and actually all other raw PCM based
demuxers) have a specific behavior that breaks backward demuxing. The
same thing also breaks persistent seek ranges in the demuxer cache,
although that's less critical (it just means some cached data gets
discarded). The backward demuxing issue is fatal,  will log the message
"Demuxer not cooperating.", and then typically stop doing anything.

Unlike modern media formats, these formats don't organize media data in
packets, but just wrap a monolithic byte stream that is described by a
header. This is good enough for PCM, which uses fixed frames (a single
sample for all audio channels), and for which it would be too expensive
to have per frame headers.

libavformat (and mpv) is heavily packet based, and using a single packet
for each PCM frame causes too much overhead. So they typically "bundle"
multiple frames into a single packet. This packet size is obviously
arbitrary, and in libavformat's case hardcoded in its source code.

The problem is that seeking doesn't respect this arbitrary packet
boundary. Seeking is sample accurate. You can essentially seek inside a
packet. The resulting packets will not be aligned with previously
demuxed packets. This is normally OK.

Backward seeking (and some other demuxer layer features) expect that
demuxing an earlier demuxed file position eventually results in the same
packets, regardless of the seeks that were done to get there. I like to
call this "deterministic" demuxing. Backward demuxing in particular
requires this to avoid overlaps, which would make it rather hard to get
continuous output.

Fix this issue by detecting wav and hopefully other raw audio formats
with a heuristic (even PCM needs to be detected as heuristic). Then, if
a seek is requested, align the seek timestamps on the guessed number of
samples in the audio packets returned by the demuxer.

The heuristic excludes files with multiple streams. (Except "attachment"
video streams, which could be an ID3 tag. Yes, FFmpeg allows ID3 tags on
WAV files.) Such files will inherently use the packet concept in some
way.

We don't know how the demuxer chooses the internal packet size, but we
assume that it's fixed and aligned to PCM frame sizes. The frame size is
most likely given by block_align (the native wav frame size, according
to Microsoft). We possibly need to explicitly read and discard a packet
if the seek is done without reading anything before that. We ignore any
subsequent packet sizes; we need to avoid the very last packet, which
likely has a different size.

This hack should be rather benign. In the worst case, it will "round"
the seek target a little, but the maximum rounding amount is bounded.
Maybe we _could_ round up if SEEK_FORWARD is specified, but I didn't
bother.

An earlier commit fixed the same issue for mpv's demux_raw.

An alternative, and probably much better solution would be clipping
decoded data by timestamp. demux.c could allow the type of overlap the
wav demuxer introduces, and instruct the decoder to clip the output
against the last decoded timestamp. There's already an infrastructure
for this (demux_packet.end field) used by EDL/ordered chapters.

Although this sounds like a good solution, mpv unfortunately uses floats
for timestamps. The rounding errors break sample accuracy. Even if you
used integers, you'd need a timebase that is sample accurate (not always
easy, since EDL can merge tracks with different sample rates).
2019-09-19 20:37:04 +02:00
..
af.rst f_lavfi: add an option to use old audio PTS handling for af_lavfi 2018-04-15 23:11:33 +03:00
ao.rst ao_pulse: reduce requested device buffer size 2018-04-15 23:11:33 +03:00
changes.rst
encode.rst encode: remove old timestamp handling 2018-05-03 01:08:44 +03:00
input.rst manpage: remove double fw-bytes documentation 2019-09-19 20:37:04 +02:00
ipc.rst ipc: alias set_property_string to set_property 2018-05-25 10:45:59 +02:00
javascript.rst js: expose mpv_abort_async_command() (match dbe831bd) 2019-09-11 21:08:04 +03:00
libmpv.rst
lua.rst lua: expose mpv_abort_async_command() 2018-05-24 19:56:34 +02:00
mpv.rst Remove libdvdread support in favor of libdvdnav 2019-09-13 15:29:27 +02:00
options.rst demux_lavf: implement bad hack for backward playback of wav 2019-09-19 20:37:04 +02:00
osc.rst osc: improve look of seekranges 2019-09-02 01:11:04 +03:00
stats.rst config: replace config dir lua-settings/ with dir script-opts/ 2018-04-07 16:02:16 -07:00
vf.rst DOCS: remove references to --video-stereo-mode 2019-09-14 21:16:38 +02:00
vo.rst image_writer: add webp-compression option 2019-09-14 23:02:39 +02:00