demux: another hack to deal with track switching refresh

The demuxer cache employs a strange method to make track switching
instant with caching enabled. Normally this would mean you have to wait
until the cache has played out (and you get new packets, including
packets from the newly selected track), or you have to perform a slow
high level seek (decoding video again etc.). The strange method is that
it performs a demuxer-level seek without a high level seek so it looks
like a continuous stream to the decoder, and the newly select stream
gets packets at the current playback position. This is called a refresh
seek.

This works only if some weird heuristics work. It needs a packet "unique
ID", for which it uses either dts or pts. The value must be strictly
monotonic increasing. If this doesn't work, the referesh seek can't be
executed, and the user has to wait until the end of the cache. Sometimes
there are files that simply do not work.

In the present case, there's actually a hack that we can extend. Packets
with unset position are likely generated by the parser, and the hack
which this commit touches simply attempts to make up a new (hopefully
unique) position value, even if the value itself makes no sense. It only
ha to be deterministic.

It turns out libavcodec sometimes output packets with repeating position
values. This commit tries to handle this case too with the same hack.

Fixes: #7498
This commit is contained in:
wm4 2020-02-29 23:03:39 +01:00
parent faf24a286f
commit b31a5e3a58
1 changed files with 2 additions and 1 deletions

View File

@ -2021,7 +2021,8 @@ static void add_packet_locked(struct sh_stream *stream, demux_packet_t *dp)
if (!drop) {
// If libavformat splits packets, some packets will have pos unset, so
// make up one based on the first packet => makes refresh seeks work.
if (dp->pos < 0 && !dp->keyframe && queue->last_pos_fixup >= 0)
if ((dp->pos < 0 || dp->pos == queue->last_pos_fixup) &&
!dp->keyframe && queue->last_pos_fixup >= 0)
dp->pos = queue->last_pos_fixup + 1;
queue->last_pos_fixup = dp->pos;
}