FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/aiffdec.c
Date: 2024-02-16 17:37:06
Exec Total Coverage
Lines: 166 265 62.6%
Functions: 7 7 100.0%
Branches: 83 172 48.3%

Line Branch Exec Source
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/dict.h"
24 #include "avformat.h"
25 #include "demux.h"
26 #include "internal.h"
27 #include "pcm.h"
28 #include "aiff.h"
29 #include "id3v2.h"
30 #include "mov_chan.h"
31 #include "replaygain.h"
32
33 #define AIFF 0
34 #define AIFF_C_VERSION1 0xA2805140
35
36 typedef struct AIFFInputContext {
37 int64_t data_end;
38 int block_duration;
39 } AIFFInputContext;
40
41 6 static enum AVCodecID aiff_codec_get_id(int bps)
42 {
43
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (bps <= 8)
44 return AV_CODEC_ID_PCM_S8;
45
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (bps <= 16)
46 4 return AV_CODEC_ID_PCM_S16BE;
47
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (bps <= 24)
48 2 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 56 static int64_t get_tag(AVIOContext *pb, uint32_t * tag)
58 {
59 int64_t size;
60
61
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
56 if (avio_feof(pb))
62 return AVERROR(EIO);
63
64 56 *tag = avio_rl32(pb);
65 56 size = avio_rb32(pb);
66
67 56 return size;
68 }
69
70 /* Metadata string read */
71 6 static void get_meta(AVFormatContext *s, const char *key, int64_t size)
72 {
73 6 uint8_t *str = NULL;
74
75
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (size < SIZE_MAX)
76 6 str = av_malloc(size+1);
77
78
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (str) {
79 6 int res = avio_read(s->pb, str, size);
80
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (res < 0){
81 av_free(str);
82 return;
83 }
84 6 size -= res;
85 6 str[res] = 0;
86 6 av_dict_set(&s->metadata, key, str, AV_DICT_DONT_STRDUP_VAL);
87 }
88
89 6 avio_skip(s->pb, size);
90 }
91
92 /* Returns the number of sound data frames or negative on error */
93 12 static int get_aiff_header(AVFormatContext *s, int64_t size,
94 unsigned version)
95 {
96 12 AVIOContext *pb = s->pb;
97 12 AVCodecParameters *par = s->streams[0]->codecpar;
98 12 AIFFInputContext *aiff = s->priv_data;
99 int exp;
100 uint64_t val;
101 int sample_rate;
102 unsigned int num_frames;
103 int channels;
104
105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (size & 1)
106 size++;
107 12 par->codec_type = AVMEDIA_TYPE_AUDIO;
108 12 channels = avio_rb16(pb);
109 12 par->ch_layout.nb_channels = channels;
110 12 num_frames = avio_rb32(pb);
111 12 par->bits_per_coded_sample = avio_rb16(pb);
112
113 12 exp = avio_rb16(pb) - 16383 - 63;
114 12 val = avio_rb64(pb);
115
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (exp <-63 || exp >63) {
116 av_log(s, AV_LOG_ERROR, "exp %d is out of range\n", exp);
117 return AVERROR_INVALIDDATA;
118 }
119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (exp >= 0)
120 sample_rate = val << exp;
121 else
122 12 sample_rate = (val + (1ULL<<(-exp-1))) >> -exp;
123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (sample_rate <= 0)
124 return AVERROR_INVALIDDATA;
125
126 12 par->sample_rate = sample_rate;
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (size < 18)
128 return AVERROR_INVALIDDATA;
129 12 size -= 18;
130
131 /* get codec id for AIFF-C */
132
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (size < 4) {
133 6 version = AIFF;
134
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 } else if (version == AIFF_C_VERSION1) {
135 6 par->codec_tag = avio_rl32(pb);
136 6 par->codec_id = ff_codec_get_id(ff_codec_aiff_tags, par->codec_tag);
137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (par->codec_id == AV_CODEC_ID_NONE)
138 avpriv_request_sample(s, "unknown or unsupported codec tag: %s",
139 av_fourcc2str(par->codec_tag));
140 6 size -= 4;
141 }
142
143
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
12 if (version != AIFF_C_VERSION1 || par->codec_id == AV_CODEC_ID_PCM_S16BE) {
144 6 par->codec_id = aiff_codec_get_id(par->bits_per_coded_sample);
145 6 par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
146 6 aiff->block_duration = 1;
147 } else {
148
2/7
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
6 switch (par->codec_id) {
149 2 case AV_CODEC_ID_PCM_F32BE:
150 case AV_CODEC_ID_PCM_F64BE:
151 case AV_CODEC_ID_PCM_S16LE:
152 case AV_CODEC_ID_PCM_ALAW:
153 case AV_CODEC_ID_PCM_MULAW:
154 2 aiff->block_duration = 1;
155 2 break;
156 4 case AV_CODEC_ID_ADPCM_IMA_QT:
157 4 par->block_align = 34 * channels;
158 4 break;
159 case AV_CODEC_ID_MACE3:
160 par->block_align = 2 * channels;
161 break;
162 case AV_CODEC_ID_ADPCM_G726LE:
163 par->bits_per_coded_sample = 5;
164 case AV_CODEC_ID_ADPCM_IMA_WS:
165 case AV_CODEC_ID_ADPCM_G722:
166 case AV_CODEC_ID_MACE6:
167 case AV_CODEC_ID_CBD2_DPCM:
168 case AV_CODEC_ID_SDX2_DPCM:
169 par->block_align = 1 * channels;
170 break;
171 case AV_CODEC_ID_GSM:
172 par->block_align = 33;
173 break;
174 default:
175 aiff->block_duration = 1;
176 break;
177 }
178
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (par->block_align > 0)
179 4 aiff->block_duration = av_get_audio_frame_duration2(par,
180 par->block_align);
181 }
182
183 /* Block align needs to be computed in all cases, as the definition
184 * is specific to applications -> here we use the WAVE format definition */
185
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 if (!par->block_align)
186 8 par->block_align = (av_get_bits_per_sample(par->codec_id) * channels) >> 3;
187
188
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (aiff->block_duration) {
189 12 par->bit_rate = av_rescale(par->sample_rate, par->block_align * 8LL,
190 12 aiff->block_duration);
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (par->bit_rate < 0)
192 par->bit_rate = 0;
193 }
194
195 /* Chunk is over */
196
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (size)
197 6 avio_skip(pb, size);
198
199 12 return num_frames;
200 }
201
202 7023 static int aiff_probe(const AVProbeData *p)
203 {
204 /* check file header */
205
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 7002 times.
7023 if (AV_RL32(p->buf) == MKTAG('F', 'O', 'R', 'M') &&
206
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 AV_RB32(p->buf + 4) >= 4 &&
207
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
21 p->buf[8] == 'A' && p->buf[9] == 'I' &&
208
4/6
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
12 p->buf[10] == 'F' && (p->buf[11] == 'F' || p->buf[11] == 'C'))
209 12 return AVPROBE_SCORE_MAX;
210 else
211 7011 return 0;
212 }
213
214 /* aiff input */
215 12 static int aiff_read_header(AVFormatContext *s)
216 {
217 int ret;
218 int64_t filesize, size;
219 12 int64_t offset = 0, position;
220 uint32_t tag;
221 12 unsigned version = AIFF_C_VERSION1;
222 12 AVIOContext *pb = s->pb;
223 AVStream * st;
224 12 AIFFInputContext *aiff = s->priv_data;
225 ID3v2ExtraMeta *id3v2_extra_meta;
226
227 /* check FORM header */
228 12 filesize = get_tag(pb, &tag);
229
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (filesize < 4 || tag != MKTAG('F', 'O', 'R', 'M'))
230 return AVERROR_INVALIDDATA;
231
232 /* AIFF data type */
233 12 tag = avio_rl32(pb);
234
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (tag == MKTAG('A', 'I', 'F', 'F')) /* Got an AIFF file */
235 6 version = AIFF;
236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 else if (tag != MKTAG('A', 'I', 'F', 'C')) /* An AIFF-C file then */
237 return AVERROR_INVALIDDATA;
238
239 12 filesize -= 4;
240
241 12 st = avformat_new_stream(s, NULL);
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!st)
243 return AVERROR(ENOMEM);
244
245
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 12 times.
56 while (filesize > 0) {
246 /* parse different chunks */
247 44 size = get_tag(pb, &tag);
248
249
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
44 if (size == AVERROR_EOF && offset > 0 && st->codecpar->block_align) {
250 av_log(s, AV_LOG_WARNING, "header parser hit EOF\n");
251 goto got_sound;
252 }
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (size < 0)
254 return size;
255
256 44 filesize -= size + 8;
257
258
6/13
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
44 switch (tag) {
259 12 case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */
260 /* Then for the complete header info */
261 12 st->nb_frames = get_aiff_header(s, size, version);
262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (st->nb_frames < 0)
263 return st->nb_frames;
264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (offset > 0) // COMM is after SSND
265 goto got_sound;
266 12 break;
267 6 case MKTAG('I', 'D', '3', ' '):
268 6 position = avio_tell(pb);
269 6 ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size);
270
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (id3v2_extra_meta)
271
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
12 if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0 ||
272 6 (ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) {
273 ff_id3v2_free_extra_meta(&id3v2_extra_meta);
274 return ret;
275 }
276 6 ff_id3v2_free_extra_meta(&id3v2_extra_meta);
277
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (position + size > avio_tell(pb))
278 avio_skip(pb, position + size - avio_tell(pb));
279 6 break;
280 6 case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */
281 6 version = avio_rb32(pb);
282 6 break;
283 6 case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */
284 6 get_meta(s, "title" , size);
285 6 break;
286 case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */
287 get_meta(s, "author" , size);
288 break;
289 case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */
290 get_meta(s, "copyright", size);
291 break;
292 case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */
293 get_meta(s, "comment" , size);
294 break;
295 12 case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (size < 8)
297 return AVERROR_INVALIDDATA;
298 12 aiff->data_end = avio_tell(pb) + size;
299 12 offset = avio_rb32(pb); /* Offset of sound data */
300 12 avio_rb32(pb); /* BlockSize... don't care */
301 12 offset += avio_tell(pb); /* Compute absolute data offset */
302
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (st->codecpar->block_align && !(pb->seekable & AVIO_SEEKABLE_NORMAL)) /* Assume COMM already parsed */
303 goto got_sound;
304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) {
305 av_log(s, AV_LOG_ERROR, "file is not seekable\n");
306 return -1;
307 }
308 12 avio_skip(pb, size - 8);
309 12 break;
310 case MKTAG('w', 'a', 'v', 'e'):
311 if ((uint64_t)size > (1<<30))
312 return AVERROR_INVALIDDATA;
313 if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0)
314 return ret;
315 if ( (st->codecpar->codec_id == AV_CODEC_ID_QDMC || st->codecpar->codec_id == AV_CODEC_ID_QDM2)
316 && size>=12*4 && !st->codecpar->block_align) {
317 st->codecpar->block_align = AV_RB32(st->codecpar->extradata+11*4);
318 aiff->block_duration = AV_RB32(st->codecpar->extradata+9*4);
319 } else if (st->codecpar->codec_id == AV_CODEC_ID_QCELP) {
320 char rate = 0;
321 if (size >= 25)
322 rate = st->codecpar->extradata[24];
323 switch (rate) {
324 case 'H': // RATE_HALF
325 st->codecpar->block_align = 17;
326 break;
327 case 'F': // RATE_FULL
328 default:
329 st->codecpar->block_align = 35;
330 }
331 aiff->block_duration = 160;
332 st->codecpar->bit_rate = (int64_t)st->codecpar->sample_rate * (st->codecpar->block_align << 3) /
333 aiff->block_duration;
334 }
335 break;
336 2 case MKTAG('C','H','A','N'):
337
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = ff_mov_read_chan(s, pb, st, size)) < 0)
338 return ret;
339 2 break;
340 case MKTAG('A','P','C','M'): /* XA ADPCM compressed sound chunk */
341 st->codecpar->codec_id = AV_CODEC_ID_ADPCM_XA;
342 aiff->data_end = avio_tell(pb) + size;
343 offset = avio_tell(pb) + 8;
344 /* This field is unknown and its data seems to be irrelevant */
345 avio_rb32(pb);
346 st->codecpar->block_align = avio_rb32(pb);
347
348 goto got_sound;
349 break;
350 case 0:
351 if (offset > 0 && st->codecpar->block_align) // COMM && SSND
352 goto got_sound;
353 default: /* Jump */
354 avio_skip(pb, size);
355 }
356
357 /* Skip required padding byte for odd-sized chunks. */
358
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 42 times.
44 if (size & 1) {
359 2 filesize--;
360 2 avio_skip(pb, 1);
361 }
362 }
363
364 12 ret = ff_replaygain_export(st, s->metadata);
365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0)
366 return ret;
367
368 12 got_sound:
369
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 if (!st->codecpar->block_align && st->codecpar->codec_id == AV_CODEC_ID_QCELP) {
370 av_log(s, AV_LOG_WARNING, "qcelp without wave chunk, assuming full rate\n");
371 st->codecpar->block_align = 35;
372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 } else if (st->codecpar->block_align <= 0) {
373 av_log(s, AV_LOG_ERROR, "could not find COMM tag or invalid block_align value\n");
374 return AVERROR_INVALIDDATA;
375 }
376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (aiff->block_duration < 0)
377 return AVERROR_INVALIDDATA;
378
379 /* Now positioned, get the sound data start and end */
380 12 avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
381 12 st->start_time = 0;
382 12 st->duration = st->nb_frames * aiff->block_duration;
383
384 /* Position the stream at the first block */
385 12 avio_seek(pb, offset, SEEK_SET);
386
387 12 return 0;
388 }
389
390 #define MAX_SIZE 4096
391
392 8871 static int aiff_read_packet(AVFormatContext *s,
393 AVPacket *pkt)
394 {
395 8871 AVStream *st = s->streams[0];
396 8871 AIFFInputContext *aiff = s->priv_data;
397 int64_t max_size;
398 int res, size;
399
400 /* calculate size of remaining data */
401 8871 max_size = aiff->data_end - avio_tell(s->pb);
402
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 8850 times.
8871 if (max_size <= 0)
403 21 return AVERROR_EOF;
404
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8850 times.
8850 if (!st->codecpar->block_align) {
406 av_log(s, AV_LOG_ERROR, "block_align not set\n");
407 return AVERROR_INVALIDDATA;
408 }
409
410 /* Now for that packet */
411
2/2
✓ Branch 0 taken 8422 times.
✓ Branch 1 taken 428 times.
8850 switch (st->codecpar->codec_id) {
412 8422 case AV_CODEC_ID_ADPCM_IMA_QT:
413 case AV_CODEC_ID_GSM:
414 case AV_CODEC_ID_QDM2:
415 case AV_CODEC_ID_QCELP:
416 8422 size = st->codecpar->block_align;
417 8422 break;
418 428 default:
419
1/2
✓ Branch 0 taken 428 times.
✗ Branch 1 not taken.
428 size = st->codecpar->block_align ? (MAX_SIZE / st->codecpar->block_align) * st->codecpar->block_align : MAX_SIZE;
420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 428 times.
428 if (!size)
421 return AVERROR_INVALIDDATA;
422 }
423 8850 size = FFMIN(max_size, size);
424 8850 res = av_get_packet(s->pb, pkt, size);
425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8850 times.
8850 if (res < 0)
426 return res;
427
428
1/2
✓ Branch 0 taken 8850 times.
✗ Branch 1 not taken.
8850 if (size >= st->codecpar->block_align)
429 8850 pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
430 /* Only one stream in an AIFF file */
431 8850 pkt->stream_index = 0;
432 8850 pkt->duration = (res / st->codecpar->block_align) * (int64_t) aiff->block_duration;
433 8850 return 0;
434 }
435
436 const AVInputFormat ff_aiff_demuxer = {
437 .name = "aiff",
438 .long_name = NULL_IF_CONFIG_SMALL("Audio IFF"),
439 .priv_data_size = sizeof(AIFFInputContext),
440 .read_probe = aiff_probe,
441 .read_header = aiff_read_header,
442 .read_packet = aiff_read_packet,
443 .read_seek = ff_pcm_read_seek,
444 .codec_tag = ff_aiff_codec_tags_list,
445 };
446