]> git.sesse.net Git - vlc/blobdiff - modules/codec/flac.c
Qt: use the theme icons for the system tray too
[vlc] / modules / codec / flac.c
index 9cb441c727ed9b95891c6840b9bfff1f3a3e16e9..25bc92c51618a33981c1253be93acdf9bba62010 100644 (file)
@@ -1,25 +1,25 @@
 /*****************************************************************************
  * flac.c: flac decoder/encoder module making use of libflac
  *****************************************************************************
- * Copyright (C) 1999-2001 the VideoLAN team
+ * Copyright (C) 1999-2001 VLC authors and VideoLAN
  * $Id$
  *
  * Authors: Gildas Bazin <gbazin@videolan.org>
  *          Sigmund Augdal Helberg <dnumgis@videolan.org>
  *
- * 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
+ * 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
  * (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.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * 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.
  *****************************************************************************/
 
 /*****************************************************************************
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_codec.h>
-#include <vlc_aout.h>
 
-#include <stream_decoder.h>
-#include <stream_encoder.h>
+#include <FLAC/stream_decoder.h>
+#include <FLAC/stream_encoder.h>
 
 #include <vlc_block_helper.h>
 #include <vlc_bits.h>
@@ -57,8 +56,8 @@ struct decoder_sys_t
      * Input/Output properties
      */
     block_t *p_block;
-    aout_buffer_t *p_aout_buffer;
-    date_t        end_date;
+    block_t *p_aout_buffer;
+    date_t   end_date;
 
     /*
      * FLAC properties
@@ -81,8 +80,8 @@ static const int pi_channels_maps[9] =
     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
-     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT
-     | AOUT_CHAN_MIDDLERIGHT,
+     | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT| AOUT_CHAN_MIDDLERIGHT
+     | AOUT_CHAN_LFE,
     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
      | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
      | AOUT_CHAN_LFE
@@ -94,10 +93,12 @@ static const int pi_channels_maps[9] =
 static int  OpenDecoder   ( vlc_object_t * );
 static void CloseDecoder  ( vlc_object_t * );
 
+#ifdef ENABLE_SOUT
 static int OpenEncoder   ( vlc_object_t * );
 static void CloseEncoder ( vlc_object_t * );
+#endif
 
-static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** );
+static block_t *DecodeBlock( decoder_t *, block_t ** );
 
 /*****************************************************************************
  * Module descriptor
@@ -112,66 +113,28 @@ vlc_module_begin ()
     set_capability( "decoder", 100 )
     set_callbacks( OpenDecoder, CloseDecoder )
 
+#ifdef ENABLE_SOUT
     add_submodule ()
     add_shortcut( "flac" )
     set_description( N_("Flac audio encoder") )
     set_capability( "encoder", 100 )
     set_callbacks( OpenEncoder, CloseEncoder )
+#endif
 
 vlc_module_end ()
 
 /*****************************************************************************
  * Interleave: helper function to interleave channels
  *****************************************************************************/
-static void Interleave32( int32_t *p_out, const int32_t * const *pp_in,
-                          const int pi_index[],
-                          int i_nb_channels, int i_samples )
+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 )
 {
-    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[pi_index[i]][j];
-        }
-    }
-}
+    unsigned shift = 32 - bits;
 
-static void Interleave24( int8_t *p_out, const int32_t * const *pp_in,
-                          const int pi_index[],
-                          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++ )
-        {
-            const int i_index = pi_index[i];
-#ifdef WORDS_BIGENDIAN
-            p_out[3*(j * i_nb_channels + i)+0] = (pp_in[i_index][j] >> 16) & 0xff;
-            p_out[3*(j * i_nb_channels + i)+1] = (pp_in[i_index][j] >> 8 ) & 0xff;
-            p_out[3*(j * i_nb_channels + i)+2] = (pp_in[i_index][j] >> 0 ) & 0xff;
-#else
-            p_out[3*(j * i_nb_channels + i)+2] = (pp_in[i_index][j] >> 16) & 0xff;
-            p_out[3*(j * i_nb_channels + i)+1] = (pp_in[i_index][j] >> 8 ) & 0xff;
-            p_out[3*(j * i_nb_channels + i)+0] = (pp_in[i_index][j] >> 0 ) & 0xff;
-#endif
-        }
-    }
-}
-
-static void Interleave16( int16_t *p_out, const int32_t * const *pp_in,
-                          const int pi_index[],
-                          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[pi_index[i]][j]);
-        }
-    }
+    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;
 }
 
 /*****************************************************************************
@@ -183,17 +146,16 @@ DecoderWriteCallback( const FLAC__StreamDecoder *decoder,
                       const FLAC__int32 *const buffer[], void *client_data )
 {
     /* XXX it supposes our internal format is WG4 */
