diff options
Diffstat (limited to 'sub')
-rw-r--r-- | sub/dec_sub.c | 11 | ||||
-rw-r--r-- | sub/sd.h | 3 | ||||
-rw-r--r-- | sub/sd_ass.c | 50 | ||||
-rw-r--r-- | sub/sd_lavc_conv.c | 2 |
4 files changed, 38 insertions, 28 deletions
diff --git a/sub/dec_sub.c b/sub/dec_sub.c index 451a5cab38..e7362e1f69 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -273,6 +273,7 @@ static struct demux_packet *recode_packet(struct mp_log *log, .buffer = conv.start, .len = conv.len, .pts = in->pts, + .pos = in->pos, .duration = in->duration, .avpacket = in->avpacket, // questionable, but gives us sidedata }; @@ -305,13 +306,6 @@ static void add_sub_list(struct dec_sub *sub, struct packet_list *subs) for (int n = 0; n < subs->num_packets; n++) decode_chain_recode(sub, subs->packets[n]); - - // Hack for broken FFmpeg packet format: make sd_ass keep the subtitle - // events on reset(), even if broken FFmpeg ASS packets were received - // (from sd_lavc_conv.c). Normally, these events are removed on seek/reset, - // but this is obviously unwanted in this case. - if (sd->driver->fix_events) - sd->driver->fix_events(sd); } static void add_packet(struct packet_list *subs, struct demux_packet *pkt) @@ -446,7 +440,7 @@ struct sd_conv_buffer { }; void sd_conv_add_packet(struct sd *sd, void *data, int data_len, double pts, - double duration) + double duration, int64_t pos) { if (!sd->sd_conv_buffer) sd->sd_conv_buffer = talloc_zero(sd, struct sd_conv_buffer); @@ -462,6 +456,7 @@ void sd_conv_add_packet(struct sd *sd, void *data, int data_len, double pts, .len = data_len, .pts = pts, .duration = duration, + .pos = pos, }; memcpy(pkt->buffer, data, data_len); pkt->buffer[data_len] = 0; @@ -58,7 +58,6 @@ struct sd_functions { void (*uninit)(struct sd *sd); bool (*accepts_packet)(struct sd *sd); // implicit default if NULL: true - void (*fix_events)(struct sd *sd); int (*control)(struct sd *sd, enum sd_ctrl cmd, void *arg); // decoder @@ -71,7 +70,7 @@ struct sd_functions { }; void sd_conv_add_packet(struct sd *sd, void *data, int data_len, double pts, - double duration); + double duration, int64_t pos); struct demux_packet *sd_conv_def_get_converted(struct sd *sd); void sd_conv_def_reset(struct sd *sd); void sd_conv_def_uninit(struct sd *sd); diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 4c6296b2f4..dc045996cd 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -42,11 +42,12 @@ struct sd_ass_priv { bool is_converted; bool on_top; struct sub_bitmap *parts; - bool flush_on_seek; char last_text[500]; struct mp_image_params video_params; struct mp_image_params last_params; double sub_speed; + int64_t *seen_packets; + int num_seen_packets; }; static void mangle_colors(struct sd *sd, struct sub_bitmaps *parts); @@ -130,19 +131,42 @@ static int init(struct sd *sd) return 0; } +// Test if the packet with the given file position (used as unique ID) was +// already consumed. Return false if the packet is new (and add it to the +// internal list), and return true if it was already seen. +static bool check_packet_seen(struct sd *sd, int64_t pos) +{ + struct sd_ass_priv *priv = sd->priv; + int a = 0; + int b = priv->num_seen_packets; + while (a < b) { + int mid = a + (b - a) / 2; + int64_t val = priv->seen_packets[mid]; + if (pos == val) + return true; + if (pos > val) { + a = mid + 1; + } else { + b = mid; + } + } + MP_TARRAY_INSERT_AT(priv, priv->seen_packets, priv->num_seen_packets, a, pos); + return false; +} + static void decode(struct sd *sd, struct demux_packet *packet) { struct sd_ass_priv *ctx = sd->priv; ASS_Track *track = ctx->ass_track; if (strcmp(sd->codec, "ass") == 0) { - long long ipts = lrint(packet->pts * 1000); - long long iduration = lrint(packet->duration * 1000); - ass_process_chunk(track, packet->buffer, packet->len, ipts, iduration); - return; + // Note that for this packet format, libass has an internal mechanism + // for discarding duplicate (already seen) packets. + ass_process_chunk(track, packet->buffer, packet->len, + lrint(packet->pts * 1000), + lrint(packet->duration * 1000)); } else { - // "ssa" codec ID - ctx->flush_on_seek = true; - ass_process_data(track, packet->buffer, packet->len); + if (!check_packet_seen(sd, packet->pos)) + ass_process_data(track, packet->buffer, packet->len); } } @@ -476,18 +500,11 @@ static void fill_plaintext(struct sd *sd, double pts) track->styles[track->default_style].Alignment = ctx->on_top ? 6 : 2; } -static void fix_events(struct sd *sd) -{ - struct sd_ass_priv *ctx = sd->priv; - ctx->flush_on_seek = false; -} - 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 (sd->opts->sub_clear_on_seek) ass_flush_events(ctx->ass_track); - ctx->flush_on_seek = false; } static void uninit(struct sd *sd) @@ -530,7 +547,6 @@ const struct sd_functions sd_ass = { .decode = decode, .get_bitmaps = get_bitmaps, .get_text = get_text, - .fix_events = fix_events, .control = control, .reset = reset, .uninit = uninit, diff --git a/sub/sd_lavc_conv.c b/sub/sd_lavc_conv.c index 8074cd865e..ffea1860cd 100644 --- a/sub/sd_lavc_conv.c +++ b/sub/sd_lavc_conv.c @@ -250,7 +250,7 @@ static void decode(struct sd *sd, struct demux_packet *packet) // ASS packet format, in which case pts/duration might be ignored // at a later point. sd_conv_add_packet(sd, ass_line, strlen(ass_line), - packet->pts, packet->duration); + packet->pts, packet->duration, packet->pos + i); } } |