diff mbox series

[FFmpeg-devel,v3,1/1] avformat: Add probe_streams option

Message ID 20211012154156.1726-2-nicolas.gaullier@cji.paris
State New
Headers show
Series Add-probe_streams-option
Related show

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc success Make fate finished

Commit Message

Nicolas Gaullier Oct. 12, 2021, 3:41 p.m. UTC
Allow user to disable codec probing:
- spdif (and s337m incl. s-adm in the future) is not sub-demuxed and
  may pass-through to a muxer
- disable any stream probing in wav files (dts detection).
- mpeg-ts files missing PAT/PMT are considered invalid.

Signed-off-by: Nicolas Gaullier <nicolas.gaullier@cji.paris>
---
 doc/formats.texi            |  3 +++
 libavformat/avformat.h      |  9 +++++++++
 libavformat/mpeg.c          |  5 +++--
 libavformat/mpegts.c        | 10 ++++++----
 libavformat/options_table.h |  1 +
 libavformat/version.h       |  2 +-
 libavformat/wavdec.c        |  8 +++++---
 7 files changed, 28 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/doc/formats.texi b/doc/formats.texi
index 640b23b790..272a6a71e7 100644
--- a/doc/formats.texi
+++ b/doc/formats.texi
@@ -27,6 +27,9 @@  stream information. A higher value will enable detecting more
 information in case it is dispersed into the stream, but will increase
 latency. Must be an integer not lesser than 32. It is 5000000 by default.
 
+@item probe_streams @var{bool} (@emph{input})
+Enable codec probing if set to 1. Default is 1.
+
 @item max_probe_packets @var{integer} (@emph{input})
 Set the maximum number of buffered packets when probing a codec.
 Default is 2500 packets.
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index a2af7e9f89..daf37420d0 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1702,6 +1702,15 @@  typedef struct AVFormatContext {
      * - decoding: set by user
      */
     int max_probe_packets;
+
+    /**
+     * Enable codec probing.
+     * When disabled: always trust the descriptors and allows pass-through of data such as spdif.
+     * @note mpegts missing PAT/PMT are considered invalid if codec probing is disabled.
+     * - encoding: unused
+     * - decoding: set by user
+     */
+    int probe_streams;
 } AVFormatContext;
 
 /**
diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index ca15d9f241..f795a258d6 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -557,7 +557,7 @@  redo:
         avio_seek(s->pb, -8, SEEK_CUR);
         if (!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1))
             codec_id = AV_CODEC_ID_CAVS;
-        else
+        else if (s->probe_streams)
             request_probe= 1;
         type = AVMEDIA_TYPE_VIDEO;
     } else if (startcode == PRIVATE_STREAM_2) {
@@ -568,7 +568,8 @@  redo:
         if (m->sofdec > 0) {
             codec_id = AV_CODEC_ID_ADPCM_ADX;
             // Auto-detect AC-3
-            request_probe = 50;
+            if (s->probe_streams)
+                request_probe = 50;
         } else if (m->imkh_cctv && startcode == 0x1c0 && len > 80) {
             codec_id = AV_CODEC_ID_PCM_ALAW;
             request_probe = 50;
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 9a6bbb1c93..f9c23c49d3 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -917,7 +917,7 @@  static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
     st->codecpar->codec_tag = pes->stream_type;
 
     mpegts_find_stream_type(st, pes->stream_type, ISO_types);
-    if (pes->stream_type == 4 || pes->stream_type == 0x0f)
+    if (pes->stream->probe_streams && (pes->stream_type == 4 || pes->stream_type == 0x0f))
         sti->request_probe = 50;
     if ((prog_reg_desc == AV_RL32("HDMV") ||
          prog_reg_desc == AV_RL32("HDPR")) &&
@@ -960,7 +960,8 @@  static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
         stream_type == STREAM_TYPE_PRIVATE_DATA) {
         st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
         st->codecpar->codec_id   = AV_CODEC_ID_BIN_DATA;
-        sti->request_probe = AVPROBE_SCORE_STREAM_RETRY / 5;
+        if (pes->stream->probe_streams)
+            sti->request_probe = AVPROBE_SCORE_STREAM_RETRY / 5;
     }
 
     /* queue a context update if properties changed */
