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 <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include <libavutil/common.h>
|
#include <libavutil/common.h>
|
||||||
#include <ass/ass.h>
|
#include <ass/ass.h>
|
||||||
|
@ -39,6 +40,7 @@ struct sd_ass_priv {
|
||||||
bool is_converted;
|
bool is_converted;
|
||||||
struct sub_bitmap *parts;
|
struct sub_bitmap *parts;
|
||||||
bool flush_on_seek;
|
bool flush_on_seek;
|
||||||
|
int extend_event;
|
||||||
char last_text[500];
|
char last_text[500];
|
||||||
struct mp_image_params video_params;
|
struct mp_image_params video_params;
|
||||||
struct mp_image_params last_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);
|
struct sd_ass_priv *ctx = talloc_zero(NULL, struct sd_ass_priv);
|
||||||
sd->priv = ctx;
|
sd->priv = ctx;
|
||||||
|
|
||||||
|
ctx->extend_event = -1;
|
||||||
ctx->is_converted = sd->converted_from != NULL;
|
ctx->is_converted = sd->converted_from != NULL;
|
||||||
|
|
||||||
pthread_mutex_lock(sd->ass_lock);
|
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);
|
ass_process_data(track, packet->buffer, packet->len);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// plaintext subs
|
// plaintext subs
|
||||||
if (packet->pts == MP_NOPTS_VALUE) {
|
if (packet->pts == MP_NOPTS_VALUE) {
|
||||||
MP_WARN(sd, "Subtitle without pts, ignored\n");
|
MP_WARN(sd, "Subtitle without pts, ignored\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (packet->duration <= 0) {
|
if (ctx->extend_event >= 0 && ctx->extend_event < track->n_events) {
|
||||||
MP_WARN(sd, "Subtitle without duration or "
|
ASS_Event *event = &track->events[ctx->extend_event];
|
||||||
"duration set to 0 at pts %f, ignored\n", packet->pts);
|
if (event->Start <= ipts)
|
||||||
return;
|
event->Duration = ipts - event->Start;
|
||||||
|
ctx->extend_event = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *text = packet->buffer;
|
unsigned char *text = packet->buffer;
|
||||||
if (!sd->no_remove_duplicates) {
|
if (!sd->no_remove_duplicates) {
|
||||||
for (int i = 0; i < track->n_events; i++) {
|
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);
|
int eid = ass_alloc_event(track);
|
||||||
ASS_Event *event = track->events + eid;
|
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->Start = ipts;
|
||||||
event->Duration = iduration;
|
event->Duration = iduration;
|
||||||
event->Style = track->default_style;
|
event->Style = track->default_style;
|
||||||
|
@ -349,8 +369,10 @@ static void fix_events(struct sd *sd)
|
||||||
static void reset(struct sd *sd)
|
static void reset(struct sd *sd)
|
||||||
{
|
{
|
||||||
struct sd_ass_priv *ctx = sd->priv;
|
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);
|
ass_flush_events(ctx->ass_track);
|
||||||
|
ctx->extend_event = -1;
|
||||||
|
}
|
||||||
ctx->flush_on_seek = false;
|
ctx->flush_on_seek = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue