]> git.sesse.net Git - vlc/commitdiff
added a demux and decoder for flac files (disabled by default). Works for
authorSigmund Augdal Helberg <sigmunau@videolan.org>
Sun, 23 Feb 2003 16:31:48 +0000 (16:31 +0000)
committerSigmund Augdal Helberg <sigmunau@videolan.org>
Sun, 23 Feb 2003 16:31:48 +0000 (16:31 +0000)
16bit per sample streams, only tested with stereo

configure.ac.in
modules/codec/Modules.am
modules/codec/flacdec.c [new file with mode: 0644]
modules/demux/Modules.am
modules/demux/flac.c [new file with mode: 0644]

index a4c70546cdde1c298dda683cef06506753c2144b..c679f54baf70eaa97871e4c82cc1e5264730ea92 100644 (file)
@@ -1735,6 +1735,19 @@ dnl
 AC_ARG_ENABLE(dv,
   [  --enable-dv             DV decoder support (default disabled)])
 if test "x${enable_dv}" = "xyes"
+then
+  AC_CHECK_HEADERS(FLAC/stream_decoder.h, [
+    PLUGINS="${PLUGINS} flac flacdec"
+    LDFLAGS_flacdec="${LDFLAGS_flacdec} -lFLAC"
+   ],[])
+fi
+
+dnl
+dnl  DV plugin
+dnl
+AC_ARG_ENABLE(flac,
+  [  --enable-falc         flac decoder support (default disabled)])
+if test "x${enable_flac}" = "xyes"
 then
   AC_CHECK_HEADERS(libdv/dv.h, [
     PLUGINS="${PLUGINS} dv"
index ae0eefa8fbfbcc356133e118f8d378e11fbd8a54..701a4a2e6d2b8d332ddf6bb36fa46c7bc2789ac3 100644 (file)
@@ -1,4 +1,5 @@
 SOURCES_a52 = modules/codec/a52.c
+SOURCES_flacdec = modules/codec/flacdec.c
 SOURCES_lpcm = modules/codec/lpcm.c
 SOURCES_araw = modules/codec/araw.c
 SOURCES_vorbis = modules/codec/vorbis.c
diff --git a/modules/codec/flacdec.c b/modules/codec/flacdec.c
new file mode 100644 (file)
index 0000000..5407300
--- /dev/null
@@ -0,0 +1,456 @@
+/*****************************************************************************
+ * flac.c: flac decoder module making use of libflac
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: flacdec.c,v 1.1 2003/02/23 16:31:48 sigmunau Exp $
+ *
+ * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>                                    /* memcpy(), memset() */
+#include <errno.h>
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
+#include <input_ext-dec.h>
+
+#include <vlc/input.h>
+
+#include <FLAC/stream_decoder.h>
+
+/*****************************************************************************
+ * dec_thread_t : flac decoder thread descriptor
+ *****************************************************************************/
+typedef struct dec_thread_t
+{
+    /*
+     * Thread properties
+     */
+    vlc_thread_t        thread_id;                /* id for thread functions */
+
+    /*
+     * Input properties
+     */
+    decoder_fifo_t         *p_fifo;            /* stores the PES stream data */
+    pes_packet_t           *p_pes;            /* current PES we are decoding */
+    int                     i_last_pes_pos;             /* possition into pes*/
+
+    int i_tot;
+    /*
+     * libflac decoder struct
+     */
+    FLAC__StreamDecoder *p_decoder;
+    
+    /*
+     * Output properties
+     */
+    aout_instance_t        *p_aout;
+    aout_input_t           *p_aout_input;
+    audio_sample_format_t   output_format;
+    audio_date_t            end_date;
+    mtime_t                 pts;
+
+} dec_thread_t;
+
+static int pi_channels_maps[6] =
+{
+    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
+     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int  OpenDecoder  ( vlc_object_t * );
+static int  RunDecoder   ( decoder_fifo_t * );
+static void CloseDecoder ( dec_thread_t * );
+
+static FLAC__StreamDecoderReadStatus DecoderReadCallback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+
+static FLAC__StreamDecoderWriteStatus DecoderWriteCallback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data);
+
+static void DecoderMetadataCallback (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
+static void DecoderErrorCallback (const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
+static void Interleave32( int32_t *p_out, const int32_t * const *pp_in,
+                        int i_nb_channels, int i_samples );
+static void Interleave16( int16_t *p_out, const int32_t * const *pp_in,
+                        int i_nb_channels, int i_samples );
+static void decoder_state_error( dec_thread_t *p_dec, FLAC__StreamDecoderState state );
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+    set_description( _("flac decoder module") );
+    set_capability( "decoder", 100 );
+    set_callbacks( OpenDecoder, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+    decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
+
+    if( p_fifo->i_fourcc != VLC_FOURCC('f','l','a','c') )
+    {
+        return VLC_EGENERIC;
+    }
+
+    p_fifo->pf_run = RunDecoder;
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * RunDecoder: the vorbis decoder
+ *****************************************************************************/
+static int RunDecoder( decoder_fifo_t * p_fifo )
+{
+    dec_thread_t *p_dec;
+    FLAC__StreamDecoderState state;
+    /* Allocate the memory needed to store the thread's structure */
+    if( (p_dec = (dec_thread_t *)malloc (sizeof(dec_thread_t)) )
+            == NULL)
+    {
+        msg_Err( p_fifo, "out of memory" );
+        goto error;
+    }
+
+    /* Initialize the thread properties */
+    memset( p_dec, 0, sizeof(dec_thread_t) );
+    p_dec->p_fifo = p_fifo;
+    p_dec->p_pes  = NULL;
+    p_dec->p_decoder = FLAC__stream_decoder_new();
+    if( p_dec->p_decoder == NULL )
+    {
+        msg_Err( p_fifo, "FLAC__stream_decoder_new() failed" );
+        goto error;
+    }
+    FLAC__stream_decoder_set_read_callback( p_dec->p_decoder,
+                                               DecoderReadCallback );
+    FLAC__stream_decoder_set_write_callback( p_dec->p_decoder,
+                                               DecoderWriteCallback );
+    FLAC__stream_decoder_set_metadata_callback( p_dec->p_decoder,
+                                               DecoderMetadataCallback );
+    FLAC__stream_decoder_set_error_callback( p_dec->p_decoder,
+                                               DecoderErrorCallback );
+    FLAC__stream_decoder_set_client_data( p_dec->p_decoder,
+                                             p_dec );
+
+
+    FLAC__stream_decoder_init( p_dec->p_decoder );
+    if ( !FLAC__stream_decoder_process_until_end_of_metadata( p_dec->p_decoder ) )
+    {
+        state = FLAC__stream_decoder_get_state( p_dec->p_decoder );
+        decoder_state_error( p_dec, state );                
+        goto error;
+    }
+
+    aout_DateInit( &p_dec->end_date, p_dec->output_format.i_rate );
+    p_dec->p_aout = NULL;
+    p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
+                                       &p_dec->p_aout,
+                                       &p_dec->output_format );
+
+    if( p_dec->p_aout_input == NULL )
+    {
+        msg_Err( p_dec->p_fifo, "failed to create aout fifo" );
+        goto error;
+    }
+    
+    /* vorbis decoder thread's main loop */
+    while( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) )
+    { 
+        if ( !FLAC__stream_decoder_process_single( p_dec->p_decoder ) )
+        {
+            state = FLAC__stream_decoder_get_state( p_dec->p_decoder );
+            decoder_state_error( p_dec, state );
+        }
+    }
+
+    /* If b_error is set, the vorbis decoder thread enters the error loop */
+    if( p_dec->p_fifo->b_error )
+    {
+        DecoderError( p_dec->p_fifo );
+    }
+
+    /* End of the vorbis decoder thread */
+    CloseDecoder( p_dec );
+
+    return 0;
+
+ error:
+    DecoderError( p_fifo );
+    if( p_dec )
+    {
+        if( p_dec->p_fifo )
+            p_dec->p_fifo->b_error = 1;
+
+        /* End of the vorbis decoder thread */
+        CloseDecoder( p_dec );
+    }
+
+    return -1;
+}
+
+/*****************************************************************************
+ * CloseDecoder: closes the decoder
+ *****************************************************************************/
+static void CloseDecoder ( dec_thread_t *p_dec )
+{
+    if( p_dec->p_aout_input != NULL )
+    {
+        aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
+    }
+
+    if( p_dec )
+    {
+        if( p_dec->p_pes )
+            input_DeletePES( p_dec->p_fifo->p_packets_mgt, p_dec->p_pes );
+        FLAC__stream_decoder_finish( p_dec->p_decoder );
+        FLAC__stream_decoder_delete( p_dec->p_decoder );
+        free( p_dec );
+    }
+
+}
+
+
+    
+/*****************************************************************************
+ * DecoderReadCallback: called by libflac when it needs more data
+ *****************************************************************************/
+static FLAC__StreamDecoderReadStatus DecoderReadCallback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+{
+    dec_thread_t *p_dec = (dec_thread_t *)client_data;
+    if( !p_dec->i_last_pes_pos )
+    {
+        input_DeletePES( p_dec->p_fifo->p_packets_mgt,
+                         p_dec->p_pes );
+        input_ExtractPES( p_dec->p_fifo, &p_dec->p_pes );
+        if( !p_dec->p_pes )
+        {
+            return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+        }
+    }
+    p_dec->pts = p_dec->p_pes->i_pts;
+    if( ( p_dec->p_pes->i_pes_size - p_dec->i_last_pes_pos ) > *bytes )
+    {
+        p_dec->p_fifo->p_vlc->pf_memcpy( buffer,
+                                         p_dec->p_pes->p_first->p_payload_start
+                                         + p_dec->i_last_pes_pos,
+                                         *bytes );
+        p_dec->i_last_pes_pos += *bytes;
+    }
+    else
+    {
+        p_dec->p_fifo->p_vlc->pf_memcpy( buffer,
+                                         p_dec->p_pes->p_first->p_payload_start
+                                         + p_dec->i_last_pes_pos,
+                                         p_dec->p_pes->i_pes_size
+                                         - p_dec->i_last_pes_pos );
+        *bytes = p_dec->p_pes->i_pes_size - p_dec->i_last_pes_pos ;
+        p_dec->i_last_pes_pos = 0;
+    }
+    p_dec->i_tot += *bytes;
+
+    return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+}
+
+/*****************************************************************************
+ * 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 )
+{
+    dec_thread_t *p_dec = (dec_thread_t *)client_data;
+    int i_samples = frame->header.blocksize;
+    aout_buffer_t *p_aout_buffer;
+    p_aout_buffer = aout_DecNewBuffer( p_dec->p_aout, p_dec->p_aout_input,
+                                       i_samples );
+    if( !p_aout_buffer )
+    {
+        msg_Err( p_dec->p_fifo, "cannot get aout buffer" );
+        p_dec->p_fifo->b_error = 1;
+        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+    }
+    switch ( frame->header.bits_per_sample )
+    {
+    case 16:
+        Interleave16( (int16_t *)p_aout_buffer->p_buffer, buffer,
+                frame->header.channels, i_samples );
+        break;
+    default:
+        Interleave32( (int32_t *)p_aout_buffer->p_buffer, buffer,
+                frame->header.channels, i_samples );
+    }
+        
+    if( p_dec->pts != 0 && p_dec->pts != aout_DateGet( &p_dec->end_date ) )
+    {
+        aout_DateSet( &p_dec->end_date, p_dec->pts );
+        p_dec->pts = 0;
+    }
+    else if( !aout_DateGet( &p_dec->end_date ) )
+    {
+        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+    }
+
+    /* Date management */
+    p_aout_buffer->start_date = aout_DateGet( &p_dec->end_date );
+    p_aout_buffer->end_date = aout_DateIncrement( &p_dec->end_date,
+                                                  i_samples );
+    aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
+    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+/*****************************************************************************
+' * DecoderMetadataCallback: called by libflac to when it encounters metadata
+ *****************************************************************************/
+static void DecoderMetadataCallback (const FLAC__StreamDecoder *decoder,
+                                     const FLAC__StreamMetadata *metadata,
+                                     void *client_data)
+{
+    dec_thread_t *p_dec = (dec_thread_t *)client_data;
+    switch ( metadata->data.stream_info.bits_per_sample )
+    {
+    case 8:
+        p_dec->output_format.i_format = VLC_FOURCC('s','8',' ',' ');
+        break;
+    case 16:
+        p_dec->output_format.i_format = AOUT_FMT_S16_NE;
+        break;
+    default:
+        msg_Dbg( p_dec->p_fifo, "strange bps %d",
+                 metadata->data.stream_info.bits_per_sample );
+        p_dec->output_format.i_format = VLC_FOURCC('f','i','3','2');
+        break;
+    }
+    p_dec->output_format.i_physical_channels =
+        p_dec->output_format.i_original_channels =
+            pi_channels_maps[metadata->data.stream_info.channels];
+    p_dec->output_format.i_rate = metadata->data.stream_info.sample_rate;
+
+    return;
+}
+
+/*****************************************************************************
+ * DecoderErrorCallback: called when the libflac decoder encounters an error
+ *****************************************************************************/
+static void DecoderErrorCallback (const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+{
+    dec_thread_t *p_dec = (dec_thread_t *)client_data;
+    switch ( status )
+    {
+    case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC :
+        msg_Err( p_dec->p_fifo, "An error in the stream caused the decoder to lose synchronization.");
+        break;
+
+    case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER :
+        msg_Err( p_dec->p_fifo, "The decoder encountered a corrupted frame header.");
+        break;
+
+    case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH :
+        msg_Err( p_dec->p_fifo, "The frame's data did not match the CRC in the footer.");
+        break;
+    default:
+        msg_Err( p_dec->p_fifo, "got decoder error: %d", status );
+    }
+    return;
+}
+
+/*****************************************************************************
+ * Interleave: helper function to interleave channels
+ *****************************************************************************/
+static void Interleave32( int32_t *p_out, const int32_t * const *pp_in,
+                        int i_nb_channels, int i_samples )
+{
+    int i, j;
+
+    for ( j = 0; j < i_samples; j++ )
+    {
+        for ( i = 0; i < i_nb_channels; i++ )
+        {
+            p_out[j * i_nb_channels + i] = pp_in[i][j];
+        }
+    }
+}
+static void Interleave16( int16_t *p_out, const int32_t * const *pp_in,
+                        int i_nb_channels, int i_samples )
+{
+    int i, j;
+
+    for ( j = 0; j < i_samples; j++ )
+    {
+        for ( i = 0; i < i_nb_channels; i++ )
+        {
+            p_out[j * i_nb_channels + i] = (int32_t)(pp_in[i][j]);
+        }
+    }
+}
+
+
+static void decoder_state_error( dec_thread_t *p_dec, FLAC__StreamDecoderState state )
+{
+    switch ( state )
+    {
+    case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA  : 
+        msg_Err( p_dec->p_fifo, "The decoder is ready to search for metadata.");
+        break;
+    case FLAC__STREAM_DECODER_READ_METADATA  : 
+        msg_Err( p_dec->p_fifo, "The decoder is ready to or is in the process of reading metadata.");
+        break;
+    case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC  : 
+        msg_Err( p_dec->p_fifo, "The decoder is ready to or is in the process of searching for the frame sync code.");
+        break;
+    case FLAC__STREAM_DECODER_READ_FRAME  : 
+        msg_Err( p_dec->p_fifo, "The decoder is ready to or is in the process of reading a frame.");
+        break;
+    case FLAC__STREAM_DECODER_END_OF_STREAM  : 
+        msg_Err( p_dec->p_fifo, "The decoder has reached the end of the stream.");
+        break;
+    case FLAC__STREAM_DECODER_ABORTED  : 
+        msg_Err( p_dec->p_fifo, "The decoder was aborted by the read callback.");
+        break;
+    case FLAC__STREAM_DECODER_UNPARSEABLE_STREAM  : 
+        msg_Err( p_dec->p_fifo, "The decoder encountered reserved fields in use in the stream.");
+        break;
+    case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR  : 
+        msg_Err( p_dec->p_fifo, "An error occurred allocating memory.");
+        break;
+    case FLAC__STREAM_DECODER_ALREADY_INITIALIZED  : 
+        msg_Err( p_dec->p_fifo, "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->p_fifo, "FLAC__stream_decoder_init() was called without all callbacks being set.");
+        break;
+    case FLAC__STREAM_DECODER_UNINITIALIZED  : 
+        msg_Err( p_dec->p_fifo, "The decoder is in the uninitialized state.");
+        break;
+    default:
+        msg_Err(p_dec->p_fifo, "unknown error" );
+    }
+}
index a36c6061443e76b8090728a15932ba9d7b197dce..78101b29b83afd491d78c4b06730812112e3eec3 100644 (file)
@@ -1,4 +1,5 @@
 SOURCES_a52sys = modules/demux/a52sys.c
+SOURCES_flac = modules/demux/flac.c
 SOURCES_ogg = modules/demux/ogg.c
 SOURCES_m3u = modules/demux/m3u.c
 SOURCES_demuxdump = modules/demux/demuxdump.c
diff --git a/modules/demux/flac.c b/modules/demux/flac.c
new file mode 100644 (file)
index 0000000..4abc9bc
--- /dev/null
@@ -0,0 +1,181 @@
+/*****************************************************************************
+ * a52sys.c : A/52 input module for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: flac.c,v 1.1 2003/02/23 16:31:48 sigmunau Exp $
+ *
+ * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>                                              /* strdup() */
+#include <errno.h>
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include <sys/types.h>
+
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+#define A52_PACKET_SIZE 16384
+#define MAX_PACKETS_IN_FIFO 1
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int  Init  ( vlc_object_t * );
+static int  Demux ( input_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();                                      
+    set_description( "flac demuxer" );                       
+    set_capability( "demux", 155 );
+    set_callbacks( Init, NULL );
+    add_shortcut( "flac" );
+vlc_module_end();
+
+/*****************************************************************************
+ * Init: initializes ES structures
+ *****************************************************************************/
+static int Init( vlc_object_t * p_this )
+{
+    input_thread_t *    p_input = (input_thread_t *)p_this;
+    es_descriptor_t *   p_es;
+    byte_t *            p_peek;
+
+    /* Initialize access plug-in structures. */
+    if( p_input->i_mtu == 0 )
+    {
+        /* Improve speed. */
+        p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
+    }
+
+    p_input->pf_demux = Demux;
+    p_input->pf_rewind = NULL;
+
+    /* Have a peep at the show. */
+    if( input_Peek( p_input, &p_peek, 4 ) < 4 )
+    {
+        /* Stream shorter than 4 bytes... */
+        msg_Err( p_input, "cannot peek()" );
+        return( -1 );
+    }
+
+    if( *p_peek != 'f' || *(p_peek + 1) != 'L' || *(p_peek +2) != 'a'
+        || *(p_peek+3) != 'C')
+    {
+        if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "flac", 4 ) )
+        {
+            /* User forced */
+            msg_Err( p_input, "this doesn't look like an flac stream, continuing" );
+        }
+        else
+        {
+            msg_Warn( p_input, "flac module discarded (no startcode)" );
+            return( -1 );
+        }
+    }
+
+    if( input_InitStream( p_input, 0 ) == -1 )
+    {
+        return( -1 );
+    }
+    input_AddProgram( p_input, 0, 0 );
+    p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xBD, 0 );
+    p_es->i_stream_id = 0xBD;
+    p_es->i_fourcc = VLC_FOURCC('f','l','a','c');
+    p_es->i_cat = AUDIO_ES;
+    input_SelectES( p_input, p_es );
+    p_input->stream.p_selected_area->i_tell = 0;
+    p_input->stream.p_selected_program->b_is_ok = 1;
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+    return( 0 );
+}
+
+/*****************************************************************************
+ * Demux: reads and demuxes data packets
+ *****************************************************************************
+ * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
+ *****************************************************************************/
+static int Demux( input_thread_t * p_input )
+{
+    ssize_t         i_read;
+    decoder_fifo_t * p_fifo =
+        p_input->stream.p_selected_program->pp_es[0]->p_decoder_fifo;
+    pes_packet_t *  p_pes;
+    data_packet_t * p_data;
+
+    if( p_fifo == NULL )
+    {
+        return -1;
+    }
+
+    i_read = input_SplitBuffer( p_input, &p_data, A52_PACKET_SIZE );
+
+    if ( i_read <= 0 )
+    {
+        return i_read;
+    }
+
+    p_pes = input_NewPES( p_input->p_method_data );
+
+    if( p_pes == NULL )
+    {
+        msg_Err( p_input, "out of memory" );
+        input_DeletePacket( p_input->p_method_data, p_data );
+        return( -1 );
+    }
+
+    p_pes->i_rate = p_input->stream.control.i_rate;
+    p_pes->p_first = p_pes->p_last = p_data;
+    p_pes->i_pes_size = i_read;
+    p_pes->i_nb_data = 1;
+
+    vlc_mutex_lock( &p_fifo->data_lock );
+    if( p_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
+    {
+        /* Wait for the decoder. */
+        vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
+    }
+    vlc_mutex_unlock( &p_fifo->data_lock );
+
+    if( (p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT)
+       |(p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_START)
+         | (input_ClockManageControl( p_input, 
+                      p_input->stream.p_selected_program,
+                         (mtime_t)0 ) == PAUSE_S) )
+    {
+        msg_Warn( p_input, "synchro reinit" );
+        p_pes->i_pts = mdate() + DEFAULT_PTS_DELAY;
+        p_input->stream.p_selected_program->i_synchro_state = SYNCHRO_OK;
+    }
+
+    input_DecodePES( p_fifo, p_pes );
+
+    return 1;
+}
+