From cb32ad68f31de784a13ca5a2847143c4c37738ce Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 21 Sep 2019 20:11:18 +0200 Subject: 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. --- DOCS/man/input.rst | 11 +++++++++++ player/command.c | 34 ++++++++++++++++++++++++++++++++++ sub/dec_sub.c | 17 +++++++++++++++++ sub/dec_sub.h | 6 ++++++ sub/sd.h | 1 + sub/sd_ass.c | 30 ++++++++++++++++++++++++++++++ sub/sd_lavc.c | 41 ++++++++++++++++++++++++++++++++++------- test/subtimes.js | 7 +++++++ 8 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 test/subtimes.js diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index 52be5540df..4aba60cd8b 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -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. diff --git a/player/command.c b/player/command.c index 6239a3fa95..7db7c44ae8 100644 --- a/player/command.c +++ b/player/command.c @@ -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}, diff --git a/sub/dec_sub.c b/sub/dec_sub.c index a31cad77bc..27cab201d9 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -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); diff --git a/sub/dec_sub.h b/sub/dec_sub.h index 06d4a6127e..5449b97ad0 100644 --- a/sub/dec_sub.h +++ b/sub/dec_sub.h @@ -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); diff --git a/sub/sd.h b/sub/sd.h index 0c4dd3465b..6c3fc4e285 100644 --- a/sub/sd.h +++ b/sub/sd.h @@ -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; diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 163ffb6648..18ef961e8c 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -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, diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index 4620c8bd9b..72c89913e0 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -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, diff --git a/test/subtimes.js b/test/subtimes.js new file mode 100644 index 0000000000..7821e0b5c0 --- /dev/null +++ b/test/subtimes.js @@ -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); -- cgit v1.2.3