diff options
author | Ronald S. Bultje <rsbultje@gmail.com> | 2009-04-08 03:04:57 +0000 |
---|---|---|
committer | Ronald S. Bultje <rsbultje@gmail.com> | 2009-04-08 03:04:57 +0000 |
commit | 6e9f56c1277c19f36830c547d703e88cc41d78b7 (patch) | |
tree | 5829dea3cf920152a9c4c4c9354ba7b148f5d562 | |
parent | 7b356d39514929aaf11f0ad03d468d03e5f682aa (diff) | |
download | ffmpeg-6e9f56c1277c19f36830c547d703e88cc41d78b7.tar.gz |
Add waveformat-extensible support in the wav muxer.
Patch (GSoC qualfication task) by Zhentan Feng spyfeng gmail com, see
"[FFmpeg-devel] Add waveformat extensible support in wav muxer (SoC
qualification task)" thread on mailinglist.
Originally committed as revision 18372 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavformat/riff.c | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/libavformat/riff.c b/libavformat/riff.c index 8dda623549..014c762041 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -22,6 +22,7 @@ #include "libavcodec/avcodec.h" #include "avformat.h" #include "riff.h" +#include "libavcodec/bytestream.h" /* Note: when encoding, the first matching tag is used, so order is important if multiple tags possible for a given codec. */ @@ -284,11 +285,20 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) { int bps, blkalign, bytespersec; int hdrsize = 18; + int waveformatextensible; + uint8_t temp[256]; + uint8_t *riff_extradata= temp; + uint8_t *riff_extradata_start= temp; if(!enc->codec_tag || enc->codec_tag > 0xffff) return -1; + waveformatextensible = enc->channels > 2 && enc->channel_layout; + if (waveformatextensible) { + put_le16(pb, 0xfffe); + } else { put_le16(pb, enc->codec_tag); + } put_le16(pb, enc->channels); put_le32(pb, enc->sample_rate); if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3 || enc->codec_id == CODEC_ID_GSM_MS) { @@ -326,43 +336,52 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) put_le16(pb, blkalign); /* block align */ put_le16(pb, bps); /* bits per sample */ if (enc->codec_id == CODEC_ID_MP3) { - put_le16(pb, 12); /* wav_extra_size */ hdrsize += 12; - put_le16(pb, 1); /* wID */ - put_le32(pb, 2); /* fdwFlags */ - put_le16(pb, 1152); /* nBlockSize */ - put_le16(pb, 1); /* nFramesPerBlock */ - put_le16(pb, 1393); /* nCodecDelay */ + bytestream_put_le16(&riff_extradata, 1); /* wID */ + bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ + bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ + bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ + bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ } else if (enc->codec_id == CODEC_ID_MP2) { - put_le16(pb, 22); /* wav_extra_size */ hdrsize += 22; - put_le16(pb, 2); /* fwHeadLayer */ - put_le32(pb, enc->bit_rate); /* dwHeadBitrate */ - put_le16(pb, enc->channels == 2 ? 1 : 8); /* fwHeadMode */ - put_le16(pb, 0); /* fwHeadModeExt */ - put_le16(pb, 1); /* wHeadEmphasis */ - put_le16(pb, 16); /* fwHeadFlags */ - put_le32(pb, 0); /* dwPTSLow */ - put_le32(pb, 0); /* dwPTSHigh */ + bytestream_put_le16(&riff_extradata, 2); /* fwHeadLayer */ + bytestream_put_le32(&riff_extradata, enc->bit_rate); /* dwHeadBitrate */ + bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); /* fwHeadMode */ + bytestream_put_le16(&riff_extradata, 0); /* fwHeadModeExt */ + bytestream_put_le16(&riff_extradata, 1); /* wHeadEmphasis */ + bytestream_put_le16(&riff_extradata, 16); /* fwHeadFlags */ + bytestream_put_le32(&riff_extradata, 0); /* dwPTSLow */ + bytestream_put_le32(&riff_extradata, 0); /* dwPTSHigh */ } else if (enc->codec_id == CODEC_ID_GSM_MS) { - put_le16(pb, 2); /* wav_extra_size */ hdrsize += 2; - put_le16(pb, enc->frame_size); /* wSamplesPerBlock */ + bytestream_put_le16(&riff_extradata, enc->frame_size); /* wSamplesPerBlock */ } else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) { - put_le16(pb, 2); /* wav_extra_size */ hdrsize += 2; - put_le16(pb, enc->frame_size); /* wSamplesPerBlock */ + bytestream_put_le16(&riff_extradata, enc->frame_size); /* wSamplesPerBlock */ } else if(enc->extradata_size){ - put_le16(pb, enc->extradata_size); - put_buffer(pb, enc->extradata, enc->extradata_size); + riff_extradata_start= enc->extradata; + riff_extradata= enc->extradata + enc->extradata_size; hdrsize += enc->extradata_size; + } else if (!waveformatextensible){ + hdrsize -= 2; + } + if(waveformatextensible) { /* write WAVEFORMATEXTENSIBLE extensions */ + hdrsize += 22; + put_le16(pb, riff_extradata - riff_extradata_start + 22); /* 22 is WAVEFORMATEXTENSIBLE size */ + put_le16(pb, enc->bits_per_coded_sample); /* ValidBitsPerSample || SamplesPerBlock || Reserved */ + put_le32(pb, enc->channel_layout); /* dwChannelMask */ + put_le32(pb, enc->codec_tag); /* GUID + next 3 */ + put_le32(pb, 0x00100000); + put_le32(pb, 0xAA000080); + put_le32(pb, 0x719B3800); + } else if(riff_extradata - riff_extradata_start) { + put_le16(pb, riff_extradata - riff_extradata_start); + } + put_buffer(pb, riff_extradata_start, riff_extradata - riff_extradata_start); if(hdrsize&1){ hdrsize++; put_byte(pb, 0); } - } else { - hdrsize -= 2; - } return hdrsize; } |