summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-06-02 17:27:00 +0200
committerwm4 <wm4@nowhere>2019-09-19 20:37:05 +0200
commitc0014e2f930a545deb0bb2eb7b98f7c2d3cac2db (patch)
treeb0c0e143e4f659f35258553b921f7904122ccc7b /demux
parenta0d59a9a15efb60fc6015e8b49a0e2a5990fd060 (diff)
downloadmpv-c0014e2f930a545deb0bb2eb7b98f7c2d3cac2db.tar.bz2
mpv-c0014e2f930a545deb0bb2eb7b98f7c2d3cac2db.tar.xz
demux: update some comments
Mostly about the packet queue and the subtitle handling of it. (This mess sure sounds like a good argument to give up the separate stream queues, and using a single packet queue per cached range.)
Diffstat (limited to 'demux')
-rw-r--r--demux/demux.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/demux/demux.c b/demux/demux.c
index bfe1989b7e..39142817ab 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -600,19 +600,30 @@ static void update_seek_ranges(struct demux_cached_range *range)
if (range->is_bof)
range->seek_start = min_start_pts;
- // Sparse stream behavior is not very clearly defined, but usually we don't
- // want it to restrict the range of other streams, unless
+ // Sparse (subtitle) stream behavior is not very clearly defined, but
+ // usually we don't want it to restrict the range of other streams. For
+ // example, if there are subtitle packets at position 5 and 10 seconds, and
+ // the demuxer demuxed the other streams until position 7 seconds, the seek
+ // range end position is 7.
+ // Assume that reading a non-sparse (audio/video) packet gets all sparse
+ // packets that are needed before that non-sparse packet.
// This is incorrect in any of these cases:
// - sparse streams only (it's unknown how to determine an accurate range)
// - if sparse streams have non-keyframe packets (we set queue->last_pruned
// to the start of the pruned keyframe range - we'd need the end or so)
- // We also assume that ds->eager equals to a stream being sparse (usually
- // true, except if only sparse streams are selected).
+ // We also assume that ds->eager equals to a stream not being sparse
+ // (usually true, except if only sparse streams are selected).
// We also rely on the fact that the demuxer position will always be ahead
// of the seek_end for audio/video, because they need to prefetch at least
- // 1 packet to detect the end of a keyframe range. This means that we're
- // relatively guaranteed to have all sparse (subtitle) packets within the
- // seekable range.
+ // 1 packet to detect the end of a keyframe range. This means that there's
+ // a relatively high guarantee to have all sparse (subtitle) packets within
+ // the seekable range.
+ // As a consequence, the code _never_ checks queue->seek_end for a sparse
+ // queue, as the end of it is implied by the highest PTS of a non-sparse
+ // stream (i.e. the latest demuxer position).
+ // On the other hand, if a sparse packet was pruned, and that packet has
+ // a higher PTS than seek_start for non-sparse queues, that packet is
+ // missing. So the range's seek_start needs to be adjusted accordingly.
for (int n = 0; n < range->num_streams; n++) {
struct demux_queue *queue = range->streams[n];
if (queue->ds->selected && !queue->ds->eager &&
@@ -2094,12 +2105,13 @@ static void prune_old_packets(struct demux_internal *in)
struct demux_queue *queue = range->streams[ds->index];
// Prune all packets until the next keyframe or reader_head. Keeping
- // those packets would not help with seeking at all, so we strictly
- // drop them.
+ // leading non-keyframe packets would not help with seeking at all (as
+ // seeking requires keyframe packets as target), so we strictly drop
+ // them. But obviously, you can't prune reader_head.
// In addition, we need to find the new possibly min. seek target,
// which in the worst case could be inside the forward buffer. The fact
- // that many keyframe ranges without keyframes exist (audio packets)
- // makes this much harder.
+ // that there's not necessarily a keyframe packet anywhere in the
+ // current queue makes this harder.
if (in->seekable_cache && !queue->next_prune_target) {
// (Has to be _after_ queue->head to drop at least 1 packet.)
struct demux_packet *prev = queue->head;
@@ -2109,8 +2121,9 @@ static void prune_old_packets(struct demux_internal *in)
queue->next_prune_target = queue->tail; // (prune all if none found)
while (prev->next) {
struct demux_packet *dp = prev->next;
- // Note that the next back_pts might be above the lowest buffered
- // packet, but it will still be only viable lowest seek target.
+ // Prune until the next keyframe-marked packet (which is the
+ // lowest viable seek target and thus the first packet useful to
+ // keep). Can be after reader_head, or not exist (=> prune_all).
if (dp->keyframe && dp->kf_seek_pts != MP_NOPTS_VALUE) {
queue->seek_start = dp->kf_seek_pts;
queue->next_prune_target = prev;
@@ -2398,8 +2411,7 @@ static int dequeue_packet(struct demux_stream *ds, struct demux_packet **res)
// Poll the demuxer queue, and if there's a packet, return it. Otherwise, just
// make the demuxer thread read packets for this stream, and if there's at
// least one packet, call the wakeup callback.
-// Unlike demux_read_packet(), this always enables readahead (except for
-// interleaved subtitles).
+// This enables readahead if it wasn't yet (except for interleaved subtitles).
// Returns:
// < 0: EOF was reached, *out_pkt=NULL
// == 0: no new packet yet, but maybe later, *out_pkt=NULL
@@ -2429,6 +2441,7 @@ int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt)
}
// Read and return any packet we find. NULL means EOF.
+// Does not work with threading (don't call demux_start_thread()).
struct demux_packet *demux_read_any_packet(struct demuxer *demuxer)
{
struct demux_internal *in = demuxer->in;