* Hugly hack: break huge block of samples into smaller ones else
authorLaurent Aimar <fenrir@videolan.org>
Tue, 11 Mar 2003 06:14:16 +0000 (06:14 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Tue, 11 Mar 2003 06:14:16 +0000 (06:14 +0000)
some avi/mov file with raw audio can't be played, *BUT* it's not the
good fix (as the problem seems to be elsewhere).

modules/codec/araw.c

index f0b886f..d85abbb 100644 (file)
@@ -2,15 +2,15 @@
  * araw.c: Pseudo audio decoder; for raw pcm data
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: araw.c,v 1.11 2003/01/07 21:49:01 fenrir Exp $
+ * $Id: araw.c,v 1.12 2003/03/11 06:14:16 fenrir Exp $
  *
  * Authors: Laurent Aimar <fenrir@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
 typedef struct adec_thread_s
 {
     WAVEFORMATEX    *p_wf;
-    
-    //waveformatex_t  format;
 
     /* The bit stream structure handles the PES stream at the bit level */
 //    bit_stream_t        bit_stream;
 
     /* Input properties */
     decoder_fifo_t *p_fifo;
-    
+    int16_t        *p_logtos16;  // used with m/alaw to s16
+
     /* Output properties */
     aout_instance_t *   p_aout;       /* opaque */
     aout_input_t *      p_aout_input; /* opaque */
@@ -70,23 +69,12 @@ static void EndThread      ( adec_thread_t * );
  *****************************************************************************/
 
 vlc_module_begin();
-    set_description( _("Pseudo Raw Audio decoder") );
+    set_description( _("Pseudo Raw/Log Audio decoder") );
     set_capability( "decoder", 50 );
     set_callbacks( OpenDecoder, NULL );
 vlc_module_end();
 
 
-static int pi_channels_maps[6] =
-{
-    0,
-    AOUT_CHAN_CENTER,
-    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
-    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER,
-    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT,
-    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
-     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT 
-};
-
 /*****************************************************************************
  * OpenDecoder: probe the decoder and return score
  *****************************************************************************
@@ -96,20 +84,107 @@ static int pi_channels_maps[6] =
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
-    
+
     switch( p_fifo->i_fourcc )
-    {   
-        case VLC_FOURCC('a','r','a','w'):
-        case VLC_FOURCC('t','w','o','s'): /* for mov file */
+    {
+        case VLC_FOURCC('a','r','a','w'): /* from wav/avi/asf file */
+        case VLC_FOURCC('t','w','o','s'): /* _signed_ big endian samples (mov)*/
+        case VLC_FOURCC('s','o','w','t'): /* _signed_ little endian samples (mov)*/
+
+        case VLC_FOURCC('a','l','a','w'):
+        case VLC_FOURCC('u','l','a','w'):
             p_fifo->pf_run = RunDecoder;
             return VLC_SUCCESS;
-            
+
         default:
             return VLC_EGENERIC;
     }
 
 }
 
+static int pi_channels_maps[6] =
+{
+    0,
+    AOUT_CHAN_CENTER,
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER,
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT,
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
+     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARLEFT
+};
+
+static int16_t ulawtos16[256] =
+{
+    -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
+    -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
+    -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
+    -11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316,
+     -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
+     -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
+     -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
+     -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
+     -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
+     -1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924,
+      -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
+      -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
+      -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
+      -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
+      -120,   -112,   -104,    -96,    -88,    -80,    -72,    -64,
+       -56,    -48,    -40,    -32,    -24,    -16,     -8,      0,
+     32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
+     23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
+     15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
+     11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316,
+      7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
+      5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
+      3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
+      2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
+      1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
+      1372,   1308,   1244,   1180,   1116,   1052,    988,    924,
+       876,    844,    812,    780,    748,    716,    684,    652,
+       620,    588,    556,    524,    492,    460,    428,    396,
+       372,    356,    340,    324,    308,    292,    276,    260,
+       244,    228,    212,    196,    180,    164,    148,    132,
+       120,    112,    104,     96,     88,     80,     72,     64,
+        56,     48,     40,     32,     24,     16,      8,      0
+};
+
+static int16_t alawtos16[256] =
+{
+     -5504,  -5248,  -6016,  -5760,  -4480,  -4224,  -4992,  -4736,
+     -7552,  -7296,  -8064,  -7808,  -6528,  -6272,  -7040,  -6784,
+     -2752,  -2624,  -3008,  -2880,  -2240,  -2112,  -2496,  -2368,
+     -3776,  -3648,  -4032,  -3904,  -3264,  -3136,  -3520,  -3392,
+    -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
+    -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
+    -11008, -10496, -12032, -11520,  -8960,  -8448,  -9984,  -9472,
+    -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
+      -344,   -328,   -376,   -360,   -280,   -264,   -312,   -296,
+      -472,   -456,   -504,   -488,   -408,   -392,   -440,   -424,
+       -88,    -72,   -120,   -104,    -24,     -8,    -56,    -40,
+      -216,   -200,   -248,   -232,   -152,   -136,   -184,   -168,
+     -1376,  -1312,  -1504,  -1440,  -1120,  -1056,  -1248,  -1184,
+     -1888,  -1824,  -2016,  -1952,  -1632,  -1568,  -1760,  -1696,
+      -688,   -656,   -752,   -720,   -560,   -528,   -624,   -592,
+      -944,   -912,  -1008,   -976,   -816,   -784,   -880,   -848,
+      5504,   5248,   6016,   5760,   4480,   4224,   4992,   4736,
+      7552,   7296,   8064,   7808,   6528,   6272,   7040,   6784,
+      2752,   2624,   3008,   2880,   2240,   2112,   2496,   2368,
+      3776,   3648,   4032,   3904,   3264,   3136,   3520,   3392,
+     22016,  20992,  24064,  23040,  17920,  16896,  19968,  18944,
+     30208,  29184,  32256,  31232,  26112,  25088,  28160,  27136,
+     11008,  10496,  12032,  11520,   8960,   8448,   9984,   9472,
+     15104,  14592,  16128,  15616,  13056,  12544,  14080,  13568,
+       344,    328,    376,    360,    280,    264,    312,    296,
+       472,    456,    504,    488,    408,    392,    440,    424,
+        88,     72,    120,    104,     24,      8,     56,     40,
+       216,    200,    248,    232,    152,    136,    184,    168,
+      1376,   1312,   1504,   1440,   1120,   1056,   1248,   1184,
+      1888,   1824,   2016,   1952,   1632,   1568,   1760,   1696,
+       688,    656,    752,    720,    560,    528,    624,    592,
+       944,    912,   1008,    976,    816,    784,    880,    848
+};
+
 /*****************************************************************************
  * RunDecoder: this function is called just after the thread is created
  *****************************************************************************/
@@ -125,7 +200,7 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
         return( -1 );
     }
     memset( p_adec, 0, sizeof( adec_thread_t ) );
