diff mbox series

[FFmpeg-devel,10/13] avformat/mux: Add flag for "only default codecs allowed"

Message ID AS8P250MB07446C6F0A09FA8C8940802C8F332@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM
State Accepted
Headers show
Series [FFmpeg-devel,01/13] avformat/mp3enc: Improve query_codec | expand

Checks

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

Commit Message

Andreas Rheinhardt March 20, 2024, 2:12 a.m. UTC
AVOutputFormat has default codecs for audio, video and subtitle
and often these are the only codecs of this type allowed.
So add a flag to AVOutputFormat so that this can be checked generically.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavformat/ac4enc.c          | 17 ++---------------
 libavformat/adtsenc.c         |  7 ++-----
 libavformat/aeaenc.c          |  8 ++------
 libavformat/alp.c             |  9 ++-------
 libavformat/amvenc.c          |  9 +++------
 libavformat/apm.c             |  9 ++-------
 libavformat/apngenc.c         |  9 ++-------
 libavformat/argo_asf.c        |  9 ++-------
 libavformat/argo_cvg.c        |  9 ++-------
 libavformat/assenc.c          |  7 ++-----
 libavformat/bit.c             |  5 +++--
 libavformat/codec2.c          | 12 +++---------
 libavformat/gif.c             |  9 ++-------
 libavformat/ilbc.c            |  8 ++------
 libavformat/kvag.c            |  9 ++-------
 libavformat/microdvdenc.c     |  8 ++------
 libavformat/mux.c             | 11 +++++++++--
 libavformat/mux.h             |  9 +++++++++
 libavformat/mux_utils.c       |  2 ++
 libavformat/rcwtenc.c         |  8 ++------
 libavformat/sccenc.c          |  9 ++-------
 libavformat/ttmlenc.c         |  8 ++------
 libavformat/vc1testenc.c      |  7 ++-----
 libavformat/webpenc.c         | 10 +++-------
 libavformat/webvttenc.c       |  9 ++-------
 libavformat/westwood_audenc.c | 10 ++--------
 libavformat/wvenc.c           | 14 ++------------
 27 files changed, 72 insertions(+), 169 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/ac4enc.c b/libavformat/ac4enc.c
index 02b8d4d976..0505b05147 100644
--- a/libavformat/ac4enc.c
+++ b/libavformat/ac4enc.c
@@ -19,7 +19,6 @@ 
  */
 
 #include "libavcodec/codec_id.h"
-#include "libavcodec/codec_par.h"
 #include "libavcodec/packet.h"
 #include "libavutil/crc.h"
 #include "libavutil/opt.h"
@@ -31,18 +30,6 @@  typedef struct AC4Context {
     int write_crc;
 } AC4Context;
 
-static int ac4_init(AVFormatContext *s)
-{
-    AVCodecParameters *par = s->streams[0]->codecpar;
-
-    if (par->codec_id != AV_CODEC_ID_AC4) {
-        av_log(s, AV_LOG_ERROR, "Only one AC-4 stream can be muxed by the AC-4 muxer\n");
-        return AVERROR(EINVAL);
-    }
-
-    return 0;
-}
-
 static int ac4_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     AC4Context *ac4 = s->priv_data;
