Coverage Report

Created: 2026-05-21 08:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/codec/avcodec/audio.c
Line
Count
Source
1
/*****************************************************************************
2
 * audio.c: audio decoder using libavcodec library
3
 *****************************************************************************
4
 * Copyright (C) 1999-2003 VLC authors and VideoLAN
5
 *
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *          Gildas Bazin <gbazin@videolan.org>
8
 *
9
 * This program is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation; either version 2.1 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program; if not, write to the Free Software Foundation,
21
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22
 *****************************************************************************/
23
24
/*****************************************************************************
25
 * Preamble
26
 *****************************************************************************/
27
#ifdef HAVE_CONFIG_H
28
# include "config.h"
29
#endif
30
31
#include <assert.h>
32
33
#include <vlc_common.h>
34
#include <vlc_aout.h>
35
#include <vlc_codec.h>
36
#include <vlc_avcodec.h>
37
38
#include "avcodec.h"
39
40
#include <libavcodec/avcodec.h>
41
#include <libavutil/mem.h>
42
43
#define API_CHANNEL_LAYOUT_STRUCT (LIBAVCODEC_VERSION_CHECK(59, 24, 100)) // AVCodecContext.ch_layout
44
45
#include <libavutil/channel_layout.h>
46
47
48
/*****************************************************************************
49
 * decoder_sys_t : decoder descriptor
50
 *****************************************************************************/
