This is a pretty big change. Instead of doing a half-hearted passthrough
of the playback timestamp, we attempt to rewrite the raw MPEG timestamps
such that they match with the playback time.
We add the offset between raw start timestamp and playback time to the
packet timestamps. This is the easy part; but the problem is with
timestamp resets. We simply detect timestamp discontinuities by checking
whether they are more than 500ms apart (large enough for all video
faster than 2 FPS and audio with reasonable framesizes/samplerates), and
adjust the timestamp offset accordingly.
This should work pretty well. There may be some problems with subtitles.
If the first packet after a timestamp reset is a subtitle instead of
video, it will fail. Also, selecting multiple audio or video streams
won't work (but mpv doesn't allow selecting several anyway). Trying to
demux subtitles with no video stream enabled will probably fail.
Untested with Bluray, because I have no Bluray sample.
Background:
libdvdnav/libdvdread/libbluray make this relatively hard. They return a
raw MPEG (PS/TS) byte stream, and additionally to that provide a
function to retrieve the current "playback" time. The playback time is
what should be displayed to the user, while the MPEG timestamps can be
completely different. Even worse, the MPEG timestamps can reset. Since
we use the libavformat demuxer (instead of parsing the MPEG packets in
the DVD/BD code), it's hard to associate between these timestamps. As a
result, the time display is special cased in the playloop, and of low
quality (updates only all 1 or 2 seconds, sometimes is incorrect). The
fact that the stream cache can be between demuxer and the stream source
makes things worse.
All the libs seem to provide an event that tells whether timestamps are
resetting. But since this signalling is byte based, it's hard to connect
it to the demuxed MPEG packets. It might be possible to create some sort
of table mapping file positions to discontinuities and new timestamps.
(For simplicity, this table could be 2 entries large, sufficient to
catch all discontinuities if the distance between them is larger than
the total buffering.)
DVD and Bluray (and to some extent cdda) require awful hacks all over
the codebase to make them work. The main reason is that they act like
container, but are entirely implemented on the stream layer. The raw
mpeg data resulting from these streams must be "extended" with the
container-like metadata transported via STREAM_CTRLs. The result were
hacks all over demux.c and some higher-level parts.
Add a "disc" pseudo-demuxer, and move all these hacks and special-cases
to it.