flac.c 26.1 KB
Newer Older
1
/*****************************************************************************
2
 * flac.c: flac decoder/encoder module making use of libflac
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
4
 * Copyright (C) 1999-2001 VLC authors and VideoLAN
5
 * $Id$
6
 *
7
 * Authors: Gildas Bazin <gbazin@videolan.org>
8
 *          Sigmund Augdal Helberg <dnumgis@videolan.org>
9
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
10 11 12
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
13
 * (at your option) any later version.
14
 *
15 16
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
17 18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
19
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
20 21 22
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 24 25 26 27
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
28

29 30 31
/* workaround libflac overriding assert.h system header */
#define assert(x) do {} while(0)

32 33 34 35
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

36
#include <vlc_common.h>
37
#include <vlc_plugin.h>
Clément Stenac's avatar
Clément Stenac committed
38
#include <vlc_codec.h>
39

40 41
#include <FLAC/stream_decoder.h>
#include <FLAC/stream_encoder.h>
42

Clément Stenac's avatar
Clément Stenac committed
43 44
#include <vlc_block_helper.h>
#include <vlc_bits.h>
45

46 47 48 49
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT >= 8
#   define USE_NEW_FLAC_API
#endif

50 51 52 53 54 55 56 57 58
/*****************************************************************************
 * decoder_sys_t : FLAC decoder descriptor
 *****************************************************************************/
struct decoder_sys_t
{
    /*
     * Input/Output properties
     */
    block_t *p_block;
59 60
    block_t *p_aout_buffer;
    date_t   end_date;
61 62 63 64 65 66

    /*
     * FLAC properties
     */
    FLAC__StreamDecoder *p_flac;
    FLAC__StreamMetadata_StreamInfo stream_info;
67
    bool b_stream_info;
68 69
};

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
70
static const int pi_channels_maps[9] =
71 72 73 74 75 76 77 78
{
    0,
    AOUT_CHAN_CENTER,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
    AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
     | AOUT_CHAN_REARRIGHT,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
79 80
     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
81 82
     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
83 84
     | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT| AOUT_CHAN_MIDDLERIGHT
     | AOUT_CHAN_LFE,
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
85 86 87
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
     | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
     | AOUT_CHAN_LFE
88 89 90 91 92 93 94 95
};

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static int  OpenDecoder   ( vlc_object_t * );
static void CloseDecoder  ( vlc_object_t * );

96
#ifdef ENABLE_SOUT
97 98
static int OpenEncoder   ( vlc_object_t * );
static void CloseEncoder ( vlc_object_t * );
99
#endif
100

101
static block_t *DecodeBlock( decoder_t *, block_t ** );
102 103 104 105

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
106
vlc_module_begin ()
107

108 109 110
    set_category( CAT_INPUT )
    set_subcategory( SUBCAT_INPUT_ACODEC )
    add_shortcut( "flac" )
111

112 113 114
    set_description( N_("Flac audio decoder") )
    set_capability( "decoder", 100 )
    set_callbacks( OpenDecoder, CloseDecoder )
115

116
#ifdef ENABLE_SOUT
117
    add_submodule ()
118
    add_shortcut( "flac" )
119 120 121
    set_description( N_("Flac audio encoder") )
    set_capability( "encoder", 100 )
    set_callbacks( OpenEncoder, CloseEncoder )
122
#endif
123

124
vlc_module_end ()
125 126

/*****************************************************************************
127
 * Interleave: helper function to interleave channels
128
 *****************************************************************************/
129 130 131
static void Interleave( int32_t *p_out, const int32_t * const *pp_in,
                        const unsigned char *restrict pi_index, unsigned i_nb_channels,
                        unsigned i_samples, unsigned bits )
132
{
133
    unsigned shift = 32 - bits;
134

135 136 137
    for( unsigned j = 0; j < i_samples; j++ )
        for( unsigned i = 0; i < i_nb_channels; i++ )
            p_out[j * i_nb_channels + i] = pp_in[pi_index[i]][j] << shift;
138 139 140 141 142 143 144 145 146 147
}

