diff --git a/libavformat/ac4enc.c b/libavformat/ac4enc.c index aefbfc2684..02b8d4d976 100644 --- a/libavformat/ac4enc.c +++ b/libavformat/ac4enc.c @@ -35,7 +35,7 @@ static int ac4_init(AVFormatContext *s) { AVCodecParameters *par = s->streams[0]->codecpar; - if (s->nb_streams != 1 || par->codec_id != AV_CODEC_ID_AC4) { + 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); } @@ -95,6 +95,8 @@ const FFOutputFormat ff_ac4_muxer = { .priv_data_size = sizeof(AC4Context), .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, .write_packet = ac4_write_packet, .p.priv_class = &ac4_muxer_class, diff --git a/libavformat/aeaenc.c b/libavformat/aeaenc.c index 495e98c6a2..3303d108a5 100644 --- a/libavformat/aeaenc.c +++ b/libavformat/aeaenc.c @@ -29,14 +29,8 @@ static int aea_write_header(AVFormatContext *s) { const AVDictionaryEntry *title_entry; size_t title_length = 0; - AVStream *st; - - if (s->nb_streams > 1) { - av_log(s, AV_LOG_ERROR, "Got more than one stream to encode. This is not supported.\n"); - return AVERROR(EINVAL); - } + AVStream *st = s->streams[0]; - st = s->streams[0]; if (st->codecpar->ch_layout.nb_channels != 1 && st->codecpar->ch_layout.nb_channels != 2) { av_log(s, AV_LOG_ERROR, "Only maximum 2 channels are supported in the audio" " stream, %d channels were found.\n", st->codecpar->ch_layout.nb_channels); @@ -108,7 +102,10 @@ const FFOutputFormat ff_aea_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("MD STUDIO audio"), .p.extensions = "aea", .p.audio_codec = AV_CODEC_ID_ATRAC1, + .p.video_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .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 3db256cd05..9d507cb310 100644 --- a/libavformat/alp.c +++ b/libavformat/alp.c @@ -189,11 +189,6 @@ static int alp_write_init(AVFormatContext *s) alp->type = ALP_TYPE_TUN; } - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "Too many streams\n"); - return AVERROR(EINVAL); - } - par = s->streams[0]->codecpar; if (par->codec_id != AV_CODEC_ID_ADPCM_IMA_ALP) { @@ -298,7 +293,9 @@ const FFOutputFormat ff_alp_muxer = { .p.extensions = "tun,pcm", .p.audio_codec = AV_CODEC_ID_ADPCM_IMA_ALP, .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, .init = alp_write_init, .write_header = alp_write_header, .write_packet = ff_raw_write_packet, diff --git a/libavformat/apm.c b/libavformat/apm.c index bcde82d958..89401dcf5b 100644 --- a/libavformat/apm.c +++ b/libavformat/apm.c @@ -215,14 +215,7 @@ const FFInputFormat ff_apm_demuxer = { #if CONFIG_APM_MUXER static int apm_write_init(AVFormatContext *s) { - AVCodecParameters *par; - - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "APM files have exactly one stream\n"); - return AVERROR(EINVAL); - } - - par = s->streams[0]->codecpar; + 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", @@ -311,6 +304,8 @@ const FFOutputFormat ff_apm_muxer = { .p.extensions = "apm", .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, .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 a0af916f14..79b0dbf0f7 100644 --- a/libavformat/apngenc.c +++ b/libavformat/apngenc.c @@ -84,9 +84,7 @@ static int apng_write_header(AVFormatContext *format_context) APNGMuxContext *apng = format_context->priv_data; AVCodecParameters *par = format_context->streams[0]->codecpar; - if (format_context->nb_streams != 1 || - format_context->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || - format_context->streams[0]->codecpar->codec_id != AV_CODEC_ID_APNG) { + 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); @@ -315,6 +313,8 @@ const FFOutputFormat ff_apng_muxer = { .priv_data_size = sizeof(APNGMuxContext), .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, .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 0e1eae24fb..28e3844394 100644 --- a/libavformat/argo_asf.c +++ b/libavformat/argo_asf.c @@ -288,14 +288,7 @@ const FFInputFormat ff_argo_asf_demuxer = { static int argo_asf_write_init(AVFormatContext *s) { ArgoASFMuxContext *ctx = s->priv_data; - const AVCodecParameters *par; - - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "ASF files have exactly one stream\n"); - return AVERROR(EINVAL); - } - - par = s->streams[0]->codecpar; + 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", @@ -481,7 +474,9 @@ const FFOutputFormat ff_argo_asf_muxer = { */ .p.audio_codec = AV_CODEC_ID_ADPCM_ARGO, .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, .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 0cf0bf3e9a..aacc34daeb 100644 --- a/libavformat/argo_cvg.c +++ b/libavformat/argo_cvg.c @@ -269,14 +269,7 @@ const FFInputFormat ff_argo_cvg_demuxer = { static int argo_cvg_write_init(AVFormatContext *s) { ArgoCVGMuxContext *ctx = s->priv_data; - const AVCodecParameters *par; - - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "CVG files have exactly one stream\n"); - return AVERROR(EINVAL); - } - - par = s->streams[0]->codecpar; + 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", @@ -408,7 +401,9 @@ const FFOutputFormat ff_argo_cvg_muxer = { .p.extensions = "cvg", .p.audio_codec = AV_CODEC_ID_ADPCM_PSX, .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, .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 dad0d81ca8..c23c77acda 100644 --- a/libavformat/assenc.c +++ b/libavformat/assenc.c @@ -50,7 +50,7 @@ static int write_header(AVFormatContext *s) ASSContext *ass = s->priv_data; AVCodecParameters *par = s->streams[0]->codecpar; - if (s->nb_streams != 1 || par->codec_id != AV_CODEC_ID_ASS) { + 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); } @@ -237,8 +237,11 @@ const FFOutputFormat ff_ass_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"), .p.mime_type = "text/x-ass", .p.extensions = "ass,ssa", + .p.audio_codec = AV_CODEC_ID_NONE, + .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, .p.priv_class = &ass_class, .priv_data_size = sizeof(ASSContext), .write_header = write_header, diff --git a/libavformat/astenc.c b/libavformat/astenc.c index c6b02e3848..1fa06a2da8 100644 --- a/libavformat/astenc.c +++ b/libavformat/astenc.c @@ -49,16 +49,9 @@ static int ast_write_header(AVFormatContext *s) { ASTMuxContext *ast = s->priv_data; AVIOContext *pb = s->pb; - AVCodecParameters *par; + AVCodecParameters *par = s->streams[0]->codecpar; unsigned int codec_tag; - if (s->nb_streams == 1) { - par = s->streams[0]->codecpar; - } else { - av_log(s, AV_LOG_ERROR, "only one stream is supported\n"); - return AVERROR(EINVAL); - } - if (par->codec_id == AV_CODEC_ID_ADPCM_AFC) { av_log(s, AV_LOG_ERROR, "muxing ADPCM AFC is not implemented\n"); return AVERROR_PATCHWELCOME; @@ -204,6 +197,8 @@ const FFOutputFormat ff_ast_muxer = { .priv_data_size = sizeof(ASTMuxContext), .p.audio_codec = AV_CODEC_ID_PCM_S16BE_PLANAR, .p.video_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_header = ast_write_header, .write_packet = ast_write_packet, .write_trailer = ast_write_trailer, diff --git a/libavformat/au.c b/libavformat/au.c index da1fc79f0d..98f1a5b507 100644 --- a/libavformat/au.c +++ b/libavformat/au.c @@ -291,11 +291,6 @@ static int au_write_header(AVFormatContext *s) AVCodecParameters *par = s->streams[0]->codecpar; AVBPrint annotations; - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "only one stream is supported\n"); - return AVERROR(EINVAL); - } - par->codec_tag = ff_codec_get_tag(codec_au_tags, par->codec_id); if (!par->codec_tag) { av_log(s, AV_LOG_ERROR, "unsupported codec\n"); @@ -346,7 +341,9 @@ const FFOutputFormat ff_au_muxer = { .p.codec_tag = au_codec_tags, .p.audio_codec = AV_CODEC_ID_PCM_S16BE, .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, .priv_data_size = sizeof(AUContext), .write_header = au_write_header, .write_packet = ff_raw_write_packet, diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index 67be59806c..426bc05209 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -118,11 +118,6 @@ static int caf_write_header(AVFormatContext *s) int64_t chunk_size = 0; int frame_size = par->frame_size, sample_rate = par->sample_rate; - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "CAF files have exactly one stream\n"); - return AVERROR(EINVAL); - } - switch (par->codec_id) { case AV_CODEC_ID_AAC: av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n"); @@ -284,6 +279,8 @@ const FFOutputFormat ff_caf_muxer = { .priv_data_size = sizeof(CAFContext), .p.audio_codec = AV_CODEC_ID_PCM_S16BE, .p.video_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_header = caf_write_header, .write_packet = caf_write_packet, .write_trailer = caf_write_trailer, diff --git a/libavformat/chromaprint.c b/libavformat/chromaprint.c index 3229e9160d..62264d6a4b 100644 --- a/libavformat/chromaprint.c +++ b/libavformat/chromaprint.c @@ -85,11 +85,6 @@ static int write_header(AVFormatContext *s) #endif } - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "Only one stream is supported\n"); - return AVERROR(EINVAL); - } - st = s->streams[0]; if (st->codecpar->ch_layout.nb_channels > 2) { @@ -182,6 +177,9 @@ const FFOutputFormat ff_chromaprint_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("Chromaprint"), .priv_data_size = sizeof(ChromaprintMuxContext), .p.audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), + .p.video_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_header = write_header, .write_packet = write_packet, .write_trailer = write_trailer, diff --git a/libavformat/codec2.c b/libavformat/codec2.c index 9ed57af0a8..e49408e0fb 100644 --- a/libavformat/codec2.c +++ b/libavformat/codec2.c @@ -216,7 +216,7 @@ static int codec2_write_header(AVFormatContext *s) { AVStream *st; - if (s->nb_streams != 1 || s->streams[0]->codecpar->codec_id != AV_CODEC_ID_CODEC2) { + 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); } @@ -317,7 +317,9 @@ const FFOutputFormat ff_codec2_muxer = { .p.extensions = "c2", .p.audio_codec = AV_CODEC_ID_CODEC2, .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, .write_header = codec2_write_header, .write_packet = ff_raw_write_packet, }; diff --git a/libavformat/gif.c b/libavformat/gif.c index 568867cc5d..fe45637814 100644 --- a/libavformat/gif.c +++ b/libavformat/gif.c @@ -42,9 +42,7 @@ typedef struct GIFContext { static int gif_write_header(AVFormatContext *s) { - if (s->nb_streams != 1 || - s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || - s->streams[0]->codecpar->codec_id != AV_CODEC_ID_GIF) { + 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); @@ -213,6 +211,8 @@ const FFOutputFormat ff_gif_muxer = { .priv_data_size = sizeof(GIFContext), .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, .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 bb98d0e62a..2e102a4be7 100644 --- a/libavformat/ilbc.c +++ b/libavformat/ilbc.c @@ -33,13 +33,7 @@ static const char mode30_header[] = "#!iLBC30\n"; static int ilbc_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; - AVCodecParameters *par; - - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "Unsupported number of streams\n"); - return AVERROR(EINVAL); - } - par = s->streams[0]->codecpar; + AVCodecParameters *par = s->streams[0]->codecpar; if (par->codec_id != AV_CODEC_ID_ILBC) { av_log(s, AV_LOG_ERROR, "Unsupported codec\n"); @@ -127,8 +121,11 @@ const FFOutputFormat ff_ilbc_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("iLBC storage"), .p.mime_type = "audio/iLBC", .p.extensions = "lbc", + .p.video_codec = AV_CODEC_ID_NONE, .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, .write_header = ilbc_write_header, .write_packet = ff_raw_write_packet, }; diff --git a/libavformat/ircamenc.c b/libavformat/ircamenc.c index ceeab2b305..7600d9a8a9 100644 --- a/libavformat/ircamenc.c +++ b/libavformat/ircamenc.c @@ -32,11 +32,6 @@ static int ircam_write_header(AVFormatContext *s) AVCodecParameters *par = s->streams[0]->codecpar; uint32_t tag; - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "only one stream is supported\n"); - return AVERROR(EINVAL); - } - tag = ff_codec_get_tag(ff_codec_ircam_le_tags, par->codec_id); if (!tag) { av_log(s, AV_LOG_ERROR, "unsupported codec\n"); @@ -57,6 +52,8 @@ const FFOutputFormat ff_ircam_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("Berkeley/IRCAM/CARL Sound Format"), .p.audio_codec = AV_CODEC_ID_PCM_S16LE, .p.video_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_header = ircam_write_header, .write_packet = ff_raw_write_packet, .p.codec_tag = (const AVCodecTag *const []){ ff_codec_ircam_le_tags, 0 }, diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c index 88399099d4..09782eecd6 100644 --- a/libavformat/ivfenc.c +++ b/libavformat/ivfenc.c @@ -29,15 +29,9 @@ typedef struct IVFEncContext { static int ivf_init(AVFormatContext *s) { - AVCodecParameters *par; + AVCodecParameters *par = s->streams[0]->codecpar; - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "Format supports only exactly one video stream\n"); - return AVERROR(EINVAL); - } - par = s->streams[0]->codecpar; - if (par->codec_type != AVMEDIA_TYPE_VIDEO || - !(par->codec_id == AV_CODEC_ID_AV1 || + if (!(par->codec_id == AV_CODEC_ID_AV1 || par->codec_id == AV_CODEC_ID_VP8 || par->codec_id == AV_CODEC_ID_VP9)) { av_log(s, AV_LOG_ERROR, "Currently only VP8, VP9 and AV1 are supported!\n"); @@ -125,7 +119,9 @@ const FFOutputFormat ff_ivf_muxer = { .p.extensions = "ivf", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_VP8, + .p.subtitle_codec = AV_CODEC_ID_NONE, .p.codec_tag = (const AVCodecTag* const []){ codec_ivf_tags, 0 }, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .priv_data_size = sizeof(IVFEncContext), .init = ivf_init, .write_header = ivf_write_header, diff --git a/libavformat/kvag.c b/libavformat/kvag.c index bea1dda3e5..2053f4730d 100644 --- a/libavformat/kvag.c +++ b/libavformat/kvag.c @@ -129,14 +129,7 @@ const FFInputFormat ff_kvag_demuxer = { #if CONFIG_KVAG_MUXER static int kvag_write_init(AVFormatContext *s) { - AVCodecParameters *par; - - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "KVAG files have exactly one stream\n"); - return AVERROR(EINVAL); - } - - par = s->streams[0]->codecpar; + 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", @@ -196,6 +189,8 @@ const FFOutputFormat ff_kvag_muxer = { .p.extensions = "vag", .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, .init = kvag_write_init, .write_header = kvag_write_header, .write_packet = ff_raw_write_packet, diff --git a/libavformat/lrcenc.c b/libavformat/lrcenc.c index d66be9a8fa..15c31d33b3 100644 --- a/libavformat/lrcenc.c +++ b/libavformat/lrcenc.c @@ -37,12 +37,6 @@ static int lrc_write_header(AVFormatContext *s) { const AVDictionaryEntry *metadata_item; - if(s->nb_streams != 1 || - s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) { - av_log(s, AV_LOG_ERROR, - "LRC supports only a single subtitle stream.\n"); - return AVERROR(EINVAL); - } if(s->streams[0]->codecpar->codec_id != AV_CODEC_ID_SUBRIP && s->streams[0]->codecpar->codec_id != AV_CODEC_ID_TEXT) { av_log(s, AV_LOG_ERROR, "Unsupported subtitle codec: %s\n", @@ -131,7 +125,10 @@ const FFOutputFormat ff_lrc_muxer = { .p.extensions = "lrc", .p.flags = AVFMT_VARIABLE_FPS | AVFMT_GLOBALHEADER | AVFMT_TS_NEGATIVE | AVFMT_TS_NONSTRICT, + .p.video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_NONE, .p.subtitle_codec = AV_CODEC_ID_SUBRIP, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .priv_data_size = 0, .write_header = lrc_write_header, .write_packet = lrc_write_packet, diff --git a/libavformat/microdvdenc.c b/libavformat/microdvdenc.c index 950309981b..b9cadb8be4 100644 --- a/libavformat/microdvdenc.c +++ b/libavformat/microdvdenc.c @@ -29,7 +29,7 @@ static int microdvd_write_header(struct AVFormatContext *s) AVCodecParameters *par = s->streams[0]->codecpar; AVRational framerate = s->streams[0]->avg_frame_rate; - if (s->nb_streams != 1 || par->codec_id != AV_CODEC_ID_MICRODVD) { + if (par->codec_id != AV_CODEC_ID_MICRODVD) { av_log(s, AV_LOG_ERROR, "Exactly one MicroDVD stream is needed.\n"); return -1; } @@ -62,7 +62,10 @@ const FFOutputFormat ff_microdvd_muxer = { .p.mime_type = "text/x-microdvd", .p.extensions = "sub", .p.flags = AVFMT_NOTIMESTAMPS, + .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, .write_header = microdvd_write_header, .write_packet = microdvd_write_packet, }; diff --git a/libavformat/mux.c b/libavformat/mux.c index a2cae97397..134c2875b6 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -188,6 +188,12 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) AVDictionary *tmp = NULL; const FFOutputFormat *of = ffofmt(s->oformat); AVDictionaryEntry *e; + static const unsigned default_codec_offsets[] = { + [AVMEDIA_TYPE_VIDEO] = offsetof(AVOutputFormat, video_codec), + [AVMEDIA_TYPE_AUDIO] = offsetof(AVOutputFormat, audio_codec), + [AVMEDIA_TYPE_SUBTITLE] = offsetof(AVOutputFormat, subtitle_codec), + }; + unsigned nb_type[FF_ARRAY_ELEMS(default_codec_offsets)] = { 0 }; int ret = 0; if (options) @@ -262,6 +268,23 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) } break; } + if (of->flags_internal & FF_OFMT_FLAG_MAX_ONE_OF_EACH) { + enum AVCodecID default_codec_id = AV_CODEC_ID_NONE; + unsigned nb; + if ((unsigned)par->codec_type < FF_ARRAY_ELEMS(default_codec_offsets)) { + nb = ++nb_type[par->codec_type]; + 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) { + 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", + type ? type : "unknown"); + ret = AVERROR(EINVAL); + goto fail; + } + } #if FF_API_AVSTREAM_SIDE_DATA FF_DISABLE_DEPRECATION_WARNINGS diff --git a/libavformat/mux.h b/libavformat/mux.h index bd3eb53380..a13721a03e 100644 --- a/libavformat/mux.h +++ b/libavformat/mux.h @@ -36,6 +36,18 @@ struct AVDeviceInfoList; * of the return value in case of flushing. */ #define FF_OFMT_FLAG_ALLOW_FLUSH (1 << 1) +/** + * If this flag is set, it indicates that for each codec type + * whose corresponding default codec (i.e. AVOutputFormat.audio_codec, + * AVOutputFormat.video_codec and AVOutputFormat.subtitle_codec) + * is set (i.e. != AV_CODEC_ID_NONE) only one stream of this type + * can be muxed. It furthermore indicates that no stream with + * a codec type that has no default codec or whose default codec + * is AV_CODEC_ID_NONE can be muxed. + * Both of these restrictions are checked generically before + * the actual muxer's init/write_header callbacks. + */ +#define FF_OFMT_FLAG_MAX_ONE_OF_EACH (1 << 2) typedef struct FFOutputFormat { /** diff --git a/libavformat/mux_utils.c b/libavformat/mux_utils.c index 841a19a3a2..8a0ad4c9aa 100644 --- a/libavformat/mux_utils.c +++ b/libavformat/mux_utils.c @@ -44,6 +44,25 @@ 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_MAX_ONE_OF_EACH) { + enum AVMediaType type = avcodec_get_type(codec_id); + switch (type) { + case AVMEDIA_TYPE_AUDIO: + if (ofmt->audio_codec == AV_CODEC_ID_NONE) + return 0; + break; + case AVMEDIA_TYPE_VIDEO: + if (ofmt->video_codec == AV_CODEC_ID_NONE) + return 0; + break; + case AVMEDIA_TYPE_SUBTITLE: + if (ofmt->subtitle_codec == AV_CODEC_ID_NONE) + return 0; + break; + default: + return 0; + } + } } return AVERROR_PATCHWELCOME; } diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index f916db13a2..49dc0a9109 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -34,28 +34,6 @@ int ff_raw_write_packet(AVFormatContext *s, AVPacket *pkt) return 0; } -static int force_one_stream(AVFormatContext *s) -{ - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "%s files have exactly one stream\n", - s->oformat->name); - return AVERROR(EINVAL); - } - if ( s->oformat->audio_codec != AV_CODEC_ID_NONE - && s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { - av_log(s, AV_LOG_ERROR, "%s files have exactly one audio stream\n", - s->oformat->name); - return AVERROR(EINVAL); - } - if ( s->oformat->video_codec != AV_CODEC_ID_NONE - && s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) { - av_log(s, AV_LOG_ERROR, "%s files have exactly one video stream\n", - s->oformat->name); - return AVERROR(EINVAL); - } - return 0; -} - /* Note: Do not forget to add new entries to the Makefile as well. */ #if CONFIG_AC3_MUXER @@ -66,7 +44,8 @@ const FFOutputFormat ff_ac3_muxer = { .p.extensions = "ac3", .p.audio_codec = AV_CODEC_ID_AC3, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -98,7 +77,8 @@ const FFOutputFormat ff_adx_muxer = { .p.extensions = "adx", .p.audio_codec = AV_CODEC_ID_ADPCM_ADX, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .write_trailer = adx_write_trailer, .p.flags = AVFMT_NOTIMESTAMPS, @@ -112,7 +92,8 @@ const FFOutputFormat ff_aptx_muxer = { .p.extensions = "aptx", .p.audio_codec = AV_CODEC_ID_APTX, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -125,7 +106,8 @@ const FFOutputFormat ff_aptx_hd_muxer = { .p.extensions = "aptxhd", .p.audio_codec = AV_CODEC_ID_APTX_HD, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -138,7 +120,8 @@ const FFOutputFormat ff_avs2_muxer = { .p.extensions = "avs,avs2", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_AVS2, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -151,7 +134,8 @@ const FFOutputFormat ff_avs3_muxer = { .p.extensions = "avs3", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_AVS3, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -165,7 +149,8 @@ const FFOutputFormat ff_cavsvideo_muxer = { .p.extensions = "cavs", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_CAVS, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -177,7 +162,8 @@ const FFOutputFormat ff_codec2raw_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("raw codec2 muxer"), .p.audio_codec = AV_CODEC_ID_CODEC2, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -185,6 +171,15 @@ const FFOutputFormat ff_codec2raw_muxer = { #if CONFIG_DATA_MUXER +static av_cold int force_one_stream(AVFormatContext *s) +{ + if (s->nb_streams != 1) { + av_log(s, AV_LOG_ERROR, "This muxer supports only one stream.\n"); + return AVERROR(EINVAL); + } + return 0; +} + const FFOutputFormat ff_data_muxer = { .p.name = "data", .p.long_name = NULL_IF_CONFIG_SMALL("raw data"), @@ -201,7 +196,8 @@ const FFOutputFormat ff_dfpwm_muxer = { .p.extensions = "dfpwm", .p.audio_codec = AV_CODEC_ID_DFPWM, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -214,7 +210,8 @@ const FFOutputFormat ff_dirac_muxer = { .p.extensions = "drc,vc2", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_DIRAC, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -227,7 +224,8 @@ const FFOutputFormat ff_dnxhd_muxer = { .p.extensions = "dnxhd,dnxhr", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_DNXHD, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -241,7 +239,8 @@ const FFOutputFormat ff_dts_muxer = { .p.extensions = "dts", .p.audio_codec = AV_CODEC_ID_DTS, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -255,7 +254,8 @@ const FFOutputFormat ff_eac3_muxer = { .p.extensions = "eac3,ec3", .p.audio_codec = AV_CODEC_ID_EAC3, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -269,7 +269,8 @@ const FFOutputFormat ff_g722_muxer = { .p.extensions = "g722", .p.audio_codec = AV_CODEC_ID_ADPCM_G722, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -283,7 +284,8 @@ const FFOutputFormat ff_g723_1_muxer = { .p.extensions = "tco,rco", .p.audio_codec = AV_CODEC_ID_G723_1, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -295,7 +297,8 @@ const FFOutputFormat ff_g726_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("raw big-endian G.726 (\"left-justified\")"), .p.audio_codec = AV_CODEC_ID_ADPCM_G726, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -307,7 +310,8 @@ const FFOutputFormat ff_g726le_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("raw little-endian G.726 (\"right-justified\")"), .p.audio_codec = AV_CODEC_ID_ADPCM_G726LE, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -321,7 +325,8 @@ const FFOutputFormat ff_gsm_muxer = { .p.extensions = "gsm", .p.audio_codec = AV_CODEC_ID_GSM, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -335,7 +340,8 @@ const FFOutputFormat ff_h261_muxer = { .p.extensions = "h261", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_H261, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -349,7 +355,8 @@ const FFOutputFormat ff_h263_muxer = { .p.extensions = "h263", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_H263, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -371,7 +378,8 @@ const FFOutputFormat ff_h264_muxer = { .p.extensions = "h264,264", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_H264, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .check_bitstream = h264_check_bitstream, .p.flags = AVFMT_NOTIMESTAMPS, @@ -394,7 +402,8 @@ const FFOutputFormat ff_vvc_muxer = { .p.extensions = "vvc,h266,266", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_VVC, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .check_bitstream = vvc_check_bitstream, .p.flags = AVFMT_NOTIMESTAMPS, @@ -417,7 +426,8 @@ const FFOutputFormat ff_hevc_muxer = { .p.extensions = "hevc,h265,265", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_HEVC, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .check_bitstream = hevc_check_bitstream, .p.flags = AVFMT_NOTIMESTAMPS, @@ -431,7 +441,8 @@ const FFOutputFormat ff_evc_muxer = { .p.extensions = "evc", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_EVC, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -444,7 +455,8 @@ const FFOutputFormat ff_m4v_muxer = { .p.extensions = "m4v", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_MPEG4, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -458,7 +470,8 @@ const FFOutputFormat ff_mjpeg_muxer = { .p.extensions = "mjpg,mjpeg", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_MJPEG, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -471,7 +484,8 @@ const FFOutputFormat ff_mlp_muxer = { .p.extensions = "mlp", .p.audio_codec = AV_CODEC_ID_MLP, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -485,7 +499,8 @@ const FFOutputFormat ff_mp2_muxer = { .p.extensions = "mp2,m2a,mpa", .p.audio_codec = AV_CODEC_ID_MP2, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -499,7 +514,8 @@ const FFOutputFormat ff_mpeg1video_muxer = { .p.extensions = "mpg,mpeg,m1v", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_MPEG1VIDEO, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -512,7 +528,8 @@ const FFOutputFormat ff_mpeg2video_muxer = { .p.extensions = "m2v", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_MPEG2VIDEO, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -531,7 +548,8 @@ const FFOutputFormat ff_obu_muxer = { .p.extensions = "obu", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_AV1, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .check_bitstream = obu_check_bitstream, .p.flags = AVFMT_NOTIMESTAMPS, @@ -545,6 +563,7 @@ const FFOutputFormat ff_rawvideo_muxer = { .p.extensions = "yuv,rgb", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_RAWVIDEO, + .p.subtitle_codec = AV_CODEC_ID_NONE, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -557,7 +576,9 @@ const FFOutputFormat ff_sbc_muxer = { .p.mime_type = "audio/x-sbc", .p.extensions = "sbc,msbc", .p.audio_codec = AV_CODEC_ID_SBC, - .init = force_one_stream, + .p.video_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -570,7 +591,8 @@ const FFOutputFormat ff_truehd_muxer = { .p.extensions = "thd", .p.audio_codec = AV_CODEC_ID_TRUEHD, .p.video_codec = AV_CODEC_ID_NONE, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; @@ -583,7 +605,8 @@ const FFOutputFormat ff_vc1_muxer = { .p.extensions = "vc1", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_VC1, - .init = force_one_stream, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_packet = ff_raw_write_packet, .p.flags = AVFMT_NOTIMESTAMPS, }; diff --git a/libavformat/rcwtenc.c b/libavformat/rcwtenc.c index ed72de81ef..4ccd7b93c8 100644 --- a/libavformat/rcwtenc.c +++ b/libavformat/rcwtenc.c @@ -84,10 +84,8 @@ static void rcwt_flush_cluster(AVFormatContext *avf) static int rcwt_write_header(AVFormatContext *avf) { - if (avf->nb_streams != 1 || avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_EIA_608) { - av_log(avf, AV_LOG_ERROR, - "RCWT supports only one CC (608/708) stream, more than one stream was " - "provided or its codec type was not CC (608/708)\n"); + 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); } @@ -168,7 +166,10 @@ const FFOutputFormat ff_rcwt_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("RCWT (Raw Captions With Time)"), .p.extensions = "bin", .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .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, .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 ea7865ecf2..040d1ac96c 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->nb_streams != 1 || - avf->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) { - av_log(avf, AV_LOG_ERROR, - "SCC supports only a single subtitles stream.\n"); - return AVERROR(EINVAL); - } if (avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_EIA_608) { av_log(avf, AV_LOG_ERROR, "Unsupported subtitles codec: %s\n", @@ -117,7 +111,10 @@ const FFOutputFormat ff_scc_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("Scenarist Closed Captions"), .p.extensions = "scc", .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .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, .priv_data_size = sizeof(SCCContext), .write_header = scc_write_header, .write_packet = scc_write_packet, diff --git a/libavformat/segafilmenc.c b/libavformat/segafilmenc.c index ba06dc655d..88a5b9f972 100644 --- a/libavformat/segafilmenc.c +++ b/libavformat/segafilmenc.c @@ -124,10 +124,6 @@ static int film_init(AVFormatContext *format_context) for (int i = 0; i < format_context->nb_streams; i++) { AVStream *st = format_context->streams[i]; if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - if (film->audio_index > -1) { - av_log(format_context, AV_LOG_ERROR, "Sega FILM allows a maximum of one audio stream.\n"); - return AVERROR(EINVAL); - } if (get_audio_codec_id(st->codecpar->codec_id) < 0) { av_log(format_context, AV_LOG_ERROR, "Incompatible audio stream format.\n"); @@ -137,10 +133,6 @@ static int film_init(AVFormatContext *format_context) } if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - if (film->video_index > -1) { - av_log(format_context, AV_LOG_ERROR, "Sega FILM allows a maximum of one video stream.\n"); - return AVERROR(EINVAL); - } if (st->codecpar->codec_id != AV_CODEC_ID_CINEPAK && st->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) { av_log(format_context, AV_LOG_ERROR, @@ -287,6 +279,8 @@ const FFOutputFormat ff_segafilm_muxer = { .priv_data_size = sizeof(FILMOutputContext), .p.audio_codec = AV_CODEC_ID_PCM_S16BE_PLANAR, .p.video_codec = AV_CODEC_ID_CINEPAK, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .init = film_init, .write_trailer = film_write_header, .write_packet = film_write_packet, diff --git a/libavformat/srtenc.c b/libavformat/srtenc.c index 30dc59e0f8..a8a16a7f50 100644 --- a/libavformat/srtenc.c +++ b/libavformat/srtenc.c @@ -39,12 +39,6 @@ static int srt_write_header(AVFormatContext *avf) { SRTContext *srt = avf->priv_data; - if (avf->nb_streams != 1 || - avf->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) { - av_log(avf, AV_LOG_ERROR, - "SRT supports only a single subtitles stream.\n"); - return AVERROR(EINVAL); - } if (avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_TEXT && avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_SUBRIP) { av_log(avf, AV_LOG_ERROR, @@ -103,7 +97,10 @@ const FFOutputFormat ff_srt_muxer = { .p.mime_type = "application/x-subrip", .p.extensions = "srt", .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .p.video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_NONE, .p.subtitle_codec = AV_CODEC_ID_SUBRIP, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .priv_data_size = sizeof(SRTContext), .write_header = srt_write_header, .write_packet = srt_write_packet, diff --git a/libavformat/supenc.c b/libavformat/supenc.c index 4af92fefa2..9d5ca51894 100644 --- a/libavformat/supenc.c +++ b/libavformat/supenc.c @@ -74,12 +74,6 @@ static int sup_write_packet(AVFormatContext *s, AVPacket *pkt) static int sup_write_header(AVFormatContext *s) { - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "%s files have exactly one stream\n", - s->oformat->name); - return AVERROR(EINVAL); - } - avpriv_set_pts_info(s->streams[0], 32, 1, 90000); return 0; @@ -90,8 +84,11 @@ const FFOutputFormat ff_sup_muxer = { .p.long_name = NULL_IF_CONFIG_SMALL("raw HDMV Presentation Graphic Stream subtitles"), .p.extensions = "sup", .p.mime_type = "application/x-pgs", + .p.video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_NONE, .p.subtitle_codec = AV_CODEC_ID_HDMV_PGS_SUBTITLE, .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .write_header = sup_write_header, .write_packet = sup_write_packet, }; diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c index f9ac69539b..d106e16d19 100644 --- a/libavformat/swfenc.c +++ b/libavformat/swfenc.c @@ -208,10 +208,6 @@ static int swf_write_header(AVFormatContext *s) for(i=0;inb_streams;i++) { AVCodecParameters *par = s->streams[i]->codecpar; if (par->codec_type == AVMEDIA_TYPE_AUDIO) { - if (swf->audio_par) { - av_log(s, AV_LOG_ERROR, "SWF muxer only supports 1 audio stream\n"); - return AVERROR_INVALIDDATA; - } if (par->codec_id == AV_CODEC_ID_MP3) { swf->audio_par = par; swf->audio_fifo = av_fifo_alloc2(AUDIO_FIFO_SIZE, 1, 0); @@ -222,10 +218,6 @@ static int swf_write_header(AVFormatContext *s) return -1; } } else { - if (swf->video_par) { - av_log(s, AV_LOG_ERROR, "SWF muxer only supports 1 video stream\n"); - return AVERROR_INVALIDDATA; - } if (ff_codec_get_tag(ff_swf_codec_tags, par->codec_id) || par->codec_id == AV_CODEC_ID_PNG || par->codec_id == AV_CODEC_ID_MJPEG) { @@ -556,11 +548,13 @@ const FFOutputFormat ff_swf_muxer = { .priv_data_size = sizeof(SWFEncContext), .p.audio_codec = AV_CODEC_ID_MP3, .p.video_codec = AV_CODEC_ID_FLV1, + .p.subtitle_codec = AV_CODEC_ID_NONE, .write_header = swf_write_header, .write_packet = swf_write_packet, .write_trailer = swf_write_trailer, .deinit = swf_deinit, .p.flags = AVFMT_TS_NONSTRICT, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, }; #endif #if CONFIG_AVM2_MUXER @@ -571,10 +565,12 @@ const FFOutputFormat ff_avm2_muxer = { .priv_data_size = sizeof(SWFEncContext), .p.audio_codec = AV_CODEC_ID_MP3, .p.video_codec = AV_CODEC_ID_FLV1, + .p.subtitle_codec = AV_CODEC_ID_NONE, .write_header = swf_write_header, .write_packet = swf_write_packet, .write_trailer = swf_write_trailer, .deinit = swf_deinit, .p.flags = AVFMT_TS_NONSTRICT, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, }; #endif diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index c7f7e065dc..661aa8fc83 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -40,13 +40,7 @@ typedef struct TTAMuxContext { static int tta_init(AVFormatContext *s) { TTAMuxContext *tta = s->priv_data; - AVCodecParameters *par; - - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "Only one stream is supported\n"); - return AVERROR(EINVAL); - } - par = s->streams[0]->codecpar; + AVCodecParameters *par = s->streams[0]->codecpar; if (par->codec_id != AV_CODEC_ID_TTA) { av_log(s, AV_LOG_ERROR, "Unsupported codec\n"); @@ -174,6 +168,8 @@ const FFOutputFormat ff_tta_muxer = { .priv_data_size = sizeof(TTAMuxContext), .p.audio_codec = AV_CODEC_ID_TTA, .p.video_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_NONE, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, .init = tta_init, .deinit = tta_deinit, .write_header = tta_write_header, diff --git a/libavformat/ttmlenc.c b/libavformat/ttmlenc.c index 212994be50..0af82d5753 100644 --- a/libavformat/ttmlenc.c +++ b/libavformat/ttmlenc.c @@ -126,8 +126,7 @@ static int ttml_write_header(AVFormatContext *ctx) TTMLMuxContext *ttml_ctx = ctx->priv_data; ttml_ctx->document_written = 0; - if (ctx->nb_streams != 1 || - ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_TTML) { + 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); } @@ -224,7 +223,10 @@ const FFOutputFormat ff_ttml_muxer = { .priv_data_size = sizeof(TTMLMuxContext), .p.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .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, .write_header = ttml_write_header, .write_packet = ttml_write_packet, .write_trailer = ttml_write_trailer, diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c index 19daa813a0..7e853ce2fb 100644 --- a/libavformat/wavenc.c +++ b/libavformat/wavenc.c @@ -304,11 +304,6 @@ static int wav_write_header(AVFormatContext *s) AVIOContext *pb = s->pb; int64_t fmt; - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "WAVE files have exactly one stream\n"); - return AVERROR(EINVAL); - } - if (wav->rf64 == RF64_ALWAYS) { ffio_wfourcc(pb, "RF64"); avio_wl32(pb, -1); /* RF64 chunk size: use size in ds64 */ @@ -516,6 +511,7 @@ const FFOutputFormat ff_wav_muxer = { .priv_data_size = sizeof(WAVMuxContext), .p.audio_codec = AV_CODEC_ID_PCM_S16LE, .p.video_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_NONE, .write_header = wav_write_header, .write_packet = wav_write_packet, .write_trailer = wav_write_trailer, @@ -523,22 +519,13 @@ const FFOutputFormat ff_wav_muxer = { .p.flags = AVFMT_TS_NONSTRICT, .p.codec_tag = ff_wav_codec_tags_list, .p.priv_class = &wav_muxer_class, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, }; #endif /* CONFIG_WAV_MUXER */ #if CONFIG_W64_MUXER #include "w64.h" -static av_cold int w64_init(AVFormatContext *ctx) -{ - if (ctx->nb_streams != 1) { - av_log(ctx, AV_LOG_ERROR, "This muxer only supports a single stream.\n"); - return AVERROR(EINVAL); - } - - return 0; -} - static void start_guid(AVIOContext *pb, const uint8_t *guid, int64_t *pos) { *pos = avio_tell(pb); @@ -624,11 +611,12 @@ const FFOutputFormat ff_w64_muxer = { .priv_data_size = sizeof(WAVMuxContext), .p.audio_codec = AV_CODEC_ID_PCM_S16LE, .p.video_codec = AV_CODEC_ID_NONE, - .init = w64_init, + .p.subtitle_codec = AV_CODEC_ID_NONE, .write_header = w64_write_header, .write_packet = wav_write_packet, .write_trailer = w64_write_trailer, .p.flags = AVFMT_TS_NONSTRICT, .p.codec_tag = ff_wav_codec_tags_list, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, }; #endif /* CONFIG_W64_MUXER */ diff --git a/libavformat/webpenc.c b/libavformat/webpenc.c index ea7a321975..85074ae315 100644 --- a/libavformat/webpenc.c +++ b/libavformat/webpenc.c @@ -42,10 +42,6 @@ static int webp_init(AVFormatContext *s) w->last_pkt = ffformatcontext(s)->pkt; - if (s->nb_streams != 1) { - av_log(s, AV_LOG_ERROR, "Only exactly 1 stream is supported\n"); - return AVERROR(EINVAL); - } st = s->streams[0]; if (st->codecpar->codec_id != AV_CODEC_ID_WEBP) { av_log(s, AV_LOG_ERROR, "Only WebP is supported\n"); @@ -230,9 +226,12 @@ const FFOutputFormat ff_webp_muxer = { .p.extensions = "webp", .priv_data_size = sizeof(WebpContext), .p.video_codec = AV_CODEC_ID_WEBP, + .p.audio_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_NONE, .init = webp_init, .write_packet = webp_write_packet, .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, }; diff --git a/libavformat/webvttenc.c b/libavformat/webvttenc.c index 1337045325..12a4b776dc 100644 --- a/libavformat/webvttenc.c +++ b/libavformat/webvttenc.c @@ -50,7 +50,7 @@ static int webvtt_write_header(AVFormatContext *ctx) AVCodecParameters *par = ctx->streams[0]->codecpar; AVIOContext *pb = ctx->pb; - if (ctx->nb_streams != 1 || par->codec_id != AV_CODEC_ID_WEBVTT) { + if (par->codec_id != AV_CODEC_ID_WEBVTT) { av_log(ctx, AV_LOG_ERROR, "Exactly one WebVTT stream is needed.\n"); return AVERROR(EINVAL); } @@ -109,7 +109,10 @@ const FFOutputFormat ff_webvtt_muxer = { .p.extensions = "vtt", .p.mime_type = "text/vtt", .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .p.video_codec = AV_CODEC_ID_NONE, + .p.audio_codec = AV_CODEC_ID_NONE, .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, }; diff --git a/libavformat/westwood_audenc.c b/libavformat/westwood_audenc.c index 46456e2ecb..2240d130b6 100644 --- a/libavformat/westwood_audenc.c +++ b/libavformat/westwood_audenc.c @@ -59,11 +59,6 @@ static int wsaud_write_init(AVFormatContext *ctx) return AVERROR(EINVAL); } - if (ctx->nb_streams != 1) { - av_log(ctx, AV_LOG_ERROR, "AUD files have exactly one stream\n"); - return AVERROR(EINVAL); - } - return 0; } @@ -133,8 +128,10 @@ const FFOutputFormat ff_wsaud_muxer = { .priv_data_size = sizeof(AUDMuxContext), .p.audio_codec = AV_CODEC_ID_ADPCM_IMA_WS, .p.video_codec = AV_CODEC_ID_NONE, + .p.subtitle_codec = AV_CODEC_ID_NONE, .init = wsaud_write_init, .write_header = wsaud_write_header, .write_packet = wsaud_write_packet, .write_trailer = wsaud_write_trailer, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, }; diff --git a/libavformat/wvenc.c b/libavformat/wvenc.c index 9d9190f252..6d5fefe1bc 100644 --- a/libavformat/wvenc.c +++ b/libavformat/wvenc.c @@ -33,8 +33,7 @@ typedef struct WvMuxContext { static av_cold int wv_init(AVFormatContext *ctx) { - if (ctx->nb_streams > 1 || - ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_WAVPACK) { + 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); } @@ -85,8 +84,10 @@ const FFOutputFormat ff_wv_muxer = { .priv_data_size = sizeof(WvMuxContext), .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, }; diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c index 1d641eb9e4..35397cbde0 100644 --- a/libavformat/yuv4mpegenc.c +++ b/libavformat/yuv4mpegenc.c @@ -221,9 +221,6 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) static int yuv4_init(AVFormatContext *s) { - if (s->nb_streams != 1) - return AVERROR(EIO); - if (s->streams[0]->codecpar->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME && s->streams[0]->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) { av_log(s, AV_LOG_ERROR, "ERROR: Codec not supported.\n"); @@ -297,7 +294,9 @@ const FFOutputFormat ff_yuv4mpegpipe_muxer = { .p.extensions = "y4m", .p.audio_codec = AV_CODEC_ID_NONE, .p.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, + .p.subtitle_codec = AV_CODEC_ID_NONE, .init = yuv4_init, .write_header = yuv4_write_header, .write_packet = yuv4_write_packet, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, };