command: add sub-start & sub-end properties

These properties contain the current subtitle's start and end times.
Can be useful to cut sample audio through the scripting interface.
This commit is contained in:
Stefano Pigozzi 2019-09-21 20:11:18 +02:00
parent 0f938b197a
commit cb32ad68f3
8 changed files with 140 additions and 7 deletions

View File

@ -1916,6 +1916,17 @@ Property list
This property is experimental and might be removed in the future.
``sub-start``
Return the current subtitle start time (in seconds). If there's multiple
current subtitles, returns the first start time. If no current subtitle is
present null is returned instead.
``sub-end``
Return the current subtitle start time (in seconds). If there's multiple
current subtitles, return the last end time. If no current subtitle is
present, or if it's present but has unknown or incorrect duration, null
is returned instead.
``playlist-pos`` (RW)
Current position on playlist. The first entry is on position 0. Writing
to the property will restart playback at the written entry.

View File

@ -2845,6 +2845,38 @@ static int mp_property_sub_text(void *ctx, struct m_property *prop,
return m_property_strdup_ro(action, arg, text);
}
static struct sd_times get_times(void *ctx, struct m_property *prop,
int action, void *arg)
{
struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE };
MPContext *mpctx = ctx;
struct track *track = mpctx->current_track[0][STREAM_SUB];
struct dec_sub *sub = track ? track->d_sub : NULL;
double pts = mpctx->playback_pts;
if (!sub || pts == MP_NOPTS_VALUE)
return res;
return sub_get_times(sub, pts);
}
static int mp_property_sub_start(void *ctx, struct m_property *prop,
int action, void *arg)
{
double start = get_times(ctx, prop, action, arg).start;
if (start == MP_NOPTS_VALUE)
return M_PROPERTY_UNAVAILABLE;
return m_property_double_ro(action, arg, start);
}
static int mp_property_sub_end(void *ctx, struct m_property *prop,
int action, void *arg)
{
double end = get_times(ctx, prop, action, arg).end;
if (end == MP_NOPTS_VALUE)
return M_PROPERTY_UNAVAILABLE;
return m_property_double_ro(action, arg, end);
}
static int mp_property_cursor_autohide(void *ctx, struct m_property *prop,
int action, void *arg)
{
@ -3548,6 +3580,8 @@ static const struct m_property mp_properties_base[] = {
{"sub-speed", mp_property_sub_speed},
{"sub-pos", mp_property_sub_pos},
{"sub-text", mp_property_sub_text},
{"sub-start", mp_property_sub_start},
{"sub-end", mp_property_sub_end},
{"vf", mp_property_vf},
{"af", mp_property_af},

View File

@ -372,6 +372,23 @@ char *sub_get_text(struct dec_sub *sub, double pts)
return text;
}
struct sd_times sub_get_times(struct dec_sub *sub, double pts)
{
pthread_mutex_lock(&sub->lock);
struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE };
pts = pts_to_subtitle(sub, pts);
sub->last_vo_pts = pts;
update_segment(sub);
if (sub->sd->driver->get_times)
res = sub->sd->driver->get_times(sub->sd, pts);
pthread_mutex_unlock(&sub->lock);
return res;
}
void sub_reset(struct dec_sub *sub)
{
pthread_mutex_lock(&sub->lock);

View File

@ -21,6 +21,11 @@ enum sd_ctrl {
SD_CTRL_SET_VIDEO_DEF_FPS,
};
struct sd_times {
double start;
double end;
};
struct attachment_list {
struct demux_attachment *entries;
int num_entries;
@ -38,6 +43,7 @@ bool sub_read_packets(struct dec_sub *sub, double video_pts);
void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, int format,
double pts, struct sub_bitmaps *res);
char *sub_get_text(struct dec_sub *sub, double pts);
struct sd_times sub_get_times(struct dec_sub *sub, double pts);
void sub_reset(struct dec_sub *sub);
void sub_select(struct dec_sub *sub, bool selected);
void sub_update_opts(struct dec_sub *sub);

View File

@ -40,6 +40,7 @@ struct sd_functions {
void (*get_bitmaps)(struct sd *sd, struct mp_osd_res dim, int format,
double pts, struct sub_bitmaps *res);
char *(*get_text)(struct sd *sd, double pts);
struct sd_times (*get_times)(struct sd *sd, double pts);
};
struct lavc_conv;

View File

@ -593,6 +593,35 @@ static char *get_text(struct sd *sd, double pts)
return ctx->last_text;
}
static struct sd_times get_times(struct sd *sd, double pts)
{
struct sd_ass_priv *ctx = sd->priv;
ASS_Track *track = ctx->ass_track;
struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE };
if (pts == MP_NOPTS_VALUE || ctx->duration_unknown)
return res;
long long ipts = find_timestamp(sd, pts);
for (int i = 0; i < track->n_events; ++i) {
ASS_Event *event = track->events + i;
if (ipts >= event->Start && ipts < event->Start + event->Duration) {
double start = event->Start / 1000.0;
double end = event->Duration == UNKNOWN_DURATION ?
MP_NOPTS_VALUE : (event->Start + event->Duration) / 1000.0;
if (res.start == MP_NOPTS_VALUE || res.start > start)
res.start = start;
if (res.end == MP_NOPTS_VALUE || res.end < end)
res.end = end;
}
}
return res;
}
static void fill_plaintext(struct sd *sd, double pts)
{
struct sd_ass_priv *ctx = sd->priv;
@ -687,6 +716,7 @@ const struct sd_functions sd_ass = {
.decode = decode,
.get_bitmaps = get_bitmaps,
.get_text = get_text,
.get_times = get_times,
.control = control,
.reset = reset,
.select = enable_output,

View File

@ -383,14 +383,8 @@ static void decode(struct sd *sd, struct demux_packet *packet)
}
}
static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
double pts, struct sub_bitmaps *res)
static struct sub *get_current(struct sd_lavc_priv *priv, double pts)
{
struct sd_lavc_priv *priv = sd->priv;
struct mp_subtitle_opts *opts = sd->opts;
priv->current_pts = pts;
struct sub *current = NULL;
for (int n = 0; n < MAX_QUEUE; n++) {
struct sub *sub = &priv->subs[n];
@ -407,6 +401,19 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
break;
}
}
return current;
}
static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
double pts, struct sub_bitmaps *res)
{
struct sd_lavc_priv *priv = sd->priv;
struct mp_subtitle_opts *opts = sd->opts;
priv->current_pts = pts;
struct sub *current = get_current(priv, pts);
if (!current)
return;
@ -483,6 +490,25 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
}
static struct sd_times get_times(struct sd *sd, double pts)
{
struct sd_lavc_priv *priv = sd->priv;
struct sd_times res = { .start = MP_NOPTS_VALUE, .end = MP_NOPTS_VALUE };
if (pts == MP_NOPTS_VALUE)
return res;
struct sub *current = get_current(priv, pts);
if (!current)
return res;
res.start = current->pts;
res.end = current->endpts;
return res;
}
static bool accepts_packet(struct sd *sd, double min_pts)
{
struct sd_lavc_priv *priv = sd->priv;
@ -622,6 +648,7 @@ const struct sd_functions sd_lavc = {
.init = init,
.decode = decode,
.get_bitmaps = get_bitmaps,
.get_times = get_times,
.accepts_packet = accepts_packet,
.control = control,
.reset = reset,

7
test/subtimes.js Normal file
View File

@ -0,0 +1,7 @@
function subtimes() {
mp.msg.info("sub-start: " + mp.get_property_number("sub-start"));
mp.msg.info("sub-end: " + mp.get_property_number("sub-end"));
mp.msg.info("sub-text: " + mp.get_property_native("sub-text"));
}
mp.add_key_binding("t", "subtimes", subtimes);