From 56d9dafbbb1a5051a40968dec297e018d04a950f Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 25 Oct 2017 14:18:51 +0200 Subject: demux: respect timeline boundaries for cache seeks With the timeline code, a packet at the start or end of a segment can refer to an invisible frame. So it doesn't extend the seek range, and the timestamp should be clipped to the actual segment range. Also restructure recompute_keyframe_target_pts() to be hopefully less confusing. --- demux/demux.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'demux') diff --git a/demux/demux.c b/demux/demux.c index 03895610a6..39828627fc 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -557,17 +557,25 @@ static double get_refresh_seek_pts(struct demux_internal *in) // This function does not assume dp->keyframe==true, because it deals with weird // cases like apparently seeking to non-keyframes, or pruning the complete // backbuffer, which might end up with non-keyframes even at queue start. +// The caller assumption is that the first frame decoded from this packet +// position will result in a frame with the PTS returned from this function. +// (For corner cases with non-key frames, assuming those packets are skipped.) static double recompute_keyframe_target_pts(struct demux_packet *dp) { - int keyframes = 0; + bool in_keyframe_range = false; double res = MP_NOPTS_VALUE; while (dp) { - if (dp->keyframe) - keyframes++; - if (keyframes == 2) - break; - if (keyframes == 1) - res = MP_PTS_MIN(res, dp->pts); + if (dp->keyframe) { + if (in_keyframe_range) + break; + in_keyframe_range = true; + } + if (in_keyframe_range) { + double ts = dp->pts; + if (dp->segmented && (ts < dp->start || ts > dp->end)) + ts = MP_NOPTS_VALUE; + res = MP_PTS_MIN(res, ts); + } dp = dp->next; } return res; @@ -1966,6 +1974,8 @@ static int cached_demux_control(struct demux_internal *in, int cmd, void *arg) double ts = PTS_OR_DEF(ds->queue_head->dts, ds->queue_head->pts); r->ts_start = MP_PTS_MIN(r->ts_start, ts); + if (ds->queue_tail->segmented) + r->ts_max = MP_PTS_MIN(r->ts_max, ds->queue_tail->end); } } } -- cgit v1.2.3