summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
Diffstat (limited to 'sub')
-rw-r--r--sub/dec_sub.c16
-rw-r--r--sub/dec_sub.h2
-rw-r--r--sub/sd.h1
-rw-r--r--sub/sd_lavc.c33
4 files changed, 44 insertions, 8 deletions
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index c357f1d369..9261e2570d 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -415,7 +415,9 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_stream *sh)
pthread_mutex_lock(&sub->lock);
- if (!sub_accept_packets_in_advance(sub) || sub->num_sd < 1) {
+ // Converters are assumed to always accept packets in advance
+ struct sd *sd = sub_get_last_sd(sub);
+ if (!(sd && sd->driver->accept_packets_in_advance)) {
pthread_mutex_unlock(&sub->lock);
return false;
}
@@ -486,14 +488,16 @@ bool sub_read_all_packets(struct dec_sub *sub, struct sh_stream *sh)
return true;
}
-bool sub_accept_packets_in_advance(struct dec_sub *sub)
+bool sub_accepts_packet_in_advance(struct dec_sub *sub)
{
+ bool res = true;
pthread_mutex_lock(&sub->lock);
- // Converters are assumed to always accept packets in advance
- struct sd *sd = sub_get_last_sd(sub);
- bool r = sd && sd->driver->accept_packets_in_advance;
+ for (int n = 0; n < sub->num_sd; n++) {
+ if (sub->sd[n]->driver->accepts_packet)
+ res &= sub->sd[n]->driver->accepts_packet(sub->sd[n]);
+ }
pthread_mutex_unlock(&sub->lock);
- return r;
+ return res;
}
// You must call sub_lock/sub_unlock if more than 1 thread access sub.
diff --git a/sub/dec_sub.h b/sub/dec_sub.h
index b9f81a77b7..0c4d59f395 100644
--- a/sub/dec_sub.h
+++ b/sub/dec_sub.h
@@ -40,7 +40,7 @@ void sub_init_from_sh(struct dec_sub *sub, struct sh_stream *sh);
bool sub_is_initialized(struct dec_sub *sub);
bool sub_read_all_packets(struct dec_sub *sub, struct sh_stream *sh);
-bool sub_accept_packets_in_advance(struct dec_sub *sub);
+bool sub_accepts_packet_in_advance(struct dec_sub *sub);
void sub_decode(struct dec_sub *sub, struct demux_packet *packet);
void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, double pts,
struct sub_bitmaps *res);
diff --git a/sub/sd.h b/sub/sd.h
index a77028a43c..4be48fedb8 100644
--- a/sub/sd.h
+++ b/sub/sd.h
@@ -52,6 +52,7 @@ struct sd_functions {
void (*reset)(struct sd *sd);
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);
diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c
index 88c45856b4..1e6180b074 100644
--- a/sub/sd_lavc.c
+++ b/sub/sd_lavc.c
@@ -53,6 +53,7 @@ struct sd_lavc_priv {
int64_t displayed_id;
int64_t new_id;
struct mp_image_params video_params;
+ double current_pts;
};
static bool supports_format(const char *format)
@@ -116,6 +117,7 @@ static int init(struct sd *sd)
priv->avctx = ctx;
sd->priv = priv;
priv->displayed_id = -1;
+ priv->current_pts = MP_NOPTS_VALUE;
return 0;
error:
@@ -138,8 +140,10 @@ static void clear_sub(struct sub *sub)
static void alloc_sub(struct sd_lavc_priv *priv)
{
clear_sub(&priv->subs[MAX_QUEUE - 1]);
+ struct sub tmp = priv->subs[MAX_QUEUE - 1];
for (int n = MAX_QUEUE - 1; n > 0; n--)
priv->subs[n] = priv->subs[n - 1];
+ priv->subs[0] = tmp;
// clear only some fields; the memory allocs can be reused
priv->subs[0].valid = false;
priv->subs[0].count = 0;
@@ -239,8 +243,10 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts,
struct sd_lavc_priv *priv = sd->priv;
struct MPOpts *opts = sd->opts;
+ priv->current_pts = pts;
+
struct sub *current = NULL;
- for (int n = 0; n < MAX_QUEUE; n++) {
+ for (int n = MAX_QUEUE - 1; n >= 0; n--) {
struct sub *sub = &priv->subs[n];
if (!sub->valid)
continue;
@@ -297,6 +303,28 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts,
osd_rescale_bitmaps(res, insize[0], insize[1], d, video_par);
}
+static bool accepts_packet(struct sd *sd)
+{
+ struct sd_lavc_priv *priv = sd->priv;
+
+ double pts = priv->current_pts;
+ int last_needed = -1;
+ for (int n = 0; n < MAX_QUEUE; n++) {
+ struct sub *sub = &priv->subs[n];
+ if (!sub->valid)
+ continue;
+ if (pts == MP_NOPTS_VALUE ||
+ ((sub->pts == MP_NOPTS_VALUE || sub->pts >= pts) ||
+ (sub->endpts == MP_NOPTS_VALUE || pts < sub->endpts)))
+ {
+ last_needed = n;
+ }
+ }
+ // We can accept a packet if it wouldn't overflow the fixed subtitle queue.
+ // We assume that get_bitmaps() never decreases the PTS.
+ return last_needed + 1 < MAX_QUEUE;
+}
+
static void reset(struct sd *sd)
{
struct sd_lavc_priv *priv = sd->priv;
@@ -305,6 +333,8 @@ static void reset(struct sd *sd)
clear_sub(&priv->subs[n]);
// lavc might not do this right for all codecs; may need close+reopen
avcodec_flush_buffers(priv->avctx);
+
+ priv->current_pts = MP_NOPTS_VALUE;
}
static void uninit(struct sd *sd)
@@ -340,6 +370,7 @@ const struct sd_functions sd_lavc = {
.init = init,
.decode = decode,
.get_bitmaps = get_bitmaps,
+ .accepts_packet = accepts_packet,
.control = control,
.reset = reset,
.uninit = uninit,