Coverage Report

Created: 2026-08-13 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/codec/flac.c
Line
Count
Source
1
/*****************************************************************************
2
 * flac.c: flac decoder/encoder module making use of libflac
3
 *****************************************************************************
4
 * Copyright (C) 1999-2001 VLC authors and VideoLAN
5
 *
6
 * Authors: Gildas Bazin <gbazin@videolan.org>
7
 *          Sigmund Augdal Helberg <dnumgis@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
28
/* workaround libflac overriding assert.h system header */
29
#define assert(x) do {} while(0)
30
31
#ifdef HAVE_CONFIG_H
32
# include "config.h"
33
#endif
34
35
#include <stdbit.h>
36
37
#include <vlc_common.h>
38
#include <vlc_plugin.h>
39
#include <vlc_codec.h>
40
#include <vlc_codecs.h>
41
#include <vlc_aout.h>
42
43
#ifdef _WIN32
44
# define FLAC__NO_DLL
45
#endif
46
47
#include <FLAC/stream_decoder.h>
48
#include <FLAC/stream_encoder.h>
49
50
#include <vlc_block_helper.h>
51
#include <vlc_bits.h>
52
53
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT >= 8
54
#   define USE_NEW_FLAC_API
55
#endif
56
57
/*****************************************************************************
58
 * decoder_sys_t : FLAC decoder descriptor
59
 *****************************************************************************/
60
typedef struct
61
{
62
    /*
63
     * Input/Output properties
64
     */
65
    block_t *p_block;
66
    block_t *p_aout_buffer;
67
    date_t   end_date;
68
69
    /*
70
     * FLAC properties
71
     */
72
    FLAC__StreamDecoder *p_flac;
73
    FLAC__StreamMetadata_StreamInfo stream_info;
74
75
    uint8_t rgi_channels_reorder[AOUT_CHAN_MAX];
76
    bool b_stream_info;
77
} decoder_sys_t;
78
79
static const int pi_channels_maps[FLAC__MAX_CHANNELS + 1] =
80
{
81
    0,
82
    AOUT_CHAN_CENTER,
83
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
84
    AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
85
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
86
     | AOUT_CHAN_REARRIGHT,
87
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
88
     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
89
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
90
     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
91
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
92
     | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT| AOUT_CHAN_MIDDLERIGHT
93
     | AOUT_CHAN_LFE,
94
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
95
     | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
96
     | AOUT_CHAN_LFE
97
};
98
99
/* XXX it supposes our internal format is WG4 */
100
static const uint8_t ppi_reorder[1+FLAC__MAX_CHANNELS][FLAC__MAX_CHANNELS] =
101
{
102
    { 0 },
103
    { 0, },
104
    { 0, 1 },
105
    { 0, 1, 2 },
106
    { 0, 1, 2, 3 },
107
    { 0, 1, 3, 4, 2 },
108
    { 0, 1, 4, 5, 2, 3 },
109
    { 0, 1, 5, 6, 4, 2, 3 },
110
    { 0, 1, 6, 7, 4, 5, 2, 3 },
111
};
112
113
/* Flac uses same order as waveformatex */
114
0
#define MAPPED_WFX_CHANNELS 9
115
static const uint32_t wfx_remapping[MAPPED_WFX_CHANNELS][2] =
116
{
117
    { WAVE_SPEAKER_FRONT_LEFT,              AOUT_CHAN_LEFT },
118
    { WAVE_SPEAKER_FRONT_RIGHT,             AOUT_CHAN_RIGHT },
119
    { WAVE_SPEAKER_FRONT_CENTER,            AOUT_CHAN_CENTER },
120
    { WAVE_SPEAKER_LOW_FREQUENCY,           AOUT_CHAN_LFE },
121
    { WAVE_SPEAKER_BACK_LEFT,               AOUT_CHAN_REARLEFT },
122
    { WAVE_SPEAKER_BACK_RIGHT,              AOUT_CHAN_REARRIGHT },
123
    { WAVE_SPEAKER_BACK_CENTER,             AOUT_CHAN_REARCENTER },
124
    { WAVE_SPEAKER_SIDE_LEFT,               AOUT_CHAN_MIDDLELEFT },
125
    { WAVE_SPEAKER_SIDE_RIGHT,              AOUT_CHAN_MIDDLERIGHT },
126
};
127
128
static const uint32_t wfx_chans_order[MAPPED_WFX_CHANNELS + 1] =
129
{
130
    AOUT_CHAN_LEFT,
131
    AOUT_CHAN_RIGHT,
132
    AOUT_CHAN_CENTER,
133
    AOUT_CHAN_LFE,
134
    AOUT_CHAN_REARLEFT,
135
    AOUT_CHAN_REARRIGHT,
136
    AOUT_CHAN_REARCENTER,
137
    AOUT_CHAN_MIDDLELEFT,
138
    AOUT_CHAN_MIDDLERIGHT,
139
    0
140
};
141
142
/*****************************************************************************
143
 * Local prototypes
144
 *****************************************************************************/
