From 46a3d0685df667158628a8037faa0383f9bd4c22 Mon Sep 17 00:00:00 2001 From: Fabrice Bellard Date: Mon, 24 Sep 2001 23:26:46 +0000 Subject: [PATCH] correct pcm audio format handling Originally committed as revision 147 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libav/asf.c | 16 ++++++++++------ libav/avi.h | 3 ++- libav/avidec.c | 8 +++++--- libav/avienc.c | 32 ++++--------------------------- libav/wav.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 75 insertions(+), 43 deletions(-) diff --git a/libav/asf.c b/libav/asf.c index 41b1369..60960db 100644 --- a/libav/asf.c +++ b/libav/asf.c @@ -301,7 +301,8 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu if (enc->codec_type == CODEC_TYPE_AUDIO) { /* WAVEFORMATEX header */ - put_wav_header(pb, enc); + if (put_wav_header(pb, enc) < 0) + return -1; } else { put_le32(pb, enc->width); put_le32(pb, enc->height); @@ -376,7 +377,10 @@ static int asf_write_header(AVFormatContext *s) asf->packet_size = PACKET_SIZE; asf->nb_packets = 0; - asf_write_header1(s, 0, 24); + if (asf_write_header1(s, 0, 24) < 0) { + free(asf); + return -1; + } put_flush_packet(&s->pb); @@ -637,7 +641,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) ByteIOContext *pb = &s->pb; AVStream *st; ASFStream *asf_st; - int size, i; + int size, i, bps; INT64 gsize; asf = av_mallocz(sizeof(ASFContext)); @@ -710,13 +714,13 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) if (type == CODEC_TYPE_AUDIO) { id = get_le16(pb); st->codec.codec_tag = id; - st->codec.codec_id = codec_get_id(codec_wav_tags, id); st->codec.channels = get_le16(pb); st->codec.sample_rate = get_le32(pb); st->codec.bit_rate = get_le32(pb) * 8; get_le16(pb); /* block align */ - get_le16(pb); /* bits per sample */ - size = get_le16(pb); + bps = get_le16(pb); /* bits per sample */ + st->codec.codec_id = wav_codec_get_id(id, bps); + size = get_le16(pb); url_fskip(pb, size); } else { get_le32(pb); diff --git a/libav/avi.h b/libav/avi.h index 06834cf..e44f5b7 100644 --- a/libav/avi.h +++ b/libav/avi.h @@ -10,7 +10,8 @@ offset_t start_tag(ByteIOContext *pb, char *tag); void end_tag(ByteIOContext *pb, offset_t start); void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc); -void put_wav_header(ByteIOContext *pb, AVCodecContext *enc); +int put_wav_header(ByteIOContext *pb, AVCodecContext *enc); +int wav_codec_get_id(unsigned int tag, int bps); typedef struct CodecTag { int id; diff --git a/libav/avidec.c b/libav/avidec.c index 342bfd0..a3d5a8f 100644 --- a/libav/avidec.c +++ b/libav/avidec.c @@ -51,7 +51,7 @@ int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) ByteIOContext *pb = &s->pb; UINT32 tag, tag1; int codec_type, stream_index, size, frame_period, bit_rate; - int i; + int i, bps; AVStream *st; avi = malloc(sizeof(AVIContext)); @@ -169,14 +169,16 @@ int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) tag1 = get_le16(pb); st->codec.codec_type = CODEC_TYPE_AUDIO; st->codec.codec_tag = tag1; - st->codec.codec_id = codec_get_id(codec_wav_tags, tag1); #ifdef DEBUG printf("audio: 0x%x\n", tag1); #endif st->codec.channels = get_le16(pb); st->codec.sample_rate = get_le32(pb); st->codec.bit_rate = get_le32(pb) * 8; - url_fskip(pb, size - 3 * 4); + get_le16(pb); /* block align */ + bps = get_le16(pb); + st->codec.codec_id = wav_codec_get_id(tag1, bps); + url_fskip(pb, size - 4 * 4); break; default: url_fskip(pb, size); diff --git a/libav/avienc.c b/libav/avienc.c index 8c5848d..c971ef0 100644 --- a/libav/avienc.c +++ b/libav/avienc.c @@ -67,17 +67,6 @@ CodecTag codec_bmp_tags[] = { { 0, 0 }, }; -CodecTag codec_wav_tags[] = { - { CODEC_ID_MP2, 0x55 }, - { CODEC_ID_MP2, 0x50 }, - { CODEC_ID_AC3, 0x2000 }, - { CODEC_ID_PCM_S16LE, 0x01 }, - { CODEC_ID_PCM_ALAW, 0x06 }, - { CODEC_ID_PCM_MULAW, 0x07 }, - { 0, 0 }, -}; - - unsigned int codec_get_tag(CodecTag *tags, int id) { while (tags->id != 0) { @@ -120,22 +109,6 @@ void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc) put_le32(pb, 0); } -/* WAVEFORMATEX header */ -void put_wav_header(ByteIOContext *pb, AVCodecContext *enc) -{ - int tag; - - tag = codec_get_tag(codec_wav_tags, enc->codec_id); - - put_le16(pb, tag); - put_le16(pb, enc->channels); - put_le32(pb, enc->sample_rate); - put_le32(pb, enc->bit_rate / 8); - put_le16(pb, 1); /* block align */ - put_le16(pb, 16); /* bits per sample */ - put_le16(pb, 0); /* wav_extra_size */ -} - static int avi_write_header(AVFormatContext *s) { AVIContext *avi; @@ -247,7 +220,10 @@ static int avi_write_header(AVFormatContext *s) put_bmp_header(pb, stream); break; case CODEC_TYPE_AUDIO: - put_wav_header(pb, stream); + if (put_wav_header(pb, stream) < 0) { + free(avi); + return -1; + } break; } end_tag(pb, strf); diff --git a/libav/wav.c b/libav/wav.c index 59994bb..d367be7 100644 --- a/libav/wav.c +++ b/libav/wav.c @@ -19,6 +19,55 @@ #include "avformat.h" #include "avi.h" +CodecTag codec_wav_tags[] = { + { CODEC_ID_MP2, 0x55 }, + { CODEC_ID_MP2, 0x50 }, + { CODEC_ID_AC3, 0x2000 }, + { CODEC_ID_PCM_S16LE, 0x01 }, + { CODEC_ID_PCM_U8, 0x01 }, /* must come after s16le in this list */ + { CODEC_ID_PCM_ALAW, 0x06 }, + { CODEC_ID_PCM_MULAW, 0x07 }, + { 0, 0 }, +}; + +/* WAVEFORMATEX header */ +int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) +{ + int tag, bps; + + tag = codec_get_tag(codec_wav_tags, enc->codec_id); + if (tag == 0) + return -1; + put_le16(pb, tag); + put_le16(pb, enc->channels); + put_le32(pb, enc->sample_rate); + put_le32(pb, enc->bit_rate / 8); + put_le16(pb, 1); /* block align */ + if (enc->codec_id == CODEC_ID_PCM_U8 || + enc->codec_id == CODEC_ID_PCM_ALAW || + enc->codec_id == CODEC_ID_PCM_MULAW) { + bps = 8; + } else { + bps = 16; + } + put_le16(pb, bps); /* bits per sample */ + + put_le16(pb, 0); /* wav_extra_size */ + return 0; +} + +int wav_codec_get_id(unsigned int tag, int bps) +{ + int id; + id = codec_get_id(codec_wav_tags, tag); + if (id <= 0) + return id; + /* handle specific u8 codec */ + if (id == CODEC_ID_PCM_S16LE && bps == 8) + id = CODEC_ID_PCM_U8; + return id; +} + typedef struct { offset_t data; } WAVContext; @@ -41,7 +90,10 @@ static int wav_write_header(AVFormatContext *s) /* format header */ fmt = start_tag(pb, "fmt "); - put_wav_header(pb, &s->streams[0]->codec); + if (put_wav_header(pb, &s->streams[0]->codec) < 0) { + free(wav); + return -1; + } end_tag(pb, fmt); /* data header */ @@ -155,12 +207,9 @@ static int wav_read_header(AVFormatContext *s, st->codec.codec_type = CODEC_TYPE_AUDIO; st->codec.codec_tag = id; - st->codec.codec_id = codec_get_id(codec_wav_tags, id); + st->codec.codec_id = wav_codec_get_id(id, bps); st->codec.channels = channels; st->codec.sample_rate = rate; - if (st->codec.codec_id == CODEC_ID_PCM_S16LE && bps == 8) { - st->codec.codec_id = CODEC_ID_PCM_U8; - } return 0; } -- 2.7.4