]> git.sesse.net Git - vlc/blobdiff - modules/codec/flac.c
Replace argument = realloc( argument, size ); with realloc_or_free() in modules/...
[vlc] / modules / codec / flac.c
index d7130dc3dec31f2f4f84e6cb52829082a0741573..13f0e3020b5ddd90c5d127a8ecea6c000a1ce263 100644 (file)
 # include "config.h"
 #endif
 
+#include <assert.h>
+
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_codec.h>
 #include <vlc_aout.h>
+#include <vlc_memory.h>
 
 #ifdef HAVE_FLAC_STREAM_DECODER_H
 #   include <FLAC/stream_decoder.h>
@@ -90,7 +93,7 @@ struct decoder_sys_t
     /*
      * Common properties
      */
-    audio_date_t end_date;
+    date_t  end_date;
     mtime_t i_pts;
 
     int i_frame_size, i_frame_length, i_bits_per_sample;
@@ -160,11 +163,11 @@ static void DecoderErrorCallback( const FLAC__StreamDecoder *decoder,
                                   void *client_data);
 
 static void Interleave32( int32_t *p_out, const int32_t * const *pp_in,
-                          int i_nb_channels, int i_samples );
+                          const int *pi_order, int i_nb_channels, int i_samples );
 static void Interleave24( int8_t *p_out, const int32_t * const *pp_in,
-                          int i_nb_channels, int i_samples );
+                          const int *pi_order, 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 );
+                          const int *pi_order, int i_nb_channels, int i_samples );
 
 static void decoder_state_error( decoder_t *p_dec,
                                  FLAC__StreamDecoderState state );
@@ -188,11 +191,13 @@ vlc_module_begin ()
     set_callbacks( OpenDecoder, CloseDecoder )
 
     add_submodule ()
+    add_shortcut( "flac" )
     set_description( N_("Flac audio encoder") )
     set_capability( "encoder", 100 )
     set_callbacks( OpenEncoder, CloseEncoder )
 
     add_submodule ()
+    add_shortcut( "flac" )
 #endif
     set_description( N_("Flac audio packetizer") )
     set_capability( "packetizer", 100 )
@@ -208,18 +213,17 @@ 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_FOURCC('f','l','a','c') )
+    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 =
-          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
+    if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
         return VLC_ENOMEM;
 
     /* Misc init */
-    aout_DateSet( &p_sys->end_date, 0 );
+    date_Set( &p_sys->end_date, 0 );
     p_sys->i_state = STATE_NOSYNC;
     p_sys->b_stream_info = false;
     p_sys->p_block=NULL;
@@ -269,7 +273,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_FOURCC('f','l','3','2');
+    p_dec->fmt_out.i_codec = VLC_CODEC_FL32;
 
     /* Set callbacks */
 #ifdef USE_LIBFLAC
@@ -293,7 +297,7 @@ static int OpenPacketizer( vlc_object_t *p_this )
     p_dec->pf_packetize    = PacketizeBlock;
 
     /* Set output properties */
-    p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','a','c');
+    p_dec->fmt_out.i_codec = VLC_CODEC_FLAC;
 
     if( i_ret != VLC_SUCCESS )
     {
@@ -358,11 +362,12 @@ static void ProcessHeader( decoder_t *p_dec )
 
     if( !p_sys->b_stream_info ) return;
 
-    if( p_dec->fmt_out.i_codec == VLC_FOURCC('f','l','a','c') )
+    if( p_dec->fmt_out.i_codec == VLC_CODEC_FLAC )
     {
         p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
-        p_dec->fmt_out.p_extra =
-            realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
+        p_dec->fmt_out.p_extra = realloc_or_free( p_dec->fmt_out.p_extra,
+                                                  p_dec->fmt_out.i_extra );
+        assert( p_dec->fmt_out.p_extra );
         memcpy( p_dec->fmt_out.p_extra,
                 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
     }
@@ -386,9 +391,9 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
         if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
         {
             p_sys->i_state = STATE_NOSYNC;
-            block_BytestreamFlush( &p_sys->bytestream );
+            block_BytestreamEmpty( &p_sys->bytestream );
         }
-        aout_DateSet( &p_sys->end_date, 0 );
+        date_Set( &p_sys->end_date, 0 );
         block_Release( *pp_block );
         return NULL;
     }
@@ -401,18 +406,18 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
         return NULL;
     }
 
-    if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
+    if( !date_Get( &p_sys->end_date ) && !(*pp_block)->i_pts )
     {
         /* We've just started the stream, wait for the first PTS. */
         block_Release( *pp_block );
         return NULL;
     }