145
static int  OpenDecoder   ( vlc_object_t * );
146
static void CloseDecoder  ( vlc_object_t * );
147
148
#ifdef ENABLE_SOUT
149
static int OpenEncoder   ( vlc_object_t * );
150
static void CloseEncoder ( encoder_t * );
151
#endif
152
153
static int DecodeBlock( decoder_t *, block_t * );
154
static void Flush( decoder_t * );
155
156
/*****************************************************************************
157
 * Module descriptor
158
 *****************************************************************************/
159
168
vlc_module_begin ()
160
161
84
    set_subcategory( SUBCAT_INPUT_ACODEC )
162
84
    add_shortcut( "flac" )
163
164
84
    set_description( N_("Flac audio decoder") )
165
84
    set_capability( "audio decoder", 100 )
166
168
    set_callbacks( OpenDecoder, CloseDecoder )
167
168
84
#ifdef ENABLE_SOUT
169
84
    add_submodule ()
170
84
    add_shortcut( "flac" )
171
84
    set_description( N_("Flac audio encoder") )
172
84
    set_capability( "audio encoder", 100 )
173
84
    set_callback( OpenEncoder )
174
84
#endif
175
176
84
vlc_module_end ()
177
178
/*****************************************************************************
179
 * Interleave: helper function to interleave channels
180
 *****************************************************************************/
181
static void Interleave( int32_t *p_out, const int32_t * const *pp_in,
182
                        const uint8_t *restrict pi_index, unsigned i_nb_channels,
183
                        unsigned i_samples, unsigned bits )
184
0
{
185
0
    unsigned shift = 32 - bits;
186
187
0
    for( unsigned j = 0; j < i_samples; j++ )
188
0
        for( unsigned i = 0; i < i_nb_channels; i++ )
189
0
        {
190
0
            union { int32_t i; uint32_t u; } spl;
191
192
0
            spl.u = ((uint32_t)pp_in[pi_index[i]][j]) << shift;
193
0
            p_out[j * i_nb_channels + i] = spl.i;
194
0
        }
195
0
}
196
197
/*****************************************************************************
198
 * DecoderSetOutputFormat: helper function to convert and check frame format
199
 *****************************************************************************/
200
static int DecoderSetOutputFormat( unsigned i_channels, unsigned i_rate,
201
                                   unsigned i_streaminfo_rate,
202
                                   unsigned i_bitspersample,
203
                                   audio_format_t *fmt,
204
                                   uint8_t *pi_channels_reorder )
205
13.2k
{
206
13.2k
    if( i_channels == 0 || i_channels > FLAC__MAX_CHANNELS ||
207
13.2k
        i_bitspersample == 0 || (i_rate == 0 && i_streaminfo_rate == 0) )
208
0
        return VLC_EGENERIC;
209
210
13.2k
    fmt->i_channels = i_channels;
211
13.2k
    fmt->i_rate = (i_rate > 0 ) ? i_rate : i_streaminfo_rate;
212
13.2k
    fmt->i_physical_channels = pi_channels_maps[i_channels];
213
13.2k
    memcpy( pi_channels_reorder, ppi_reorder[i_channels], i_channels );
214
13.2k
    fmt->i_bitspersample = i_bitspersample;
215
216
13.2k
    return VLC_SUCCESS;
217
13.2k
}
218
219
/*****************************************************************************
220
 * DecoderWriteCallback: called by libflac to output decoded samples
221
 *****************************************************************************/
222
static FLAC__StreamDecoderWriteStatus
223
DecoderWriteCallback( const FLAC__StreamDecoder *decoder,
224
                      const FLAC__Frame *frame,
225
                      const FLAC__int32 *const buffer[], void *client_data )
