path: root/demux
diff options
authorwm4 <wm4@nowhere>2017-11-11 05:51:17 +0100
committerwm4 <wm4@nowhere>2017-11-11 06:23:50 +0100
commit871a8a316a7437bc0daed347d9e7f9a66b5c3821 (patch)
tree560461aa41475f7039089878d6fb11cd485ca322 /demux
parent8e50dc1b4dda5d15ddf0b1cc28b907356b956512 (diff)
demux: avoid queue overflow warning when joining two ranges
If the backbuffer is much larger than the forward buffer, and if you join a small range with a large range (larger than the forward buffer), then the seek issues to the end of the range after joining will overflow the queue. Normally, read_more will be false when the forward buffer is full, but the resume seek after joining will set need_refresh to true, which forces more reading and thus triggers the overfloe warning. Attempt to fix this by not setting read_more to true on refresh seeks. Set prefetch_more instead. read_more will still be set if an A/V stream has no data. This doesn't help with the following problems related to using refresh seeks for track switching: - If the forward buffer is full, then enabling another track will obviously immediately overflow the queue, and immediately lead to marking the new track as having no more data (i.e. EOF). We could cut down the forward buffer or so, but there's no simple way to implement it. Another possibility would be dropping all buffers and trying to resume again, but this would likely be complex as well. - Subtitle tracks will not even show a warning (because they are sparse, and we have no way of telling whether a packet is missing, or there's just no packet near the current position). Before this commit, enabling an empty subtitle track would probably have overflown the queue, because ds->refreshing was never set to true. Possibly this could be solved by determining a demuxer read position, which would reflect until which PTS all subtitle packets should have been demuxed. The forward buffer limit was intended as a last safeguard to avoid excessive memory usage against badly interleaved files or decoders going crazy (up to reading the whole into memory and OOM'ing the user's system). It's not good at all to limit prefetch. Possibly solutions include having another smaller limit for prefetch, or maybe having only a total buffer limit, and discarding back buffer if more data has to be read. The current solution is making the forward buffer larger than the forward duration (--cache-secs) would require, but of course this depends on the stream's bitrate.
Diffstat (limited to 'demux')
1 files changed, 3 insertions, 1 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 342eb7fb56..6289699e56 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -1208,7 +1208,8 @@ static bool read_packet(struct demux_internal *in)
bool read_more = false, prefetch_more = false;
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
- read_more |= (ds->eager && !ds->reader_head) || ds->refreshing;
+ read_more |= ds->eager && !ds->reader_head;
+ prefetch_more |= ds->refreshing;
if (ds->eager && ds->queue->last_ts != MP_NOPTS_VALUE &&
in->min_secs > 0 && ds->base_ts != MP_NOPTS_VALUE &&
ds->queue->last_ts >= ds->base_ts)
@@ -1217,6 +1218,7 @@ static bool read_packet(struct demux_internal *in)
MP_TRACE(in, "bytes=%zd, read_more=%d prefetch_more=%d\n",
in->fw_bytes, read_more, prefetch_more);
if (in->fw_bytes >= in->max_bytes) {
+ // if we hit the limit just by prefetching, simply stop prefetching
if (!read_more)
return false;
if (!in->warned_queue_overflow) {