- Versions defined for libav/libavcodec.
[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, 0x50 },
24     { CODEC_ID_MP3LAME, 0x55 },
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 || enc->codec_id == CODEC_ID_MP3LAME) {
49         bps = 0;
50     } else {
51         bps = 16;
52     }
53     
54     if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3LAME) {
55         blkalign = 1;
56         //blkalign = 144 * enc->bit_rate/enc->sample_rate;
57     } else
58         blkalign = enc->channels*bps >> 3;
59     if (enc->codec_id == CODEC_ID_PCM_U8 ||
60         enc->codec_id == CODEC_ID_PCM_S16LE) {
61         bytespersec = enc->sample_rate * blkalign;
62     } else {
63         bytespersec = enc->bit_rate / 8;
64     }
65     put_le32(pb, bytespersec); /* bytes per second */
66     put_le16(pb, blkalign); /* block align */
67     put_le16(pb, bps); /* bits per sample */
68     if (enc->codec_id == CODEC_ID_MP3LAME) {
69         put_le16(pb, 12); /* wav_extra_size */
70         put_le16(pb, 1); /* wID */
71         put_le32(pb, 2); /* fdwFlags */
72         put_le16(pb, 1152); /* nBlockSize */
73         put_le16(pb, 1); /* nFramesPerBlock */
74         put_le16(pb, 1393); /* nCodecDelay */
75     } else if (enc->codec_id == CODEC_ID_MP2) {
76         put_le16(pb, 22); /* wav_extra_size */
77         put_le16(pb, 2);  /* fwHeadLayer */
78         put_le32(pb, enc->bit_rate); /* dwHeadBitrate */
79         put_le16(pb, enc->channels == 2 ? 1 : 8); /* fwHeadMode */
80         put_le16(pb, 0);  /* fwHeadModeExt */
81         put_le16(pb, 1);  /* wHeadEmphasis */
82         put_le16(pb, 16); /* fwHeadFlags */
83         put_le32(pb, 0);  /* dwPTSLow */
84         put_le32(pb, 0);  /* dwPTSHigh */
85     } else
86         put_le16(pb, 0); /* wav_extra_size */
87
88     return 0;
89 }
90
91 int wav_codec_get_id(unsigned int tag, int bps)
92 {
93     int id;
94     id = codec_get_id(codec_wav_tags, tag);
95     if (id <= 0)
96         return id;
97     /* handle specific u8 codec */
98     if (id == CODEC_ID_PCM_S16LE && bps == 8)
99         id = CODEC_ID_PCM_U8;
100     return id;
101 }
102
103 typedef struct {
104     offset_t data;
105 } WAVContext;
106
107 static int wav_write_header(AVFormatContext *s)
108 {
109     WAVContext *wav;
110     ByteIOContext *pb = &s->pb;
111     offset_t fmt;
112
113     wav = malloc(sizeof(WAVContext));
114     if (!wav)
115         return -1;
116     memset(wav, 0, sizeof(WAVContext));
117     s->priv_data = wav;
118
119     put_tag(pb, "RIFF");
120     put_le32(pb, 0); /* file length */
121     put_tag(pb, "WAVE");
122
123     /* format header */
124     fmt = start_tag(pb, "fmt ");
125     if (put_wav_header(pb, &s->streams[0]->codec) < 0) {
126         free(wav);
127         return -1;
128     }
129     end_tag(pb, fmt);
130
131     /* data header */
132     wav->data = start_tag(pb, "data");
133     
134     put_flush_packet(pb);
135
136     return 0;
137 }
138
139 static int wav_write_packet(AVFormatContext *s, int stream_index_ptr,
140                            UINT8 *buf, int size, int force_pts)
141 {
142     ByteIOContext *pb = &s->pb;
143     put_buffer(pb, buf, size);
144     return 0;
145 }
146
147 static int wav_write_trailer(AVFormatContext *s)
148 {
149     ByteIOContext *pb = &s->pb;
150     WAVContext *wav = s->priv_data;
151     offset_t file_size;
152
153     if (!url_is_streamed(&s->pb)) {
154         end_tag(pb, wav->data);
155
156         /* update file size */
157         file_size = url_ftell(pb);
158         url_fseek(pb, 4, SEEK_SET);
159         put_le32(pb, (UINT32)(file_size - 8));
160         url_fseek(pb, file_size, SEEK_SET);
161
162         put_flush_packet(pb);
163     }
164
165     free(wav);
166     return 0;
167 }
168
169 /* return the size of the found tag */
170 /* XXX: > 2GB ? */
171 static int find_tag(ByteIOContext *pb, UINT32 tag1)
172 {
173     unsigned int tag;
174     int size;
175
176     for(;;) {
177         if (url_feof(pb))
178             return -1;
179         tag = get_le32(pb);
180         size = get_le32(pb);
181         if (tag == tag1)
182             break;
183         url_fseek(pb, size, SEEK_CUR);
184     }
185     if (size < 0)
186         size = 0x7fffffff;
187     return size;
188 }
189
190 /* wav input */
191 static int wav_read_header(AVFormatContext *s,
192                            AVFormatParameters *ap)
193 {
194     int size;
195     unsigned int tag;
196     ByteIOContext *pb = &s->pb;
197     unsigned int id, channels, rate, bit_rate, extra_size, bps;
198     AVStream *st;
199
200     /* check RIFF header */
201     tag = get_le32(pb);
202
203     if (tag != MKTAG('R', 'I', 'F', 'F'))
204         return -1;
205     get_le32(pb); /* file size */
206     tag = get_le32(pb);
207     if (tag != MKTAG('W', 'A', 'V', 'E'))
208         return -1;
209     
210     /* parse fmt header */
211     size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
212     if (size < 0)
213         return -1;
214     id = get_le16(pb); 
215     channels = get_le16(pb);
216     rate = get_le32(pb);
217     bit_rate = get_le32(pb) * 8;
218     get_le16(pb); /* block align */
219     bps = get_le16(pb); /* bits per sample */
220     if (size >= 18) {
221         /* wav_extra_size */
222         extra_size = get_le16(pb); 
223         /* skip unused data */
224         url_fseek(pb, size - 18, SEEK_CUR);
225     }
226
227     size = find_tag(pb, MKTAG('d', 'a', 't', 'a'));
228     if (size < 0)
229         return -1;
230     
231     /* now we are ready: build format streams */
232     st = malloc(sizeof(AVStream));
233     if (!st)
234         return -1;
235     s->nb_streams = 1;
236     s->streams[0] = st;
237
238     st->id = 0;
239     
240     st->codec.codec_type = CODEC_TYPE_AUDIO;
241     st->codec.codec_tag = id;
242     st->codec.codec_id = wav_codec_get_id(id, bps);
243     st->codec.channels = channels;
244     st->codec.sample_rate = rate;
245     return 0;
246 }
247
248 #define MAX_SIZE 4096
249
250 static int wav_read_packet(AVFormatContext *s,
251                            AVPacket *pkt)
252 {
253     int packet_size, n, ret;
254
255     if (url_feof(&s->pb))
256         return -EIO;
257     packet_size = url_get_packet_size(&s->pb);
258     n = MAX_SIZE / packet_size;
259     if (n <= 0)
260         return n = 1;
261     if (av_new_packet(pkt, n * packet_size))
262         return -EIO;
263     pkt->stream_index = 0;
264
265     ret = get_buffer(&s->pb, pkt->data, pkt->size);
266     if (ret < 0)
267         av_free_packet(pkt);
268     /* note: we need to modify the packet size here to handle the last
269        packet */
270     pkt->size = ret;
271     return ret;
272 }
273
274 static int wav_read_close(AVFormatContext *s)
275 {
276     return 0;
277 }
278
279 AVFormat wav_format = {
280     "wav",
281     "wav format",
282     "audio/x-wav",
283     "wav",
284     CODEC_ID_PCM_S16LE,
285     CODEC_ID_NONE,
286     wav_write_header,
287     wav_write_packet,
288     wav_write_trailer,
289
290     wav_read_header,
291     wav_read_packet,
292     wav_read_close,
293 };