226
3.38k
{
227
3.38k
    VLC_UNUSED(decoder);
228
3.38k
    decoder_t *p_dec = (decoder_t *)client_data;
229
3.38k
    decoder_sys_t *p_sys = p_dec->p_sys;
230
231
3.38k
    if( DecoderSetOutputFormat( frame->header.channels,
232
3.38k
                                frame->header.sample_rate,
233
3.38k
                                p_sys->b_stream_info ? p_sys->stream_info.sample_rate : 0,
234
3.38k
                                frame->header.bits_per_sample,
235
3.38k
                                &p_dec->fmt_out.audio,
236
3.38k
                                p_sys->rgi_channels_reorder ) )
237
0
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
238
239
3.38k
    if( p_sys->end_date.i_divider_num != p_dec->fmt_out.audio.i_rate )
240
0
    {
241
0
        if( p_sys->end_date.i_divider_num > 0 )
242
0
            date_Change( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
243
0
        else
244
0
            date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
245
0
    }
246
247
3.38k
    if( decoder_UpdateAudioFormat( p_dec ) )
248
3.38k
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
249
250
0
    if( date_Get( &p_sys->end_date ) == VLC_TICK_INVALID )
251
0
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
252
253
0
    p_sys->p_aout_buffer =
254
0
        decoder_NewAudioBuffer( p_dec, frame->header.blocksize );
255
256
0
    if( p_sys->p_aout_buffer == NULL )
257
0
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
258
259
0
    Interleave( (int32_t *)p_sys->p_aout_buffer->p_buffer, buffer,
260
0
                 p_sys->rgi_channels_reorder,
261
0
                 frame->header.channels, frame->header.blocksize,
262
0
                 frame->header.bits_per_sample );
263
264
    /* Date management (already done by packetizer) */
265
0
    p_sys->p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
266
0
    p_sys->p_aout_buffer->i_length =
267
0
        date_Increment( &p_sys->end_date, frame->header.blocksize ) -
268
0
        p_sys->p_aout_buffer->i_pts;
269
270
0
    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
271
0
}
272
273
/*****************************************************************************
274
 * DecoderReadCallback: called by libflac when it needs more data
275
 *****************************************************************************/
276
static FLAC__StreamDecoderReadStatus
277
DecoderReadCallback( const FLAC__StreamDecoder *decoder, FLAC__byte buffer[],
278
                     size_t *bytes, void *client_data )
279
90.5k
{
280
90.5k
    VLC_UNUSED(decoder);
281
90.5k
    decoder_t *p_dec = (decoder_t *)client_data;
282
90.5k
    decoder_sys_t *p_sys = p_dec->p_sys;
283
284
90.5k
    if( p_sys->p_block && p_sys->p_block->i_buffer )
285
51.6k
    {
286
51.6k
        *bytes = __MIN(*bytes, p_sys->p_block->i_buffer);
287
51.6k
        memcpy( buffer, p_sys->p_block->p_buffer, *bytes );
288
51.6k
        p_sys->p_block->i_buffer -= *bytes;
289
51.6k
        p_sys->p_block->p_buffer += *bytes;
290
51.6k
    }
291
38.8k
    else
292
38.8k
    {
293
38.8k
        *bytes = 0;
294
38.8k
        return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
295
38.8k
    }
296
297
51.6k
    return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
298
90.5k
}
299
300
/*****************************************************************************
301
 * DecoderMetadataCallback: called by libflac to when it encounters metadata
302
 *****************************************************************************/
303
static void DecoderMetadataCallback( const FLAC__StreamDecoder *decoder,
304
                                     const FLAC__StreamMetadata *metadata,
305
                                     void *client_data )
306
9.90k
{
307
9.90k
    VLC_UNUSED(decoder);
308
9.90k
    decoder_t *p_dec = (decoder_t *)client_data;
309
9.90k
    decoder_sys_t *p_sys = p_dec->p_sys;
310
311
9.90k
    switch(metadata->type)
312
9.90k
    {
313
9.90k
        case FLAC__METADATA_TYPE_STREAMINFO:
314
            /* Setup the format */
315
9.90k
            DecoderSetOutputFormat( metadata->data.stream_info.channels,
316
9.90k
                                    metadata->data.stream_info.sample_rate,
317
9.90k
                                    metadata->data.stream_info.sample_rate,
318
9.90k
                                    metadata->data.stream_info.bits_per_sample,
319
9.90k
                                    &p_dec->fmt_out.audio, p_sys->rgi_channels_reorder );
320
321
9.90k
            msg_Dbg( p_dec, "channels:%d samplerate:%d bitspersamples:%d",
322
9.90k
                     p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_rate,
323
9.90k
                     p_dec->fmt_out.audio.i_bitspersample );
324
325
9.90k
            p_sys->b_stream_info = true;
326
9.90k
            p_sys->stream_info = metadata->data.stream_info;
327
328
9.90k
            date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
329
9.90k
            break;
330
331
0
        case FLAC__METADATA_TYPE_VORBIS_COMMENT:
332
0
            for( FLAC__uint32 i=0; i<metadata->data.vorbis_comment.num_comments; i++ )
333
0
            {
334
0
                const FLAC__StreamMetadata_VorbisComment_Entry *comment =
335
0
                        &metadata->data.vorbis_comment.comments[i];
336
                /* Check for custom WAVEFORMATEX channel ordering */
337
0
                if( comment->length > 34 &&
338
0
                    !strncmp( "WAVEFORMATEXTENSIBLE_CHANNEL_MASK=", (char *) comment->entry, 34 ) )
339
0
                {
340
0
                    char *endptr = (char *) &comment->entry[34] + comment->length;
341
0
                    const uint32_t i_wfxmask = strtoul( (char *) &comment->entry[34], &endptr, 16 );
342
0
                    const unsigned i_wfxchannels = stdc_count_ones( i_wfxmask );
343
0
                    if( i_wfxchannels > 0 && i_wfxchannels <= AOUT_CHAN_MAX )
344
0
                    {
345
                        /* Create the vlc bitmap from wfx channels */
346
0
                        uint32_t i_vlcmask = 0;
347
0
                        for( uint32_t i_chan = 1; i_chan && i_chan <= i_wfxmask; i_chan <<= 1 )
348
0
                        {
349
0
                            if( (i_chan & i_wfxmask) == 0 )
350
0
                                continue;
351
0
                            for( size_t j=0; j<MAPPED_WFX_CHANNELS; j++ )
352
0
                            {
353
0
                                if( wfx_remapping[j][0] == i_chan )
354
0
                                    i_vlcmask |= wfx_remapping[j][1];
355
0
                            }
356
0
                        }
357
                        /* Check if we have the 1 to 1 mapping */
358
0
                        if( stdc_count_ones(i_vlcmask) != i_wfxchannels )
359
0
                        {
360
0
                            msg_Warn( p_dec, "Unsupported channel mask %x", i_wfxmask );
361
0
                            return;
362
0
                        }
363
364
                        /* Compute the remapping */
365
0
                        uint8_t neworder[AOUT_CHAN_MAX] = {0};
366
0
                        aout_CheckChannelReorder( wfx_chans_order, NULL,
367
0
                                                  i_vlcmask, neworder );
368
369
                        /* /!\ Invert our source/dest reordering,
370
                         * as Interleave() here works source indexes */
371
0
                        for( unsigned j=0; j<i_wfxchannels; j++ )
372
0
                            p_sys->rgi_channels_reorder[neworder[j]] = j;
373
374
0
                        p_dec->fmt_out.audio.i_physical_channels = i_vlcmask;
375
0
                        p_dec->fmt_out.audio.i_channels = i_wfxchannels;
376
0
                    }
377
378
0
                    break;
379
0
                }
380
0
            }
381
382
0
        default:
383
0
            break;
384
9.90k
    }
385
9.90k
}
386
387
/*****************************************************************************
388
 * DecoderErrorCallback: called when the libflac decoder encounters an error
389
 *****************************************************************************/
390
static void DecoderErrorCallback( const FLAC__StreamDecoder *decoder,
391
                                  FLAC__StreamDecoderErrorStatus status,
392
                                  void *client_data )
393
38.8k
{
394
38.8k
    VLC_UNUSED(decoder);
395
38.8k
    decoder_t *p_dec = (decoder_t *)client_data;
396
38.8k
    decoder_sys_t *p_sys = p_dec->p_sys;
397
398
38.8k
    switch( status )
399
38.8k
    {
400
8.88k
    case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
401
8.88k
        msg_Warn( p_dec, "an error in the stream caused the decoder to "
402
8.88k
                 "lose synchronization." );
403
8.88k
        break;
404
875
    case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
405
875
        msg_Err( p_dec, "the decoder encountered a corrupted frame header." );
406
875
        break;
407
3.03k
    case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
408
3.03k
        msg_Err( p_dec, "frame's data did not match the CRC in the "
409
3.03k
                 "footer." );
410
3.03k
        break;
411
25.2k
    case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
412
25.2k
        msg_Err( p_dec, "The decoder encountered reserved fields in use in "
413
25.2k
                 "the stream." );
414
25.2k
        break;
415
723
    default:
416
723
        msg_Err( p_dec, "got decoder error: %d", status );
417
38.8k
    }
418
419
38.8k
    FLAC__stream_decoder_flush( p_sys->p_flac );
420
38.8k
    return;
421
38.8k
}
422
/*****************************************************************************
423
 * OpenDecoder: probe the decoder and return score
424
 *****************************************************************************/
425
static int OpenDecoder( vlc_object_t *p_this )
426
706k
{
427
706k
    decoder_t *p_dec = (decoder_t*)p_this;
428
706k
    decoder_sys_t *p_sys;
429
430
706k
    if( p_dec->fmt_in->i_codec != VLC_CODEC_FLAC )
431
696k
    {
432
696k
        return VLC_EGENERIC;
433
696k
    }
434
435
    /* Allocate the memory needed to store the decoder's structure */
436
10.4k
    if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
437
0
        return VLC_ENOMEM;
438
439
    /* Misc init */
440
10.4k
    p_sys->b_stream_info = false;
441
10.4k
    memset(p_sys->rgi_channels_reorder, 0, AOUT_CHAN_MAX);
442
10.4k
    p_sys->p_block = NULL;
443
444
    /* Take care of flac init */
445
10.4k
    if( !(p_sys->p_flac = FLAC__stream_decoder_new()) )
446
0
    {
447
0
        msg_Err( p_dec, "FLAC__stream_decoder_new() failed" );
448
0
        free( p_sys );
449
0
        return VLC_EGENERIC;
450
0
    }
451
452
    /* Enable STREAMINFO + COMMENTS */
453
10.4k
    FLAC__stream_decoder_set_metadata_respond( p_sys->p_flac,
454
10.4k
                                               FLAC__METADATA_TYPE_VORBIS_COMMENT );
455
456
10.4k
#ifdef USE_NEW_FLAC_API
457
10.4k
    if( FLAC__stream_decoder_init_stream( p_sys->p_flac,
458
10.4k
                                          DecoderReadCallback,
459
10.4k
                                          NULL,
460
10.4k
                                          NULL,
461
10.4k
                                          NULL,
462
10.4k
                                          NULL,
463
10.4k
                                          DecoderWriteCallback,
464
10.4k
                                          DecoderMetadataCallback,
465
10.4k
                                          DecoderErrorCallback,
466
10.4k
                                          p_dec )
467
10.4k
        != FLAC__STREAM_DECODER_INIT_STATUS_OK )
468
0
    {
469
0
        msg_Err( p_dec, "FLAC__stream_decoder_init_stream() failed" );
470
0
        FLAC__stream_decoder_delete( p_sys->p_flac );
471
0
        free( p_sys );
472
0
        return VLC_EGENERIC;
473
0
    }
474
#else
475
    FLAC__stream_decoder_set_read_callback( p_sys->p_flac,
476
                                            DecoderReadCallback );
477
    FLAC__stream_decoder_set_write_callback( p_sys->p_flac,
478
                                             DecoderWriteCallback );
479
    FLAC__stream_decoder_set_metadata_callback( p_sys->p_flac,
480
                                                DecoderMetadataCallback );
481
    FLAC__stream_decoder_set_error_callback( p_sys->p_flac,
482
                                             DecoderErrorCallback );
483
    FLAC__stream_decoder_set_client_data( p_sys->p_flac, p_dec );
484
485
    FLAC__stream_decoder_init( p_sys->p_flac );
486
#endif
487
488
    /* Set output properties */
489
10.4k
    p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
490
491
    /* Set callbacks */
492
10.4k
    p_dec->pf_decode = DecodeBlock;
493
10.4k
    p_dec->pf_flush  = Flush;
494
495
10.4k
    return VLC_SUCCESS;
496
10.4k
}
497
498
/*****************************************************************************
499
 * CloseDecoder: flac decoder destruction
500
 *****************************************************************************/
501
static void CloseDecoder( vlc_object_t *p_this )
502
10.4k
{
503
10.4k
    decoder_t *p_dec = (decoder_t *)p_this;
504
10.4k
    decoder_sys_t *p_sys = p_dec->p_sys;
505
506
10.4k
    FLAC__stream_decoder_finish( p_sys->p_flac );
507
10.4k
    FLAC__stream_decoder_delete( p_sys->p_flac );
508
509
10.4k
    if( p_sys->p_block )
510
0
        block_Release( p_sys->p_block );
511
10.4k
    free( p_sys );
512
10.4k
}
513
514
/*****************************************************************************
515
 * ProcessHeader: process Flac header.
516
 *****************************************************************************/
517
static void ProcessHeader( decoder_t *p_dec )
518
{
519
    decoder_sys_t *p_sys = p_dec->p_sys;
520
521
    if( !p_dec->fmt_in->i_extra )
522
        return;
523
524
    /* Decode STREAMINFO */
525
    msg_Dbg( p_dec, "decode STREAMINFO" );
526
    size_t i_extra = p_dec->fmt_in->i_extra;
527
528
    static const char header[4] = { 'f', 'L', 'a', 'C' };
529
530
    if( memcmp( p_dec->fmt_in->p_extra, header, 4 ) )
531
        i_extra += 8;
532
533
    p_sys->p_block = block_Alloc( i_extra );
534
    if( p_sys->p_block == NULL )
535
        return;
536
537
    uint8_t *p_data = p_sys->p_block->p_buffer;
538
    if( i_extra != p_dec->fmt_in->i_extra )
539
    {
540
        memcpy( p_data, header, 4);
541
        p_data[4] = 0x80 | 0; /* STREAMINFO faked as last block */
542
        p_data[5] = 0;
543
        p_data[6] = 0;
544
        p_data[7] = 34; /* block size */
545
        p_data += 8;
546
    }
547
    memcpy( p_data, p_dec->fmt_in->p_extra, p_dec->fmt_in->i_extra );
548
549
    FLAC__stream_decoder_process_until_end_of_metadata( p_sys->p_flac );
550
    msg_Dbg( p_dec, "STREAMINFO decoded" );
551
552
    block_Release( p_sys->p_block );
553
    p_sys->p_block = NULL;
554
}
555
556
/*****************************************************************************
557
 * decoder_state_error: print meaningful error messages
558
 *****************************************************************************/
559
static void decoder_state_error( decoder_t *p_dec,
560
                                 FLAC__StreamDecoderState state )
561
1.84k
{
562
1.84k
    switch ( state )
563
1.84k
    {
564
0
    case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
565
0
        msg_Dbg( p_dec, "the decoder is ready to search for metadata." );
566
0
        break;
567
0
    case FLAC__STREAM_DECODER_READ_METADATA:
568
0
        msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
569
0
                 "reading metadata." );
570
0
        break;
571
0
    case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
572
0
        msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
573
0
                 "searching for the frame sync code." );
574
0
        break;
575
0
    case FLAC__STREAM_DECODER_READ_FRAME:
576
0
        msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
577
0
                 "reading a frame." );
