mirror of https://github.com/mpv-player/mpv
demux_raw: fix operation with demuxer cache and backward playback
Raw audio formats can be accessed sample-wise, and logically audio packets demuxed from it would contain only 1 sample. This is inefficient, so raw audio demuxers typically "bundle" multiple samples in one packet. The problem for the demuxer cache and backward playback is that they need properly aligned packets to make seeking "deterministic". The requirement is that if you read some packets, and then seek back, you eventually see the same packets again. demux_raw basically allowed to seek into the middle of a previously returned packet, which makes it impossible to make the transition seamless. (Unless you'd be aware of the packet data format and cut them to make it seamless, which is too complex for such a use case.) Solve this by always aligning seeks to packet boundaries. This reduces the seek accuracy to the arbitrarily chosen packet size. But you can use hr-seek to fix this. The gain from not making raw audio an awful special case pays in exchange for this "stupid" suggestion to use hr-seek. It appears this also fixes that it could and did seek into the middle of the frame (not sure if this code was ever tested - it goes back to removing the code duplication between the former demux_rawaudio.c and demux_rawvideo.c). If you really cared, you could introduce a seek flag that controls whether the seek is aligned or not. Then code which requires "deterministic" demuxing could set it. But this isn't really useful for us, and we'd always set the flag anyway, unless maybe the caching were forced disabled. libavformat's wav demuxer exhibits the same issue. We can't fix it (it would require the unpleasant experience of contributing to FFmpeg), so document this in otions.rst. In theory, this also affects seek range joining, but the only bad effect should be that cached data is discarded.
This commit is contained in:
parent
5d69dcfb89
commit
5b4ae42328
|
@ -479,6 +479,16 @@ Playback Control
|
|||
framestep commands are transposed. Backstepping will perform very
|
||||
expensive work to step forward by 1 frame.
|
||||
|
||||
- Backward playback in wav files does not work properly (and possibly
|
||||
similar formats, typically raw audio formats used through libavformat).
|
||||
This is because libavformat does not align seeks on the packet sizes it
|
||||
uses. (The packet sizes are arbitrary and chosen by libavformat
|
||||
internally. Seeks on the other hand are sample-exact, which leads to
|
||||
overlapping packets if the backward playback state machine seeks back.
|
||||
This is very complex to work around, so it doesn't attempt to.)
|
||||
A workaround is to remux to a format like mkv, which enforces packet
|
||||
boundaries. Making mpv cache the entire file in memory also works.
|
||||
|
||||
Tuning:
|
||||
|
||||
- Remove all ``--vf``/``--af`` filters you have set. Disable deinterlacing.
|
||||
|
|
|
@ -301,7 +301,9 @@ static void raw_seek(demuxer_t *demuxer, double seek_pts, int flags)
|
|||
stream_t *s = demuxer->stream;
|
||||
int64_t end = 0;
|
||||
stream_control(s, STREAM_CTRL_GET_SIZE, &end);
|
||||
int64_t pos = seek_pts * p->frame_rate * p->frame_size;
|
||||
int64_t frame_nr = seek_pts * p->frame_rate;
|
||||
frame_nr = frame_nr - (frame_nr % p->read_frames);
|
||||
int64_t pos = frame_nr * p->frame_size;
|
||||
if (flags & SEEK_FACTOR)
|
||||
pos = end * seek_pts;
|
||||
if (pos < 0)
|
||||
|
|
Loading…
Reference in New Issue