@@ -96,8 +83,8 @@  const FFOutputFormat ff_ac4_muxer = {
     .p.audio_codec     = AV_CODEC_ID_AC4,
     .p.video_codec     = AV_CODEC_ID_NONE,
     .p.subtitle_codec  = AV_CODEC_ID_NONE,
-    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
-    .init              = ac4_init,
+    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                         FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .write_packet      = ac4_write_packet,
     .p.priv_class      = &ac4_muxer_class,
     .p.flags           = AVFMT_NOTIMESTAMPS,
diff --git a/libavformat/adtsenc.c b/libavformat/adtsenc.c
index 7eaf91630c..0671224fc2 100644
--- a/libavformat/adtsenc.c
+++ b/libavformat/adtsenc.c
@@ -106,10 +106,6 @@  static int adts_init(AVFormatContext *s)
     ADTSContext *adts = s->priv_data;
     AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (par->codec_id != AV_CODEC_ID_AAC) {
-        av_log(s, AV_LOG_ERROR, "Only AAC streams can be muxed by the ADTS muxer\n");
-        return AVERROR(EINVAL);
-    }
     if (par->extradata_size > 0)
         return adts_decode_extradata(s, adts, par->extradata,
                                      par->extradata_size);
@@ -242,7 +238,8 @@  const FFOutputFormat ff_adts_muxer = {
     .p.audio_codec     = AV_CODEC_ID_AAC,
     .p.video_codec     = AV_CODEC_ID_NONE,
     .p.subtitle_codec  = AV_CODEC_ID_NONE,
-    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                         FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .init              = adts_init,
     .write_header      = adts_write_header,
     .write_packet      = adts_write_packet,
diff --git a/libavformat/aeaenc.c b/libavformat/aeaenc.c
index 3303d108a5..f7969526f4 100644
--- a/libavformat/aeaenc.c
+++ b/libavformat/aeaenc.c
@@ -37,11 +37,6 @@  static int aea_write_header(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
-    if (st->codecpar->codec_id != AV_CODEC_ID_ATRAC1) {
-        av_log(s, AV_LOG_ERROR, "AEA can only store ATRAC1 streams, %s was found.\n", avcodec_get_name(st->codecpar->codec_id));
-        return AVERROR(EINVAL);
-    }
-
     if (st->codecpar->sample_rate != 44100) {
         av_log(s, AV_LOG_ERROR, "Invalid sample rate (%d) AEA only supports 44.1kHz.\n", st->codecpar->sample_rate);
         return AVERROR(EINVAL);
@@ -105,7 +100,8 @@  const FFOutputFormat ff_aea_muxer = {
     .p.video_codec    = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
 
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .write_header     = aea_write_header,
     .write_packet     = ff_raw_write_packet,
     .write_trailer    = aea_write_trailer,
diff --git a/libavformat/alp.c b/libavformat/alp.c
index 9d507cb310..ad8e160223 100644
--- a/libavformat/alp.c
+++ b/libavformat/alp.c
@@ -191,12 +191,6 @@  static int alp_write_init(AVFormatContext *s)
 
     par = s->streams[0]->codecpar;
 
-    if (par->codec_id != AV_CODEC_ID_ADPCM_IMA_ALP) {
-        av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
-               avcodec_get_name(par->codec_id));
-        return AVERROR(EINVAL);
-    }
-
     if (par->ch_layout.nb_channels > 2) {
         av_log(s, AV_LOG_ERROR, "A maximum of 2 channels are supported\n");
         return AVERROR(EINVAL);
@@ -295,7 +289,8 @@  const FFOutputFormat ff_alp_muxer = {
     .p.video_codec  = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
     .p.priv_class   = &alp_muxer_class,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .init           = alp_write_init,
     .write_header   = alp_write_header,
     .write_packet   = ff_raw_write_packet,
diff --git a/libavformat/amvenc.c b/libavformat/amvenc.c
index 9fcc09add2..5ff4f69cfa 100644
--- a/libavformat/amvenc.c
+++ b/libavformat/amvenc.c
@@ -113,11 +113,7 @@  static av_cold int amv_init(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
-    if (ast->codecpar->codec_id != AV_CODEC_ID_ADPCM_IMA_AMV) {
-        av_log(s, AV_LOG_ERROR, "Second AMV stream must be %s\n",
-                avcodec_get_name(AV_CODEC_ID_ADPCM_IMA_AMV));
-        return AVERROR(EINVAL);
-    }
+    av_assert1(ast->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_AMV);
 
     /* These files are broken-enough as they are. They shouldn't be streamed. */
     if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
@@ -411,7 +407,8 @@  const FFOutputFormat ff_amv_muxer = {
     .p.audio_codec  = AV_CODEC_ID_ADPCM_IMA_AMV,
     .p.video_codec  = AV_CODEC_ID_AMV,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .init           = amv_init,
     .deinit         = amv_deinit,
     .write_header   = amv_write_header,
diff --git a/libavformat/apm.c b/libavformat/apm.c
index 89401dcf5b..98c5439738 100644
--- a/libavformat/apm.c
+++ b/libavformat/apm.c
@@ -217,12 +217,6 @@  static int apm_write_init(AVFormatContext *s)
 {
     AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (par->codec_id != AV_CODEC_ID_ADPCM_IMA_APM) {
-        av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
-               avcodec_get_name(par->codec_id));
-        return AVERROR(EINVAL);
-    }
-
     if (par->ch_layout.nb_channels > 2) {
         av_log(s, AV_LOG_ERROR, "APM files only support up to 2 channels\n");
         return AVERROR(EINVAL);
@@ -305,7 +299,8 @@  const FFOutputFormat ff_apm_muxer = {
     .p.audio_codec  = AV_CODEC_ID_ADPCM_IMA_APM,
     .p.video_codec  = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .init           = apm_write_init,
     .write_header   = apm_write_header,
     .write_packet   = ff_raw_write_packet,
diff --git a/libavformat/apngenc.c b/libavformat/apngenc.c
index 79b0dbf0f7..4d0438f824 100644
--- a/libavformat/apngenc.c
+++ b/libavformat/apngenc.c
@@ -84,12 +84,6 @@  static int apng_write_header(AVFormatContext *format_context)
     APNGMuxContext *apng = format_context->priv_data;
     AVCodecParameters *par = format_context->streams[0]->codecpar;
 
-    if (format_context->streams[0]->codecpar->codec_id   != AV_CODEC_ID_APNG) {
-        av_log(format_context, AV_LOG_ERROR,
-               "APNG muxer supports only a single video APNG stream.\n");
-        return AVERROR(EINVAL);
-    }
-
     if (apng->last_delay.num > UINT16_MAX || apng->last_delay.den > UINT16_MAX) {
         av_reduce(&apng->last_delay.num, &apng->last_delay.den,
                   apng->last_delay.num, apng->last_delay.den, UINT16_MAX);
@@ -314,7 +308,8 @@  const FFOutputFormat ff_apng_muxer = {
     .p.audio_codec  = AV_CODEC_ID_NONE,
     .p.video_codec  = AV_CODEC_ID_APNG,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .write_header   = apng_write_header,
     .write_packet   = apng_write_packet,
     .write_trailer  = apng_write_trailer,
diff --git a/libavformat/argo_asf.c b/libavformat/argo_asf.c
index 28e3844394..61bfc6de1f 100644
--- a/libavformat/argo_asf.c
+++ b/libavformat/argo_asf.c
@@ -290,12 +290,6 @@  static int argo_asf_write_init(AVFormatContext *s)
     ArgoASFMuxContext *ctx = s->priv_data;
     const AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (par->codec_id != AV_CODEC_ID_ADPCM_ARGO) {
-        av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
-               avcodec_get_name(par->codec_id));
-        return AVERROR(EINVAL);
-    }
-
     if (ctx->version_major == 1 && ctx->version_minor == 1 && par->sample_rate != 22050) {
         av_log(s, AV_LOG_ERROR, "ASF v1.1 files only support a sample rate of 22050\n");
         return AVERROR(EINVAL);
@@ -476,7 +470,8 @@  const FFOutputFormat ff_argo_asf_muxer = {
     .p.video_codec  = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
     .p.priv_class   = &argo_asf_muxer_class,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .init           = argo_asf_write_init,
     .write_header   = argo_asf_write_header,
     .write_packet   = argo_asf_write_packet,
diff --git a/libavformat/argo_cvg.c b/libavformat/argo_cvg.c
index aacc34daeb..5db2a85dd8 100644
--- a/libavformat/argo_cvg.c
+++ b/libavformat/argo_cvg.c
@@ -271,12 +271,6 @@  static int argo_cvg_write_init(AVFormatContext *s)
     ArgoCVGMuxContext *ctx = s->priv_data;
     const AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (par->codec_id != AV_CODEC_ID_ADPCM_PSX) {
-        av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
-               avcodec_get_name(par->codec_id));
-        return AVERROR(EINVAL);
-    }
-
     if (par->ch_layout.nb_channels != 1) {
         av_log(s, AV_LOG_ERROR, "CVG files only support 1 channel\n");
         return AVERROR(EINVAL);
@@ -403,7 +397,8 @@  const FFOutputFormat ff_argo_cvg_muxer = {
     .p.video_codec  = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
     .p.priv_class   = &argo_cvg_muxer_class,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .init           = argo_cvg_write_init,
     .write_header   = argo_cvg_write_header,
     .write_packet   = argo_cvg_write_packet,
diff --git a/libavformat/assenc.c b/libavformat/assenc.c
index c23c77acda..7b474a6005 100644
--- a/libavformat/assenc.c
+++ b/libavformat/assenc.c
@@ -50,10 +50,6 @@  static int write_header(AVFormatContext *s)
     ASSContext *ass = s->priv_data;
     AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (par->codec_id != AV_CODEC_ID_ASS) {
-        av_log(s, AV_LOG_ERROR, "Exactly one ASS/SSA stream is needed.\n");
-        return AVERROR(EINVAL);
-    }
     avpriv_set_pts_info(s->streams[0], 64, 1, 100);
     if (par->extradata_size > 0) {
         size_t header_size = par->extradata_size;
@@ -241,7 +237,8 @@  const FFOutputFormat ff_ass_muxer = {
     .p.video_codec    = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_ASS,
     .p.flags          = AVFMT_GLOBALHEADER | AVFMT_NOTIMESTAMPS | AVFMT_TS_NONSTRICT,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .p.priv_class     = &ass_class,
     .priv_data_size = sizeof(ASSContext),
     .write_header   = write_header,
diff --git a/libavformat/bit.c b/libavformat/bit.c
index 81a954c392..cd088b87ff 100644
--- a/libavformat/bit.c
+++ b/libavformat/bit.c
@@ -129,7 +129,7 @@  static int write_header(AVFormatContext *s)
 {
     AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if ((par->codec_id != AV_CODEC_ID_G729) || par->ch_layout.nb_channels != 1) {
+    if (par->ch_layout.nb_channels != 1) {
         av_log(s, AV_LOG_ERROR,
                "only codec g729 with 1 channel is supported by this format\n");
         return AVERROR(EINVAL);
@@ -168,7 +168,8 @@  const FFOutputFormat ff_bit_muxer = {
     .p.audio_codec  = AV_CODEC_ID_G729,
     .p.video_codec  = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .write_header = write_header,
     .write_packet = write_packet,
 };
diff --git a/libavformat/codec2.c b/libavformat/codec2.c
index e49408e0fb..dcc3ed9e59 100644
--- a/libavformat/codec2.c
+++ b/libavformat/codec2.c
@@ -214,14 +214,7 @@  static int codec2_read_packet(AVFormatContext *s, AVPacket *pkt)
 
 static int codec2_write_header(AVFormatContext *s)
 {
-    AVStream *st;
-
-    if (s->streams[0]->codecpar->codec_id != AV_CODEC_ID_CODEC2) {
-        av_log(s, AV_LOG_ERROR, ".c2 files must have exactly one codec2 stream\n");
-        return AVERROR(EINVAL);
-    }
-
-    st = s->streams[0];
+    AVStream *st = s->streams[0];
 
     if (st->codecpar->extradata_size != CODEC2_EXTRADATA_SIZE) {
         av_log(s, AV_LOG_ERROR, ".c2 files require exactly %i bytes of extradata (got %i)\n",
@@ -319,7 +312,8 @@  const FFOutputFormat ff_codec2_muxer = {
     .p.video_codec  = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
     .p.flags        = AVFMT_NOTIMESTAMPS,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .write_header   = codec2_write_header,
     .write_packet   = ff_raw_write_packet,
 };
diff --git a/libavformat/gif.c b/libavformat/gif.c
index fe45637814..8264e118c6 100644
--- a/libavformat/gif.c
+++ b/libavformat/gif.c
@@ -42,12 +42,6 @@  typedef struct GIFContext {
 
 static int gif_write_header(AVFormatContext *s)
 {
-    if (s->streams[0]->codecpar->codec_id   != AV_CODEC_ID_GIF) {
-        av_log(s, AV_LOG_ERROR,
-               "GIF muxer supports only a single video GIF stream.\n");
-        return AVERROR(EINVAL);
-    }
-
     avpriv_set_pts_info(s->streams[0], 64, 1, 100);
 
     return 0;
@@ -212,7 +206,8 @@  const FFOutputFormat ff_gif_muxer = {
     .p.audio_codec  = AV_CODEC_ID_NONE,
     .p.video_codec  = AV_CODEC_ID_GIF,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .write_header   = gif_write_header,
     .write_packet   = gif_write_packet,
     .write_trailer  = gif_write_trailer,
diff --git a/libavformat/ilbc.c b/libavformat/ilbc.c
index 2e102a4be7..a24aa3da9d 100644
--- a/libavformat/ilbc.c
+++ b/libavformat/ilbc.c
@@ -35,11 +35,6 @@  static int ilbc_write_header(AVFormatContext *s)
     AVIOContext *pb = s->pb;
     AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (par->codec_id != AV_CODEC_ID_ILBC) {
-        av_log(s, AV_LOG_ERROR, "Unsupported codec\n");
-        return AVERROR(EINVAL);
-    }
-
     if (par->block_align == 50) {
         avio_write(pb, mode30_header, sizeof(mode30_header) - 1);
     } else if (par->block_align == 38) {
@@ -125,7 +120,8 @@  const FFOutputFormat ff_ilbc_muxer = {
     .p.audio_codec  = AV_CODEC_ID_ILBC,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
     .p.flags        = AVFMT_NOTIMESTAMPS,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .write_header = ilbc_write_header,
     .write_packet = ff_raw_write_packet,
 };
diff --git a/libavformat/kvag.c b/libavformat/kvag.c
index 2053f4730d..1d0aee0994 100644
--- a/libavformat/kvag.c
+++ b/libavformat/kvag.c
@@ -131,12 +131,6 @@  static int kvag_write_init(AVFormatContext *s)
 {
     AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (par->codec_id != AV_CODEC_ID_ADPCM_IMA_SSI) {
-        av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
-               avcodec_get_name(par->codec_id));
-        return AVERROR(EINVAL);
-    }
-
     if (par->ch_layout.nb_channels > 2) {
         av_log(s, AV_LOG_ERROR, "KVAG files only support up to 2 channels\n");
         return AVERROR(EINVAL);
@@ -190,7 +184,8 @@  const FFOutputFormat ff_kvag_muxer = {
     .p.audio_codec  = AV_CODEC_ID_ADPCM_IMA_SSI,
     .p.video_codec  = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_NONE,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .init           = kvag_write_init,
     .write_header   = kvag_write_header,
     .write_packet   = ff_raw_write_packet,
diff --git a/libavformat/microdvdenc.c b/libavformat/microdvdenc.c
index b9cadb8be4..d4910ecf71 100644
--- a/libavformat/microdvdenc.c
+++ b/libavformat/microdvdenc.c
@@ -29,11 +29,6 @@  static int microdvd_write_header(struct AVFormatContext *s)
     AVCodecParameters *par = s->streams[0]->codecpar;
     AVRational framerate = s->streams[0]->avg_frame_rate;
 
-    if (par->codec_id != AV_CODEC_ID_MICRODVD) {
-        av_log(s, AV_LOG_ERROR, "Exactly one MicroDVD stream is needed.\n");
-        return -1;
-    }
-
     if (par->extradata && par->extradata_size > 0) {
         avio_write(s->pb, "{DEFAULT}{}", 11);
         avio_write(s->pb, par->extradata, par->extradata_size);
@@ -65,7 +60,8 @@  const FFOutputFormat ff_microdvd_muxer = {
     .p.video_codec    = AV_CODEC_ID_NONE,
     .p.audio_codec    = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_MICRODVD,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .write_header   = microdvd_write_header,
     .write_packet   = microdvd_write_packet,
 };
diff --git a/libavformat/mux.c b/libavformat/mux.c
index 134c2875b6..f23eb0188d 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -268,7 +268,7 @@  static int init_muxer(AVFormatContext *s, AVDictionary **options)
             }
             break;
         }
-        if (of->flags_internal & FF_OFMT_FLAG_MAX_ONE_OF_EACH) {
+        if (of->flags_internal & (FF_OFMT_FLAG_MAX_ONE_OF_EACH | FF_OFMT_FLAG_ONLY_DEFAULT_CODECS)) {
             enum AVCodecID default_codec_id = AV_CODEC_ID_NONE;
             unsigned nb;
             if ((unsigned)par->codec_type < FF_ARRAY_ELEMS(default_codec_offsets)) {
@@ -276,7 +276,14 @@  static int init_muxer(AVFormatContext *s, AVDictionary **options)
                 if (default_codec_offsets[par->codec_type])
                     default_codec_id = *(const enum AVCodecID*)((const char*)of + default_codec_offsets[par->codec_type]);
             }
-            if (default_codec_id == AV_CODEC_ID_NONE || nb > 1) {
+            if (of->flags_internal & FF_OFMT_FLAG_ONLY_DEFAULT_CODECS &&
+                default_codec_id != AV_CODEC_ID_NONE && par->codec_id != default_codec_id) {
+                av_log(s, AV_LOG_ERROR, "%s muxer supports only codec %s for type %s\n",
+                       of->p.name, avcodec_get_name(default_codec_id), av_get_media_type_string(par->codec_type));
+                ret = AVERROR(EINVAL);
+                goto fail;
+            } else if (default_codec_id == AV_CODEC_ID_NONE ||
+                       (of->flags_internal & FF_OFMT_FLAG_MAX_ONE_OF_EACH && nb > 1)) {
                 const char *type = av_get_media_type_string(par->codec_type);
                 av_log(s, AV_LOG_ERROR, "%s muxer does not support %s stream of type %s\n",
                        of->p.name, default_codec_id == AV_CODEC_ID_NONE ? "any" : "more than one",
diff --git a/libavformat/mux.h b/libavformat/mux.h
index 71ee5fd06b..1f386e4488 100644
--- a/libavformat/mux.h
+++ b/libavformat/mux.h
@@ -50,6 +50,15 @@  struct AVDeviceInfoList;
  * This flag is incompatible with FF_OFMT_FLAG_SUPPORT_ATTACHMENTS.
  */
 #define FF_OFMT_FLAG_MAX_ONE_OF_EACH                (1 << 2)
+/**
+ * If this flag is set, then the only permitted audio/video/subtitle
+ * codec ids are AVOutputFormat.audio/video/subtitle_codec;
+ * if any of the latter is unset (i.e. equal to AV_CODEC_ID_NONE),
+ * then no stream of the corresponding type is supported.
+ * In addition, codec types without default codec field
+ * are disallowed.
+ */
+#define FF_OFMT_FLAG_ONLY_DEFAULT_CODECS            (1 << 3)
 
 typedef struct FFOutputFormat {
     /**
diff --git a/libavformat/mux_utils.c b/libavformat/mux_utils.c
index 8a0ad4c9aa..ed1242a6a2 100644
--- a/libavformat/mux_utils.c
+++ b/libavformat/mux_utils.c
@@ -44,6 +44,8 @@  int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,
                   codec_id == ofmt->audio_codec ||
                   codec_id == ofmt->subtitle_codec))
             return 1;
+        else if (ffofmt(ofmt)->flags_internal & FF_OFMT_FLAG_ONLY_DEFAULT_CODECS)
+            return 0;
         else if (ffofmt(ofmt)->flags_internal & FF_OFMT_FLAG_MAX_ONE_OF_EACH) {
             enum AVMediaType type = avcodec_get_type(codec_id);
             switch (type) {
diff --git a/libavformat/rcwtenc.c b/libavformat/rcwtenc.c
index 4ccd7b93c8..f2459ef1d3 100644
--- a/libavformat/rcwtenc.c
+++ b/libavformat/rcwtenc.c
@@ -84,11 +84,6 @@  static void rcwt_flush_cluster(AVFormatContext *avf)
 
 static int rcwt_write_header(AVFormatContext *avf)
 {
-    if (avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_EIA_608) {
-        av_log(avf, AV_LOG_ERROR, "RCWT supports only CC (608/708)\n");
-        return AVERROR(EINVAL);
-    }
-
     avpriv_set_pts_info(avf->streams[0], 64, 1, 1000);
 
     /* magic number */
@@ -169,7 +164,8 @@  const FFOutputFormat ff_rcwt_muxer = {
     .p.video_codec      = AV_CODEC_ID_NONE,
     .p.audio_codec      = AV_CODEC_ID_NONE,
     .p.subtitle_codec   = AV_CODEC_ID_EIA_608,
-    .flags_internal     = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal     = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                          FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .priv_data_size     = sizeof(RCWTContext),
     .write_header       = rcwt_write_header,
     .write_packet       = rcwt_write_packet,
diff --git a/libavformat/sccenc.c b/libavformat/sccenc.c
index 040d1ac96c..ced7208c12 100644
--- a/libavformat/sccenc.c
+++ b/libavformat/sccenc.c
@@ -35,12 +35,6 @@  static int scc_write_header(AVFormatContext *avf)
 {
     SCCContext *scc = avf->priv_data;
 
-    if (avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_EIA_608) {
-        av_log(avf, AV_LOG_ERROR,
-               "Unsupported subtitles codec: %s\n",
-               avcodec_get_name(avf->streams[0]->codecpar->codec_id));
-        return AVERROR(EINVAL);
-    }
     avpriv_set_pts_info(avf->streams[0], 64, 1, 1000);
     avio_printf(avf->pb, "Scenarist_SCC V1.0\n");
 
@@ -114,7 +108,8 @@  const FFOutputFormat ff_scc_muxer = {
     .p.video_codec    = AV_CODEC_ID_NONE,
     .p.audio_codec    = AV_CODEC_ID_NONE,
     .p.subtitle_codec = AV_CODEC_ID_EIA_608,
-    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal   = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                        FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .priv_data_size = sizeof(SCCContext),
     .write_header   = scc_write_header,
     .write_packet   = scc_write_packet,
diff --git a/libavformat/ttmlenc.c b/libavformat/ttmlenc.c
index 0af82d5753..af2e2b85a5 100644
--- a/libavformat/ttmlenc.c
+++ b/libavformat/ttmlenc.c
@@ -126,11 +126,6 @@  static int ttml_write_header(AVFormatContext *ctx)
     TTMLMuxContext *ttml_ctx = ctx->priv_data;
     ttml_ctx->document_written = 0;
 
-    if (ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_TTML) {
-        av_log(ctx, AV_LOG_ERROR, "Exactly one TTML stream is required!\n");
-        return AVERROR(EINVAL);
-    }
-
     {
         AVStream    *st = ctx->streams[0];
         AVIOContext *pb = ctx->pb;
@@ -226,7 +221,8 @@  const FFOutputFormat ff_ttml_muxer = {
     .p.video_codec     = AV_CODEC_ID_NONE,
     .p.audio_codec     = AV_CODEC_ID_NONE,
     .p.subtitle_codec  = AV_CODEC_ID_TTML,
-    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                         FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
     .write_header      = ttml_write_header,
     .write_packet      = ttml_write_packet,
     .write_trailer     = ttml_write_trailer,
diff --git a/libavformat/vc1testenc.c b/libavformat/vc1testenc.c
index 6b4cbd1152..40d764c4de 100644
--- a/libavformat/vc1testenc.c
+++ b/libavformat/vc1testenc.c
@@ -31,10 +31,6 @@  static int vc1test_write_header(AVFormatContext *s)
     AVCodecParameters *par = s->streams[0]->codecpar;
     AVIOContext *pb = s->pb;
 
-    if (par->codec_id != AV_CODEC_ID_WMV3) {
-        av_log(s, AV_LOG_ERROR, "Only WMV3 is accepted!\n");
-        return -1;
-    }
     avio_wl24(pb, 0); //frames count will be here
     avio_w8(pb, 0xC5);
     avio_wl32(pb, 4);
@@ -92,5 +88,6 @@  const FFOutputFormat ff_vc1t_muxer = {
     .write_header      = vc1test_write_header,
     .write_packet      = vc1test_write_packet,
     .write_trailer     = vc1test_write_trailer,
-    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                         FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
 };
diff --git a/libavformat/webpenc.c b/libavformat/webpenc.c
index 85074ae315..1c5b93e0ab 100644
--- a/libavformat/webpenc.c
+++ b/libavformat/webpenc.c
@@ -38,15 +38,10 @@  typedef struct WebpContext{
 static int webp_init(AVFormatContext *s)
 {
     WebpContext *const w = s->priv_data;
-    AVStream *st;
+    AVStream *st = s->streams[0];
 
     w->last_pkt = ffformatcontext(s)->pkt;
 
-    st = s->streams[0];
-    if (st->codecpar->codec_id != AV_CODEC_ID_WEBP) {
-        av_log(s, AV_LOG_ERROR, "Only WebP is supported\n");
-        return AVERROR(EINVAL);
-    }
     avpriv_set_pts_info(st, 24, 1, 1000);
 
     return 0;
@@ -233,5 +228,6 @@  const FFOutputFormat ff_webp_muxer = {
     .write_trailer  = webp_write_trailer,
     .p.priv_class   = &webp_muxer_class,
     .p.flags        = AVFMT_VARIABLE_FPS,
-    .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                      FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
 };
diff --git a/libavformat/webvttenc.c b/libavformat/webvttenc.c
index 12a4b776dc..e71a6224ae 100644
--- a/libavformat/webvttenc.c
+++ b/libavformat/webvttenc.c
@@ -47,14 +47,8 @@  static void webvtt_write_time(AVIOContext *pb, int64_t millisec)
 static int webvtt_write_header(AVFormatContext *ctx)
 {
     AVStream     *s = ctx->streams[0];
-    AVCodecParameters *par = ctx->streams[0]->codecpar;
     AVIOContext *pb = ctx->pb;
 
-    if (par->codec_id != AV_CODEC_ID_WEBVTT) {
-        av_log(ctx, AV_LOG_ERROR, "Exactly one WebVTT stream is needed.\n");
-        return AVERROR(EINVAL);
-    }
-
     avpriv_set_pts_info(s, 64, 1, 1000);
 
     avio_printf(pb, "WEBVTT\n");
@@ -114,5 +108,6 @@  const FFOutputFormat ff_webvtt_muxer = {
     .p.subtitle_codec  = AV_CODEC_ID_WEBVTT,
     .write_header      = webvtt_write_header,
     .write_packet      = webvtt_write_packet,
-    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                         FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
 };
diff --git a/libavformat/westwood_audenc.c b/libavformat/westwood_audenc.c
index 2240d130b6..ab47e0ff8e 100644
--- a/libavformat/westwood_audenc.c
+++ b/libavformat/westwood_audenc.c
@@ -43,7 +43,6 @@  typedef struct AUDMuxContext {
 
 static int wsaud_write_init(AVFormatContext *ctx)
 {
-    AVStream     *st = ctx->streams[0];
     AVIOContext  *pb = ctx->pb;
 
     /* Stream must be seekable to correctly write the file. */
@@ -53,12 +52,6 @@  static int wsaud_write_init(AVFormatContext *ctx)
         return AVERROR(EINVAL);
     }
 
-    if (st->codecpar->codec_id != AV_CODEC_ID_ADPCM_IMA_WS) {
-        av_log(ctx, AV_LOG_ERROR, "%s codec not supported for Westwood AUD.\n",
-               avcodec_get_name(st->codecpar->codec_id));
-        return AVERROR(EINVAL);
-    }
-
     return 0;
 }
 
@@ -133,5 +126,6 @@  const FFOutputFormat ff_wsaud_muxer = {
     .write_header      = wsaud_write_header,
     .write_packet      = wsaud_write_packet,
     .write_trailer     = wsaud_write_trailer,
-    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                         FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
 };
diff --git a/libavformat/wvenc.c b/libavformat/wvenc.c
index 6d5fefe1bc..7da0879050 100644
--- a/libavformat/wvenc.c
+++ b/libavformat/wvenc.c
@@ -31,16 +31,6 @@  typedef struct WvMuxContext {
     int64_t samples;
 } WvMuxContext;
 
-static av_cold int wv_init(AVFormatContext *ctx)
-{
-    if (ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_WAVPACK) {
-        av_log(ctx, AV_LOG_ERROR, "This muxer only supports a single WavPack stream.\n");
-        return AVERROR(EINVAL);
-    }
-
-    return 0;
-}
-
 static int wv_write_packet(AVFormatContext *ctx, AVPacket *pkt)
 {
     WvMuxContext *s = ctx->priv_data;
@@ -85,9 +75,9 @@  const FFOutputFormat ff_wv_muxer = {
     .p.audio_codec     = AV_CODEC_ID_WAVPACK,
     .p.video_codec     = AV_CODEC_ID_NONE,
     .p.subtitle_codec  = AV_CODEC_ID_NONE,
-    .init              = wv_init,
     .write_packet      = wv_write_packet,
     .write_trailer     = wv_write_trailer,
     .p.flags           = AVFMT_NOTIMESTAMPS,
-    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
+    .flags_internal    = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
+                         FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
 };