-    else if( !aout_DateGet( &p_sys->end_date ) )
+    else if( !date_Get( &p_sys->end_date ) )
     {
         /* The first PTS is as good as anything else. */
         p_sys->i_rate = p_dec->fmt_out.audio.i_rate;
-        aout_DateInit( &p_sys->end_date, p_sys->i_rate );
-        aout_DateSet( &p_sys->end_date, (*pp_block)->i_pts );
+        date_Init( &p_sys->end_date, p_sys->i_rate, 1 );
+        date_Set( &p_sys->end_date, (*pp_block)->i_pts );
     }
 
     block_BytestreamPush( &p_sys->bytestream, *pp_block );
@@ -444,9 +449,9 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
             /* New frame, set the Presentation Time Stamp */
             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
             if( p_sys->i_pts != 0 &&
-                p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
+                p_sys->i_pts != date_Get( &p_sys->end_date ) )
             {
-                aout_DateSet( &p_sys->end_date, p_sys->i_pts );
+                date_Set( &p_sys->end_date, p_sys->i_pts );
             }
             p_sys->i_state = STATE_HEADER;
 
@@ -475,7 +480,7 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
             if( p_sys->i_rate != p_dec->fmt_out.audio.i_rate )
             {
                 p_dec->fmt_out.audio.i_rate = p_sys->i_rate;
-                aout_DateInit( &p_sys->end_date, p_sys->i_rate );
+                date_Init( &p_sys->end_date, p_sys->i_rate, 1 );
             }
             p_sys->i_state = STATE_NEXT_SYNC;
             p_sys->i_frame_size = 1;
@@ -534,10 +539,10 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
 
             /* Date management */
             p_sout_block->i_pts =
-                p_sout_block->i_dts = aout_DateGet( &p_sys->end_date );
-            aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
+                p_sout_block->i_dts = date_Get( &p_sys->end_date );
+            date_Increment( &p_sys->end_date, p_sys->i_frame_length );
             p_sout_block->i_length =
-                aout_DateGet( &p_sys->end_date ) - p_sout_block->i_pts;
+                date_Get( &p_sys->end_date ) - p_sout_block->i_pts;
 
             return p_sout_block;
         }
@@ -616,10 +621,29 @@ DecoderWriteCallback( const FLAC__StreamDecoder *decoder,
                       const FLAC__Frame *frame,
                       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},
+        { 0, },
+        { 0, 1 },
+        { 0, 1, 2 },
+        { 0, 1, 2, 3 },
+        { 0, 1, 3, 4, 2 },
+        { 0, 1, 4, 5, 2, 3 },
+
+        { 0, 1, 6, 2, 3, 4, 5 },    /* 7.0 Unspecified by flac */
+        { 0, 1, 6, 7, 2, 3, 4, 5 }, /* 7.1 Unspecified by flac */
+    };
+
     VLC_UNUSED(decoder);
     decoder_t *p_dec = (decoder_t *)client_data;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
+    if( p_dec->fmt_out.audio.i_channels <= 0 ||
+        p_dec->fmt_out.audio.i_channels > 8 )
+        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+    const int * const pi_reorder = ppi_reorder[p_dec->fmt_out.audio.i_channels];
+
     p_sys->p_aout_buffer =
         decoder_NewAudioBuffer( p_dec, frame->header.blocksize );
 