-    
+
     p_adec->p_fifo = p_fifo;
 
     if( InitThread( p_adec ) != 0 )
@@ -163,34 +238,10 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
     (  *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) + \
         ( *((u8*)(p)+2) << 16 ) + ( *((u8*)(p)+3) << 24 ) )
 
-#if 0
-static void GetWaveFormatEx( waveformatex_t *p_wh,
-                             u8 *p_data )
-{
-
-    p_wh->i_formattag     = GetWLE( p_data );
-    p_wh->i_channels      = GetWLE( p_data + 2 );
-    p_wh->i_samplespersec = GetDWLE( p_data + 4 );
-    p_wh->i_avgbytespersec= GetDWLE( p_data + 8 );
-    p_wh->i_blockalign    = GetWLE( p_data + 12 );
-    p_wh->i_bitspersample = GetWLE( p_data + 14 );
-    if( p_wh->i_formattag != 1 )
-    {
-        p_wh->i_size          = GetWLE( p_data + 16 );
-
-        if( p_wh->i_size )
-        {
-            p_wh->p_data = malloc( p_wh->i_size );
-            memcpy( p_wh->p_data, p_data + 18, p_wh->i_size );
-        }
-    }
-}
-#endif
 
 /*****************************************************************************
  * InitThread: initialize data before entering main loop
  *****************************************************************************/
-
 static int InitThread( adec_thread_t * p_adec )
 {
     if( ( p_adec->p_wf = (WAVEFORMATEX*)p_adec->p_fifo->p_waveformatex ) == NULL )
@@ -200,11 +251,12 @@ static int InitThread( adec_thread_t * p_adec )
     }
 
     /* fixing some values */
-    if( p_adec->p_wf->wFormatTag  == WAVE_FORMAT_PCM && 
+    if( ( p_adec->p_wf->wFormatTag  == WAVE_FORMAT_PCM ||
+          p_adec->p_wf->wFormatTag  == WAVE_FORMAT_IEEE_FLOAT )&&
         !p_adec->p_wf->nBlockAlign )
     {
-        p_adec->p_wf->nBlockAlign = 
-            p_adec->p_wf->nChannels * 
+        p_adec->p_wf->nBlockAlign =
+            p_adec->p_wf->nChannels *
                 ( ( p_adec->p_wf->wBitsPerSample + 7 ) / 8 );
     }
 
@@ -212,38 +264,112 @@ static int InitThread( adec_thread_t * p_adec )
              "raw format: samplerate:%dHz channels:%d bits/sample:%d blockalign:%d",
              p_adec->p_wf->nSamplesPerSec,
              p_adec->p_wf->nChannels,
-             p_adec->p_wf->wBitsPerSample, 
+             p_adec->p_wf->wBitsPerSample,
              p_adec->p_wf->nBlockAlign );
 
     /* Initialize the thread properties */