/*****************************************************************************
 * DecoderWriteCallback: called by libflac to output decoded samples
 *****************************************************************************/
static FLAC__StreamDecoderWriteStatus
DecoderWriteCallback( const FLAC__StreamDecoder *decoder,
                      const FLAC__Frame *frame,
                      const FLAC__int32 *const buffer[], void *client_data )
{
148
    /* XXX it supposes our internal format is WG4 */
149
    static const unsigned char ppi_reorder[1+8][8] = {
150
        { },
151 152 153 154 155 156
        { 0, },
        { 0, 1 },
        { 0, 1, 2 },
        { 0, 1, 2, 3 },
        { 0, 1, 3, 4, 2 },
        { 0, 1, 4, 5, 2, 3 },
157 158
        { 0, 1, 5, 6, 4, 2, 3 },
        { 0, 1, 6, 7, 4, 5, 2, 3 },
159 160
    };

161
    VLC_UNUSED(decoder);
162 163 164
    decoder_t *p_dec = (decoder_t *)client_data;
    decoder_sys_t *p_sys = p_dec->p_sys;

165 166 167
    if( p_dec->fmt_out.audio.i_channels <= 0 ||
        p_dec->fmt_out.audio.i_channels > 8 )
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
168 169 170
    if( date_Get( &p_sys->end_date ) <= VLC_TS_INVALID )
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;

171
    const unsigned char *pi_reorder = ppi_reorder[p_dec->fmt_out.audio.i_channels];
172

173
    p_sys->p_aout_buffer =
174
        decoder_NewAudioBuffer( p_dec, frame->header.blocksize );
175 176 177 178

    if( p_sys->p_aout_buffer == NULL )
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;

179 180 181
    Interleave( (int32_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
                 frame->header.channels, frame->header.blocksize,
                 frame->header.bits_per_sample );
182

183
    /* Date management (already done by packetizer) */
184 185 186 187
    p_sys->p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
    p_sys->p_aout_buffer->i_length =
        date_Increment( &p_sys->end_date, frame->header.blocksize ) -
        p_sys->p_aout_buffer->i_pts;
188 189 190 191

    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
/*****************************************************************************
 * DecoderReadCallback: called by libflac when it needs more data
 *****************************************************************************/
static FLAC__StreamDecoderReadStatus
DecoderReadCallback( const FLAC__StreamDecoder *decoder, FLAC__byte buffer[],
                     size_t *bytes, void *client_data )
{
    VLC_UNUSED(decoder);
    decoder_t *p_dec = (decoder_t *)client_data;
    decoder_sys_t *p_sys = p_dec->p_sys;

    if( p_sys->p_block && p_sys->p_block->i_buffer )
    {
        *bytes = __MIN(*bytes, p_sys->p_block->i_buffer);
        memcpy( buffer, p_sys->p_block->p_buffer, *bytes );
        p_sys->p_block->i_buffer -= *bytes;
        p_sys->p_block->p_buffer += *bytes;
    }
    else
    {
        *bytes = 0;
        return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
    }

    return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}

219 220 221 222 223 224 225
/*****************************************************************************
 * DecoderMetadataCallback: called by libflac to when it encounters metadata
 *****************************************************************************/
static void DecoderMetadataCallback( const FLAC__StreamDecoder *decoder,
                                     const FLAC__StreamMetadata *metadata,
                                     void *client_data )
{
226
    VLC_UNUSED(decoder);
227 228 229 230 231 232 233 234 235
    decoder_t *p_dec = (decoder_t *)client_data;
    decoder_sys_t *p_sys = p_dec->p_sys;

    /* Setup the format */
    p_dec->fmt_out.audio.i_rate     = metadata->data.stream_info.sample_rate;
    p_dec->fmt_out.audio.i_channels = metadata->data.stream_info.channels;
    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels =
            pi_channels_maps[metadata->data.stream_info.channels];
236 237 238
    if (!p_dec->fmt_out.audio.i_bitspersample)
        p_dec->fmt_out.audio.i_bitspersample =
            metadata->data.stream_info.bits_per_sample;
239 240 241 242 243

    msg_Dbg( p_dec, "channels:%d samplerate:%d bitspersamples:%d",
             p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_rate,
             p_dec->fmt_out.audio.i_bitspersample );

244
    p_sys->b_stream_info = true;
245 246
    p_sys->stream_info = metadata->data.stream_info;

247 248
    date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
    date_Set( &p_sys->end_date, VLC_TS_INVALID );
249 250 251 252 253 254 255 256 257
}

/*****************************************************************************
 * DecoderErrorCallback: called when the libflac decoder encounters an error
 *****************************************************************************/
static void DecoderErrorCallback( const FLAC__StreamDecoder *decoder,
                                  FLAC__StreamDecoderErrorStatus status,
                                  void *client_data )
{
258
    VLC_UNUSED(decoder);
259 260 261 262 263
    decoder_t *p_dec = (decoder_t *)client_data;

    switch( status )
    {
    case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
264
        msg_Warn( p_dec, "an error in the stream caused the decoder to "
265
                 "lose synchronization." );
266 267
        break;
    case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
Benjamin Pracht's avatar
Benjamin Pracht committed
268
        msg_Err( p_dec, "the decoder encountered a corrupted frame header." );
269 270
        break;
    case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
Benjamin Pracht's avatar
Benjamin Pracht committed
271
        msg_Err( p_dec, "frame's data did not match the CRC in the "
272 273
                 "footer." );
        break;
274 275 276 277
    case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
        msg_Err( p_dec, "The decoder encountered reserved fields in use in "
                 "the stream." );
        break;
278 279 280
    default:
        msg_Err( p_dec, "got decoder error: %d", status );
    }
281

282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
    FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );
    return;
}
/*****************************************************************************
 * OpenDecoder: probe the decoder and return score
 *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;

    if( p_dec->fmt_in.i_codec != VLC_CODEC_FLAC )
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
        return VLC_ENOMEM;

    /* Misc init */
    p_sys->b_stream_info = false;
    p_sys->p_block = NULL;

    /* Take care of flac init */
    if( !(p_sys->p_flac = FLAC__stream_decoder_new()) )
    {
        msg_Err( p_dec, "FLAC__stream_decoder_new() failed" );
        free( p_sys );
        return VLC_EGENERIC;
    }

#ifdef USE_NEW_FLAC_API
    if( FLAC__stream_decoder_init_stream( p_sys->p_flac,
                                          DecoderReadCallback,
                                          NULL,
                                          NULL,
                                          NULL,
                                          NULL,
                                          DecoderWriteCallback,
                                          DecoderMetadataCallback,
                                          DecoderErrorCallback,
                                          p_dec )
        != FLAC__STREAM_DECODER_INIT_STATUS_OK )
    {
        msg_Err( p_dec, "FLAC__stream_decoder_init_stream() failed" );
        FLAC__stream_decoder_delete( p_sys->p_flac );
        free( p_sys );
        return VLC_EGENERIC;
    }
#else
    FLAC__stream_decoder_set_read_callback( p_sys->p_flac,
                                            DecoderReadCallback );
    FLAC__stream_decoder_set_write_callback( p_sys->p_flac,
                                             DecoderWriteCallback );
    FLAC__stream_decoder_set_metadata_callback( p_sys->p_flac,
                                                DecoderMetadataCallback );
    FLAC__stream_decoder_set_error_callback( p_sys->p_flac,
                                             DecoderErrorCallback );
    FLAC__stream_decoder_set_client_data( p_sys->p_flac, p_dec );

    FLAC__stream_decoder_init( p_sys->p_flac );
#endif

    /* Set output properties */
    p_dec->fmt_out.i_cat = AUDIO_ES;
348
    p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
349 350 351 352 353 354 355 356

    /* Set callbacks */
    p_dec->pf_decode_audio = DecodeBlock;

    /* */
    p_dec->b_need_packetized = true;

    return VLC_SUCCESS;
357 358 359
}

