mirror of https://github.com/mpv-player/mpv
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:
parent
3c86bd2bb5
commit
c61675320b
32
sub/sd_ass.c
32
sub/sd_ass.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue