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"
28 #define AIFF_C_VERSION1 0xA2805140
34 static enum CodecID
aiff_codec_get_id(int bps
)
37 return CODEC_ID_PCM_S8
;
39 return CODEC_ID_PCM_S16BE
;
41 return CODEC_ID_PCM_S24BE
;
43 return CODEC_ID_PCM_S32BE
;
45 /* bigger than 32 isn't allowed */
49 /* returns the size of the found tag */
50 static int get_tag(ByteIOContext
*pb
, uint32_t * tag
)
66 /* Metadata string read */
67 static void get_meta(AVFormatContext
*s
, const char *key
, int size
)
70 int res
= get_buffer(s
->pb
, str
, FFMIN(sizeof(str
)-1, size
));
79 url_fskip(s
->pb
, size
);
81 av_metadata_set(&s
->metadata
, key
, str
);
84 /* Returns the number of sound data frames or negative on error */
85 static unsigned int get_aiff_header(ByteIOContext
*pb
, AVCodecContext
*codec
,
86 int size
, unsigned version
)
90 unsigned int num_frames
;
94 codec
->codec_type
= CODEC_TYPE_AUDIO
;
95 codec
->channels
= get_be16(pb
);
96 num_frames
= get_be32(pb
);
97 codec
->bits_per_coded_sample
= get_be16(pb
);
99 get_buffer(pb
, (uint8_t*)&ext
, sizeof(ext
));/* Sample rate is in */
100 sample_rate
= av_ext2dbl(ext
); /* 80 bits BE IEEE extended float */
101 codec
->sample_rate
= sample_rate
;
105 if (version
== AIFF_C_VERSION1
) {
106 codec
->codec_tag
= get_le32(pb
);
107 codec
->codec_id
= ff_codec_get_id(ff_codec_aiff_tags
, codec
->codec_tag
);
109 switch (codec
->codec_id
) {
110 case CODEC_ID_PCM_S16BE
:
111 codec
->codec_id
= aiff_codec_get_id(codec
->bits_per_coded_sample
);
112 codec
->bits_per_coded_sample
= av_get_bits_per_sample(codec
->codec_id
);
114 case CODEC_ID_ADPCM_IMA_QT
:
115 codec
->block_align
= 34*codec
->channels
;
116 codec
->frame_size
= 64;
119 codec
->block_align
= 2*codec
->channels
;
120 codec
->frame_size
= 6;
123 codec
->block_align
= 1*codec
->channels
;
124 codec
->frame_size
= 6;
127 codec
->block_align
= 33;
128 codec
->frame_size
= 160;
135 /* Need the codec type */
136 codec
->codec_id
= aiff_codec_get_id(codec
->bits_per_coded_sample
);
137 codec
->bits_per_coded_sample
= av_get_bits_per_sample(codec
->codec_id
);
140 /* Block align needs to be computed in all cases, as the definition
141 * is specific to applications -> here we use the WAVE format definition */
142 if (!codec
->block_align
)
143 codec
->block_align
= (codec
->bits_per_coded_sample
* codec
->channels
) >> 3;
145 codec
->bit_rate
= (codec
->frame_size
? codec
->sample_rate
/codec
->frame_size
:
146 codec
->sample_rate
) * (codec
->block_align
<< 3);
150 url_fseek(pb
, size
, SEEK_CUR
);
155 static int aiff_probe(AVProbeData
*p
)
157 /* check file header */
158 if (p
->buf
[0] == 'F' && p
->buf
[1] == 'O' &&
159 p
->buf
[2] == 'R' && p
->buf
[3] == 'M' &&
160 p
->buf
[8] == 'A' && p
->buf
[9] == 'I' &&
161 p
->buf
[10] == 'F' && (p
->buf
[11] == 'F' || p
->buf
[11] == 'C'))
162 return AVPROBE_SCORE_MAX
;
168 static int aiff_read_header(AVFormatContext
*s
,
169 AVFormatParameters
*ap
)
174 unsigned version
= AIFF_C_VERSION1
;
175 ByteIOContext
*pb
= s
->pb
;
177 AIFFInputContext
*aiff
= s
->priv_data
;
179 /* check FORM header */
180 filesize
= get_tag(pb
, &tag
);
181 if (filesize
< 0 || tag
!= MKTAG('F', 'O', 'R', 'M'))
182 return AVERROR_INVALIDDATA
;
186 if (tag
== MKTAG('A', 'I', 'F', 'F')) /* Got an AIFF file */
188 else if (tag
!= MKTAG('A', 'I', 'F', 'C')) /* An AIFF-C file then */
189 return AVERROR_INVALIDDATA
;
193 st
= av_new_stream(s
, 0);
195 return AVERROR(ENOMEM
);
197 while (filesize
> 0) {
198 /* parse different chunks */
199 size
= get_tag(pb
, &tag
);
203 filesize
-= size
+ 8;
206 case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */
207 /* Then for the complete header info */
208 st
->nb_frames
= get_aiff_header(pb
, st
->codec
, size
, version
);
209 if (st
->nb_frames
< 0)
210 return st
->nb_frames
;
211 if (offset
> 0) // COMM is after SSND
214 case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */
215 version
= get_be32(pb
);
217 case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */
218 get_meta(s
, "title" , size
);
220 case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */
221 get_meta(s
, "author" , size
);
223 case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */
224 get_meta(s
, "copyright", size
);
226 case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */
227 get_meta(s
, "comment" , size
);
229 case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */
230 aiff
->data_end
= url_ftell(pb
) + size
;
231 offset
= get_be32(pb
); /* Offset of sound data */
232 get_be32(pb
); /* BlockSize... don't care */
233 offset
+= url_ftell(pb
); /* Compute absolute data offset */
234 if (st
->codec
->block_align
) /* Assume COMM already parsed */
236 if (url_is_streamed(pb
)) {
237 av_log(s
, AV_LOG_ERROR
, "file is not seekable\n");
240 url_fskip(pb
, size
- 8);
242 case MKTAG('w', 'a', 'v', 'e'):
243 if ((uint64_t)size
> (1<<30))
245 st
->codec
->extradata
= av_mallocz(size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
246 if (!st
->codec
->extradata
)
247 return AVERROR(ENOMEM
);
248 st
->codec
->extradata_size
= size
;
249 get_buffer(pb
, st
->codec
->extradata
, size
);
252 if (size
& 1) /* Always even aligned */
254 url_fskip (pb
, size
);
258 if (!st
->codec
->block_align
) {
259 av_log(s
, AV_LOG_ERROR
, "could not find COMM tag\n");
264 /* Now positioned, get the sound data start and end */
266 s
->file_size
= st
->nb_frames
* st
->codec
->block_align
;
268 av_set_pts_info(st
, 64, 1, st
->codec
->sample_rate
);
270 st
->duration
= st
->codec
->frame_size
?
271 st
->nb_frames
* st
->codec
->frame_size
: st
->nb_frames
;
273 /* Position the stream at the first block */
274 url_fseek(pb
, offset
, SEEK_SET
);
279 #define MAX_SIZE 4096
281 static int aiff_read_packet(AVFormatContext
*s
,
284 AVStream
*st
= s
->streams
[0];
285 AIFFInputContext
*aiff
= s
->priv_data
;
289 /* calculate size of remaining data */
290 max_size
= aiff
->data_end
- url_ftell(s
->pb
);
294 /* Now for that packet */
295 max_size
= FFMIN(max_size
, (MAX_SIZE
/ st
->codec
->block_align
) * st
->codec
->block_align
);
296 res
= av_get_packet(s
->pb
, pkt
, max_size
);
300 /* Only one stream in an AIFF file */
301 pkt
->stream_index
= 0;
305 AVInputFormat aiff_demuxer
= {
307 NULL_IF_CONFIG_SMALL("Audio IFF"),
308 sizeof(AIFFInputContext
),
314 .codec_tag
= (const AVCodecTag
* const []){ff_codec_aiff_tags
, 0},