578
0
        break;
579
0
    case FLAC__STREAM_DECODER_END_OF_STREAM:
580
0
        msg_Dbg( p_dec, "the decoder has reached the end of the stream." );
581
0
        break;
582
0
#ifdef USE_NEW_FLAC_API
583
0
    case FLAC__STREAM_DECODER_OGG_ERROR:
584
0
        msg_Err( p_dec, "error occurred in the Ogg layer." );
585
0
        break;
586
0
    case FLAC__STREAM_DECODER_SEEK_ERROR:
587
0
        msg_Err( p_dec, "error occurred while seeking." );
588
0
        break;
589
0
#endif
590
1.84k
    case FLAC__STREAM_DECODER_ABORTED:
591
1.84k
        msg_Warn( p_dec, "the decoder was aborted by the read callback." );
592
1.84k
        break;
593
#ifndef USE_NEW_FLAC_API
594
    case FLAC__STREAM_DECODER_UNPARSEABLE_STREAM:
595
        msg_Warn( p_dec, "the decoder encountered reserved fields in use "
596
                 "in the stream." );
597
        break;
598
#endif
599
0
    case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
600
0
        msg_Err( p_dec, "error when allocating memory." );
601
0
        break;
602
#ifndef USE_NEW_FLAC_API
603
    case FLAC__STREAM_DECODER_ALREADY_INITIALIZED:
