From c61675320b6f04684677e7064b0d6e38f6b23547 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 27 Aug 2015 23:45:02 +0200 Subject: sd_ass: assume negative durations are unknown durations, and handle them The FFmpeg can officially not distinguish between unknown subtitle durations, and subtitle durations being 0. (It documents the value 0 meaning unknown duration.) In practice, at least the LRC demuxer signals unknown subtitle durations with a negative value. Assume negative durations mean unknown duration. Show subtitles with unknown duration forever. Unless there's a subtitle event following it; then reset the duration so that it ends on the new subtitle event. Fixes #2244. --- sub/sd_ass.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/sub/sd_ass.c b/sub/sd_ass.c index f8b1180560..baec35faa9 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ struct sd_ass_priv { bool is_converted; struct sub_bitmap *parts; bool flush_on_seek; + int extend_event; char last_text[500]; struct mp_image_params video_params; struct mp_image_params last_params; @@ -65,6 +67,7 @@ static int init(struct sd *sd) struct sd_ass_priv *ctx = talloc_zero(NULL, struct sd_ass_priv); sd->priv = ctx; + ctx->extend_event = -1; ctx->is_converted = sd->converted_from != NULL; pthread_mutex_lock(sd->ass_lock); @@ -100,16 +103,19 @@ static void decode(struct sd *sd, struct demux_packet *packet) ass_process_data(track, packet->buffer, packet->len); return; } + // plaintext subs if (packet->pts == MP_NOPTS_VALUE) { MP_WARN(sd, "Subtitle without pts, ignored\n"); return; } - if (packet->duration <= 0) { - MP_WARN(sd, "Subtitle without duration or " - "duration set to 0 at pts %f, ignored\n", packet->pts); - return; + if (ctx->extend_event >= 0 && ctx->extend_event < track->n_events) { + ASS_Event *event = &track->events[ctx->extend_event]; + if (event->Start <= ipts) + event->Duration = ipts - event->Start; + ctx->extend_event = -1; } + unsigned char *text = packet->buffer; if (!sd->no_remove_duplicates) { for (int i = 0; i < track->n_events; i++) { @@ -121,6 +127,20 @@ static void decode(struct sd *sd, struct demux_packet *packet) } int eid = ass_alloc_event(track); ASS_Event *event = track->events + eid; + + if (packet->duration == 0) { + MP_WARN(sd, "Subtitle without duration or " + "duration set to 0 at pts %f.\n", packet->pts); + } + if (packet->duration < 0) { + // Assume unknown duration. The FFmpeg API is very unclear about this. + MP_WARN(sd, "Assuming subtitle without duration at pts %f\n", packet->pts); + // _If_ there's a next subtitle, the duration will be adjusted again. + // If not, show it forever. + iduration = INT_MAX; + ctx->extend_event = eid; + } + event->Start = ipts; event->Duration = iduration; event->Style = track->default_style; @@ -349,8 +369,10 @@ static void fix_events(struct sd *sd) static void reset(struct sd *sd) { struct sd_ass_priv *ctx = sd->priv; - if (ctx->flush_on_seek || sd->opts->sub_clear_on_seek) + if (ctx->flush_on_seek || sd->opts->sub_clear_on_seek) { ass_flush_events(ctx->ass_track); + ctx->extend_event = -1; + } ctx->flush_on_seek = false; } -- cgit v1.2.3