2 * AIFF/AIFF-C muxer and demuxer
3 * Copyright (c) 2006 Patrick Guimond
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/intfloat_readwrite.h"
27 static const AVCodecTag codec_aiff_tags
[] = {
28 { CODEC_ID_PCM_S16BE
, MKTAG('N','O','N','E') },
29 { CODEC_ID_PCM_S8
, MKTAG('N','O','N','E') },
30 { CODEC_ID_PCM_S24BE
, MKTAG('N','O','N','E') },
31 { CODEC_ID_PCM_S32BE
, MKTAG('N','O','N','E') },
32 { CODEC_ID_PCM_F32BE
, MKTAG('f','l','3','2') },
33 { CODEC_ID_PCM_F64BE
, MKTAG('f','l','6','4') },
34 { CODEC_ID_PCM_ALAW
, MKTAG('a','l','a','w') },
35 { CODEC_ID_PCM_MULAW
, MKTAG('u','l','a','w') },
36 { CODEC_ID_MACE3
, MKTAG('M','A','C','3') },
37 { CODEC_ID_MACE6
, MKTAG('M','A','C','6') },
38 { CODEC_ID_GSM
, MKTAG('G','S','M',' ') },
39 { CODEC_ID_ADPCM_G726
, MKTAG('G','7','2','6') },
40 { CODEC_ID_PCM_S16LE
, MKTAG('s','o','w','t') },
41 { CODEC_ID_ADPCM_IMA_QT
, MKTAG('i','m','a','4') },
42 { CODEC_ID_QDM2
, MKTAG('Q','D','M','2') },
47 #define AIFF_C_VERSION1 0xA2805140
49 static int aiff_codec_get_id(int bps
)
52 return CODEC_ID_PCM_S8
;
54 return CODEC_ID_PCM_S16BE
;
56 return CODEC_ID_PCM_S24BE
;
58 return CODEC_ID_PCM_S32BE
;
60 /* bigger than 32 isn't allowed */
64 /* returns the size of the found tag */
65 static int get_tag(ByteIOContext
*pb
, uint32_t * tag
)
81 /* Metadata string read */
82 static void get_meta(ByteIOContext
*pb
, char * str
, int strsize
, int size
)
87 res
= get_buffer(pb
, (uint8_t*)str
, strsize
-1);
89 res
= get_buffer(pb
, (uint8_t*)str
, size
);
102 /* Returns the number of sound data frames or negative on error */
103 static unsigned int get_aiff_header(ByteIOContext
*pb
, AVCodecContext
*codec
,
104 int size
, unsigned version
)
108 unsigned int num_frames
;
112 codec
->codec_type
= CODEC_TYPE_AUDIO
;
113 codec
->channels
= get_be16(pb
);
114 num_frames
= get_be32(pb
);
115 codec
->bits_per_coded_sample
= get_be16(pb
);
117 get_buffer(pb
, (uint8_t*)&ext
, sizeof(ext
));/* Sample rate is in */
118 sample_rate
= av_ext2dbl(ext
); /* 80 bits BE IEEE extended float */
119 codec
->sample_rate
= sample_rate
;
123 if (version
== AIFF_C_VERSION1
) {
124 codec
->codec_tag
= get_le32(pb
);
125 codec
->codec_id
= codec_get_id(codec_aiff_tags
, codec
->codec_tag
);
127 switch (codec
->codec_id
) {
128 case CODEC_ID_PCM_S16BE
:
129 codec
->codec_id
= aiff_codec_get_id(codec
->bits_per_coded_sample
);
130 codec
->bits_per_coded_sample
= av_get_bits_per_sample(codec
->codec_id
);
132 case CODEC_ID_ADPCM_IMA_QT
:
133 codec
->block_align
= 34*codec
->channels
;
134 codec
->frame_size
= 64;
137 codec
->block_align
= 2*codec
->channels
;
138 codec
->frame_size
= 6;
141 codec
->block_align
= 1*codec
->channels
;
142 codec
->frame_size
= 6;
145 codec
->block_align
= 33;
146 codec
->frame_size
= 160;
153 /* Need the codec type */
154 codec
->codec_id
= aiff_codec_get_id(codec
->bits_per_coded_sample
);
155 codec
->bits_per_coded_sample
= av_get_bits_per_sample(codec
->codec_id
);
158 /* Block align needs to be computed in all cases, as the definition
159 * is specific to applications -> here we use the WAVE format definition */
160 if (!codec
->block_align
)
161 codec
->block_align
= (codec
->bits_per_coded_sample
* codec
->channels
) >> 3;
163 codec
->bit_rate
= (codec
->frame_size
? codec
->sample_rate
/codec
->frame_size
:
164 codec
->sample_rate
) * (codec
->block_align
<< 3);
168 url_fseek(pb
, size
, SEEK_CUR
);
173 #ifdef CONFIG_AIFF_MUXER
180 static int aiff_write_header(AVFormatContext
*s
)
182 AIFFOutputContext
*aiff
= s
->priv_data
;
183 ByteIOContext
*pb
= s
->pb
;
184 AVCodecContext
*enc
= s
->streams
[0]->codec
;
185 AVExtFloat sample_rate
;
188 /* First verify if format is ok */
191 if (enc
->codec_tag
!= MKTAG('N','O','N','E'))
194 /* FORM AIFF header */
196 aiff
->form
= url_ftell(pb
);
197 put_be32(pb
, 0); /* file length */
198 put_tag(pb
, aifc
? "AIFC" : "AIFF");
200 if (aifc
) { // compressed audio
201 enc
->bits_per_coded_sample
= 16;
202 if (!enc
->block_align
) {
203 av_log(s
, AV_LOG_ERROR
, "block align not set\n");
209 put_be32(pb
, 0xA2805140);
214 put_be32(pb
, aifc
? 24 : 18); /* size */
215 put_be16(pb
, enc
->channels
); /* Number of channels */
217 aiff
->frames
= url_ftell(pb
);
218 put_be32(pb
, 0); /* Number of frames */
220 if (!enc
->bits_per_coded_sample
)
221 enc
->bits_per_coded_sample
= av_get_bits_per_sample(enc
->codec_id
);
222 if (!enc
->bits_per_coded_sample
) {
223 av_log(s
, AV_LOG_ERROR
, "could not compute bits per sample\n");
226 if (!enc
->block_align
)
227 enc
->block_align
= (enc
->bits_per_coded_sample
* enc
->channels
) >> 3;
229 put_be16(pb
, enc
->bits_per_coded_sample
); /* Sample size */
231 sample_rate
= av_dbl2ext((double)enc
->sample_rate
);
232 put_buffer(pb
, (uint8_t*)&sample_rate
, sizeof(sample_rate
));
235 put_le32(pb
, enc
->codec_tag
);
239 /* Sound data chunk */
241 aiff
->ssnd
= url_ftell(pb
); /* Sound chunk size */
242 put_be32(pb
, 0); /* Sound samples data size */
243 put_be32(pb
, 0); /* Data offset */
244 put_be32(pb
, 0); /* Block-size (block align) */
246 av_set_pts_info(s
->streams
[0], 64, 1, s
->streams
[0]->codec
->sample_rate
);
248 /* Data is starting here */
249 put_flush_packet(pb
);
254 static int aiff_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
256 ByteIOContext
*pb
= s
->pb
;
257 put_buffer(pb
, pkt
->data
, pkt
->size
);
261 static int aiff_write_trailer(AVFormatContext
*s
)
263 ByteIOContext
*pb
= s
->pb
;
264 AIFFOutputContext
*aiff
= s
->priv_data
;
265 AVCodecContext
*enc
= s
->streams
[0]->codec
;
267 /* Chunks sizes must be even */
268 offset_t file_size
, end_size
;
269 end_size
= file_size
= url_ftell(pb
);
275 if (!url_is_streamed(s
->pb
)) {
277 url_fseek(pb
, aiff
->form
, SEEK_SET
);
278 put_be32(pb
, file_size
- aiff
->form
- 4);
280 /* Number of sample frames */
281 url_fseek(pb
, aiff
->frames
, SEEK_SET
);
282 put_be32(pb
, (file_size
-aiff
->ssnd
-12)/enc
->block_align
);
284 /* Sound Data chunk size */
285 url_fseek(pb
, aiff
->ssnd
, SEEK_SET
);
286 put_be32(pb
, file_size
- aiff
->ssnd
- 4);
288 /* return to the end */
289 url_fseek(pb
, end_size
, SEEK_SET
);
291 put_flush_packet(pb
);
296 #endif /* CONFIG_AIFF_MUXER */
298 static int aiff_probe(AVProbeData
*p
)
300 /* check file header */
301 if (p
->buf
[0] == 'F' && p
->buf
[1] == 'O' &&
302 p
->buf
[2] == 'R' && p
->buf
[3] == 'M' &&
303 p
->buf
[8] == 'A' && p
->buf
[9] == 'I' &&
304 p
->buf
[10] == 'F' && (p
->buf
[11] == 'F' || p
->buf
[11] == 'C'))
305 return AVPROBE_SCORE_MAX
;
311 static int aiff_read_header(AVFormatContext
*s
,
312 AVFormatParameters
*ap
)
317 unsigned version
= AIFF_C_VERSION1
;
318 ByteIOContext
*pb
= s
->pb
;
319 AVStream
* st
= s
->streams
[0];
321 /* check FORM header */
322 filesize
= get_tag(pb
, &tag
);
323 if (filesize
< 0 || tag
!= MKTAG('F', 'O', 'R', 'M'))
324 return AVERROR_INVALIDDATA
;
328 if (tag
== MKTAG('A', 'I', 'F', 'F')) /* Got an AIFF file */
330 else if (tag
!= MKTAG('A', 'I', 'F', 'C')) /* An AIFF-C file then */
331 return AVERROR_INVALIDDATA
;
335 st
= av_new_stream(s
, 0);
337 return AVERROR(ENOMEM
);
339 while (filesize
> 0) {
340 /* parse different chunks */
341 size
= get_tag(pb
, &tag
);
345 filesize
-= size
+ 8;
348 case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */
349 /* Then for the complete header info */
350 st
->nb_frames
= get_aiff_header(pb
, st
->codec
, size
, version
);
351 if (st
->nb_frames
< 0)
352 return st
->nb_frames
;
353 if (offset
> 0) // COMM is after SSND
356 case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */
357 version
= get_be32(pb
);
359 case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */
360 get_meta(pb
, s
->title
, sizeof(s
->title
), size
);
362 case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */
363 get_meta(pb
, s
->author
, sizeof(s
->author
), size
);
365 case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */
366 get_meta(pb
, s
->copyright
, sizeof(s
->copyright
), size
);
368 case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */
369 get_meta(pb
, s
->comment
, sizeof(s
->comment
), size
);
371 case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */
372 offset
= get_be32(pb
); /* Offset of sound data */
373 get_be32(pb
); /* BlockSize... don't care */
374 offset
+= url_ftell(pb
); /* Compute absolute data offset */
375 if (st
->codec
->block_align
) /* Assume COMM already parsed */
377 if (url_is_streamed(pb
)) {
378 av_log(s
, AV_LOG_ERROR
, "file is not seekable\n");
381 url_fskip(pb
, size
- 8);
383 case MKTAG('w', 'a', 'v', 'e'):
384 if ((uint64_t)size
> (1<<30))
386 st
->codec
->extradata
= av_mallocz(size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
387 if (!st
->codec
->extradata
)
388 return AVERROR(ENOMEM
);
389 st
->codec
->extradata_size
= size
;
390 get_buffer(pb
, st
->codec
->extradata
, size
);
393 if (size
& 1) /* Always even aligned */
395 url_fskip (pb
, size
);
399 if (!st
->codec
->block_align
) {
400 av_log(s
, AV_LOG_ERROR
, "could not find COMM tag\n");
405 /* Now positioned, get the sound data start and end */
407 s
->file_size
= st
->nb_frames
* st
->codec
->block_align
;
409 av_set_pts_info(st
, 64, 1, st
->codec
->sample_rate
);
411 st
->duration
= st
->codec
->frame_size
?
412 st
->nb_frames
* st
->codec
->frame_size
: st
->nb_frames
;
414 /* Position the stream at the first block */
415 url_fseek(pb
, offset
, SEEK_SET
);
420 #define MAX_SIZE 4096
422 static int aiff_read_packet(AVFormatContext
*s
,
425 AVStream
*st
= s
->streams
[0];
428 /* End of stream may be reached */
432 /* Now for that packet */
433 res
= av_get_packet(s
->pb
, pkt
, (MAX_SIZE
/ st
->codec
->block_align
) * st
->codec
->block_align
);
437 /* Only one stream in an AIFF file */
438 pkt
->stream_index
= 0;
442 #ifdef CONFIG_AIFF_DEMUXER
443 AVInputFormat aiff_demuxer
= {
445 NULL_IF_CONFIG_SMALL("Audio IFF"),
452 .codec_tag
= (const AVCodecTag
* const []){codec_aiff_tags
, 0},
456 #ifdef CONFIG_AIFF_MUXER
457 AVOutputFormat aiff_muxer
= {
459 NULL_IF_CONFIG_SMALL("Audio IFF"),
462 sizeof(AIFFOutputContext
),
468 .codec_tag
= (const AVCodecTag
* const []){codec_aiff_tags
, 0},