Commit 53c4520719 for ffmpeg
commit 53c45207199542ded829856984f6894fa800c562
Author: Jun Zhao <barryjzhao@tencent.com>
Date: Sat Oct 31 17:02:42 2026 +0800
avformat/mpegtsenc: keep the hard of hearing subtitling type
The subtitling type written into the subtitling descriptor is taken from
the stream extradata whenever it holds a full record, five bytes per
service: composition page id, ancillary page id and subtitling type.
That record can come from an encoder, which cannot know dispositions, so
a stream for the hard of hearing would be written as a normal subtitle.
Replace a normal subtitling type (0x1x) with the matching one for the
hard of hearing (0x2x, same monitor aspect ratio criticality) when the
stream disposition says so. Only single-service records are adjusted:
the demuxer flags the whole stream as soon as one of several services is
for the hard of hearing, so rewriting a multi-service record would also
change the type of the other services.
Covered by fate-mpegts-dvbsub-hearing-impaired (single service) and
fate-mpegts-dvbsub-multi-service (several services).
Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index e57889cb2d..594ade3d97 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -757,7 +757,20 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
language++;
if (st->codecpar->extradata_size - extradata_copied >= 5) {
- *q++ = st->codecpar->extradata[extradata_copied + 4]; /* subtitling_type */
+ /* subtitling_type: encoders are not aware of the hard
+ * of hearing flag, so rederive it from the disposition:
+ * 0x1x is a normal subtitle, 0x2x the same subtitle for
+ * the hard of hearing. Only single-service records are
+ * adjusted: the demuxer flags the whole stream as soon
+ * as one of several services is for the hard of
+ * hearing, so rewriting a multi-service record would
+ * also change the type of the other services. */
+ uint8_t subtitling_type = st->codecpar->extradata[extradata_copied + 4];
+ if (st->codecpar->extradata_size == 5 &&
+ (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED) &&
+ (subtitling_type & 0xF0) == 0x10)
+ subtitling_type = 0x20 | (subtitling_type & 0x0F);
+ *q++ = subtitling_type;
memcpy(q, st->codecpar->extradata + extradata_copied, 4); /* composition_page_id and ancillary_page_id */
extradata_copied += 5;
q += 4;
diff --git a/tests/fate/mpegts.mak b/tests/fate/mpegts.mak
index 39600294df..fcc8f7d63c 100644
--- a/tests/fate/mpegts.mak
+++ b/tests/fate/mpegts.mak
@@ -65,6 +65,28 @@ fate-mpegts-lcevc-vvc-dual-track: CMD = stream_demux mpegts $(TARGET_SAMPLES)/lc
"" "-c:v copy -map 0:1" \
"-show_entries stream_group=index,id,nb_streams,type:stream=index,id,codec_name"
+# The subtitling descriptor must keep the type of a stream for the hard of
+# hearing (0x2x) when the encoder supplies the type itself, and must not
+# touch the types of a record holding several subtitle services.
+FATE_MPEGTS_FFMPEG_FFPROBE-$(call FRAMECRC, MPEGTS, DVBSUB, DVBSUB_ENCODER DVBSUB_PARSER MPEGTS_MUXER) += fate-mpegts-dvbsub-hearing-impaired
+fate-mpegts-dvbsub-hearing-impaired: CMD = transcode mpegts $(TARGET_SAMPLES)/sub/dvbsubtest_filter.ts mpegts \
+ "-map 0:s -c dvbsub -disposition:s:0 hearing_impaired" "-map 0:s -c copy" \
+ "-show_entries stream_disposition=hearing_impaired -of default=nw=1:nk=1"
+
+FATE_MPEGTS_FFMPEG_FFPROBE-$(call ALLYES, MPEGTS_MUXER MPEGTS_DEMUXER DVBSUB_DECODER DVBSUB_PARSER FILE_PROTOCOL) += fate-mpegts-dvbsub-multi-service
+fate-mpegts-dvbsub-multi-service: CMD = \
+ cleanfiles="$${cleanfiles} $$(target_path tests/data/fate/mpegts-dvbsub-multi-service.src.ts) \
+ $$(target_path tests/data/fate/mpegts-dvbsub-multi-service.ts)"; \
+ ffmpeg -i $(TARGET_SAMPLES)/sub/dvbsubtest_filter.ts -map 0:s -c copy \
+ -metadata:s:0 language=eng,deu -bitexact -f mpegts -y \
+ "$$(target_path tests/data/fate/mpegts-dvbsub-multi-service.src.ts)" && \
+ ffmpeg -i "$$(target_path tests/data/fate/mpegts-dvbsub-multi-service.src.ts)" \
+ -map 0:s -c copy -disposition:s:0 hearing_impaired -bitexact -f mpegts -y \
+ "$$(target_path tests/data/fate/mpegts-dvbsub-multi-service.ts)" && \
+ probe -show_entries stream_disposition=hearing_impaired -of default=nw=1:nk=1 \
+ "$$(target_path tests/data/fate/mpegts-dvbsub-multi-service.ts)"; \
+ test $$? -eq 0
+
FATE_SAMPLES_FFPROBE += $(FATE_MPEGTS_PROBE-yes)
FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_MPEGTS_FFMPEG_FFPROBE-yes)
diff --git a/tests/ref/fate/mpegts-dvbsub-hearing-impaired b/tests/ref/fate/mpegts-dvbsub-hearing-impaired
new file mode 100644
index 0000000000..7341e2046d
--- /dev/null
+++ b/tests/ref/fate/mpegts-dvbsub-hearing-impaired
@@ -0,0 +1,79 @@
+1cef36900963b9ab9aa766cbfe06e577 *tests/data/fate/mpegts-dvbsub-hearing-impaired.mpegts
+225976 tests/data/fate/mpegts-dvbsub-hearing-impaired.mpegts
+#extradata 0: 5, 0x00260022
+#tb 0: 1/90000
+#media_type 0: subtitle
+#codec_id 0: dvb_subtitle
+0, 0, 0, 0, 1168, 0xd0f89d82, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 14310, 14310, 0, 14, 0x064900eb, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 14400, 14400, 0, 1544, 0xe60f1751, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 35910, 35910, 0, 14, 0x0729010b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 36000, 36000, 0, 1658, 0xbe343093, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 66510, 66510, 0, 14, 0x0809012b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 66600, 66600, 0, 2343, 0xc68f07ef, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 120510, 120510, 0, 14, 0x08e9014b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 120600, 120600, 0, 2568, 0x0ee657b1, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 161910, 161910, 0, 14, 0x09c9016b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 162000, 162000, 0, 3422, 0xba5b63ce, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 194310, 194310, 0, 14, 0x0aa9018b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 194400, 194400, 0, 5078, 0x95b19902, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 214110, 214110, 0, 14, 0x0b8901ab, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 214200, 214200, 0, 5808, 0xc9717b89, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 300510, 300510, 0, 14, 0x0c6901cb, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 300600, 300600, 0, 6015, 0x0becbfac, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 320310, 320310, 0, 14, 0x064900eb, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 320400, 320400, 0, 6519, 0xfcd24d26, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 343710, 343710, 0, 14, 0x0729010b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 343800, 343800, 0, 7061, 0xf0320408, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 352710, 352710, 0, 14, 0x0809012b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 352800, 352800, 0, 4773, 0x66c93074, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 372510, 372510, 0, 14, 0x08e9014b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 372600, 372600, 0, 5546, 0x06052c81, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 392310, 392310, 0, 14, 0x09c9016b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 392400, 392400, 0, 5754, 0x904f7325, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 413910, 413910, 0, 14, 0x0aa9018b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 414000, 414000, 0, 6099, 0xe30cde07, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 426510, 426510, 0, 14, 0x0b8901ab, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 426600, 426600, 0, 6839, 0x770fcb6c, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 498510, 498510, 0, 14, 0x0c6901cb, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 498600, 498600, 0, 4744, 0xa91e1b41, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 520110, 520110, 0, 14, 0x064900eb, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 520200, 520200, 0, 5824, 0xcf6d782b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 550710, 550710, 0, 14, 0x0729010b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 550800, 550800, 0, 6212, 0xabf8f7cf, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 680310, 680310, 0, 14, 0x0809012b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 680400, 680400, 0, 7082, 0xd7ca10f2, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 799110, 799110, 0, 14, 0x08e9014b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 799200, 799200, 0, 5345, 0x12b2cae0, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 818910, 818910, 0, 14, 0x09c9016b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 819000, 819000, 0, 5765, 0xc7d46192, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 838710, 838710, 0, 14, 0x0aa9018b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 838800, 838800, 0, 6557, 0xcb995d30, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 892710, 892710, 0, 14, 0x0b8901ab, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 892800, 892800, 0, 7091, 0xe6ea0559, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 912510, 912510, 0, 14, 0x0c6901cb, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 912600, 912600, 0, 7305, 0xb66c404e, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 934110, 934110, 0, 14, 0x064900eb, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 934200, 934200, 0, 7590, 0x0cc2a481, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 966510, 966510, 0, 14, 0x0729010b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 966600, 966600, 0, 4629, 0xe18cfea8, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 986310, 986310, 0, 14, 0x0809012b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 986400, 986400, 0, 4785, 0x82043fc0, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1051110, 1051110, 0, 14, 0x08e9014b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1051200, 1051200, 0, 6061, 0xbde7d245, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1092510, 1092510, 0, 14, 0x09c9016b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1092600, 1092600, 0, 6301, 0x92d01a51, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1114110, 1114110, 0, 14, 0x0aa9018b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1114200, 1114200, 0, 6736, 0xbd25a134, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1123110, 1123110, 0, 14, 0x0b8901ab, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1123200, 1123200, 0, 7214, 0x7ef93c13, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1142910, 1142910, 0, 14, 0x0c6901cb, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1143000, 1143000, 0, 7366, 0x5bed7fcd, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1164510, 1164510, 0, 14, 0x064900eb, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1164600, 1164600, 0, 4564, 0x7f4c014b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1218510, 1218510, 0, 14, 0x0729010b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1218600, 1218600, 0, 4637, 0x682626b7, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1238310, 1238310, 0, 14, 0x0809012b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1238400, 1238400, 0, 5358, 0x29e30c48, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+0, 1389510, 1389510, 0, 14, 0x08e9014b, S=1, MPEGTS Stream ID, 1, 0x00bd00bd
+1
diff --git a/tests/ref/fate/mpegts-dvbsub-multi-service b/tests/ref/fate/mpegts-dvbsub-multi-service
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/tests/ref/fate/mpegts-dvbsub-multi-service
@@ -0,0 +1 @@
+0