@@ -1195,7 +1196,8 @@  static int mpegts_push_data(MpegTSFilter *filter,
                         pes->stream_id != STREAM_ID_TYPE_E_STREAM) {
                         FFStream *const pes_sti = ffstream(pes->st);
                         pes->state = MPEGTS_PESHEADER;
-                        if (pes->st->codecpar->codec_id == AV_CODEC_ID_NONE && !pes_sti->request_probe) {
+                        if (pes->stream->probe_streams &&
+                            pes->st->codecpar->codec_id == AV_CODEC_ID_NONE && !pes_sti->request_probe) {
                             av_log(pes->stream, AV_LOG_TRACE,
                                     "pid=%x stream_type=%x probing\n",
                                     pes->pid,
@@ -2002,7 +2004,7 @@  int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
         av_log(fc, AV_LOG_TRACE, "reg_desc=%.4s\n", (char *)&st->codecpar->codec_tag);
         if (st->codecpar->codec_id == AV_CODEC_ID_NONE || sti->request_probe > 0) {
             mpegts_find_stream_type(st, st->codecpar->codec_tag, REGD_types);
-            if (st->codecpar->codec_tag == MKTAG('B', 'S', 'S', 'D'))
+            if (fc->probe_streams && st->codecpar->codec_tag == MKTAG('B', 'S', 'S', 'D'))
                 sti->request_probe = 50;
         }
         break;
diff --git a/libavformat/options_table.h b/libavformat/options_table.h
index 62c5bb40a3..20cf46fa25 100644
--- a/libavformat/options_table.h
+++ b/libavformat/options_table.h
@@ -106,6 +106,7 @@  static const AVOption avformat_options[] = {
 {"max_streams", "maximum number of streams", OFFSET(max_streams), AV_OPT_TYPE_INT, { .i64 = 1000 }, 0, INT_MAX, D },
 {"skip_estimate_duration_from_pts", "skip duration calculation in estimate_timings_from_pts", OFFSET(skip_estimate_duration_from_pts), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, D},
 {"max_probe_packets", "Maximum number of packets to probe a codec", OFFSET(max_probe_packets), AV_OPT_TYPE_INT, { .i64 = 2500 }, 0, INT_MAX, D },
+{"probe_streams", "enable probing for codec detection", OFFSET(probe_streams), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, D},
 {NULL},
 };
 
diff --git a/libavformat/version.h b/libavformat/version.h
index d5dd22059b..474640bb78 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@ 
 // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
 // Also please add any ticket numbers that you believe might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  59
-#define LIBAVFORMAT_VERSION_MINOR   6
+#define LIBAVFORMAT_VERSION_MINOR   7
 #define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
index 01090b6947..024d91ea2f 100644
--- a/libavformat/wavdec.c
+++ b/libavformat/wavdec.c
@@ -78,7 +78,7 @@  static const AVOption demux_options[] = {
 
 static void set_spdif(AVFormatContext *s, WAVDemuxContext *wav)
 {
-    if (CONFIG_SPDIF_DEMUXER && s->streams[0]->codecpar->codec_tag == 1) {
+    if (CONFIG_SPDIF_DEMUXER && s->probe_streams && s->streams[0]->codecpar->codec_tag == 1) {
         enum AVCodecID codec;
         int len = 1<<16;
         int ret = ffio_ensure_seekback(s->pb, len);
@@ -182,7 +182,8 @@  static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream *st)
     ret = ff_get_wav_header(s, pb, st->codecpar, size, wav->rifx);
     if (ret < 0)
         return ret;
-    handle_stream_probing(st);
+    if (s->probe_streams)
+        handle_stream_probing(st);
 
     ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW;
 
@@ -952,7 +953,8 @@  static int w64_read_header(AVFormatContext *s)
     ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
     ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);
 
-    handle_stream_probing(st);
+    if (s->probe_streams)
+        handle_stream_probing(st);
     ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW;
 
     avio_seek(pb, data_ofs, SEEK_SET);