/*****************************************************************************
360
 * CloseDecoder: flac decoder destruction
361
 *****************************************************************************/
362
static void CloseDecoder( vlc_object_t *p_this )
363
{
364 365
    decoder_t *p_dec = (decoder_t *)p_this;
    decoder_sys_t *p_sys = p_dec->p_sys;
366

367 368 369 370 371 372
    FLAC__stream_decoder_finish( p_sys->p_flac );
    FLAC__stream_decoder_delete( p_sys->p_flac );

    if( p_sys->p_block )
        block_Release( p_sys->p_block );
    free( p_sys );
373 374
}

375 376 377 378
/*****************************************************************************
 * ProcessHeader: process Flac header.
 *****************************************************************************/
static void ProcessHeader( decoder_t *p_dec )
379
{
380 381 382 383 384 385 386
    decoder_sys_t *p_sys = p_dec->p_sys;

    if( !p_dec->fmt_in.i_extra )
        return;

    /* Decode STREAMINFO */
    msg_Dbg( p_dec, "decode STREAMINFO" );
387
    size_t i_extra = p_dec->fmt_in.i_extra;
388 389 390 391 392 393 394
    static const char header[4] = { 'f', 'L', 'a', 'C' };

    if (i_extra > 42 && !memcmp(p_dec->fmt_in.p_extra, header, 4))
        i_extra = 42;
    else if (i_extra > 34 && memcmp(p_dec->fmt_in.p_extra, header, 4))
        i_extra = 34;

395 396 397 398
    switch (i_extra) {
    case 34:
        p_sys->p_block = block_Alloc( 8 + i_extra );
        memcpy( p_sys->p_block->p_buffer + 8, p_dec->fmt_in.p_extra, i_extra );
399
        memcpy( p_sys->p_block->p_buffer, header, 4);
400
        uint8_t *p = p_sys->p_block->p_buffer;
401
        p[4] = 0x80 | 0; /* STREAMINFO faked as last block */
402 403 404 405 406 407 408 409 410
        p[5] = 0;
        p[6] = 0;
        p[7] = 34; /* block size */
        break;
    case 42:
        p_sys->p_block = block_Alloc( i_extra );
        memcpy( p_sys->p_block->p_buffer, p_dec->fmt_in.p_extra, i_extra );
        break;
    default:
411
        msg_Err(p_dec, "Invalid flac header size %zu", i_extra);
412 413
        return;
    }
414 415
    FLAC__stream_decoder_process_until_end_of_metadata( p_sys->p_flac );
    msg_Dbg( p_dec, "STREAMINFO decoded" );
416 417 418 419 420 421 422 423 424 425 426
}

