correct pcm audio format handling
authorFabrice Bellard <fabrice@bellard.org>
Mon, 24 Sep 2001 23:26:46 +0000 (23:26 +0000)
committerFabrice Bellard <fabrice@bellard.org>
Mon, 24 Sep 2001 23:26:46 +0000 (23:26 +0000)
Originally committed as revision 147 to svn://svn.ffmpeg.org/ffmpeg/trunk

libav/asf.c
libav/avi.h
libav/avidec.c
libav/avienc.c
libav/wav.c

index 41b1369..60960db 100644 (file)
@@ -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);
index 06834cf..e44f5b7 100644 (file)
@@ -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;
index 342bfd0..a3d5a8f 100644 (file)
@@ -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);
index 8c5848d..c971ef0 100644 (file)
@@ -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);
index 59994bb..d367be7 100644 (file)
 #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;
 }