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.
This commit is contained in:
wm4 2015-08-27 23:45:02 +02:00
parent 3c86bd2bb5
commit c61675320b
1 changed files with 27 additions and 5 deletions

View File

@ -19,6 +19,7 @@
#include <assert.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <libavutil/common.h>
#include <ass/ass.h>
@ -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;
}