/*****************************************************************************
 * decoder_state_error: print meaningful error messages
 *****************************************************************************/
static void decoder_state_error( decoder_t *p_dec,
                                 FLAC__StreamDecoderState state )
{
    switch ( state )
    {
    case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
427
        msg_Dbg( p_dec, "the decoder is ready to search for metadata." );
428 429
        break;
    case FLAC__STREAM_DECODER_READ_METADATA:
430
        msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
431 432 433
                 "reading metadata." );
        break;
    case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
434
        msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
435 436 437
                 "searching for the frame sync code." );
        break;
    case FLAC__STREAM_DECODER_READ_FRAME:
438
        msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
439 440 441
                 "reading a frame." );
        break;
    case FLAC__STREAM_DECODER_END_OF_STREAM:
442
        msg_Dbg( p_dec, "the decoder has reached the end of the stream." );
443
        break;
444 445 446 447 448 449 450 451
#ifdef USE_NEW_FLAC_API
    case FLAC__STREAM_DECODER_OGG_ERROR:
        msg_Err( p_dec, "error occurred in the Ogg layer." );
        break;
    case FLAC__STREAM_DECODER_SEEK_ERROR:
        msg_Err( p_dec, "error occurred while seeking." );
        break;
#endif
452
    case FLAC__STREAM_DECODER_ABORTED:
