summaryrefslogtreecommitdiffstats
path: root/sub/sd_lavc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sub/sd_lavc.c')
-rw-r--r--sub/sd_lavc.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c
index 4fbabaf864..56377b213e 100644
--- a/sub/sd_lavc.c
+++ b/sub/sd_lavc.c
@@ -54,6 +54,7 @@ struct seekpoint {
struct sd_lavc_priv {
AVCodecContext *avctx;
+ AVRational pkt_timebase;
struct sub subs[MAX_QUEUE]; // most recent event first
struct sub_bitmap *outbitmaps;
int64_t displayed_id;
@@ -117,6 +118,22 @@ static int init(struct sd *sd)
if (!ctx)
goto error;
mp_lavc_set_extradata(ctx, sd->codec->extradata, sd->codec->extradata_size);
+ if (cid == AV_CODEC_ID_HDMV_PGS_SUBTITLE) {
+ // We don't always want to set this, because the ridiculously shitty
+ // libavcodec API will mess with certain fields (end_display_time)
+ // when setting it. On the other hand, PGS in particular needs PTS
+ // mangling. While the PGS decoder doesn't modify the timestamps (just
+ // reorder it), the ridiculously shitty libavcodec wants a timebase
+ // anyway and for no good reason. It always sets end_display_time to
+ // UINT32_MAX (which is a broken and undocumented way to say "unknown"),
+ // which coincidentally won't be overridden by the ridiculously shitty
+ // pkt_timebase code. also, Libav doesn't have the pkt_timebase field,
+ // because Libav tends to avoid _adding_ ridiculously shitty APIs.
+#if LIBAVCODEC_VERSION_MICRO >= 100
+ priv->pkt_timebase = (AVRational){1, AV_TIME_BASE};
+ ctx->pkt_timebase = priv->pkt_timebase;
+#endif
+ }
if (avcodec_open2(ctx, sub_codec, NULL) < 0)
goto error;
priv->avctx = ctx;
@@ -166,7 +183,9 @@ static void decode(struct sd *sd, struct demux_packet *packet)
AVSubtitle sub;
AVPacket pkt;
- // libavformat sets duration==0, even if the duration is unknown.
+ // libavformat sets duration==0, even if the duration is unknown. Some files
+ // also have actually subtitle packets with duration explicitly set to 0
+ // (yes, at least some of such mkv files were muxed by libavformat).
// Assume there are no bitmap subs that actually use duration==0 for
// hidden subtitle events.
if (duration == 0)
@@ -175,14 +194,15 @@ static void decode(struct sd *sd, struct demux_packet *packet)
if (pts == MP_NOPTS_VALUE)
MP_WARN(sd, "Subtitle with unknown start time.\n");
- av_init_packet(&pkt);
- pkt.data = packet->buffer;
- pkt.size = packet->len;
+ mp_set_av_packet(&pkt, packet, &priv->pkt_timebase);
int got_sub;
int res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt);
if (res < 0 || !got_sub)
return;
+ if (sub.pts != AV_NOPTS_VALUE)
+ pts = sub.pts / (double)AV_TIME_BASE;
+
if (pts != MP_NOPTS_VALUE) {
if (sub.end_display_time > sub.start_display_time &&
sub.end_display_time != UINT32_MAX)
@@ -284,7 +304,7 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts,
priv->current_pts = pts;
struct sub *current = NULL;
- for (int n = MAX_QUEUE - 1; n >= 0; n--) {
+ for (int n = 0; n < MAX_QUEUE; n++) {
struct sub *sub = &priv->subs[n];
if (!sub->valid)
continue;