-    static const int ppi_reorder[1+8][8] = {
-        {-1},
+    static const unsigned char ppi_reorder[1+8][8] = {
+        { },
         { 0, },
         { 0, 1 },
         { 0, 1, 2 },
         { 0, 1, 2, 3 },
         { 0, 1, 3, 4, 2 },
         { 0, 1, 4, 5, 2, 3 },
-
-        { 0, 1, 6, 4, 5, 2, 3 },    /* 7.0 Unspecified by flac, but following SMPTE */
-        { 0, 1, 6, 7, 4, 5, 2, 3 }, /* 7.1 Unspecified by flac, but following SMPTE */
+        { 0, 1, 5, 6, 4, 2, 3 },
+        { 0, 1, 6, 7, 4, 5, 2, 3 },
     };
 
     VLC_UNUSED(decoder);
@@ -206,7 +168,7 @@ DecoderWriteCallback( const FLAC__StreamDecoder *decoder,
     if( date_Get( &p_sys->end_date ) <= VLC_TS_INVALID )
         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 
-    const int * const pi_reorder = ppi_reorder[p_dec->fmt_out.audio.i_channels];
+    const unsigned char *pi_reorder = ppi_reorder[p_dec->fmt_out.audio.i_channels];
 
     p_sys->p_aout_buffer =
         decoder_NewAudioBuffer( p_dec, frame->header.blocksize );
@@ -214,20 +176,9 @@ DecoderWriteCallback( const FLAC__StreamDecoder *decoder,
     if( p_sys->p_aout_buffer == NULL )
         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 
-    switch( frame->header.bits_per_sample )
-    {
-    case 16:
-        Interleave16( (int16_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
-                      frame->header.channels, frame->header.blocksize );
-        break;
-    case 24:
-        Interleave24( (int8_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
-                      frame->header.channels, frame->header.blocksize );
-        break;
-    default:
-        Interleave32( (int32_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
-                      frame->header.channels, frame->header.blocksize );
-    }
+    Interleave( (int32_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
+                 frame->header.channels, frame->header.blocksize,
+                 frame->header.bits_per_sample );
 
     /* Date management (already done by packetizer) */
     p_sys->p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
@@ -276,27 +227,6 @@ static void DecoderMetadataCallback( const FLAC__StreamDecoder *decoder,
     decoder_t *p_dec = (decoder_t *)client_data;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    if( p_dec->pf_decode_audio )
-    {
-        switch( metadata->data.stream_info.bits_per_sample )
-        {
-        case 8:
-            p_dec->fmt_out.i_codec = VLC_CODEC_S8;
-            break;
-        case 16:
-            p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
-            break;
-        case 24:
-            p_dec->fmt_out.i_codec = VLC_CODEC_S24N;
-            break;
-        default:
-            msg_Dbg( p_dec, "strange bit/sample value: %d",
-                     metadata->data.stream_info.bits_per_sample );
-            p_dec->fmt_out.i_codec = VLC_CODEC_FI32;
-            break;
-        }
-    }
-
     /* 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;
@@ -410,7 +340,7 @@ static int OpenDecoder( vlc_object_t *p_this )
 
     /* Set output properties */
     p_dec->fmt_out.i_cat = AUDIO_ES;
-    p_dec->fmt_out.i_codec = VLC_CODEC_FL32;
+    p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
 
     /* Set callbacks */
     p_dec->pf_decode_audio = DecodeBlock;
@@ -449,7 +379,7 @@ static void ProcessHeader( decoder_t *p_dec )
 
     /* Decode STREAMINFO */
     msg_Dbg( p_dec, "decode STREAMINFO" );
-    p_sys->p_block = block_New( p_dec, p_dec->fmt_in.i_extra );
+    p_sys->p_block = block_Alloc( p_dec->fmt_in.i_extra );
     memcpy( p_sys->p_block->p_buffer, p_dec->fmt_in.p_extra,
             p_dec->fmt_in.i_extra );
     FLAC__stream_decoder_process_until_end_of_metadata( p_sys->p_flac );
@@ -524,23 +454,22 @@ static void decoder_state_error( decoder_t *p_dec,
 /****************************************************************************
  * DecodeBlock: the whole thing
  ****************************************************************************/
-static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
+static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    block_t *p_block = *pp_block;
 
-    if( !p_block )
+    if( !pp_block || !*pp_block )
         return NULL;
-    if( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
+    if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
     {
-        block_Release( p_block );
+        block_Release( *pp_block );
         return NULL;
     }
 
     if( !p_sys->b_stream_info )
         ProcessHeader( p_dec );
 
-    p_sys->p_block = p_block;
+    p_sys->p_block = *pp_block;
     *pp_block = NULL;
 
     if( p_sys->p_block->i_pts > VLC_TS_INVALID &&
@@ -570,6 +499,8 @@ static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
     return p_sys->p_aout_buffer;
 }
 
+#ifdef ENABLE_SOUT
+
 /*****************************************************************************
  * encoder_sys_t : flac encoder descriptor
  *****************************************************************************/
@@ -581,7 +512,6 @@ struct encoder_sys_t
     int i_headers;
 
     int i_samples_delay;
-    int i_channels;
 
     FLAC__int32 *p_buffer;
     unsigned int i_buffer;
@@ -602,7 +532,7 @@ struct encoder_sys_t
 
 #define STREAMINFO_SIZE 38
 
-static block_t *Encode( encoder_t *, aout_buffer_t * );
+static block_t *Encode( encoder_t *, block_t * );
 
 /*****************************************************************************
  * EncoderWriteCallback: called by libflac to output encoded samples
@@ -638,7 +568,7 @@ EncoderWriteCallback( const FLAC__StreamEncoder *encoder,
         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
     }
 
-    p_block = block_New( p_enc, bytes );
+    p_block = block_Alloc( bytes );
     memcpy( p_block->p_buffer, buffer, bytes );
 
     p_block->i_dts = p_block->i_pts = p_sys->i_pts;
@@ -746,12 +676,15 @@ static int OpenEncoder( vlc_object_t *p_this )
  ****************************************************************************
  * This function spits out ogg packets.
  ****************************************************************************/
-static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
+static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf )
 {
     encoder_sys_t *p_sys = p_enc->p_sys;
     block_t *p_chain;
     unsigned int i;
 
+    /* FIXME: p_aout_buf is NULL when it's time to flush*/
+    if( unlikely( !p_aout_buf ) ) return NULL;
+
     p_sys->i_pts = p_aout_buf->i_pts -
                 (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
                 (mtime_t)p_enc->fmt_in.audio.i_rate;
@@ -793,3 +726,4 @@ static void CloseEncoder( vlc_object_t *p_this )
     free( p_sys->p_buffer );
     free( p_sys );
 }
+#endif