From e9cc6953ef45b80362619ccb008499402a58550c Mon Sep 17 00:00:00 2001 From: kaihere14 Date: Sun, 6 Sep 2026 06:27:12 +0530 Subject: [PATCH] [FIX] Warn when non-DVB caption PIDs are silently ignored MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #2333 When a program contains multiple caption-carrying PIDs of the same non-DVB codec (Teletext, ISDB, or ATSC), only one is ever decoded — every other same-type PID is silently discarded with no warning, no log line, and no indication to the user that a second language track existed. This adds a warning at the actual root cause: the DVB-only exemption in `ignore_other_stream()` and `ignore_other_sib_stream()` (`src/lib_ccx/ts_info.c`). A new static helper, `warn_ignored_caption_stream()`, prints the ignored PID and points the user to `--datapid` to recover it manually. DVB is explicitly excluded since it already has its own extra-PID handling and doesn't need this. **Scope**: this is a warning only. It does NOT add multi-PID decoding support for Teletext/ISDB/ATSC — see #2333 for why that's a separate, larger effort (per-PID decoder allocation, per-language encoder routing, and ISO-639 storage for Teletext don't exist today for non-DVB codecs). **Real broadcast sample** (two Teletext PIDs, one program — from samples.ffmpeg.org/ffmpeg-bugs/trac/ticket3514): $ ccextractor --tpages-all t3514.ts VBI/teletext stream ID 3401 (0xd49) for SID 1002 (0x3ea) VBI/teletext stream ID 3402 (0xd4a) for SID 1002 (0x3ea) Warning: Teletext caption stream ID 3402 (0xd4a) for SID 1002 (0x3ea) will be ignored - only one caption stream per program is extracted. Use --datapid 3402 to extract it in a separate run. Correct PID, correct SID. The 8 DVB subtitle PIDs in the same file stay silent, as expected. **Synthetic two-PID split** (dvbteletext.ts split across two PIDs): same correct behavior, warns on the dropped PID (202/0xca). **ISDB and ATSC branches** — verified against a constructed sample (`mixed_codecs.ts`, built from `dvbteletext.ts` by injecting two ES entries into its PMT: PID 0xca as ISDB via a data_component descriptor, PID 0xcb as ATSC via a caption_service descriptor): $ ccextractor --tpages-all mixed_codecs.ts VBI/teletext stream ID 201 (0xc9) for SID 201 (0xc9) *****ISDB subtitles detected Warning: ISDB caption stream ID 202 (0xca) for SID 201 (0xc9) will be ignored - only one caption stream per program is extracted. Use --datapid 202 to extract it in a separate run. Warning: ATSC caption stream ID 203 (0xcb) for SID 201 (0xc9) will be ignored - only one caption stream per program is extracted. Use --datapid 203 to extract it in a separate run. Teletext output (`mixed_codecs_p694.srt`, `_p765.srt`) is byte-identical to the unmodified `dvbteletext.ts` baseline — the injected PIDs change nothing except triggering the new warnings. Note: I could not source a real multi-PID ISDB recording — the one public ARIB sample I found (samples.ffmpeg.org/MPEG2/subcc, single PID) has a multi-TS-packet PMT my synthetic splitter doesn't handle, so the ISDB/ATSC branches above are exercised by a constructed sample rather than a genuine broadcast recording. Flagging this rather than implying otherwise — the Teletext path is verified on real broadcast data (see above), ISDB/ATSC are verified by construction. **DVB control** — confirms no regression: ran both a single-PID and a split two-PID DVB sample before and after the patch. No new warnings on either, and output is byte-identical (PNG counts and `diff -rq` match exactly pre- and post-patch). All decoded `.srt` files from the Teletext samples are also byte-identical to their pre-patch versions — this change only adds a print statement, no decoding logic is touched. **Caught during testing, fixed before this PR**: the first version of this warned on every video PID in every file, because 608/708 captions are internally tagged `CCX_CODEC_ATSC_CC` even though they live inside the video stream, not a separate PID (`ts_tables.c:492-498`). Fixed by excluding `CCX_STREAM_TYPE_VIDEO_MPEG2/_H264/_HEVC` from the warning. Re-verified against a European DVB file (now silent, as it should be) and a US ATSC file with real 608/708 captions in video (still silent, correct — genuine caption-only ATSC PIDs still warn correctly). **Known cosmetic issue, pre-existing, not introduced by this patch**: under `--pmt`, the ATSC warning can visually run together with a preceding debug line (`ts_tables.c:445-449` emits its `dbg_print` without a trailing newline, so whatever prints next collides with it on the same line). This only occurs with `--pmt` and would happen with any output following that debug line, not just this warning. Out of scope for this PR per its stated scope, noting it here so it isn't mistaken for something this patch caused. **Reason for this PR:** - [ ] This PR adds new functionality. - [x] This PR fixes a bug that I have personally experienced or that a real user has reported and for which a sample exists. - [ ] This PR is porting code from C to Rust. **Sanity check:** - [x] I have read and understood the contributors guide. - [x] I have checked that another pull request for this purpose does not exist. - [x] If the PR adds new functionality, I've added it to the changelog. If it's just a bug fix, I have NOT added it to the changelog. - [x] I am NOT adding new C code unless it's to fix an existing, reproducible bug. --- src/lib_ccx/ts_info.c | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/lib_ccx/ts_info.c b/src/lib_ccx/ts_info.c index 19f705766..18911e35a 100644 --- a/src/lib_ccx/ts_info.c +++ b/src/lib_ccx/ts_info.c @@ -37,13 +37,62 @@ int need_cap_info(struct ccx_demuxer *ctx, int program_number) return CCX_FALSE; } +/** + Warn once about a caption stream that is about to be discarded because it is not + the single PID that get_best_stream() selected for this program. + + DVB subtitles are deliberately excluded: extra DVB PIDs are picked up later by the + multi-language loop in process_non_multiprogram_general_loop(), so they are not lost + and must stay silent. Teletext, ISDB and ATSC caption PIDs have no such handling, so + without this notice they would disappear with no indication at all (issue #2333). + + The caller only reaches this for a stream whose ignore flag is still clear, which + keeps the message to one line per PID instead of one per demuxer iteration. +*/ +static void warn_ignored_caption_stream(struct cap_info *iter) +{ + const char *codec_name; + + /* Every video elementary stream is registered as CCX_CODEC_ATSC_CC because 608/708 + can ride inside it, so an ignored video PID is not a caption stream the user lost + and --datapid is not the way to reach it. Those PIDs also keep being fed to the + decoder when --analyze-video-stream is on. Warn only about the caption-only PIDs. */ + if (iter->stream == CCX_STREAM_TYPE_VIDEO_MPEG2 || + iter->stream == CCX_STREAM_TYPE_VIDEO_H264 || + iter->stream == CCX_STREAM_TYPE_VIDEO_HEVC) + return; + + switch (iter->codec) + { + case CCX_CODEC_TELETEXT: + codec_name = "Teletext"; + break; + case CCX_CODEC_ISDB_CC: + codec_name = "ISDB"; + break; + case CCX_CODEC_ATSC_CC: + codec_name = "ATSC"; + break; + default: + return; + } + + mprint("Warning: %s caption stream ID %u (0x%x) for SID %u (0x%x) will be ignored - only one caption stream per program is extracted.\n", + codec_name, iter->pid, iter->pid, iter->program_number, iter->program_number); + mprint(" Use --datapid %u to extract it in a separate run.\n", iter->pid); +} + void ignore_other_stream(struct ccx_demuxer *ctx, int pid) { struct cap_info *iter; list_for_each_entry(iter, &ctx->cinfo_tree.all_stream, all_stream, struct cap_info) { if (iter->pid != pid && iter->codec != CCX_CODEC_DVB) + { + if (!iter->ignore) + warn_ignored_caption_stream(iter); iter->ignore = 1; + } } } @@ -93,7 +142,11 @@ void ignore_other_sib_stream(struct cap_info *head, int pid) list_for_each_entry(iter, &head->sib_head, sib_stream, struct cap_info) { if (iter->pid != pid && iter->codec != CCX_CODEC_DVB) + { + if (!iter->ignore) + warn_ignored_caption_stream(iter); iter->ignore = 1; + } } }