summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2001-09-24 23:26:46 +0000
committerFabrice Bellard <fabrice@bellard.org>2001-09-24 23:26:46 +0000
commit46a3d0685df667158628a8037faa0383f9bd4c22 (patch)
tree2beb53820c1270a5d56e0417a21a56c27ea89a29
parent96baaa6affc11ebd71b8f84c11086c92e1c7248b (diff)
correct pcm audio format handling
Originally committed as revision 147 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libav/asf.c16
-rw-r--r--libav/avi.h3
-rw-r--r--libav/avidec.c8
-rw-r--r--libav/avienc.c32
-rw-r--r--libav/wav.c59
5 files changed, 75 insertions, 43 deletions
diff --git a/libav/asf.c b/libav/asf.c
index 41b1369665..60960db2b9 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 06834cfcbf..e44f5b782b 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 342bfd0f07..a3d5a8fa6d 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 8c5848d2e6..c971ef03ae 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 59994bbb26..d367be7fe4 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;
}