f909ddf73823595d881d3b454db707f0a9d9525a
[ffmpeg.git] / libav / wav.c
1 /* 
2  * WAV encoder and decoder
3  * Copyright (c) 2001 Gerard Lantau.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 #include "avformat.h"
20 #include "avi.h"
21
22 CodecTag codec_wav_tags[] = {
23     { CODEC_ID_MP2, 0x55 },
24     { CODEC_ID_MP2, 0x50 },
25     { CODEC_ID_AC3, 0x2000 },
26     { CODEC_ID_PCM_S16LE, 0x01 },
27     { CODEC_ID_PCM_U8, 0x01 }, /* must come after s16le in this list */
28     { CODEC_ID_PCM_ALAW, 0x06 },
29     { CODEC_ID_PCM_MULAW, 0x07 },
30     { 0, 0 },
31 };
32
33 /* WAVEFORMATEX header */
34 int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
35 {
36     int tag, bps, blkalign, bytespersec;
37
38     tag = codec_get_tag(codec_wav_tags, enc->codec_id);
39     if (tag == 0)
40         return -1;
41     put_le16(pb, tag); 
42     put_le16(pb, enc->channels);
43     put_le32(pb, enc->sample_rate);
44     if (enc->codec_id == CODEC_ID_PCM_U8 ||
45         enc->codec_id == CODEC_ID_PCM_ALAW ||
46         enc->codec_id == CODEC_ID_PCM_MULAW) {
47         bps = 8;
48     } else if (enc->codec_id == CODEC_ID_MP2) {
49         bps = 0;
50     } else {
51         bps = 16;
52     }
53     
54     if (enc->codec_id == CODEC_ID_MP2)
55         blkalign = 1;
56     else
57         blkalign = enc->channels*bps >> 3;
58     if (enc->codec_id == CODEC_ID_PCM_U8 ||
59         enc->codec_id == CODEC_ID_PCM_S16LE) {
60         bytespersec = enc->sample_rate * blkalign;
61     } else {
62         bytespersec = enc->bit_rate / 8;
63     }
64     put_le32(pb, bytespersec); /* bytes per second */
65     put_le16(pb, blkalign); /* block align */
66     put_le16(pb, bps); /* bits per sample */
67     if (enc->codec_id == CODEC_ID_MP2) {
68         put_le16(pb, 12); /* wav_extra_size */
69         put_le16(pb, 1); /* wID */
70         put_le32(pb, 2); /* fdwFlags */
71         put_le16(pb, 1152); /* nBlockSize */
72         put_le16(pb, 1); /* nFramesPerBlock */
73         put_le16(pb, 1393); /* nCodecDelay */
74     } else
75         put_le16(pb, 0); /* wav_extra_size */
76
77     return 0;
78 }
79
80 int wav_codec_get_id(unsigned int tag, int bps)
81 {
82     int id;
83     id = codec_get_id(codec_wav_tags, tag);
84     if (id <= 0)
85         return id;
86     /* handle specific u8 codec */
87     if (id == CODEC_ID_PCM_S16LE && bps == 8)
88         id = CODEC_ID_PCM_U8;
89     return id;
90 }
91
92 typedef struct {
93     offset_t data;
94 } WAVContext;
95
96 static int wav_write_header(AVFormatContext *s)
97 {
98     WAVContext *wav;
99     ByteIOContext *pb = &s->pb;
100     offset_t fmt;
101
102     wav = malloc(sizeof(WAVContext));
103     if (!wav)
104         return -1;
105     memset(wav, 0, sizeof(WAVContext));
106     s->priv_data = wav;
107
108     put_tag(pb, "RIFF");
109     put_le32(pb, 0); /* file length */
110     put_tag(pb, "WAVE");
111
112     /* format header */
113     fmt = start_tag(pb, "fmt ");
114     if (put_wav_header(pb, &s->streams[0]->codec) < 0) {
115         free(wav);
116         return -1;
117     }
118     end_tag(pb, fmt);
119
120     /* data header */
121     wav->data = start_tag(pb, "data");
122     
123     put_flush_packet(pb);
124
125     return 0;
126 }
127
128 static int wav_write_packet(AVFormatContext *s, int stream_index_ptr,
129                            UINT8 *buf, int size)
130 {
131     ByteIOContext *pb = &s->pb;
132     put_buffer(pb, buf, size);
133     return 0;
134 }
135
136 static int wav_write_trailer(AVFormatContext *s)
137 {
138     ByteIOContext *pb = &s->pb;
139     WAVContext *wav = s->priv_data;
140     offset_t file_size;
141
142     if (!url_is_streamed(&s->pb)) {
143         end_tag(pb, wav->data);
144
145         /* update file size */
146         file_size = url_ftell(pb);
147         url_fseek(pb, 4, SEEK_SET);
148         put_le32(pb, (UINT32)(file_size - 8));
149         url_fseek(pb, file_size, SEEK_SET);
150
151         put_flush_packet(pb);
152     }
153
154     free(wav);
155     return 0;
156 }
157
158 /* return the size of the found tag */
159 /* XXX: > 2GB ? */
160 static int find_tag(ByteIOContext *pb, UINT32 tag1)
161 {
162     unsigned int tag;
163     int size;
164
165     for(;;) {
166         if (url_feof(pb))
167             return -1;
168         tag = get_le32(pb);
169         size = get_le32(pb);
170         if (tag == tag1)
171             break;
172         url_fseek(pb, size, SEEK_CUR);
173     }
174     if (size < 0)
175         size = 0x7fffffff;
176     return size;
177 }
178
179 /* wav input */
180 static int wav_read_header(AVFormatContext *s,
181                            AVFormatParameters *ap)
182 {
183     int size;
184     unsigned int tag;
185     ByteIOContext *pb = &s->pb;
186     unsigned int id, channels, rate, bit_rate, extra_size, bps;
187     AVStream *st;
188
189     /* check RIFF header */
190     tag = get_le32(pb);
191
192     if (tag != MKTAG('R', 'I', 'F', 'F'))
193         return -1;
194     get_le32(pb); /* file size */
195     tag = get_le32(pb);
196     if (tag != MKTAG('W', 'A', 'V', 'E'))
197         return -1;
198     
199     /* parse fmt header */
200     size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
201     if (size < 0)
202         return -1;
203     id = get_le16(pb); 
204     channels = get_le16(pb);
205     rate = get_le32(pb);
206     bit_rate = get_le32(pb) * 8;
207     get_le16(pb); /* block align */
208     bps = get_le16(pb); /* bits per sample */
209     if (size >= 18) {
210         /* wav_extra_size */
211         extra_size = get_le16(pb); 
212         /* skip unused data */
213         url_fseek(pb, size - 18, SEEK_CUR);
214     }
215
216     size = find_tag(pb, MKTAG('d', 'a', 't', 'a'));
217     if (size < 0)
218         return -1;
219     
220     /* now we are ready: build format streams */
221     st = malloc(sizeof(AVStream));
222     if (!st)
223         return -1;
224     s->nb_streams = 1;
225     s->streams[0] = st;
226
227     st->id = 0;
228     
229     st->codec.codec_type = CODEC_TYPE_AUDIO;
230     st->codec.codec_tag = id;
231     st->codec.codec_id = wav_codec_get_id(id, bps);
232     st->codec.channels = channels;
233     st->codec.sample_rate = rate;
234     return 0;
235 }
236
237 #define MAX_SIZE 4096
238
239 static int wav_read_packet(AVFormatContext *s,
240                            AVPacket *pkt)
241 {
242     int packet_size, n, ret;
243
244     if (url_feof(&s->pb))
245         return -EIO;
246     packet_size = url_get_packet_size(&s->pb);
247     n = MAX_SIZE / packet_size;
248     if (n <= 0)
249         return n = 1;
250     if (av_new_packet(pkt, n * packet_size))
251         return -EIO;
252     pkt->stream_index = 0;
253
254     ret = get_buffer(&s->pb, pkt->data, pkt->size);
255     if (ret < 0)
256         av_free_packet(pkt);
257     /* note: we need to modify the packet size here to handle the last
258        packet */
259     pkt->size = ret;
260     return ret;
261 }
262
263 static int wav_read_close(AVFormatContext *s)
264 {
265     return 0;
266 }
267
268 AVFormat wav_format = {
269     "wav",
270     "wav format",
271     "audio/x-wav",
272     "wav",
273     CODEC_ID_PCM_S16LE,
274     CODEC_ID_NONE,
275     wav_write_header,
276     wav_write_packet,
277     wav_write_trailer,
278
279     wav_read_header,
280     wav_read_packet,
281     wav_read_close,
282 };