summaryrefslogtreecommitdiffstats
path: root/demux/demux.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-07-10 21:38:37 +0200
committerwm4 <wm4@nowhere>2019-09-19 20:37:05 +0200
commit82f2613adee9d18ad9baba6da42ba94c5dbbccbb (patch)
treecfef428ed4b040c85a0ff99d53964112bcd1ec69 /demux/demux.c
parent1dd0b2fe3468f690d23049343aa03c15abb8672f (diff)
downloadmpv-82f2613adee9d18ad9baba6da42ba94c5dbbccbb.tar.bz2
mpv-82f2613adee9d18ad9baba6da42ba94c5dbbccbb.tar.xz
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.
Diffstat (limited to 'demux/demux.c')
-rw-r--r--demux/demux.c77
1 files changed, 77 insertions, 0 deletions
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).