604
        msg_Err( p_dec, "FLAC__stream_decoder_init() was called when the "
605
                 "decoder was already initialized, usually because "
606
                 "FLAC__stream_decoder_finish() was not called." );
607
        break;
608
    case FLAC__STREAM_DECODER_INVALID_CALLBACK:
609
        msg_Err( p_dec, "FLAC__stream_decoder_init() was called without "
610
                 "all callbacks being set." );
611
        break;
612
#endif
613
0
    case FLAC__STREAM_DECODER_UNINITIALIZED:
614
0
        msg_Err( p_dec, "decoder in uninitialized state." );
615
0
        break;
616
0
    default:
617
0
        msg_Warn(p_dec, "unknown error" );
618
1.84k
    }
619
1.84k
}
620
621
/*****************************************************************************
622
 * Flush:
623
 *****************************************************************************/
624
static void Flush( decoder_t *p_dec )
625
{
626
    decoder_sys_t *p_sys = p_dec->p_sys;
627
628
    if( p_sys->b_stream_info )
629
        FLAC__stream_decoder_flush( p_sys->p_flac );
630
    date_Set( &p_sys->end_date, VLC_TICK_INVALID );
631
}
632
633
/****************************************************************************
634
 * DecodeBlock: the whole thing
635
 ****************************************************************************/