453
        msg_Warn( p_dec, "the decoder was aborted by the read callback." );
454
        break;
455
#ifndef USE_NEW_FLAC_API
456
    case FLAC__STREAM_DECODER_UNPARSEABLE_STREAM:
457
        msg_Warn( p_dec, "the decoder encountered reserved fields in use "
458 459
                 "in the stream." );
        break;
460
#endif
461
    case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
Benjamin Pracht's avatar
Benjamin Pracht committed
462
        msg_Err( p_dec, "error when allocating memory." );
463
        break;
464
#ifndef USE_NEW_FLAC_API
465 466 467 468 469 470 471 472 473
    case FLAC__STREAM_DECODER_ALREADY_INITIALIZED:
        msg_Err( p_dec, "FLAC__stream_decoder_init() was called when the "
                 "decoder was already initialized, usually because "
                 "FLAC__stream_decoder_finish() was not called." );
        break;
    case FLAC__STREAM_DECODER_INVALID_CALLBACK:
        msg_Err( p_dec, "FLAC__stream_decoder_init() was called without "
                 "all callbacks being set." );
        break;
474
#endif
475
    case FLAC__STREAM_DECODER_UNINITIALIZED:
Benjamin Pracht's avatar
Benjamin Pracht committed
476
        msg_Err( p_dec, "decoder in uninitialized state." );
477 478
        break;
    default:
479
        msg_Warn(p_dec, "unknown error" );
480 481 482
    }
}

483 484 485
/****************************************************************************
 * DecodeBlock: the whole thing
 ****************************************************************************/
486
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
487 488 489
{
    decoder_sys_t *p_sys = p_dec->p_sys;

490
    if( !pp_block || !*pp_block )
491
        return NULL;
492
    if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
493
    {
494
        block_Release( *pp_block );
495 496 497 498 499 500
        return NULL;
    }

    if( !p_sys->b_stream_info )
        ProcessHeader( p_dec );

501
    p_sys->p_block = *pp_block;
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
    *pp_block = NULL;

    if( p_sys->p_block->i_pts > VLC_TS_INVALID &&
        p_sys->p_block->i_pts != date_Get( &p_sys->end_date ) )
        date_Set( &p_sys->end_date, p_sys->p_block->i_pts );

    p_sys->p_aout_buffer = 0;

    if( !FLAC__stream_decoder_process_single( p_sys->p_flac ) )
    {
        decoder_state_error( p_dec,
                             FLAC__stream_decoder_get_state( p_sys->p_flac ) );
        FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );
    }

    /* If the decoder is in the "aborted" state,
     * FLAC__stream_decoder_process_single() won't return an error. */
    if( FLAC__stream_decoder_get_state(p_dec->p_sys->p_flac)
        == FLAC__STREAM_DECODER_ABORTED )
    {
        FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );
    }

    block_Release( p_sys->p_block );
    p_sys->p_block = NULL;

    return p_sys->p_aout_buffer;
}

531 532
#ifdef ENABLE_SOUT

533 534 535 536 537 538 539 540 541 542 543 544 545
/*****************************************************************************
 * encoder_sys_t : flac encoder descriptor
 *****************************************************************************/
struct encoder_sys_t
{
    /*
     * Input properties
     */
    int i_headers;

    int i_samples_delay;

    FLAC__int32 *p_buffer;
546
    unsigned int i_buffer;
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561

    block_t *p_chain;

