mirror of
https://github.com/mpv-player/mpv
synced 2025-01-29 19:22:48 +00:00
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.
This commit is contained in:
parent
1dd0b2fe34
commit
82f2613ade
@ -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).
|
||||
|
||||
|
@ -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).
|
||||
|
@ -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);
|
||||
|
@ -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}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user