diff --git a/libavformat/avienc.c b/libavformat/avienc.c index a79f156ab2..649961d11c 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -34,6 +34,7 @@ #include "libavutil/dict.h" #include "libavutil/avassert.h" #include "libavutil/timestamp.h" +#include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavcodec/raw.h" @@ -58,9 +59,11 @@ typedef struct AVIIndex { } AVIIndex; typedef struct AVIContext { + const AVClass *class; int64_t riff_start, movi_list, odml_list; int64_t frames_hdr_all; int riff_id; + int write_channel_mask; } AVIContext; typedef struct AVIStream { @@ -339,7 +342,7 @@ static int avi_write_header(AVFormatContext *s) ff_end_tag(pb, strh); if (enc->codec_type != AVMEDIA_TYPE_DATA) { - int ret; + int ret, flags; enum AVPixelFormat pix_fmt; strf = ff_start_tag(pb, "strf"); @@ -367,7 +370,8 @@ static int avi_write_header(AVFormatContext *s) av_get_pix_fmt_name(enc->pix_fmt)); break; case AVMEDIA_TYPE_AUDIO: - if ((ret = ff_put_wav_header(pb, enc, 0)) < 0) + flags = (avi->write_channel_mask == 0) ? FF_PUT_WAV_HEADER_SKIP_CHANNELMASK : 0; + if ((ret = ff_put_wav_header(pb, enc, flags)) < 0) return ret; break; default: @@ -782,6 +786,20 @@ static int avi_write_trailer(AVFormatContext *s) return res; } +#define OFFSET(x) offsetof(AVIContext, x) +#define ENC AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "write_channel_mask", "write channel mask into wave format header", OFFSET(write_channel_mask), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC }, + { NULL }, +}; + +static const AVClass avi_muxer_class = { + .class_name = "AVI muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVOutputFormat ff_avi_muxer = { .name = "avi", .long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"), @@ -796,4 +814,5 @@ AVOutputFormat ff_avi_muxer = { .codec_tag = (const AVCodecTag * const []) { ff_codec_bmp_tags, ff_codec_wav_tags, 0 }, + .priv_class = &avi_muxer_class, }; diff --git a/libavformat/riff.h b/libavformat/riff.h index 399c52738f..d6d91ef52d 100644 --- a/libavformat/riff.h +++ b/libavformat/riff.h @@ -52,6 +52,11 @@ void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *t */ #define FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX 0x00000001 +/** + * Tell ff_put_wav_header() to write an empty channel mask. + */ +#define FF_PUT_WAV_HEADER_SKIP_CHANNELMASK 0x00000002 + /** * Write WAVEFORMAT header structure. * diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c index 85c953f2ef..ceb27f272c 100644 --- a/libavformat/riffenc.c +++ b/libavformat/riffenc.c @@ -168,8 +168,9 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags) } /* write WAVEFORMATEXTENSIBLE extensions */ if (waveformatextensible) { - int write_channel_mask = enc->strict_std_compliance < FF_COMPLIANCE_NORMAL || - enc->channel_layout < 0x40000; + int write_channel_mask = !(flags & FF_PUT_WAV_HEADER_SKIP_CHANNELMASK) && + (enc->strict_std_compliance < FF_COMPLIANCE_NORMAL || + enc->channel_layout < 0x40000); /* 22 is WAVEFORMATEXTENSIBLE size */ avio_wl16(pb, riff_extradata - riff_extradata_start + 22); /* ValidBitsPerSample || SamplesPerBlock || Reserved */