@@ -629,22 +653,21 @@ DecoderWriteCallback( const FLAC__StreamDecoder *decoder,
     switch( frame->header.bits_per_sample )
     {
     case 16:
-        Interleave16( (int16_t *)p_sys->p_aout_buffer->p_buffer, buffer,
+        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,
+        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,
+        Interleave32( (int32_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
                       frame->header.channels, frame->header.blocksize );
     }
 
     /* Date management (already done by packetizer) */
-    p_sys->p_aout_buffer->start_date = p_sys->p_block->i_pts;
-    p_sys->p_aout_buffer->end_date =
-        p_sys->p_block->i_pts + p_sys->p_block->i_length;
+    p_sys->p_aout_buffer->i_pts = p_sys->p_block->i_pts;
+    p_sys->p_aout_buffer->i_length = p_sys->p_block->i_length;
 
     return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 }
@@ -665,18 +688,18 @@ static void DecoderMetadataCallback( const FLAC__StreamDecoder *decoder,
         switch( metadata->data.stream_info.bits_per_sample )
         {
         case 8:
-            p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
+            p_dec->fmt_out.i_codec = VLC_CODEC_S8;
             break;
         case 16:
-            p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
+            p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
             break;
         case 24:
-            p_dec->fmt_out.i_codec = AOUT_FMT_S24_NE;
+            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_FOURCC('f','i','3','2');
+            p_dec->fmt_out.i_codec = VLC_CODEC_FI32;
             break;
         }
     }
@@ -690,7 +713,7 @@ static void DecoderMetadataCallback( const FLAC__StreamDecoder *decoder,
     p_dec->fmt_out.audio.i_bitspersample =
         metadata->data.stream_info.bits_per_sample;
 
-    aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate );
+    date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
 
     msg_Dbg( p_dec, "channels:%d samplerate:%d bitspersamples:%d",
              p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_rate,
@@ -737,6 +760,7 @@ static void DecoderErrorCallback( const FLAC__StreamDecoder *decoder,
  * 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 )
 {
     int i, j;
@@ -744,12 +768,13 @@ static void Interleave32( int32_t *p_out, const int32_t * const *pp_in,
     {
         for ( i = 0; i < i_nb_channels; i++ )
         {
-            p_out[j * i_nb_channels + i] = pp_in[i][j];
+            p_out[j * i_nb_channels + i] = pp_in[pi_index[i]][j];
         }
     }
 }
 
 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;
@@ -757,20 +782,22 @@ static void Interleave24( int8_t *p_out, const int32_t * const *pp_in,
     {
         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][j] >> 16) & 0xff;
-            p_out[3*(j * i_nb_channels + i)+1] = (pp_in[i][j] >> 8 ) & 0xff;
-            p_out[3*(j * i_nb_channels + i)+2] = (pp_in[i][j] >> 0 ) & 0xff;
+            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][j] >> 16) & 0xff;
-            p_out[3*(j * i_nb_channels + i)+1] = (pp_in[i][j] >> 8 ) & 0xff;
-            p_out[3*(j * i_nb_channels + i)+0] = (pp_in[i][j] >> 0 ) & 0xff;
+            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;
@@ -778,7 +805,7 @@ static void Interleave16( int16_t *p_out, const int32_t * const *pp_in,
     {
         for ( i = 0; i < i_nb_channels; i++ )
         {
-            p_out[j * i_nb_channels + i] = (int32_t)(pp_in[i][j]);
+            p_out[j * i_nb_channels + i] = (int32_t)(pp_in[pi_index[i]][j]);
         }
     }
 }
@@ -1260,7 +1287,7 @@ static int OpenEncoder( vlc_object_t *p_this )
     encoder_t *p_enc = (encoder_t *)p_this;
     encoder_sys_t *p_sys;
 
-    if( p_enc->fmt_out.i_codec != VLC_FOURCC('f','l','a','c') &&
+    if( p_enc->fmt_out.i_codec != VLC_CODEC_FLAC &&
         !p_enc->b_force )
     {
         return VLC_EGENERIC;
@@ -1271,7 +1298,7 @@ static int OpenEncoder( vlc_object_t *p_this )
         return VLC_ENOMEM;
     p_enc->p_sys = p_sys;
     p_enc->pf_encode_audio = Encode;
-    p_enc->fmt_out.i_codec = VLC_FOURCC('f','l','a','c');
+    p_enc->fmt_out.i_codec = VLC_CODEC_FLAC;
 
     p_sys->i_headers = 0;
     p_sys->p_buffer = 0;
@@ -1292,7 +1319,7 @@ static int OpenEncoder( vlc_object_t *p_this )
     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 );
-    p_enc->fmt_in.i_codec = AOUT_FMT_S16_NE;
+    p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
 
     /* Get and store the STREAMINFO metadata block as a p_extra */
     p_sys->p_chain = 0;
@@ -1335,21 +1362,22 @@ static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
     block_t *p_chain;
     unsigned int i;
 
-    p_sys->i_pts = p_aout_buf->start_date -
+    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;
 
     p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
 
     /* Convert samples to FLAC__int32 */
-    if( p_sys->i_buffer < p_aout_buf->i_nb_bytes * 2 )
+    if( p_sys->i_buffer < p_aout_buf->i_buffer * 2 )
     {
         p_sys->p_buffer =
-            realloc( p_sys->p_buffer, p_aout_buf->i_nb_bytes * 2 );
-        p_sys->i_buffer = p_aout_buf->i_nb_bytes * 2;
+            realloc_or_free( p_sys->p_buffer, p_aout_buf->i_buffer * 2 );
+        assert( p_sys->p_buffer );
+        p_sys->i_buffer = p_aout_buf->i_buffer * 2;
     }
 
-    for( i = 0 ; i < p_aout_buf->i_nb_bytes / 2 ; i++ )
+    for( i = 0 ; i < p_aout_buf->i_buffer / 2 ; i++ )
     {
         p_sys->p_buffer[i]= ((int16_t *)p_aout_buf->p_buffer)[i];
     }
@@ -1414,6 +1442,7 @@ EncoderWriteCallback( const FLAC__StreamEncoder *encoder,
             /* Backup the STREAMINFO metadata block */
             p_enc->fmt_out.i_extra = STREAMINFO_SIZE + 4;
             p_enc->fmt_out.p_extra = malloc( STREAMINFO_SIZE + 4 );
+            assert( p_enc->fmt_out.p_extra );
             memcpy( p_enc->fmt_out.p_extra, "fLaC", 4 );
             memcpy( ((uint8_t *)p_enc->fmt_out.p_extra) + 4, buffer,
                     STREAMINFO_SIZE );