summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demux/demux.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 5a052fc787..94966f1fc4 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -258,7 +258,8 @@ struct demux_stream {
bool eager; // try to keep at least 1 packet queued
// if false, this stream is disabled, or passively
// read (like subtitles)
- bool refreshing;
+ bool refreshing; // finding old position after track switches
+ bool eof; // end of demuxed stream? (true if no more packets)
bool global_correct_dts;// all observed so far
bool global_correct_pos;
@@ -274,11 +275,14 @@ struct demux_stream {
double bitrate;
size_t fw_packs; // number of packets in buffer (forward)
size_t fw_bytes; // total bytes of packets in buffer (forward)
- bool eof; // end of demuxed stream? (true if no more packets)
struct demux_packet *reader_head; // points at current decoder position
bool skip_to_keyframe;
bool attached_picture_added;
+ // for refresh seeks: pos/dts of last packet returned to reader
+ int64_t last_ret_pos;
+ double last_ret_dts;
+
// for closed captions (demuxer_feed_caption)
struct sh_stream *cc;
bool ignore_eof; // ignore stream in underrun detection
@@ -537,19 +541,26 @@ static void free_empty_cached_ranges(struct demux_internal *in)
}
}
-static void ds_clear_reader_state(struct demux_stream *ds)
+static void ds_clear_reader_queue_state(struct demux_stream *ds)
{
ds->in->fw_bytes -= ds->fw_bytes;
-
ds->reader_head = NULL;
+ ds->fw_bytes = 0;
+ ds->fw_packs = 0;
ds->eof = false;
+}
+
+static void ds_clear_reader_state(struct demux_stream *ds)
+{
+ ds_clear_reader_queue_state(ds);
+
ds->base_ts = ds->last_br_ts = MP_NOPTS_VALUE;
ds->last_br_bytes = 0;
ds->bitrate = -1;
ds->skip_to_keyframe = false;
ds->attached_picture_added = false;
- ds->fw_bytes = 0;
- ds->fw_packs = 0;
+ ds->last_ret_pos = -1;
+ ds->last_ret_dts = MP_NOPTS_VALUE;
}
static void update_stream_selection_state(struct demux_internal *in,
@@ -1474,6 +1485,9 @@ static struct demux_packet *dequeue_packet(struct demux_stream *ds)
ds->fw_bytes -= bytes;
ds->in->fw_bytes -= bytes;
+ ds->last_ret_pos = pkt->pos;
+ ds->last_ret_dts = pkt->dts;
+
// The returned packet is mutated etc. and will be owned by the user.
pkt = demux_copy_packet(pkt);
if (!pkt)
@@ -2449,10 +2463,31 @@ static void initiate_refresh_seek(struct demux_internal *in,
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
+
+ bool correct_pos = ds->queue->correct_pos;
+ bool correct_dts = ds->queue->correct_dts;
+
+ // We need to re-read all packets anyway, so discard the buffered
+ // data. (In theory, we could keep the packets, and be able to use
+ // it for seeking if partially read streams are deselected again,
+ // but this causes other problems like queue overflows when
+ // selecting a new stream.)
+ ds_clear_reader_queue_state(ds);
+ clear_queue(ds->queue);
+
// Streams which didn't have any packets yet will return all packets,
// other streams return packets only starting from the last position.
- if (ds->queue->last_pos != -1 || ds->queue->last_dts != MP_NOPTS_VALUE)
- ds->refreshing |= ds->selected;
+ if (ds->selected && (ds->last_ret_pos != -1 ||
+ ds->last_ret_dts != MP_NOPTS_VALUE))
+ {
+ ds->refreshing = true;
+ ds->queue->correct_dts = correct_dts;
+ ds->queue->correct_pos = correct_pos;
+ ds->queue->last_pos = ds->last_ret_pos;
+ ds->queue->last_dts = ds->last_ret_dts;
+ }
+
+ update_seek_ranges(in->current_range);
}
start_ts -= 1.0; // small offset to get correct overlap