Mercurial > libavformat.hg
comparison riff.c @ 4833:d607731c2cf8 libavformat
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.
author | rbultje |
---|---|
date | Wed, 08 Apr 2009 03:04:57 +0000 |
parents | f83f6caa42bc |
children | 231479c86582 |
comparison
equal
deleted
inserted
replaced
4832:b367d80986b3 | 4833:d607731c2cf8 |
---|---|
20 */ | 20 */ |
21 | 21 |
22 #include "libavcodec/avcodec.h" | 22 #include "libavcodec/avcodec.h" |
23 #include "avformat.h" | 23 #include "avformat.h" |
24 #include "riff.h" | 24 #include "riff.h" |
25 #include "libavcodec/bytestream.h" | |
25 | 26 |
26 /* Note: when encoding, the first matching tag is used, so order is | 27 /* Note: when encoding, the first matching tag is used, so order is |
27 important if multiple tags possible for a given codec. */ | 28 important if multiple tags possible for a given codec. */ |
28 const AVCodecTag codec_bmp_tags[] = { | 29 const AVCodecTag codec_bmp_tags[] = { |
29 { CODEC_ID_H264, MKTAG('H', '2', '6', '4') }, | 30 { CODEC_ID_H264, MKTAG('H', '2', '6', '4') }, |
282 /* returns the size or -1 on error */ | 283 /* returns the size or -1 on error */ |
283 int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) | 284 int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) |
284 { | 285 { |
285 int bps, blkalign, bytespersec; | 286 int bps, blkalign, bytespersec; |
286 int hdrsize = 18; | 287 int hdrsize = 18; |
288 int waveformatextensible; | |
289 uint8_t temp[256]; | |
290 uint8_t *riff_extradata= temp; | |
291 uint8_t *riff_extradata_start= temp; | |
287 | 292 |
288 if(!enc->codec_tag || enc->codec_tag > 0xffff) | 293 if(!enc->codec_tag || enc->codec_tag > 0xffff) |
289 return -1; | 294 return -1; |
290 | 295 waveformatextensible = enc->channels > 2 && enc->channel_layout; |
296 | |
297 if (waveformatextensible) { | |
298 put_le16(pb, 0xfffe); | |
299 } else { | |
291 put_le16(pb, enc->codec_tag); | 300 put_le16(pb, enc->codec_tag); |
301 } | |
292 put_le16(pb, enc->channels); | 302 put_le16(pb, enc->channels); |
293 put_le32(pb, enc->sample_rate); | 303 put_le32(pb, enc->sample_rate); |
294 if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3 || enc->codec_id == CODEC_ID_GSM_MS) { | 304 if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3 || enc->codec_id == CODEC_ID_GSM_MS) { |
295 bps = 0; | 305 bps = 0; |
296 } else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV || enc->codec_id == CODEC_ID_ADPCM_MS || enc->codec_id == CODEC_ID_ADPCM_G726 || enc->codec_id == CODEC_ID_ADPCM_YAMAHA) { // | 306 } else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV || enc->codec_id == CODEC_ID_ADPCM_MS || enc->codec_id == CODEC_ID_ADPCM_G726 || enc->codec_id == CODEC_ID_ADPCM_YAMAHA) { // |
324 } | 334 } |
325 put_le32(pb, bytespersec); /* bytes per second */ | 335 put_le32(pb, bytespersec); /* bytes per second */ |
326 put_le16(pb, blkalign); /* block align */ | 336 put_le16(pb, blkalign); /* block align */ |
327 put_le16(pb, bps); /* bits per sample */ | 337 put_le16(pb, bps); /* bits per sample */ |
328 if (enc->codec_id == CODEC_ID_MP3) { | 338 if (enc->codec_id == CODEC_ID_MP3) { |
329 put_le16(pb, 12); /* wav_extra_size */ | |
330 hdrsize += 12; | 339 hdrsize += 12; |
331 put_le16(pb, 1); /* wID */ | 340 bytestream_put_le16(&riff_extradata, 1); /* wID */ |
332 put_le32(pb, 2); /* fdwFlags */ | 341 bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ |
333 put_le16(pb, 1152); /* nBlockSize */ | 342 bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ |
334 put_le16(pb, 1); /* nFramesPerBlock */ | 343 bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ |
335 put_le16(pb, 1393); /* nCodecDelay */ | 344 bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ |
336 } else if (enc->codec_id == CODEC_ID_MP2) { | 345 } else if (enc->codec_id == CODEC_ID_MP2) { |
337 put_le16(pb, 22); /* wav_extra_size */ | |
338 hdrsize += 22; | 346 hdrsize += 22; |
339 put_le16(pb, 2); /* fwHeadLayer */ | 347 bytestream_put_le16(&riff_extradata, 2); /* fwHeadLayer */ |
340 put_le32(pb, enc->bit_rate); /* dwHeadBitrate */ | 348 bytestream_put_le32(&riff_extradata, enc->bit_rate); /* dwHeadBitrate */ |
341 put_le16(pb, enc->channels == 2 ? 1 : 8); /* fwHeadMode */ | 349 bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); /* fwHeadMode */ |
342 put_le16(pb, 0); /* fwHeadModeExt */ | 350 bytestream_put_le16(&riff_extradata, 0); /* fwHeadModeExt */ |
343 put_le16(pb, 1); /* wHeadEmphasis */ | 351 bytestream_put_le16(&riff_extradata, 1); /* wHeadEmphasis */ |
344 put_le16(pb, 16); /* fwHeadFlags */ | 352 bytestream_put_le16(&riff_extradata, 16); /* fwHeadFlags */ |
345 put_le32(pb, 0); /* dwPTSLow */ | 353 bytestream_put_le32(&riff_extradata, 0); /* dwPTSLow */ |
346 put_le32(pb, 0); /* dwPTSHigh */ | 354 bytestream_put_le32(&riff_extradata, 0); /* dwPTSHigh */ |
347 } else if (enc->codec_id == CODEC_ID_GSM_MS) { | 355 } else if (enc->codec_id == CODEC_ID_GSM_MS) { |
348 put_le16(pb, 2); /* wav_extra_size */ | |
349 hdrsize += 2; | 356 hdrsize += 2; |
350 put_le16(pb, enc->frame_size); /* wSamplesPerBlock */ | 357 bytestream_put_le16(&riff_extradata, enc->frame_size); /* wSamplesPerBlock */ |
351 } else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) { | 358 } else if (enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) { |
352 put_le16(pb, 2); /* wav_extra_size */ | |
353 hdrsize += 2; | 359 hdrsize += 2; |
354 put_le16(pb, enc->frame_size); /* wSamplesPerBlock */ | 360 bytestream_put_le16(&riff_extradata, enc->frame_size); /* wSamplesPerBlock */ |
355 } else if(enc->extradata_size){ | 361 } else if(enc->extradata_size){ |
356 put_le16(pb, enc->extradata_size); | 362 riff_extradata_start= enc->extradata; |
357 put_buffer(pb, enc->extradata, enc->extradata_size); | 363 riff_extradata= enc->extradata + enc->extradata_size; |
358 hdrsize += enc->extradata_size; | 364 hdrsize += enc->extradata_size; |
365 } else if (!waveformatextensible){ | |
366 hdrsize -= 2; | |
367 } | |
368 if(waveformatextensible) { /* write WAVEFORMATEXTENSIBLE extensions */ | |
369 hdrsize += 22; | |
370 put_le16(pb, riff_extradata - riff_extradata_start + 22); /* 22 is WAVEFORMATEXTENSIBLE size */ | |
371 put_le16(pb, enc->bits_per_coded_sample); /* ValidBitsPerSample || SamplesPerBlock || Reserved */ | |
372 put_le32(pb, enc->channel_layout); /* dwChannelMask */ | |
373 put_le32(pb, enc->codec_tag); /* GUID + next 3 */ | |
374 put_le32(pb, 0x00100000); | |
375 put_le32(pb, 0xAA000080); | |
376 put_le32(pb, 0x719B3800); | |
377 } else if(riff_extradata - riff_extradata_start) { | |
378 put_le16(pb, riff_extradata - riff_extradata_start); | |
379 } | |
380 put_buffer(pb, riff_extradata_start, riff_extradata - riff_extradata_start); | |
359 if(hdrsize&1){ | 381 if(hdrsize&1){ |
360 hdrsize++; | 382 hdrsize++; |
361 put_byte(pb, 0); | 383 put_byte(pb, 0); |
362 } | 384 } |
363 } else { | |
364 hdrsize -= 2; | |
365 } | |
366 | 385 |
367 return hdrsize; | 386 return hdrsize; |
368 } | 387 } |
369 | 388 |
370 /* BITMAPINFOHEADER header */ | 389 /* BITMAPINFOHEADER header */ |