636
static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
637
215k
{
638
215k
    decoder_sys_t *p_sys = p_dec->p_sys;
639
640
215k
    if( p_block == NULL ) /* No Drain */
641
174k
        return VLCDEC_SUCCESS;
642
40.1k
    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
643
7.67k
    {
644
7.67k
        Flush( p_dec );
645
7.67k
        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
646
0
        {
647
0
            block_Release( p_block );
648
0
            return VLCDEC_SUCCESS;
649
0
        }
650
7.67k
    }
651
652
40.1k
    if( !p_sys->b_stream_info )
653
9.90k
    {
654
9.90k
        ProcessHeader( p_dec );
655
9.90k
        if( !p_sys->b_stream_info )
656
4
        {
657
4
            block_Release( p_block );
658
4
            return VLCDEC_ECRITICAL;
659
4
        }
660
9.90k
    }
661
662
40.1k
    p_sys->p_block = p_block;
663
664
40.1k
    if( p_sys->p_block->i_pts != VLC_TICK_INVALID &&
665
39.6k
        p_sys->p_block->i_pts != date_Get( &p_sys->end_date ) )
666
39.6k
        date_Set( &p_sys->end_date, p_sys->p_block->i_pts );
667
668
40.1k
    p_sys->p_aout_buffer = 0;
669
670
40.1k
    if( !FLAC__stream_decoder_process_single( p_sys->p_flac ) )
671
1.84k
    {
672
1.84k
        decoder_state_error( p_dec,
673
1.84k
                             FLAC__stream_decoder_get_state( p_sys->p_flac ) );
674
1.84k
        FLAC__stream_decoder_flush( p_sys->p_flac );
675
1.84k
    }
676
677
    /* If the decoder is in the "aborted" state,
678
     * FLAC__stream_decoder_process_single() won't return an error. */
679
40.1k
    switch ( FLAC__stream_decoder_get_state(p_sys->p_flac) )
680
40.1k
    {
681
37.0k
        case FLAC__STREAM_DECODER_ABORTED:
682
37.0k
            FLAC__stream_decoder_flush( p_sys->p_flac );
683
37.0k
            break;
684
0
        case FLAC__STREAM_DECODER_END_OF_STREAM:
685
0
            FLAC__stream_decoder_reset( p_sys->p_flac );
686
0
            break;
687
3.11k
        default:
688
3.11k
            break;
689
40.1k
    }
690
691
40.1k
    block_Release( p_sys->p_block );
692
40.1k
    p_sys->p_block = NULL;
693
694
40.1k
    if( p_sys->p_aout_buffer != NULL )
695
0
        decoder_QueueAudio( p_dec, p_sys->p_aout_buffer );
696
40.1k
    return VLCDEC_SUCCESS;
697
40.1k
}
698
699
#ifdef ENABLE_SOUT
700
701
/*****************************************************************************
702
 * encoder_sys_t : flac encoder descriptor
703
 *****************************************************************************/