    /*
     * FLAC properties
     */
    FLAC__StreamEncoder *p_flac;
    FLAC__StreamMetadata_StreamInfo stream_info;

    /*
     * Common properties
     */
    mtime_t i_pts;
};

562
#define STREAMINFO_SIZE 34
563

564
static block_t *Encode( encoder_t *, block_t * );
565

566 567 568
/*****************************************************************************
 * EncoderWriteCallback: called by libflac to output encoded samples
 *****************************************************************************/
569 570 571
static FLAC__StreamEncoderWriteStatus
EncoderWriteCallback( const FLAC__StreamEncoder *encoder,
                      const FLAC__byte buffer[],
572
                      size_t bytes, unsigned samples,
573 574 575 576 577 578 579 580 581 582 583 584 585 586
                      unsigned current_frame, void *client_data )
{
    VLC_UNUSED(encoder); VLC_UNUSED(current_frame);
    encoder_t *p_enc = (encoder_t *)client_data;
    encoder_sys_t *p_sys = p_enc->p_sys;
    block_t *p_block;

    if( samples == 0 )
    {
        if( p_sys->i_headers == 1 )
        {
            msg_Dbg( p_enc, "Writing STREAMINFO: %zu", bytes );

            /* Backup the STREAMINFO metadata block */
587 588 589 590 591 592
            p_enc->fmt_out.i_extra = STREAMINFO_SIZE + 8;
            p_enc->fmt_out.p_extra = xmalloc( STREAMINFO_SIZE + 8);
            memcpy(p_enc->fmt_out.p_extra, "fLaC", 4);
            memcpy(p_enc->fmt_out.p_extra + 4, buffer, STREAMINFO_SIZE );
            /* Fake this as the last metadata block */
            ((uint8_t*)p_enc->fmt_out.p_extra)[4] |= 0x80;
593 594 595 596 597
        }
        p_sys->i_headers++;
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
    }

598
    p_block = block_Alloc( bytes );
599 600 601 602 603 604 605 606 607 608 609 610 611
    memcpy( p_block->p_buffer, buffer, bytes );

    p_block->i_dts = p_block->i_pts = p_sys->i_pts;

    p_sys->i_samples_delay -= samples;

    p_block->i_length = (mtime_t)1000000 *
        (mtime_t)samples / (mtime_t)p_enc->fmt_in.audio.i_rate;

    /* Update pts */
    p_sys->i_pts += p_block->i_length;

    block_ChainAppend( &p_sys->p_chain, p_block );
612

613 614 615 616 617
    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
/*****************************************************************************
 * EncoderMetadataCallback: called by libflac to output metadata
 *****************************************************************************/
618 619
static void EncoderMetadataCallback( const FLAC__StreamEncoder *encoder,
                                     const FLAC__StreamMetadata *metadata,
620 621 622 623 624 625 626 627
                                     void *client_data )
{
    VLC_UNUSED(encoder);
    encoder_t *p_enc = (encoder_t *)client_data;

    msg_Err( p_enc, "MetadataCallback: %i", metadata->type );
    return;
}
628 629 630 631 632 633 634 635 636

/*****************************************************************************
 * OpenEncoder: probe the encoder and return score
 *****************************************************************************/
static int OpenEncoder( vlc_object_t *p_this )
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys;

637
    if( p_enc->fmt_out.i_codec != VLC_CODEC_FLAC &&
638
        !p_enc->b_force )
639 640 641 642 643 644
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
645
        return VLC_ENOMEM;
646 647
    p_enc->p_sys = p_sys;
    p_enc->pf_encode_audio = Encode;
648
    p_enc->fmt_out.i_codec = VLC_CODEC_FLAC;
649

650 651 652
    p_sys->i_headers = 0;
    p_sys->p_buffer = 0;
    p_sys->i_buffer = 0;
653
    p_sys->i_samples_delay = 0;
654 655

    /* Create flac encoder */
656 657 658 659 660 661
    if( !(p_sys->p_flac = FLAC__stream_encoder_new()) )
    {
        msg_Err( p_enc, "FLAC__stream_encoder_new() failed" );
        free( p_sys );
        return VLC_EGENERIC;
    }
662 663 664 665 666 667 668

    FLAC__stream_encoder_set_streamable_subset( p_sys->p_flac, 1 );
    FLAC__stream_encoder_set_channels( p_sys->p_flac,
                                       p_enc->fmt_in.audio.i_channels );
    FLAC__stream_encoder_set_sample_rate( p_sys->p_flac,
                                          p_enc->fmt_in.audio.i_rate );
    FLAC__stream_encoder_set_bits_per_sample( p_sys->p_flac, 16 );
669
    p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
670

671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
    /* Get and store the STREAMINFO metadata block as a p_extra */
    p_sys->p_chain = 0;

#ifdef USE_NEW_FLAC_API
    if( FLAC__stream_encoder_init_stream( p_sys->p_flac,
                                          EncoderWriteCallback,
                                          NULL,
                                          NULL,
                                          EncoderMetadataCallback,
                                          p_enc )
        != FLAC__STREAM_ENCODER_INIT_STATUS_OK )
    {
        msg_Err( p_enc, "FLAC__stream_encoder_init_stream() failed" );
        FLAC__stream_encoder_delete( p_sys->p_flac );
        free( p_sys );
        return VLC_EGENERIC;
    }
#else
689 690 691 692 693 694 695
    FLAC__stream_encoder_set_write_callback( p_sys->p_flac,
        EncoderWriteCallback );
    FLAC__stream_encoder_set_metadata_callback( p_sys->p_flac,
        EncoderMetadataCallback );
    FLAC__stream_encoder_set_client_data( p_sys->p_flac, p_enc );

    FLAC__stream_encoder_init( p_sys->p_flac );
696
#endif
697 698 699 700 701 702 703 704 705

    return VLC_SUCCESS;
}

