From 82f2613adee9d18ad9baba6da42ba94c5dbbccbb Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 10 Jul 2019 21:38:37 +0200 Subject: command, demux: add AB-loop keyframe cache align command Helper for the ab-loop-dump-cache command, see manpage additions. This is kind of shit. Not only is this a very "special" feature, but it also vomits more messy code into the big and already bloated demux.c, and the implementation is sort of duplicated with the dump-cache code. (Except it's different.) In addition, the results sort of depend what a video player would do with the dump-cache output, or what the user wants (for example, a user might be more interested in the range of output audio, instead of the video). But hey, I don't actually need to justify it. I'm only justifying it for fun. --- demux/demux.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'demux/demux.c') diff --git a/demux/demux.c b/demux/demux.c index 19a57a7c32..a26e3a155c 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -4174,6 +4174,83 @@ int demux_cache_dump_get_status(struct demuxer *demuxer) return status; } +// Return what range demux_cache_dump_set() would (probably) yield. This is a +// conservative amount (in addition to internal consistency of this code, it +// depends on what a player will do with the resulting file). +// Use for_end==true to get the end of dumping, other the start. +// Returns NOPTS if nothing was found. +double demux_probe_cache_dump_target(struct demuxer *demuxer, double pts, + bool for_end) +{ + struct demux_internal *in = demuxer->in; + assert(demuxer == in->d_user); + + double res = MP_NOPTS_VALUE; + if (pts == MP_NOPTS_VALUE) + return pts; + + pthread_mutex_lock(&in->lock); + + pts = MP_ADD_PTS(pts, -in->ts_offset); + + // (When determining the end, look before the keyframe at pts, so subtract + // an arbitrary amount to round down.) + double seek_pts = for_end ? pts - 0.001 : pts; + int flags = 0; + struct demux_cached_range *r = find_cache_seek_range(in, seek_pts, flags); + if (r) { + if (!for_end) + adjust_cache_seek_target(in, r, &pts, &flags); + + double t[STREAM_TYPE_COUNT]; + for (int n = 0; n < STREAM_TYPE_COUNT; n++) + t[n] = MP_NOPTS_VALUE; + + for (int n = 0; n < in->num_streams; n++) { + struct demux_stream *ds = in->streams[n]->ds; + struct demux_queue *q = r->streams[n]; + + struct demux_packet *dp = find_seek_target(q, pts, flags); + if (dp) { + if (for_end) { + while (dp) { + double pdts = MP_PTS_OR_DEF(dp->dts, dp->pts); + + if (pdts != MP_NOPTS_VALUE && pdts >= pts && dp->keyframe) + break; + + t[ds->type] = MP_PTS_MAX(t[ds->type], pdts); + + dp = dp->next; + } + } else { + double start; + compute_keyframe_times(dp, &start, NULL); + start = MP_PTS_MAX(start, r->seek_start); + t[ds->type] = MP_PTS_MAX(t[ds->type], start); + } + } + } + + res = t[STREAM_VIDEO]; + if (res == MP_NOPTS_VALUE) + res = t[STREAM_AUDIO]; + if (res == MP_NOPTS_VALUE) { + for (int n = 0; n < STREAM_TYPE_COUNT; n++) { + res = t[n]; + if (res != MP_NOPTS_VALUE) + break; + } + } + } + + res = MP_ADD_PTS(res, in->ts_offset); + + pthread_mutex_unlock(&in->lock); + + return res; +} + // Used by demuxers to report the amount of transferred bytes. This is for // streams which circumvent demuxer->stream (stream statistics are handled by // demux.c itself). -- cgit v1.2.3