704
typedef struct
705
{
706
    /*
707
     * Input properties
708
     */
709
    int i_headers;
710
711
    int i_samples_delay;
712
713
    FLAC__int32 *p_buffer;
714
    unsigned int i_buffer;
715
716
    block_t *p_chain;
717
718
    /*
719
     * FLAC properties
720
     */
721
    FLAC__StreamEncoder *p_flac;
722
    FLAC__StreamMetadata_StreamInfo stream_info;
723
724
    /*
725
     * Common properties
726
     */
727
    vlc_tick_t i_pts;
728
} encoder_sys_t;
729
730
0
#define STREAMINFO_SIZE 34
731
732
static block_t *Encode( encoder_t *, block_t * );
733
734
/*****************************************************************************
735
 * EncoderWriteCallback: called by libflac to output encoded samples
736
 *****************************************************************************/
737
static FLAC__StreamEncoderWriteStatus
738
EncoderWriteCallback( const FLAC__StreamEncoder *encoder,
739
                      const FLAC__byte buffer[],
740
                      size_t bytes, unsigned samples,
741
                      unsigned current_frame, void *client_data )
742
0
{
743
0
    VLC_UNUSED(encoder); VLC_UNUSED(current_frame);
744
0
    encoder_t *p_enc = (encoder_t *)client_data;
745
0
    encoder_sys_t *p_sys = p_enc->p_sys;
746
0
    block_t *p_block;
747
748
0
    if( samples == 0 )
749
0
    {
750
0
        if( p_sys->i_headers == 1 )
751
0
        {
752
0
            msg_Dbg( p_enc, "Writing STREAMINFO: %zu", bytes );
753
754
            /* Backup the STREAMINFO metadata block */
755
0
            p_enc->fmt_out.i_extra = STREAMINFO_SIZE + 8;
756
0
            p_enc->fmt_out.p_extra = xmalloc( STREAMINFO_SIZE + 8);
757
0
            memcpy(p_enc->fmt_out.p_extra, "fLaC", 4);
758
0
            memcpy((uint8_t*)p_enc->fmt_out.p_extra + 4, buffer, STREAMINFO_SIZE );
759
            /* Fake this as the last metadata block */
760
0
            ((uint8_t*)p_enc->fmt_out.p_extra)[4] |= 0x80;
761
0
        }
762
0
        p_sys->i_headers++;
763
0
        return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
764
0
    }
765
766
0
    p_block = block_Alloc( bytes );
767
    /* FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR would be more appropriate
768
       but it's not the right type of enum */
769
0
    if( unlikely(p_block == NULL) )
770
0
        return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
771
772
0
    memcpy( p_block->p_buffer, buffer, bytes );
773
774
0
    p_block->i_dts = p_block->i_pts = p_sys->i_pts;
775
776
0
    p_sys->i_samples_delay -= samples;
777
778
0
    p_block->i_length = vlc_tick_from_samples(samples, p_enc->fmt_in.audio.i_rate);
779
780
    /* Update pts */
781
0
    p_sys->i_pts += p_block->i_length;
782
783
0
    block_ChainAppend( &p_sys->p_chain, p_block );
784
785
0
    return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
786
0
}
787
/*****************************************************************************
788
 * EncoderMetadataCallback: called by libflac to output metadata
789
 *****************************************************************************/
790
static void EncoderMetadataCallback( const FLAC__StreamEncoder *encoder,
791
                                     const FLAC__StreamMetadata *metadata,
792
                                     void *client_data )
793
0
{
794
0
    VLC_UNUSED(encoder);
795
0
    encoder_t *p_enc = (encoder_t *)client_data;
796
797
0
    msg_Err( p_enc, "MetadataCallback: %i", metadata->type );
798
0
    return;
799
0
}
800
801
/*****************************************************************************
802
 * OpenEncoder: probe the encoder and return score
803
 *****************************************************************************/