51
typedef struct
52
{
53
    AVCodecContext *p_context;
54
    const AVCodec  *p_codec;
55
56
    /*
57
     * Output properties
58
     */
59
    audio_sample_format_t aout_format;
60
    date_t                end_date;
61
62
    /* */
63
    int     i_reject_count;
64
65
    /* */
66
    bool    b_extract;
67
    bool    discontinuity;
68
    int     pi_extraction[AOUT_CHAN_MAX];
69
    int     i_previous_channels;
70
    uint64_t i_previous_layout;
71
} decoder_sys_t;
72
73
7.88M
#define BLOCK_FLAG_PRIVATE_REALLOCATED (1 << BLOCK_FLAG_PRIVATE_SHIFT)
74
75
static void SetupOutputFormat( decoder_t *p_dec, bool b_trust );
76
static block_t * ConvertAVFrame( decoder_t *p_dec, AVFrame *frame );
77
static int  DecodeAudio( decoder_t *, block_t * );
78
static void Flush( decoder_t * );
79
80
static void InitDecoderConfig( decoder_t *p_dec, AVCodecContext *p_context )
81
649k
{
82
649k
    if( p_dec->fmt_in->i_extra > 0 )
83
66.4k
    {
84
66.4k
        const uint8_t * const p_src = p_dec->fmt_in->p_extra;
85
86
66.4k
        int i_offset = 0;
87
66.4k
        int i_size = p_dec->fmt_in->i_extra;
88
89
66.4k
        if( p_dec->fmt_in->i_codec == VLC_CODEC_ALAC )
90
1
        {
91
1
            static const uint8_t p_pattern[] = { 0, 0, 0, 36, 'a', 'l', 'a', 'c' };
92
            /* Find alac atom XXX it is a bit ugly */
93
21
            for( i_offset = 0; i_offset < i_size - (int)sizeof(p_pattern); i_offset++ )
94
21
            {
95
21
                if( !memcmp( &p_src[i_offset], p_pattern, sizeof(p_pattern) ) )
96
1
                    break;
97
21
            }
98
1
            i_size = __MIN( p_dec->fmt_in->i_extra - i_offset, 36 );
99
1
            if( i_size < 36 )
100
0
                i_size = 0;
101
1
        }
102
103
66.4k
        if( i_size > 0 )
104
66.4k
        {
105
66.4k
            p_context->extradata =
106
66.4k
                av_malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
107
66.4k
            if( p_context->extradata )
108
66.4k
            {
109
66.4k
                uint8_t *p_dst = p_context->extradata;
110
111
66.4k
                p_context->extradata_size = i_size;
112
113
66.4k
                memcpy( &p_dst[0],            &p_src[i_offset], i_size );
114
66.4k
                memset( &p_dst[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE );
115
66.4k
            }
116
66.4k
        }
117
66.4k
    }
118
583k
    else
119
583k
    {
120
583k
        p_context->extradata_size = 0;
121
583k
        p_context->extradata = NULL;
122
583k
    }
123
649k
}
124
125
static int OpenAudioCodec( decoder_t *p_dec )
126
649k
{
127
649k
    decoder_sys_t *p_sys = p_dec->p_sys;
128
649k
    AVCodecContext *ctx = p_sys->p_context;
129
649k
    const AVCodec *codec = p_sys->p_codec;
130
131
649k
    if( ctx->extradata_size <= 0 )
132
583k
    {
133
583k
        if( codec->id == AV_CODEC_ID_VORBIS ||
134
583k
            ( codec->id == AV_CODEC_ID_AAC &&
135
4.85k
              !p_dec->fmt_in->b_packetized ) )
136
0
        {
137
0
            msg_Warn( p_dec, "waiting for extra data for codec %s",
138
0
                      codec->name );
139
0
            return 1;
140
0
        }
141
583k
    }
142
143
649k
    ctx->sample_rate = p_dec->fmt_in->audio.i_rate;
144
649k
#if API_CHANNEL_LAYOUT_STRUCT && LIBAVUTIL_VERSION_CHECK(57, 24, 100)
145
649k
    av_channel_layout_default( &ctx->ch_layout, p_dec->fmt_in->audio.i_channels );
146
#else
147
    ctx->channels = p_dec->fmt_in->audio.i_channels;
148
#endif
149
649k
    ctx->block_align = p_dec->fmt_in->audio.i_blockalign;
150
649k
    ctx->bit_rate = p_dec->fmt_in->i_bitrate;
151
649k
    ctx->bits_per_coded_sample = p_dec->fmt_in->audio.i_bitspersample;
152
153
649k
    if( codec->id == AV_CODEC_ID_ADPCM_G726 &&
154
115
        ctx->bit_rate > 0 &&
155
115
        ctx->sample_rate >  0)
156
41
        ctx->bits_per_coded_sample = ctx->bit_rate / ctx->sample_rate;
157
158
649k
    return ffmpeg_OpenCodec( p_dec, ctx, codec );
159
649k
}
160
161
/**
162
 * Allocates decoded audio buffer for libavcodec to use.
163
 */
164
typedef struct
165
{
166
    block_t self;
167
    AVFrame *frame;
168
} vlc_av_frame_t;
169
170
static void vlc_av_frame_Release(block_t *block)
171
0
{
172
0
    vlc_av_frame_t *b = (void *)block;
173
174
0
    av_frame_free(&b->frame);
175
0
    free(b);
176
0
}
177
178
static const struct vlc_block_callbacks vlc_av_frame_cbs =
179
{
180
    vlc_av_frame_Release,
181
};
182
183
static block_t *vlc_av_frame_Wrap(AVFrame *frame)
184
0
{
185
0
    for (unsigned i = 1; i < AV_NUM_DATA_POINTERS; i++)
186
0
        assert(frame->linesize[i] == 0); /* only packed frame supported */
187
188
0
    if (av_frame_make_writable(frame)) /* TODO: read-only block_t */
189
0
        return NULL;
190
191
0
    vlc_av_frame_t *b = malloc(sizeof (*b));
192
0
    if (unlikely(b == NULL))
193
0
        return NULL;
194
195
0
    block_t *block = &b->self;
196
197
0
    block_Init(block, &vlc_av_frame_cbs,
198
0
               frame->extended_data[0], frame->linesize[0]);
199
0
    block->i_nb_samples = frame->nb_samples;
200
0
    b->frame = frame;
201
0
    return block;
202
0
}
203
204
/*****************************************************************************
205
 * EndAudio: decoder destruction
206
 *****************************************************************************
207
 * This function is called when the thread ends after a successful
208
 * initialization.
209
 *****************************************************************************/
210
void EndAudioDec( vlc_object_t *obj )
211
584k
{
212
584k
    decoder_t *p_dec = (decoder_t *)obj;
213
584k
    decoder_sys_t *sys = p_dec->p_sys;
214
584k
    AVCodecContext *ctx = sys->p_context;
215
216
584k
    avcodec_free_context( &ctx );
217
584k
    free( sys );
218
584k
}
219
220
/*****************************************************************************
221
 * InitAudioDec: initialize audio decoder
222
 *****************************************************************************
223
 * The avcodec codec will be opened, some memory allocated.
224
 *****************************************************************************/
225
int InitAudioDec( vlc_object_t *obj )
226
652k
{
227
652k
    decoder_t *p_dec = (decoder_t *)obj;
228
652k
    const AVCodec *codec;
229
652k
    AVCodecContext *avctx = ffmpeg_AllocContext( p_dec, &codec );
230
652k
    if( avctx == NULL )
231
2.54k
        return VLC_EGENERIC;
232
233
    /* Allocate the memory needed to store the decoder's structure */
234
649k
    decoder_sys_t *p_sys = malloc(sizeof(*p_sys));
235
649k
    if( unlikely(p_sys == NULL) )
236
0
    {
237
0
        avcodec_free_context( &avctx );
238
0
        return VLC_ENOMEM;
239
0
    }
240
241
649k
    p_dec->p_sys = p_sys;
242
649k
    p_sys->p_context = avctx;
243
649k
    p_sys->p_codec = codec;
244
245
    // Initialize decoder extradata
246
649k
    InitDecoderConfig( p_dec, avctx );
247
248
    /* ***** Open the codec ***** */
249
649k
    if( OpenAudioCodec( p_dec ) < 0 )
250
64.8k
    {
251
64.8k
        free( p_sys );
252
64.8k
        avcodec_free_context( &avctx );
253
64.8k
        return VLC_EGENERIC;
254
64.8k
    }
255
256
584k
    p_sys->i_reject_count = 0;
257
584k
    p_sys->b_extract = false;
258
584k
    p_sys->i_previous_channels = 0;
259
584k
    p_sys->i_previous_layout = 0;
260
584k
    p_sys->discontinuity = false;
261
262
    /* */
263
    /* Try to set as much information as possible but do not trust it */
264
584k
    SetupOutputFormat( p_dec, false );
265
266
584k
    if( !p_dec->fmt_out.audio.i_rate )
267
10.4k
        p_dec->fmt_out.audio.i_rate = p_dec->fmt_in->audio.i_rate;
268
584k
    if( p_dec->fmt_out.audio.i_rate )
269
574k
        date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
270
584k
    p_dec->fmt_out.audio.i_chan_mode = p_dec->fmt_in->audio.i_chan_mode;
271
272
584k
    p_dec->pf_decode = DecodeAudio;
273
584k
    p_dec->pf_flush  = Flush;
274
275
584k
    return VLC_SUCCESS;
276
649k
}
277
278
/*****************************************************************************
279
 * Flush:
280
 *****************************************************************************/
281
static void Flush( decoder_t *p_dec )
282
0
{
283
0
    decoder_sys_t *p_sys = p_dec->p_sys;
284
0
    AVCodecContext *ctx = p_sys->p_context;
285
286
0
    if( avcodec_is_open( ctx ) )
287
0
        avcodec_flush_buffers( ctx );
288
0
    date_Set( &p_sys->end_date, VLC_TICK_INVALID );
289
290
0
    if( ctx->codec_id == AV_CODEC_ID_MP2 ||
291
0
        ctx->codec_id == AV_CODEC_ID_MP3 )
292
0
        p_sys->i_reject_count = 3;
293
0
    p_sys->discontinuity = false;
294
0
}
295
296
/*****************************************************************************
297
 * DecodeBlock: Called to decode one frame
298
 *****************************************************************************/
299
static int DecodeBlock( decoder_t *p_dec, block_t **pp_block )
300
8.11M
{
301
8.11M
    decoder_sys_t *p_sys = p_dec->p_sys;
302
8.11M
    AVCodecContext *ctx = p_sys->p_context;
303
8.11M
    AVFrame *frame = NULL;
304
8.11M
    block_t *p_block = NULL;
305
8.11M
    bool b_error = false;
306
307
8.11M
    if( !ctx->extradata_size && p_dec->fmt_in->i_extra
308
0
     && !avcodec_is_open( ctx ) )
309
0
    {
310
0
        InitDecoderConfig( p_dec, ctx );
311
0
        if( OpenAudioCodec( p_dec ) < 0 )
312
0
        {
313
0
            if( pp_block != NULL && *pp_block != NULL )
314
0
                block_Release( *pp_block );
315
0
            return VLCDEC_ECRITICAL;
316
0
        }
317
0
    }
318
319
8.11M
    if( !avcodec_is_open( ctx ) )
320
0
    {
321
0
        if( pp_block )
322
0
            p_block = *pp_block;
323
0
        goto drop;
324
0
    }
325
326
8.11M
    if( pp_block == NULL ) /* Drain request */
327
4.17M
    {
328
        /* we don't need to care about return val */
329
4.17M
        (void) avcodec_send_packet( ctx, NULL );
330
4.17M
    }
331
3.94M
    else
332
3.94M
    {
333
3.94M
        p_block = *pp_block;
334
3.94M
    }
335
336
8.11M
    if( p_block )
337
3.94M
    {
338
3.94M
        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
339
0
        {
340
0
            Flush( p_dec );
341
0
            goto drop;
342
0
        }
343
344
3.94M
        if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
345
9.20k
        {
346
9.20k
            date_Set( &p_sys->end_date, VLC_TICK_INVALID );
347
9.20k
        }
348
349
        /* We've just started the stream, wait for the first PTS. */
350
3.94M
        if( p_block->i_pts == VLC_TICK_INVALID &&
351
1.15k
            date_Get( &p_sys->end_date ) == VLC_TICK_INVALID )
352
1.15k
            goto drop;
353
354
3.94M
        if( p_block->i_buffer <= 0 )
355
1.54k
            goto drop;
356
357
3.94M
        if( (p_block->i_flags & BLOCK_FLAG_PRIVATE_REALLOCATED) == 0 )
358
3.94M
        {
359
3.94M
            *pp_block = p_block = block_Realloc( p_block, 0, p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE );
360
3.94M
            if( !p_block )
361
0
                goto end;
362
3.94M
            p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE;
363
3.94M
            memset( &p_block->p_buffer[p_block->i_buffer], 0, FF_INPUT_BUFFER_PADDING_SIZE );
364
365
3.94M
            p_block->i_flags |= BLOCK_FLAG_PRIVATE_REALLOCATED;
366
3.94M
        }
367
3.94M
    }
368
369
8.11M
    frame = av_frame_alloc();
370
8.11M
    if (unlikely(frame == NULL))
371
0
        goto end;
372
373
8.11M
    bool send_failed = false;
374
13.2M
    for( int ret = 0; ret == 0; )
375
8.11M
    {
376
        /* Feed in the loop as buffer could have been full on first iterations */
377
8.11M
        if( p_block )
378
3.94M
        {
379
3.94M
            AVPacket *pkt = av_packet_alloc();
380
3.94M
            if( !pkt )
381
0
                goto end;
382
3.94M
            pkt->data = p_block->p_buffer;
383
3.94M
            pkt->size = p_block->i_buffer;
384
3.94M
            ret = avcodec_send_packet( ctx, pkt );
385
3.94M
            av_packet_free(&pkt);
386
3.94M
            if( ret == 0 ) /* Block has been consumed */
387
2.96M
            {
388
                /* Only set new pts from input block if it has been used,
389
                 * otherwise let it be through interpolation */
390
2.96M
                if( p_block->i_pts > date_Get( &p_sys->end_date ) )
391
2.62M
                {
392
2.62M
                    date_Set( &p_sys->end_date, p_block->i_pts );
393
2.62M
                }
394
395
2.96M
                block_Release( p_block );
396
2.96M
                *pp_block = p_block = NULL;
397
2.96M
            }
398
976k
            else if ( ret != AVERROR(EAGAIN) ) /* Errors other than buffer full */
399
967k
            {
400
967k
                if( ret == AVERROR(ENOMEM) || ret == AVERROR(EINVAL) )
401
134
                    goto end;
402
967k
                else
403
967k
                {
404
967k
                    char errorstring[AV_ERROR_MAX_STRING_SIZE];
405
967k
                    if( !av_strerror( ret, errorstring, AV_ERROR_MAX_STRING_SIZE ) )
406
967k
                        msg_Err( p_dec, "%s", errorstring );
407
408
                    /* Signal an error, but continue to receive all output
409
                     * frames. A discontinuity will be triggered for the
410
                     * output frame coming right after the dropped one. */
411
967k
                    send_failed = true;
412
967k
                    block_Release( p_block );
413
967k
                    *pp_block = p_block = NULL;
414
967k
                }
415
967k
            }
416
3.94M
        }
417
418
        /* Try to read one or multiple frames */
419
8.11M
        ret = avcodec_receive_frame( ctx, frame );
420
8.11M
        if( ret == 0 )
421
2.95M
        {
422
2.95M
#if LIBAVUTIL_VERSION_CHECK(57, 24, 100)
423
2.95M
            int channels = frame->ch_layout.nb_channels;
424
#else
425
            int channels = ctx->channels;
426
#endif
427
            /* checks and init from first decoded frame */
428
2.95M
            if( channels <= 0 || channels > INPUT_CHAN_MAX
429
2.94M
             || ctx->sample_rate <= 0 )
430
13.9k
            {
431
13.9k
                msg_Warn( p_dec, "invalid audio properties channels count %d, sample rate %d",
432
13.9k
                          channels, ctx->sample_rate );
433
13.9k
                goto drop;
434
13.9k
            }
435
2.94M
            else if( p_dec->fmt_out.audio.i_rate != (unsigned int)ctx->sample_rate )
436
281
            {
437
281
                date_Init( &p_sys->end_date, ctx->sample_rate, 1 );
438
281
            }
439
440
2.94M
            SetupOutputFormat( p_dec, true );
441
2.94M
            if( decoder_UpdateAudioFormat( p_dec ) )
442
2.94M
                goto drop;
443
444
0
            block_t *p_converted = ConvertAVFrame( p_dec, frame ); /* Consumes frame */
445
0
            if( p_converted )
446
0
            {
447
                /* Silent unwanted samples */
448
0
                if( p_sys->i_reject_count > 0 )
449
0
                {
450
0
                    memset( p_converted->p_buffer, 0, p_converted->i_buffer );
451
0
                    p_sys->i_reject_count--;
452
0
                }
453
0
                p_converted->i_buffer = p_converted->i_nb_samples
454
0
                                      * p_dec->fmt_out.audio.i_bytes_per_frame;
455
0
                p_converted->i_pts = date_Get( &p_sys->end_date );
456
0
                p_converted->i_length = date_Increment( &p_sys->end_date,
457
0
                                                      p_converted->i_nb_samples ) - p_converted->i_pts;
458
459
0
                if (p_sys->discontinuity)
460
0
                {
461
0
                    p_sys->discontinuity = false;
462
0
                    p_converted->i_flags |= BLOCK_FLAG_DISCONTINUITY;
463
0
                }
464
0
                decoder_QueueAudio( p_dec, p_converted );
465
0
            }
466
467
            /* Prepare new frame */
468
0
            frame = av_frame_alloc();
469
0
            if (unlikely(frame == NULL))
470
0
                break;
471
0
        }
472
5.16M
        else
473
5.16M
        {
474
            /* After draining, we need to reset decoder with a flush */
475
5.16M
            if( ret == AVERROR_EOF )
476
4.17M
                avcodec_flush_buffers( p_sys->p_context );
477
5.16M
            av_frame_free( &frame );
478
5.16M
        }
479
8.11M
    };
480
481
5.16M
    if (send_failed)
482
967k
    {
483
        /* Signal a discontinuity for the next output frame. */
484
967k
        p_sys->discontinuity = true;
485
967k
    }
486
487
5.16M
    return VLCDEC_SUCCESS;
488
489
134
end:
490
134
    b_error = true;
491
2.95M
drop:
492
    /* Signal a discontinuity for the next output frame. */
493
2.95M
    p_sys->discontinuity = true;
494
2.95M
    if( pp_block )
495
2.95M
    {
496
2.95M
        assert( *pp_block == p_block );
497
2.95M
        *pp_block = NULL;
498
2.95M
    }
499
2.95M
    if( p_block != NULL )
500
10.8k
        block_Release(p_block);
501
2.95M
    if( frame != NULL )
502
2.95M
        av_frame_free( &frame );
503
504
2.95M
    return (b_error) ? VLCDEC_ECRITICAL : VLCDEC_SUCCESS;
505
2.95M
}
506
507
static int DecodeAudio( decoder_t *p_dec, block_t *p_block )
508
8.11M
{
509
8.11M
    block_t **pp_block = p_block ? &p_block : NULL;
510
8.11M
    int i_ret;
511
8.11M
    do
512
8.11M
    {
513
8.11M
        i_ret = DecodeBlock( p_dec, pp_block );
514
8.11M
    }
515
8.11M
    while( i_ret == VLCDEC_SUCCESS && pp_block && *pp_block );
516
517
8.11M
    return i_ret;
518
8.11M
}
519
520
static block_t * ConvertAVFrame( decoder_t *p_dec, AVFrame *frame )
521
0
{
522
0
    decoder_sys_t *p_sys = p_dec->p_sys;
523
0
    AVCodecContext *ctx = p_sys->p_context;
524
0
    block_t *p_block;
525
526
    /* Interleave audio if required */
527
0
    if( av_sample_fmt_is_planar( ctx->sample_fmt ) )
528
0
    {
529
0
        p_block = block_Alloc(frame->linesize[0] * p_dec->fmt_out.audio.i_channels );
530
0
        if ( likely(p_block) )
531
0
        {
532
0
            const void *planes[p_dec->fmt_out.audio.i_channels];
533
0
            for (int i = 0; i < p_dec->fmt_out.audio.i_channels; i++)
534
0
                planes[i] = frame->extended_data[i];
535
536
0
            aout_Interleave(p_block->p_buffer, planes, frame->nb_samples,
537
0
                            p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_format);
538
0
            p_block->i_nb_samples = frame->nb_samples;
539
0
        }
540
0
        av_frame_free(&frame);
541
0
    }
542
0
    else
543
0
    {
544
0
        p_block = vlc_av_frame_Wrap(frame);
545
0
        frame = NULL;
546
0
    }
547
548
0
    if (p_sys->b_extract && p_block)
549
0
    {   /* TODO: do not drop channels... at least not here */
550
0
        block_t *p_buffer = block_Alloc( p_dec->fmt_out.audio.i_bytes_per_frame
551
0
                                         * p_block->i_nb_samples );
552
0
        if( likely(p_buffer) )
553
0
        {
554
0
            aout_ChannelExtract( p_buffer->p_buffer,
555
0
                                 p_dec->fmt_out.audio.i_channels,
556
0
                                 p_block->p_buffer, p_dec->fmt_out.audio.i_channels,
557
0
                                 p_block->i_nb_samples, p_sys->pi_extraction,
558
0
                                 p_dec->fmt_out.audio.i_bitspersample );
559
0
            p_buffer->i_nb_samples = p_block->i_nb_samples;
560
0
        }
561
0
        block_Release( p_block );
562
0
        p_block = p_buffer;
563
0
    }
564
565
0
    return p_block;
566
0
}
567
568
/*****************************************************************************
569
 *
570
 *****************************************************************************/
571
572
vlc_fourcc_t GetVlcAudioFormat( int fmt )
573
3.52M
{
574
3.52M
    static const vlc_fourcc_t fcc[] = {
575
3.52M
        [AV_SAMPLE_FMT_U8]    = VLC_CODEC_U8,
576
3.52M
        [AV_SAMPLE_FMT_S16]   = VLC_CODEC_S16N,
577
3.52M
        [AV_SAMPLE_FMT_S32]   = VLC_CODEC_S32N,
578
3.52M
        [AV_SAMPLE_FMT_FLT]   = VLC_CODEC_FL32,
579
3.52M
        [AV_SAMPLE_FMT_DBL]   = VLC_CODEC_FL64,
580
3.52M
        [AV_SAMPLE_FMT_U8P]   = VLC_CODEC_U8,
581
3.52M
        [AV_SAMPLE_FMT_S16P]  = VLC_CODEC_S16N,
582
3.52M
        [AV_SAMPLE_FMT_S32P]  = VLC_CODEC_S32N,
583
3.52M
        [AV_SAMPLE_FMT_FLTP]  = VLC_CODEC_FL32,
584
3.52M
        [AV_SAMPLE_FMT_DBLP]  = VLC_CODEC_FL64,
585
3.52M
    };
586
3.52M
    if( ARRAY_SIZE(fcc) > (unsigned)fmt )
587
3.49M
        return fcc[fmt];
588
30.5k
    return VLC_CODEC_S16N;
589
3.52M
}
590
591
static const uint64_t pi_channels_map[][2] =
592
{
593
    { AV_CH_FRONT_LEFT,        AOUT_CHAN_LEFT },
594
    { AV_CH_FRONT_RIGHT,       AOUT_CHAN_RIGHT },
595
    { AV_CH_FRONT_CENTER,      AOUT_CHAN_CENTER },
596
    { AV_CH_LOW_FREQUENCY,     AOUT_CHAN_LFE },
597
    { AV_CH_BACK_LEFT,         AOUT_CHAN_REARLEFT },
598
    { AV_CH_BACK_RIGHT,        AOUT_CHAN_REARRIGHT },
599
    { AV_CH_FRONT_LEFT_OF_CENTER, 0 },
600
    { AV_CH_FRONT_RIGHT_OF_CENTER, 0 },
601
    { AV_CH_BACK_CENTER,       AOUT_CHAN_REARCENTER },
602
    { AV_CH_SIDE_LEFT,         AOUT_CHAN_MIDDLELEFT },
603
    { AV_CH_SIDE_RIGHT,        AOUT_CHAN_MIDDLERIGHT },
604
    { AV_CH_TOP_CENTER,        0 },
605
    { AV_CH_TOP_FRONT_LEFT,    0 },
606
    { AV_CH_TOP_FRONT_CENTER,  0 },
607
    { AV_CH_TOP_FRONT_RIGHT,   0 },
608
    { AV_CH_TOP_BACK_LEFT,     0 },
609
    { AV_CH_TOP_BACK_CENTER,   0 },
610
    { AV_CH_TOP_BACK_RIGHT,    0 },
611
    { AV_CH_STEREO_LEFT,       0 },
612
    { AV_CH_STEREO_RIGHT,      0 },
613
    { 0, 0 },
614
};
615
616
static void SetupOutputFormat( decoder_t *p_dec, bool b_trust )
617
3.52M
{
618
3.52M
    decoder_sys_t *p_sys = p_dec->p_sys;
619
620
3.52M
    p_dec->fmt_out.i_codec = GetVlcAudioFormat( p_sys->p_context->sample_fmt );
621
3.52M
    p_dec->fmt_out.audio.channel_type = p_dec->fmt_in->audio.channel_type;
622
3.52M
    p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
623
3.52M
    p_dec->fmt_out.audio.i_rate = p_sys->p_context->sample_rate;
624
625
    /* */
626
3.52M
#if API_CHANNEL_LAYOUT_STRUCT
627
3.52M
    if( p_sys->i_previous_channels == p_sys->p_context->ch_layout.nb_channels &&
628
2.88M
        p_sys->i_previous_layout == p_sys->p_context->ch_layout.u.mask )
629
2.88M
        return;
630
639k
    if( b_trust )
631
85.3k
    {
632
85.3k
        p_sys->i_previous_channels = p_sys->p_context->ch_layout.nb_channels;
633
85.3k
        p_sys->i_previous_layout = p_sys->p_context->ch_layout.u.mask;
634
85.3k
    }
635
#else
636
    if( p_sys->i_previous_channels == p_sys->p_context->channels &&
637
        p_sys->i_previous_layout == p_sys->p_context->channel_layout )
638
        return;
639
    if( b_trust )
640
    {
641
        p_sys->i_previous_channels = p_sys->p_context->channels;
642
        p_sys->i_previous_layout = p_sys->p_context->channel_layout;
643
    }
644
#endif
645
646
639k
    int i_channels_src = 0;
647
639k
#if API_CHANNEL_LAYOUT_STRUCT
648
639k
    uint64_t channel_layout_mask = p_sys->p_context->ch_layout.u.mask;
649
639k
    int channel_count = p_sys->p_context->ch_layout.nb_channels;
650
#else
651
    uint64_t channel_layout_mask =
652
        p_sys->p_context->channel_layout ? p_sys->p_context->channel_layout :
653
        (uint64_t)av_get_default_channel_layout( p_sys->p_context->channels );
654
    int channel_count = p_sys->p_context->channels;
655
#endif
656
657
639k
    if( channel_layout_mask )
658
637k
    {
659
637k
        uint32_t* pi_order_src = calloc(channel_count,sizeof(uint32_t));
660
        
661
637k
        if( unlikely(pi_order_src == NULL) )
662
0
        {
663
0
            p_dec->fmt_out.audio.i_physical_channels = 0;
664
0
            p_dec->fmt_out.audio.i_channels = channel_count;
665
666
0
            aout_FormatPrepare(&p_dec->fmt_out.audio);
667
0
            return;
668
0
        }
669
670
2.96M
        for( unsigned i = 0; pi_channels_map[i][0]
671
2.96M
         && i_channels_src < channel_count; i++ )
672
2.33M
        {
673
2.33M
            if( channel_layout_mask & pi_channels_map[i][0] )
674
1.17M
                pi_order_src[i_channels_src++] = pi_channels_map[i][1];
675
2.33M
        }
676
677
637k
        if( i_channels_src != channel_count && b_trust )
678
637k
            msg_Err( p_dec, "Channel layout not understood" );
679
680
        /* Detect special dual mono case */
681
637k
        if( i_channels_src == 2 && pi_order_src[0] == AOUT_CHAN_CENTER
682
2.44k
         && pi_order_src[1] == AOUT_CHAN_CENTER )
683
0
        {
684
0
            p_dec->fmt_out.audio.i_chan_mode |= AOUT_CHANMODE_DUALMONO;
685
0
            pi_order_src[0] = AOUT_CHAN_LEFT;
686
0
            pi_order_src[1] = AOUT_CHAN_RIGHT;
687
0
        }
688
689
637k
        uint32_t i_layout_dst;
690
637k
        int      i_channels_dst;
691
637k
        p_sys->b_extract = aout_CheckChannelExtraction( p_sys->pi_extraction,
692
637k
                                                        &i_layout_dst, &i_channels_dst,
693
637k
                                                        NULL, pi_order_src, i_channels_src );
694
637k
        if( i_channels_dst != i_channels_src && b_trust )
695
637k
            msg_Warn( p_dec, "%d channels are dropped", i_channels_src - i_channels_dst );
696
697
        /* No reordering for Ambisonic order 1 channels encoded in AAC... */
698
637k
        if (p_dec->fmt_out.audio.channel_type == AUDIO_CHANNEL_TYPE_AMBISONICS
699
637k
            && p_dec->fmt_in->i_codec == VLC_CODEC_MP4A
700
0
            && i_channels_src == 4)
701
0
            p_sys->b_extract = false;
702
703
637k
        p_dec->fmt_out.audio.i_physical_channels = i_layout_dst;
704
637k
        free(pi_order_src);
705
637k
    }
706
1.93k
    else
707
1.93k
    {
708
1.93k
        msg_Warn( p_dec, "no channel layout found");
709
1.93k
        p_dec->fmt_out.audio.i_physical_channels = 0;
710
1.93k
        p_dec->fmt_out.audio.i_channels = channel_count;
711
1.93k
    }
712
713
639k
    aout_FormatPrepare( &p_dec->fmt_out.audio );
714
639k
}
715