-    switch( ( p_adec->p_wf->wBitsPerSample + 7 ) / 8 )
+    p_adec->p_logtos16 = NULL;
+    if( p_adec->p_wf->wFormatTag  == WAVE_FORMAT_IEEE_FLOAT )
     {
-        case( 2 ):
-            p_adec->output_format.i_format = VLC_FOURCC('s','1','6','l');
-            break;
-        case( 3 ):
-            p_adec->output_format.i_format = VLC_FOURCC('s','2','4','l');
-            break;
-        case( 4 ):
-            p_adec->output_format.i_format = VLC_FOURCC('s','3','2','l');
-            break;
-        case( 1 ):
-            p_adec->output_format.i_format = VLC_FOURCC('u','8',' ',' ');
-            break;
-        default:
-            msg_Err( p_adec->p_fifo, "bad parameters(bits/sample)" );
-            return( -1 );
+        switch( ( p_adec->p_wf->wBitsPerSample + 7 ) / 8 )
+        {
+            case( 4 ):
+                p_adec->output_format.i_format = VLC_FOURCC('f','l','3','2');
+                break;
+            case( 8 ):
+                p_adec->output_format.i_format = VLC_FOURCC('f','l','6','4');
+                break;
+            default:
+                msg_Err( p_adec->p_fifo, "bad parameters(bits/sample)" );
+                return( -1 );
+        }
+    }
+    else
+    {
+        if( p_adec->p_fifo->i_fourcc == VLC_FOURCC( 't', 'w', 'o', 's' ) )
+        {
+            switch( ( p_adec->p_wf->wBitsPerSample + 7 ) / 8 )
+            {
+                case( 1 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','8',' ',' ');
+                    break;
+                case( 2 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','1','6','b');
+                    break;
+                case( 3 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','2','4','b');
+                    break;
+                case( 4 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','3','2','b');
+                    break;
+                default:
+                    msg_Err( p_adec->p_fifo, "bad parameters(bits/sample)" );
+                    return( -1 );
+            }
+        }
+        else if( p_adec->p_fifo->i_fourcc == VLC_FOURCC( 's', 'o', 'w', 't' ) )
+        {
+            switch( ( p_adec->p_wf->wBitsPerSample + 7 ) / 8 )
+            {
+                case( 1 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','8',' ',' ');
+                    break;
+                case( 2 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','1','6','l');
+                    break;
+                case( 3 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','2','4','l');
+                    break;
+                case( 4 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','3','2','l');
+                    break;
+                default:
+                    msg_Err( p_adec->p_fifo, "bad parameters(bits/sample)" );
+                    return( -1 );
+            }
+        }
+        else if( p_adec->p_fifo->i_fourcc == VLC_FOURCC( 'a', 'r', 'a', 'w' ) )
+        {
+            switch( ( p_adec->p_wf->wBitsPerSample + 7 ) / 8 )
+            {
+                case( 1 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('u','8',' ',' ');
+                    break;
+                case( 2 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','1','6','l');
+                    break;
+                case( 3 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','2','4','l');
+                    break;
+                case( 4 ):
+                    p_adec->output_format.i_format = VLC_FOURCC('s','3','2','l');
+                    break;
+                default:
+                    msg_Err( p_adec->p_fifo, "bad parameters(bits/sample)" );
+                    return( -1 );
+            }
+        }
+        else if( p_adec->p_fifo->i_fourcc == VLC_FOURCC( 'a', 'l', 'a', 'w' ) )
+        {
+            p_adec->output_format.i_format = AOUT_FMT_S16_NE;
+            p_adec->p_logtos16  = alawtos16;
+        }
+        else if( p_adec->p_fifo->i_fourcc == VLC_FOURCC( 'u', 'l', 'a', 'w' ) )
+        {
+            p_adec->output_format.i_format = AOUT_FMT_S16_NE;
+            p_adec->p_logtos16  = ulawtos16;
+        }
     }
     p_adec->output_format.i_rate = p_adec->p_wf->nSamplesPerSec;
 
-    if( p_adec->p_wf->nChannels <= 0 || 
+    if( p_adec->p_wf->nChannels <= 0 ||
             p_adec->p_wf->nChannels > 5 )
     {
         msg_Err( p_adec->p_fifo, "bad channels count(1-5)" );
         return( -1 );
     }
 
-    p_adec->output_format.i_physical_channels = 
+    p_adec->output_format.i_physical_channels =
             p_adec->output_format.i_original_channels =
             pi_channels_maps[p_adec->p_wf->nChannels];
     p_adec->p_aout = NULL;
@@ -280,7 +406,7 @@ static void GetPESData( u8 *p_buf, int i_max, pes_packet_t *p_pes )
     {
 
         i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start, i_max - i_count );
-        
+
         if( i_copy > 0 )
         {
             memcpy( p_buf,
@@ -307,7 +433,7 @@ static void DecodeThread( adec_thread_t *p_adec )
     aout_buffer_t   *p_aout_buffer;
     int             i_samples; // per channels
     int             i_size;
-
+    uint8_t         *p_data;
     pes_packet_t    *p_pes;
 
     /* **** get samples count **** */
@@ -330,15 +456,15 @@ static void DecodeThread( adec_thread_t *p_adec )
         msg_Err( p_adec->p_fifo, "infinite loop..." );
         return;
     }
-    i_samples = i_size / 
-                ( ( p_adec->p_wf->wBitsPerSample + 7 ) / 8 ) / 
+    i_samples = i_size /
+                ( ( p_adec->p_wf->wBitsPerSample + 7 ) / 8 ) /
                 p_adec->p_wf->nChannels;
 
 //    msg_Warn( p_adec->p_fifo, "got %d samples (%d bytes)", i_samples, i_size );
     p_adec->pts = p_pes->i_pts;
-        
+
     /* **** Now we can output these samples **** */
-    
+
     if( p_adec->pts != 0 && p_adec->pts != aout_DateGet( &p_adec->date ) )
     {
         aout_DateSet( &p_adec->date, p_adec->pts );
@@ -348,24 +474,53 @@ static void DecodeThread( adec_thread_t *p_adec )
         return;
     }
 
-    p_aout_buffer = aout_DecNewBuffer( p_adec->p_aout, 
-                                       p_adec->p_aout_input,
-                                       i_samples );
-    if( !p_aout_buffer )
+    /* gather data */
+    p_data = alloca( i_size );
+    GetPESData( p_data, i_size, p_pes );
+
+    while( i_samples > 0 )
     {
-        msg_Err( p_adec->p_fifo, "cannot get aout buffer" );
-        p_adec->p_fifo->b_error = 1;
-        return;
-    }
-    
-    p_aout_buffer->start_date = aout_DateGet( &p_adec->date );
-    p_aout_buffer->end_date = aout_DateIncrement( &p_adec->date,
-                                                  i_samples );
+        int i_copy;
 
-    GetPESData( p_aout_buffer->p_buffer, p_aout_buffer->i_nb_bytes, p_pes );
+        i_copy = __MIN( i_samples, 1024 );
+        p_aout_buffer = aout_DecNewBuffer( p_adec->p_aout,
+                                           p_adec->p_aout_input,
+                                           i_copy );
+        if( !p_aout_buffer )
+        {
+            msg_Err( p_adec->p_fifo, "cannot get aout buffer" );
+            p_adec->p_fifo->b_error = 1;
+            return;
+        }
 
-    aout_DecPlay( p_adec->p_aout, p_adec->p_aout_input, p_aout_buffer );
+        p_aout_buffer->start_date = aout_DateGet( &p_adec->date );
+        p_aout_buffer->end_date = aout_DateIncrement( &p_adec->date,
+                                                      i_copy );
+
+        if( p_adec->p_logtos16 )
+        {
+            int16_t *s = (int16_t*)p_aout_buffer->p_buffer;
 
+            int     i;
+
+            for( i = 0; i < p_aout_buffer->i_nb_bytes; i++ )
+            {
+                *s++ = p_adec->p_logtos16[*p_data++];
+            }
+        }
+        else
+        {
+            memcpy( p_aout_buffer->p_buffer,
+                    p_data,
+                    p_aout_buffer->i_nb_bytes );
+
+            p_data += p_aout_buffer->i_nb_bytes;
+        }
+
+        aout_DecPlay( p_adec->p_aout, p_adec->p_aout_input, p_aout_buffer );
+
+        i_samples -= i_copy;
+    }
 
     input_DeletePES( p_adec->p_fifo->p_packets_mgt, p_pes );
 }
@@ -382,7 +537,7 @@ static void EndThread (adec_thread_t *p_adec)
     }
 
     msg_Dbg( p_adec->p_fifo, "raw audio decoder closed" );
-        
+
     free( p_adec );
 }