Commit 6e9f56c1 authored by Ronald S. Bultje's avatar Ronald S. Bultje

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
parent 7b356d39
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "libavcodec/avcodec.h" #include "libavcodec/avcodec.h"
#include "avformat.h" #include "avformat.h"
#include "riff.h" #include "riff.h"
#include "libavcodec/bytestream.h"
/* Note: when encoding, the first matching tag is used, so order is /* Note: when encoding, the first matching tag is used, so order is
important if multiple tags possible for a given codec. */ important if multiple tags possible for a given codec. */
...@@ -284,11 +285,20 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) ...@@ -284,11 +285,20 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
{ {
int bps, blkalign, bytespersec; int bps, blkalign, bytespersec;
int hdrsize = 18; 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) if(!enc->codec_tag || enc->codec_tag > 0xffff)
return -1; 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->codec_tag);
}
put_le16(pb, enc->channels); put_le16(pb, enc->channels);
put_le32(pb, enc->sample_rate); 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) { 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) ...@@ -326,43 +336,52 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
put_le16(pb, blkalign); /* block align */ put_le16(pb, blkalign); /* block align */
put_le16(pb, bps); /* bits per sample */ put_le16(pb, bps); /* bits per sample */
if (enc->codec_id == CODEC_ID_MP3) { if (enc->codec_id == CODEC_ID_MP3) {
put_le16(pb, 12); /* wav_extra_size */
hdrsize += 12; hdrsize += 12;
put_le16(pb, 1); /* wID */ bytestream_put_le16(&riff_extradata, 1); /* wID */
put_le32(pb, 2); /* fdwFlags */ bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */
put_le16(pb, 1152); /* nBlockSize */ bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */
put_le16(pb, 1); /* nFramesPerBlock */ bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */
put_le16(pb, 1393); /* nCodecDelay */ bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */
} else if (enc->codec_id == CODEC_ID_MP2) { } else if (enc->codec_id == CODEC_ID_MP2) {
put_le16(pb, 22); /* wav_extra_size */
hdrsize += 22; hdrsize += 22;
put_le16(pb, 2); /* fwHeadLayer */ bytestream_put_le16(&riff_extradata, 2); /* fwHeadLayer */
put_le32(pb, enc->bit_rate); /* dwHeadBitrate */ bytestream_put_le32(&riff_extradata, enc->bit_rate); /* dwHeadBitrate */
put_le16(pb, enc->channels == 2 ? 1 : 8); /* fwHeadMode */ bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); /* fwHeadMode */
put_le16(pb, 0); /* fwHeadModeExt */ bytestream_put_le16(&riff_extradata, 0); /* fwHeadModeExt */
put_le16(pb, 1); /* wHeadEmphasis */ bytestream_put_le16(&riff_extradata, 1); /* wHeadEmphasis */
put_le16(pb, 16); /* fwHeadFlags */ bytestream_put_le16(&riff_extradata, 16); /* fwHeadFlags */
put_le32(pb, 0); /* dwPTSLow */ bytestream_put_le32(&riff_extradata, 0); /* dwPTSLow */
put_le32(pb, 0); /* dwPTSHigh */ bytestream_put_le32(&riff_extradata, 0); /* dwPTSHigh */
} else if (enc->codec_id == CODEC_ID_GSM_MS) { } else if (enc->codec_id == CODEC_ID_GSM_MS) {
put_le16(pb, 2); /* wav_extra_size */
hdrsize += 2; 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) { } else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) {
put_le16(pb, 2); /* wav_extra_size */
hdrsize += 2; hdrsize += 2;
put_le16(pb, enc->frame_size); /* wSamplesPerBlock */ bytestream_put_le16(&riff_extradata, enc->frame_size); /* wSamplesPerBlock */
} else if(enc->extradata_size){ } else if(enc->extradata_size){
put_le16(pb, enc->extradata_size); riff_extradata_start= enc->extradata;
put_buffer(pb, enc->extradata, enc->extradata_size); riff_extradata= enc->extradata + enc->extradata_size;
hdrsize += 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){ if(hdrsize&1){
hdrsize++; hdrsize++;
put_byte(pb, 0); put_byte(pb, 0);
} }
} else {
hdrsize -= 2;
}
return hdrsize; return hdrsize;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment