diff options
-rw-r--r-- | demux/demux.c | 51 |
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 |