Coverage Report

Created: 2026-09-14 08:00

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