mirror of
https://github.com/mpv-player/mpv
synced 2025-04-27 22:00:23 +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
|
The author reserves the right to remove this command if enough motivation
|
||||||
is found to move this functionality to a trivial Lua script.
|
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).
|
Undocumented commands: ``ao-reload`` (experimental/internal).
|
||||||
|
|
||||||
|
@ -4174,6 +4174,83 @@ int demux_cache_dump_get_status(struct demuxer *demuxer)
|
|||||||
return status;
|
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
|
// Used by demuxers to report the amount of transferred bytes. This is for
|
||||||
// streams which circumvent demuxer->stream (stream statistics are handled by
|
// streams which circumvent demuxer->stream (stream statistics are handled by
|
||||||
// demux.c itself).
|
// demux.c itself).
|
||||||
|
@ -296,6 +296,9 @@ bool demux_cache_dump_set(struct demuxer *demuxer, double start, double end,
|
|||||||
char *file);
|
char *file);
|
||||||
int demux_cache_dump_get_status(struct demuxer *demuxer);
|
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);
|
bool demux_is_network_cached(demuxer_t *demuxer);
|
||||||
|
|
||||||
void demux_report_unbuffered_read_bytes(struct demuxer *demuxer, int64_t new);
|
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)
|
static void cmd_drop_buffers(void *p)
|
||||||
{
|
{
|
||||||
struct mp_cmd_ctx *cmd = p;
|
struct mp_cmd_ctx *cmd = p;
|
||||||
@ -5986,6 +6006,8 @@ const struct mp_cmd_def mp_cmds[] = {
|
|||||||
.can_abort = true,
|
.can_abort = true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{ "ab-loop-align-cache", cmd_align_cache_ab },
|
||||||
|
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user