summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--DOCS/man/input.rst9
-rw-r--r--demux/demux.c77
-rw-r--r--demux/demux.h3
-rw-r--r--player/command.c22
4 files changed, 111 insertions, 0 deletions
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index fdbe4e5fd8..393ac9b9ee 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -974,6 +974,15 @@ Input Commands that are Possibly Subject to Change
The author reserves the right to remove this command if enough motivation
is found to move this functionality to a trivial Lua script.
+``ab-loop-align-cache``
+ Re-adjust the A/B loop points to the start and end within the cache the
+ ``ab-loop-dump-cache`` command will (probably) dump. Basically, it aligns
+ the times on keyframes. The guess might be off especially at the end (due to
+ granularity issues due to remuxing). If the cache shrinks in the meantime,
+ the points set by the command will not be the effective parameters either.
+
+ This command has an even more uncertain future than ``ab-loop-dump-cache``
+ and might disappear without replacement if the author decides it's useless.
Undocumented commands: ``ao-reload`` (experimental/internal).
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).
diff --git a/demux/demux.h b/demux/demux.h
index 3716f28b87..ebebd0853f 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -296,6 +296,9 @@ bool demux_cache_dump_set(struct demuxer *demuxer, double start, double end,
char *file);
int demux_cache_dump_get_status(struct demuxer *demuxer);
+double demux_probe_cache_dump_target(struct demuxer *demuxer, double pts,
+ bool for_end);
+
bool demux_is_network_cached(demuxer_t *demuxer);
void demux_report_unbuffered_read_bytes(struct demuxer *demuxer, int64_t new);
diff --git a/player/command.c b/player/command.c
index b4c2ad1201..8c4f8de5ea 100644
--- a/player/command.c
+++ b/player/command.c
@@ -5336,6 +5336,26 @@ static void cmd_ab_loop(void *p)
}
}
+static void cmd_align_cache_ab(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+
+ if (!mpctx->demuxer)
+ return;
+
+ double a = demux_probe_cache_dump_target(mpctx->demuxer,
+ mpctx->opts->ab_loop[0], false);
+ double b = demux_probe_cache_dump_target(mpctx->demuxer,
+ mpctx->opts->ab_loop[1], true);
+
+ mp_property_do("ab-loop-a", M_PROPERTY_SET, &a, mpctx);
+ mp_property_do("ab-loop-b", M_PROPERTY_SET, &b, mpctx);
+
+ // Happens to cover both properties.
+ show_property_osd(mpctx, "ab-loop-b", cmd->on_osd);
+}
+
static void cmd_drop_buffers(void *p)
{
struct mp_cmd_ctx *cmd = p;
@@ -5986,6 +6006,8 @@ const struct mp_cmd_def mp_cmds[] = {
.can_abort = true,
},
+ { "ab-loop-align-cache", cmd_align_cache_ab },
+
{0}
};