summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sub/dec_sub.c55
1 files changed, 41 insertions, 14 deletions
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index c7562fe014..01ba109ad0 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -240,16 +240,22 @@ static struct demux_packet *recode_packet(struct demux_packet *in,
return pkt;
}
-void sub_decode(struct dec_sub *sub, struct demux_packet *packet)
+static void decode_chain_recode(struct dec_sub *sub, struct sd **sd, int num_sd,
+ struct demux_packet *packet)
{
- if (sub->num_sd > 0) {
+ if (num_sd > 0) {
struct demux_packet *recoded = NULL;
if (sub->charset)
recoded = recode_packet(packet, sub->charset);
- decode_chain(sub->sd, sub->num_sd, recoded ? recoded : packet);
+ decode_chain(sd, num_sd, recoded ? recoded : packet);
}
}
+void sub_decode(struct dec_sub *sub, struct demux_packet *packet)
+{
+ decode_chain_recode(sub, sub->sd, sub->num_sd, packet);
+}
+
static const char *guess_sub_cp(struct packet_list *subs, const char *usercp)
{
if (!mp_charset_requires_guess(usercp))
@@ -318,7 +324,7 @@ static void fix_overlaps_and_gaps(struct packet_list *subs)
}
}
-static void add_sub_list(struct dec_sub *sub, struct packet_list *subs)
+static void add_sub_list(struct dec_sub *sub, int at, struct packet_list *subs)
{
struct sd *sd = sub_get_last_sd(sub);
assert(sd);
@@ -326,7 +332,7 @@ static void add_sub_list(struct dec_sub *sub, struct packet_list *subs)
sd->no_remove_duplicates = true;
for (int n = 0; n < subs->num_packets; n++)
- sub_decode(sub, subs->packets[n]);
+ decode_chain_recode(sub, sub->sd + at, sub->num_sd - at, 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
@@ -338,31 +344,52 @@ static void add_sub_list(struct dec_sub *sub, struct packet_list *subs)
sd->no_remove_duplicates = false;
}
+static void add_packet(struct packet_list *subs, struct demux_packet *pkt)
+{
+ pkt = demux_copy_packet(pkt);
+ talloc_steal(subs, pkt);
+ MP_TARRAY_APPEND(subs, subs->packets, subs->num_packets, pkt);
+}
+
// Read all packets from the demuxer and decode/add them. Returns false if
// there are circumstances which makes this not possible.
bool sub_read_all_packets(struct dec_sub *sub, struct sh_sub *sh)
{
struct MPOpts *opts = sub->opts;
- if (!sub_accept_packets_in_advance(sub) || sh->track)
+ if (!sub_accept_packets_in_advance(sub) || sh->track || sub->num_sd < 1)
return false;
- const char *codec = sh->gsh->codec ? sh->gsh->codec : "";
struct packet_list *subs = talloc_zero(NULL, struct packet_list);
+ // In some cases, we want to put the packets through a decoder first.
+ // Preprocess until sub->sd[preprocess].
+ int preprocess = 0;
+
+ // movtext is currently the only subtitle format that has text output,
+ // but binary input. Do charset conversion after converting to text.
+ if (sub->sd[0]->driver == &sd_movtext)
+ preprocess = 1;
+
for (;;) {
ds_get_next_pts(sh->ds);
struct demux_packet *pkt = ds_get_packet_sub(sh->ds);
if (!pkt)
break;
- pkt = demux_copy_packet(pkt);
- talloc_steal(subs, pkt);
- MP_TARRAY_APPEND(subs, subs->packets, subs->num_packets, pkt);
+ if (preprocess) {
+ decode_chain(sub->sd, preprocess, pkt);
+ while (1) {
+ pkt = get_decoded_packet(sub->sd[preprocess - 1]);
+ if (!pkt)
+ break;
+ add_packet(subs, pkt);
+ }
+ } else {
+ add_packet(subs, pkt);
+ }
}
- // Can't run auto-detection on movtext packets: it's the only codec that
- // even though it decodes to text has binary input data.
- if (opts->sub_cp && !sh->is_utf8 && strcmp(codec, "movtext") != 0)
+ if (opts->sub_cp && !sh->is_utf8)
sub->charset = guess_sub_cp(subs, opts->sub_cp);
if (sub->charset)
@@ -378,7 +405,7 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_sub *sh)
if (!opts->suboverlap_enabled)
fix_overlaps_and_gaps(subs);
- add_sub_list(sub, subs);
+ add_sub_list(sub, preprocess, subs);
talloc_free(subs);
return true;