Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
2 | * AIFF/AIFF-C demuxer |
||
3 | * Copyright (c) 2006 Patrick Guimond |
||
4 | * |
||
5 | * This file is part of FFmpeg. |
||
6 | * |
||
7 | * FFmpeg is free software; you can redistribute it and/or |
||
8 | * modify it under the terms of the GNU Lesser General Public |
||
9 | * License as published by the Free Software Foundation; either |
||
10 | * version 2.1 of the License, or (at your option) any later version. |
||
11 | * |
||
12 | * FFmpeg is distributed in the hope that it will be useful, |
||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
15 | * Lesser General Public License for more details. |
||
16 | * |
||
17 | * You should have received a copy of the GNU Lesser General Public |
||
18 | * License along with FFmpeg; if not, write to the Free Software |
||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||
20 | */ |
||
21 | |||
22 | #include "libavutil/intreadwrite.h" |
||
23 | #include "libavutil/mathematics.h" |
||
24 | #include "libavutil/dict.h" |
||
25 | #include "avformat.h" |
||
26 | #include "internal.h" |
||
27 | #include "pcm.h" |
||
28 | #include "aiff.h" |
||
29 | #include "isom.h" |
||
30 | #include "id3v2.h" |
||
31 | #include "mov_chan.h" |
||
32 | |||
33 | #define AIFF 0 |
||
34 | #define AIFF_C_VERSION1 0xA2805140 |
||
35 | |||
36 | typedef struct { |
||
37 | int64_t data_end; |
||
38 | int block_duration; |
||
39 | } AIFFInputContext; |
||
40 | |||
41 | static enum AVCodecID aiff_codec_get_id(int bps) |
||
42 | { |
||
43 | if (bps <= 8) |
||
44 | return AV_CODEC_ID_PCM_S8; |
||
45 | if (bps <= 16) |
||
46 | return AV_CODEC_ID_PCM_S16BE; |
||
47 | if (bps <= 24) |
||
48 | return AV_CODEC_ID_PCM_S24BE; |
||
49 | if (bps <= 32) |
||
50 | return AV_CODEC_ID_PCM_S32BE; |
||
51 | |||
52 | /* bigger than 32 isn't allowed */ |
||
53 | return AV_CODEC_ID_NONE; |
||
54 | } |
||
55 | |||
56 | /* returns the size of the found tag */ |
||
57 | static int get_tag(AVIOContext *pb, uint32_t * tag) |
||
58 | { |
||
59 | int size; |
||
60 | |||
61 | if (url_feof(pb)) |
||
62 | return AVERROR(EIO); |
||
63 | |||
64 | *tag = avio_rl32(pb); |
||
65 | size = avio_rb32(pb); |
||
66 | |||
67 | if (size < 0) |
||
68 | size = 0x7fffffff; |
||
69 | |||
70 | return size; |
||
71 | } |
||
72 | |||
73 | /* Metadata string read */ |
||
74 | static void get_meta(AVFormatContext *s, const char *key, int size) |
||
75 | { |
||
76 | uint8_t *str = av_malloc(size+1); |
||
77 | |||
78 | if (str) { |
||
79 | int res = avio_read(s->pb, str, size); |
||
80 | if (res < 0){ |
||
81 | av_free(str); |
||
82 | return; |
||
83 | } |
||
84 | size += (size&1)-res; |
||
85 | str[res] = 0; |
||
86 | av_dict_set(&s->metadata, key, str, AV_DICT_DONT_STRDUP_VAL); |
||
87 | }else |
||
88 | size+= size&1; |
||
89 | |||
90 | avio_skip(s->pb, size); |
||
91 | } |
||
92 | |||
93 | /* Returns the number of sound data frames or negative on error */ |
||
94 | static unsigned int get_aiff_header(AVFormatContext *s, int size, |
||
95 | unsigned version) |
||
96 | { |
||
97 | AVIOContext *pb = s->pb; |
||
98 | AVCodecContext *codec = s->streams[0]->codec; |
||
99 | AIFFInputContext *aiff = s->priv_data; |
||
100 | int exp; |
||
101 | uint64_t val; |
||
102 | double sample_rate; |
||
103 | unsigned int num_frames; |
||
104 | |||
105 | if (size & 1) |
||
106 | size++; |
||
107 | codec->codec_type = AVMEDIA_TYPE_AUDIO; |
||
108 | codec->channels = avio_rb16(pb); |
||
109 | num_frames = avio_rb32(pb); |
||
110 | codec->bits_per_coded_sample = avio_rb16(pb); |
||
111 | |||
112 | exp = avio_rb16(pb); |
||
113 | val = avio_rb64(pb); |
||
114 | sample_rate = ldexp(val, exp - 16383 - 63); |
||
115 | codec->sample_rate = sample_rate; |
||
116 | size -= 18; |
||
117 | |||
118 | /* get codec id for AIFF-C */ |
||
119 | if (version == AIFF_C_VERSION1) { |
||
120 | codec->codec_tag = avio_rl32(pb); |
||
121 | codec->codec_id = ff_codec_get_id(ff_codec_aiff_tags, codec->codec_tag); |
||
122 | size -= 4; |
||
123 | } |
||
124 | |||
125 | if (version != AIFF_C_VERSION1 || codec->codec_id == AV_CODEC_ID_PCM_S16BE) { |
||
126 | codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); |
||
127 | codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); |
||
128 | aiff->block_duration = 1; |
||
129 | } else { |
||
130 | switch (codec->codec_id) { |
||
131 | case AV_CODEC_ID_PCM_F32BE: |
||
132 | case AV_CODEC_ID_PCM_F64BE: |
||
133 | case AV_CODEC_ID_PCM_S16LE: |
||
134 | case AV_CODEC_ID_PCM_ALAW: |
||
135 | case AV_CODEC_ID_PCM_MULAW: |
||
136 | aiff->block_duration = 1; |
||
137 | break; |
||
138 | case AV_CODEC_ID_ADPCM_IMA_QT: |
||
139 | codec->block_align = 34*codec->channels; |
||
140 | break; |
||
141 | case AV_CODEC_ID_MACE3: |
||
142 | codec->block_align = 2*codec->channels; |
||
143 | break; |
||
144 | case AV_CODEC_ID_ADPCM_G726LE: |
||
145 | codec->bits_per_coded_sample = 5; |
||
146 | case AV_CODEC_ID_ADPCM_G722: |
||
147 | case AV_CODEC_ID_MACE6: |
||
148 | codec->block_align = 1*codec->channels; |
||
149 | break; |
||
150 | case AV_CODEC_ID_GSM: |
||
151 | codec->block_align = 33; |
||
152 | break; |
||
153 | default: |
||
154 | aiff->block_duration = 1; |
||
155 | break; |
||
156 | } |
||
157 | if (codec->block_align > 0) |
||
158 | aiff->block_duration = av_get_audio_frame_duration(codec, |
||
159 | codec->block_align); |
||
160 | } |
||
161 | |||
162 | /* Block align needs to be computed in all cases, as the definition |
||
163 | * is specific to applications -> here we use the WAVE format definition */ |
||
164 | if (!codec->block_align) |
||
165 | codec->block_align = (av_get_bits_per_sample(codec->codec_id) * codec->channels) >> 3; |
||
166 | |||
167 | if (aiff->block_duration) { |
||
168 | codec->bit_rate = codec->sample_rate * (codec->block_align << 3) / |
||
169 | aiff->block_duration; |
||
170 | } |
||
171 | |||
172 | /* Chunk is over */ |
||
173 | if (size) |
||
174 | avio_skip(pb, size); |
||
175 | |||
176 | return num_frames; |
||
177 | } |
||
178 | |||
179 | static int aiff_probe(AVProbeData *p) |
||
180 | { |
||
181 | /* check file header */ |
||
182 | if (p->buf[0] == 'F' && p->buf[1] == 'O' && |
||
183 | p->buf[2] == 'R' && p->buf[3] == 'M' && |
||
184 | p->buf[8] == 'A' && p->buf[9] == 'I' && |
||
185 | p->buf[10] == 'F' && (p->buf[11] == 'F' || p->buf[11] == 'C')) |
||
186 | return AVPROBE_SCORE_MAX; |
||
187 | else |
||
188 | return 0; |
||
189 | } |
||
190 | |||
191 | /* aiff input */ |
||
192 | static int aiff_read_header(AVFormatContext *s) |
||
193 | { |
||
194 | int ret, size, filesize; |
||
195 | int64_t offset = 0, position; |
||
196 | uint32_t tag; |
||
197 | unsigned version = AIFF_C_VERSION1; |
||
198 | AVIOContext *pb = s->pb; |
||
199 | AVStream * st; |
||
200 | AIFFInputContext *aiff = s->priv_data; |
||
201 | ID3v2ExtraMeta *id3v2_extra_meta = NULL; |
||
202 | |||
203 | /* check FORM header */ |
||
204 | filesize = get_tag(pb, &tag); |
||
205 | if (filesize < 0 || tag != MKTAG('F', 'O', 'R', 'M')) |
||
206 | return AVERROR_INVALIDDATA; |
||
207 | |||
208 | /* AIFF data type */ |
||
209 | tag = avio_rl32(pb); |
||
210 | if (tag == MKTAG('A', 'I', 'F', 'F')) /* Got an AIFF file */ |
||
211 | version = AIFF; |
||
212 | else if (tag != MKTAG('A', 'I', 'F', 'C')) /* An AIFF-C file then */ |
||
213 | return AVERROR_INVALIDDATA; |
||
214 | |||
215 | filesize -= 4; |
||
216 | |||
217 | st = avformat_new_stream(s, NULL); |
||
218 | if (!st) |
||
219 | return AVERROR(ENOMEM); |
||
220 | |||
221 | while (filesize > 0) { |
||
222 | /* parse different chunks */ |
||
223 | size = get_tag(pb, &tag); |
||
224 | if (size < 0) |
||
225 | return size; |
||
226 | |||
227 | filesize -= size + 8; |
||
228 | |||
229 | switch (tag) { |
||
230 | case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */ |
||
231 | /* Then for the complete header info */ |
||
232 | st->nb_frames = get_aiff_header(s, size, version); |
||
233 | if (st->nb_frames < 0) |
||
234 | return st->nb_frames; |
||
235 | if (offset > 0) // COMM is after SSND |
||
236 | goto got_sound; |
||
237 | break; |
||
238 | case MKTAG('I', 'D', '3', ' '): |
||
239 | position = avio_tell(pb); |
||
240 | ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); |
||
241 | if (id3v2_extra_meta) |
||
242 | if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) { |
||
243 | ff_id3v2_free_extra_meta(&id3v2_extra_meta); |
||
244 | return ret; |
||
245 | } |
||
246 | ff_id3v2_free_extra_meta(&id3v2_extra_meta); |
||
247 | if (position + size > avio_tell(pb)) |
||
248 | avio_skip(pb, position + size - avio_tell(pb)); |
||
249 | break; |
||
250 | case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */ |
||
251 | version = avio_rb32(pb); |
||
252 | break; |
||
253 | case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */ |
||
254 | get_meta(s, "title" , size); |
||
255 | break; |
||
256 | case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */ |
||
257 | get_meta(s, "author" , size); |
||
258 | break; |
||
259 | case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */ |
||
260 | get_meta(s, "copyright", size); |
||
261 | break; |
||
262 | case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */ |
||
263 | get_meta(s, "comment" , size); |
||
264 | break; |
||
265 | case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */ |
||
266 | aiff->data_end = avio_tell(pb) + size; |
||
267 | offset = avio_rb32(pb); /* Offset of sound data */ |
||
268 | avio_rb32(pb); /* BlockSize... don't care */ |
||
269 | offset += avio_tell(pb); /* Compute absolute data offset */ |
||
270 | if (st->codec->block_align && !pb->seekable) /* Assume COMM already parsed */ |
||
271 | goto got_sound; |
||
272 | if (!pb->seekable) { |
||
273 | av_log(s, AV_LOG_ERROR, "file is not seekable\n"); |
||
274 | return -1; |
||
275 | } |
||
276 | avio_skip(pb, size - 8); |
||
277 | break; |
||
278 | case MKTAG('w', 'a', 'v', 'e'): |
||
279 | if ((uint64_t)size > (1<<30)) |
||
280 | return -1; |
||
281 | if (ff_alloc_extradata(st->codec, size)) |
||
282 | return AVERROR(ENOMEM); |
||
283 | avio_read(pb, st->codec->extradata, size); |
||
284 | if (st->codec->codec_id == AV_CODEC_ID_QDM2 && size>=12*4 && !st->codec->block_align) { |
||
285 | st->codec->block_align = AV_RB32(st->codec->extradata+11*4); |
||
286 | aiff->block_duration = AV_RB32(st->codec->extradata+9*4); |
||
287 | } else if (st->codec->codec_id == AV_CODEC_ID_QCELP) { |
||
288 | char rate = 0; |
||
289 | if (size >= 25) |
||
290 | rate = st->codec->extradata[24]; |
||
291 | switch (rate) { |
||
292 | case 'H': // RATE_HALF |
||
293 | st->codec->block_align = 17; |
||
294 | break; |
||
295 | case 'F': // RATE_FULL |
||
296 | default: |
||
297 | st->codec->block_align = 35; |
||
298 | } |
||
299 | aiff->block_duration = 160; |
||
300 | st->codec->bit_rate = st->codec->sample_rate * (st->codec->block_align << 3) / |
||
301 | aiff->block_duration; |
||
302 | } |
||
303 | break; |
||
304 | case MKTAG('C','H','A','N'): |
||
305 | if(ff_mov_read_chan(s, pb, st, size) < 0) |
||
306 | return AVERROR_INVALIDDATA; |
||
307 | break; |
||
308 | default: /* Jump */ |
||
309 | if (size & 1) /* Always even aligned */ |
||
310 | size++; |
||
311 | avio_skip(pb, size); |
||
312 | } |
||
313 | } |
||
314 | |||
315 | got_sound: |
||
316 | if (!st->codec->block_align) { |
||
317 | av_log(s, AV_LOG_ERROR, "could not find COMM tag or invalid block_align value\n"); |
||
318 | return -1; |
||
319 | } |
||
320 | |||
321 | /* Now positioned, get the sound data start and end */ |
||
322 | avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); |
||
323 | st->start_time = 0; |
||
324 | st->duration = st->nb_frames * aiff->block_duration; |
||
325 | |||
326 | /* Position the stream at the first block */ |
||
327 | avio_seek(pb, offset, SEEK_SET); |
||
328 | |||
329 | return 0; |
||
330 | } |
||
331 | |||
332 | #define MAX_SIZE 4096 |
||
333 | |||
334 | static int aiff_read_packet(AVFormatContext *s, |
||
335 | AVPacket *pkt) |
||
336 | { |
||
337 | AVStream *st = s->streams[0]; |
||
338 | AIFFInputContext *aiff = s->priv_data; |
||
339 | int64_t max_size; |
||
340 | int res, size; |
||
341 | |||
342 | /* calculate size of remaining data */ |
||
343 | max_size = aiff->data_end - avio_tell(s->pb); |
||
344 | if (max_size <= 0) |
||
345 | return AVERROR_EOF; |
||
346 | |||
347 | /* Now for that packet */ |
||
348 | if (st->codec->block_align >= 17) // GSM, QCLP, IMA4 |
||
349 | size = st->codec->block_align; |
||
350 | else |
||
351 | size = (MAX_SIZE / st->codec->block_align) * st->codec->block_align; |
||
352 | size = FFMIN(max_size, size); |
||
353 | res = av_get_packet(s->pb, pkt, size); |
||
354 | if (res < 0) |
||
355 | return res; |
||
356 | |||
357 | if (size >= st->codec->block_align) |
||
358 | pkt->flags &= ~AV_PKT_FLAG_CORRUPT; |
||
359 | /* Only one stream in an AIFF file */ |
||
360 | pkt->stream_index = 0; |
||
361 | pkt->duration = (res / st->codec->block_align) * aiff->block_duration; |
||
362 | return 0; |
||
363 | } |
||
364 | |||
365 | AVInputFormat ff_aiff_demuxer = { |
||
366 | .name = "aiff", |
||
367 | .long_name = NULL_IF_CONFIG_SMALL("Audio IFF"), |
||
368 | .priv_data_size = sizeof(AIFFInputContext), |
||
369 | .read_probe = aiff_probe, |
||
370 | .read_header = aiff_read_header, |
||
371 | .read_packet = aiff_read_packet, |
||
372 | .read_seek = ff_pcm_read_seek, |
||
373 | .codec_tag = (const AVCodecTag* const []){ ff_codec_aiff_tags, 0 }, |
||
374 | };>=>>><>30)) |