804
static int OpenEncoder( vlc_object_t *p_this )
805
0
{
806
0
    encoder_t *p_enc = (encoder_t *)p_this;
807
0
    encoder_sys_t *p_sys;
808
809
0
    if( p_enc->fmt_out.i_codec != VLC_CODEC_FLAC &&
810
0
        !p_enc->obj.force )
811
0
    {
812
0
        return VLC_EGENERIC;
813
0
    }
814
815
    /* Allocate the memory needed to store the decoder's structure */
816
0
    if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
817
0
        return VLC_ENOMEM;
818
0
    p_enc->p_sys = p_sys;
819
0
    p_enc->fmt_out.i_codec = VLC_CODEC_FLAC;
820
821
0
    p_sys->i_headers = 0;
822
0
    p_sys->p_buffer = 0;
823
0
    p_sys->i_buffer = 0;
824
0
    p_sys->i_samples_delay = 0;
825
826
    /* Create flac encoder */
827
0
    if( !(p_sys->p_flac = FLAC__stream_encoder_new()) )
828
0
    {
829
0
        msg_Err( p_enc, "FLAC__stream_encoder_new() failed" );
830
0
        free( p_sys );
831
0
        return VLC_EGENERIC;
832
0
    }
833
834
0
    FLAC__stream_encoder_set_streamable_subset( p_sys->p_flac, 1 );
835
0
    FLAC__stream_encoder_set_channels( p_sys->p_flac,
836
0
                                       p_enc->fmt_in.audio.i_channels );
837
0
    FLAC__stream_encoder_set_sample_rate( p_sys->p_flac,
838
0
                                          p_enc->fmt_in.audio.i_rate );
839
0
    FLAC__stream_encoder_set_bits_per_sample( p_sys->p_flac, 16 );
840
0
    p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
841
842
    /* Get and store the STREAMINFO metadata block as a p_extra */
843
0
    p_sys->p_chain = 0;
844
845
0
#ifdef USE_NEW_FLAC_API
846
0
    if( FLAC__stream_encoder_init_stream( p_sys->p_flac,
847
0
                                          EncoderWriteCallback,
848
0
                                          NULL,
849
0
                                          NULL,
850
0
                                          EncoderMetadataCallback,
851
0
                                          p_enc )
852
0
        != FLAC__STREAM_ENCODER_INIT_STATUS_OK )
853
0
    {
854
0
        msg_Err( p_enc, "FLAC__stream_encoder_init_stream() failed" );
855
0
        FLAC__stream_encoder_delete( p_sys->p_flac );
856
0
        free( p_sys );
857
0
        return VLC_EGENERIC;
858
0
    }
859
#else
860
    FLAC__stream_encoder_set_write_callback( p_sys->p_flac,
861
        EncoderWriteCallback );
862
    FLAC__stream_encoder_set_metadata_callback( p_sys->p_flac,
863
        EncoderMetadataCallback );
864
    FLAC__stream_encoder_set_client_data( p_sys->p_flac, p_enc );
865
866
    FLAC__stream_encoder_init( p_sys->p_flac );
867
#endif
868
869
0
    static const struct vlc_encoder_operations ops =
870
0
    {
871
0
        .close = CloseEncoder,
872
0
        .encode_audio = Encode,
873
0
    };
874
0
    p_enc->ops = &ops;
875
876
0
    return VLC_SUCCESS;
877
0
}
878
879
/****************************************************************************
880
 * Encode: the whole thing
881
 ****************************************************************************
882
 * This function spits out ogg packets.
883
 ****************************************************************************/
884
static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf )
885
0
{
886
0
    encoder_sys_t *p_sys = p_enc->p_sys;
887
0
    block_t *p_chain;
888
889
    /* FIXME: p_aout_buf is NULL when it's time to flush*/
890
0
    if( unlikely( !p_aout_buf ) ) return NULL;
891
892
0
    p_sys->i_pts = p_aout_buf->i_pts -
893
0
                vlc_tick_from_samples( p_sys->i_samples_delay,
894
0
                            p_enc->fmt_in.audio.i_rate );
895
896
0
    p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
897
898
    /* Convert samples to FLAC__int32 */
899
0
    if( p_sys->i_buffer < p_aout_buf->i_buffer * sizeof(FLAC__int32) )
900
0
    {
901
0
        p_sys->p_buffer =
902
0
            xrealloc( p_sys->p_buffer, p_aout_buf->i_buffer * sizeof(FLAC__int32) );
903
0
        p_sys->i_buffer = p_aout_buf->i_buffer * 2;
904
0
    }
905
906
0
    for( unsigned i = 0 ; i < p_aout_buf->i_buffer / 2 ; i++ )
907
0
    {
908
0
        p_sys->p_buffer[i]= ((int16_t *)p_aout_buf->p_buffer)[i];
909
0
    }
910
911
0
    FLAC__stream_encoder_process_interleaved( p_sys->p_flac, p_sys->p_buffer,
912
0
                                              p_aout_buf->i_nb_samples );
913
914
0
    p_chain = p_sys->p_chain;
915
0
    p_sys->p_chain = 0;
916
917
0
    return p_chain;
918
0
}
919
920
/*****************************************************************************
921
 * CloseEncoder: encoder destruction
922
 *****************************************************************************/
923
static void CloseEncoder( encoder_t *p_enc )
924
0
{
925
0
    encoder_sys_t *p_sys = p_enc->p_sys;
926
927
0
    FLAC__stream_encoder_delete( p_sys->p_flac );
928
929
0
    free( p_sys->p_buffer );
930
0
    free( p_sys );
931
0
}
932
#endif