/****************************************************************************
 * Encode: the whole thing
 ****************************************************************************
 * This function spits out ogg packets.
 ****************************************************************************/
706
static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf )
707 708 709
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    block_t *p_chain;
710
    unsigned int i;
711

712 713 714
    /* FIXME: p_aout_buf is NULL when it's time to flush*/
    if( unlikely( !p_aout_buf ) ) return NULL;

715
    p_sys->i_pts = p_aout_buf->i_pts -
716 717 718 719 720 721
                (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
                (mtime_t)p_enc->fmt_in.audio.i_rate;

    p_sys->i_samples_delay += p_aout_buf->i_nb_samples;

    /* Convert samples to FLAC__int32 */
722
    if( p_sys->i_buffer < p_aout_buf->i_buffer * sizeof(FLAC__int32) )
723 724
    {
        p_sys->p_buffer =
725
            xrealloc( p_sys->p_buffer, p_aout_buf->i_buffer * sizeof(FLAC__int32) );
726
        p_sys->i_buffer = p_aout_buf->i_buffer * 2;
727 728
    }

729
    for( i = 0 ; i < p_aout_buf->i_buffer / 2 ; i++ )
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
    {
        p_sys->p_buffer[i]= ((int16_t *)p_aout_buf->p_buffer)[i];
    }

    FLAC__stream_encoder_process_interleaved( p_sys->p_flac, p_sys->p_buffer,
                                              p_aout_buf->i_nb_samples );

    p_chain = p_sys->p_chain;
    p_sys->p_chain = 0;

    return p_chain;
}

/*****************************************************************************
 * CloseEncoder: encoder destruction
 *****************************************************************************/
static void CloseEncoder( vlc_object_t *p_this )
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys = p_enc->p_sys;

    FLAC__stream_encoder_delete( p_sys->p_flac );

753
    free( p_sys->p_buffer );
754 755
    free( p_sys );
}
756
#endif