From 30cd6327c917e3cc88db191858ddd736e5ae0c6f Mon Sep 17 00:00:00 2001 From: Miguel Borges de Freitas Date: Mon, 9 Jan 2023 22:17:18 +0000 Subject: [PATCH] libavformat/matroskadec: set fixed duration for subtitles The matroska specification states the start time and duration of subtitle entries are encoded in the block TimeStamp and BlockDuration. Furthermore, for all subtitle formats except S_HDMV/PGS the BlockDuration must always be defined and have an absolute value even if it is simply 0. ffmpeg assumes that a duration of 0 means the duration is still unknown and tries to adjust based on the next packet pts. This is wrong for all formats except S_HDMV/PGS. Since changing the semantics of duration 0 is not an option (touches too many parts of the code) this change introduces AV_PKT_FLAG_FIXED_DURATION flag which decoders might use to flag the duration of a given packet should not be changed. Signed-off-by: Miguel Borges de Freitas --- libavcodec/packet.h | 5 +++++ libavformat/demux.c | 3 ++- libavformat/matroskadec.c | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libavcodec/packet.h b/libavcodec/packet.h index f28e7e70115f1..699dcc6f79fe3 100644 --- a/libavcodec/packet.h +++ b/libavcodec/packet.h @@ -446,6 +446,11 @@ typedef struct AVPacketList { * be discarded by the decoder. I.e. Non-reference frames. */ #define AV_PKT_FLAG_DISPOSABLE 0x0010 +/** + * Flag is used to indicate packets in which the duration is absolute + * and should not be changed. + */ +#define AV_PKT_FLAG_FIXED_DURATION 0x0020 enum AVSideDataParamChangeFlags { #if FF_API_OLD_CHANNEL_LAYOUT diff --git a/libavformat/demux.c b/libavformat/demux.c index 2dfd82a63caef..471be5d3dd98e 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -914,7 +914,8 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, pktl->pkt.dts = cur_dts; if (!sti->avctx->has_b_frames) pktl->pkt.pts = cur_dts; - pktl->pkt.duration = duration; + if ((pktl->pkt.flags & AV_PKT_FLAG_FIXED_DURATION) != AV_PKT_FLAG_FIXED_DURATION) + pktl->pkt.duration = duration; } else break; cur_dts = pktl->pkt.dts + pktl->pkt.duration; diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index d582f566a214f..e887f43e1ac8a 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3673,6 +3673,10 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, pkt->pos = pos; pkt->duration = lace_duration; + if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE && + st->codecpar->codec_id != AV_CODEC_ID_HDMV_PGS_SUBTITLE) + pkt->flags |= AV_PKT_FLAG_FIXED_DURATION; + res = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); if (res < 0) { av_packet_unref(pkt);