summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sub/dec_sub.c11
-rw-r--r--sub/sd.h3
-rw-r--r--sub/sd_ass.c50
-rw-r--r--sub/sd_lavc_conv.c2
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;
diff --git a/sub/sd.h b/sub/sd.h
index d2f22c5828..39b2970911 100644
--- a/sub/sd.h
+++ b/sub/sd.h
@@ -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);
}
}