- Versions defined for libav/libavcodec.
[libav.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 };