]> git.sesse.net Git - vlc/blobdiff - modules/codec/mad/libmad.c
* modules/codec/*: reverted my previous patch that explicitly set
[vlc] / modules / codec / mad / libmad.c
index 7575224b18a71650ec4c01f130e21928109fbe64..33bba9bde19d221556762bb3420cc456cbed4f2b 100644 (file)
@@ -44,7 +44,7 @@ static void PrintFrameInfo(struct mad_header *Header);
 enum mad_flow libmad_input( void *p_data, struct mad_stream *p_stream )
 {
     mad_adec_thread_t * p_dec = (mad_adec_thread_t *) p_data;
-    size_t   i_wanted, i_left;
+    size_t   i_wanted, i_left, i_current;
 
     if ( p_dec->p_fifo->b_die )
     {
@@ -73,7 +73,8 @@ enum mad_flow libmad_input( void *p_data, struct mad_stream *p_stream )
         * (448000*(1152/32000))/8 */
         if( p_stream->next_frame )
         {
-            i_left = p_stream->bufend - p_stream->next_frame;
+            i_left    = p_stream->bufend - p_stream->next_frame;
+            i_current = p_stream->next_frame - p_dec->buffer;
             if( p_dec->buffer != p_stream->next_frame )
             {
                 memcpy( p_dec->buffer, p_stream->next_frame, i_left );
@@ -81,7 +82,17 @@ enum mad_flow libmad_input( void *p_data, struct mad_stream *p_stream )
             i_wanted = MAD_BUFFER_MDLEN - i_left;
 
             /* Store timestamp for next frame */
-            p_dec->i_next_pts = p_dec->p_fifo->p_first->i_pts;
+            if ( ( p_stream->next_frame == p_dec->buffer ) ||
+                 ( i_current >= i_left * ( ( i_current / ( MAD_BUFFER_MDLEN - i_current ) ) + 1 ) )
+               )
+            {
+                p_dec->i_next_pts = p_dec->bit_stream.p_pes->i_pts;
+            }
+            else
+            {
+                /* p_dec->bit_stream.p_pes->i_pts != p_dec->i_next_pts */
+                p_dec->i_next_pts = 0;
+            }
         }
         else
         {
@@ -89,26 +100,28 @@ enum mad_flow libmad_input( void *p_data, struct mad_stream *p_stream )
             i_left = 0;
 
             /* Store timestamp for this frame */
-            p_dec->i_current_pts = p_dec->p_fifo->p_first->i_pts;
+            p_dec->i_current_pts = p_dec->bit_stream.p_pes->i_pts;
         }
 
         /* Fill-in the buffer. If an error occurs print a message and leave
          * the decoding loop. If the end of stream is reached we also leave
          * the loop but the return status is left untouched. */
-        if( i_wanted > p_dec->p_data->p_payload_end
-                        - p_dec->p_data->p_payload_start )
+        if( i_wanted > (size_t)(p_dec->bit_stream.p_data->p_payload_end
+                                 - p_dec->bit_stream.p_data->p_payload_start) )
         {
-            i_wanted = p_dec->p_data->p_payload_end
-                        - p_dec->p_data->p_payload_start;
+            i_wanted = p_dec->bit_stream.p_data->p_payload_end
+                        - p_dec->bit_stream.p_data->p_payload_start;
             memcpy( p_dec->buffer + i_left,
-                    p_dec->p_data->p_payload_start, i_wanted );
-            NextDataPacket( p_dec->p_fifo, &p_dec->p_data );
+                    p_dec->bit_stream.p_data->p_payload_start, i_wanted );
+            NextDataPacket( p_dec->p_fifo, &p_dec->bit_stream );
+            /* No need to check that p_dec->bit_stream->p_data is valid
+             * since we check later on for b_die and b_error */
         }
         else
         {
             memcpy( p_dec->buffer + i_left,
-                    p_dec->p_data->p_payload_start, i_wanted );
-            p_dec->p_data->p_payload_start += i_wanted;
+                    p_dec->bit_stream.p_data->p_payload_start, i_wanted );
+            p_dec->bit_stream.p_data->p_payload_start += i_wanted;
         }
 
         if ( p_dec->p_fifo->b_die )
@@ -144,16 +157,20 @@ enum mad_flow libmad_output( void *p_data, struct mad_header const *p_header,
     aout_buffer_t *     p_buffer;
     mad_fixed_t const * p_left = p_pcm->samples[0];
     mad_fixed_t const * p_right = p_pcm->samples[1];
-    register int        i_samples = p_pcm->length;
+    unsigned int        i_samples = p_pcm->length;
     mad_fixed_t *       p_samples;
+    unsigned int        i_channels = (p_pcm->channels == 2) ?
+                                     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT :
+                                     AOUT_CHAN_CENTER;
 
     /* Creating the audio output fifo. Assume the samplerate and nr of channels
      * from the first decoded frame is right for the entire audio track. */
     if( (p_dec->p_aout_input != NULL) &&
-        (p_dec->output_format.i_rate != p_pcm->samplerate) )
+        (p_dec->output_format.i_rate != p_pcm->samplerate
+           || p_dec->output_format.i_physical_channels != i_channels) )
     {
         /* Parameters changed - this should not happen. */
-        aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
+        aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
         p_dec->p_aout_input = NULL;
     }
 
@@ -161,11 +178,12 @@ enum mad_flow libmad_output( void *p_data, struct mad_header const *p_header,
     if( p_dec->p_aout_input == NULL )
     {
         p_dec->output_format.i_rate = p_pcm->samplerate;
-        /* p_dec->output_format.i_channels = p_pcm->channels; */
+        p_dec->output_format.i_physical_channels = i_channels;
+        p_dec->output_format.i_original_channels = i_channels;
         aout_DateInit( &p_dec->end_date, p_pcm->samplerate );
-        p_dec->p_aout_input = aout_InputNew( p_dec->p_fifo,
-                                             &p_dec->p_aout,
-                                             &p_dec->output_format );
+        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 )
         {
@@ -197,7 +215,7 @@ enum mad_flow libmad_output( void *p_data, struct mad_header const *p_header,
         return MAD_FLOW_CONTINUE;
     }
 
-    p_buffer = aout_BufferNew( p_dec->p_aout, p_dec->p_aout_input, i_samples );
+    p_buffer = aout_DecNewBuffer( p_dec->p_aout, p_dec->p_aout_input, i_samples );
 
     if ( p_buffer == NULL )
     {
@@ -220,19 +238,18 @@ enum mad_flow libmad_output( void *p_data, struct mad_header const *p_header,
             *p_samples++ = *p_right++;
         }
         break;
+
     case 1:
-        while( i_samples-- )
-        {
-            *p_samples++ = *p_left;
-            *p_samples++ = *p_left++;
-        }
+        p_dec->p_fifo->p_vlc->pf_memcpy( p_samples, p_left,
+                                         i_samples * sizeof(mad_fixed_t) );
         break;
+
     default:
         msg_Err( p_dec->p_fifo, "cannot interleave %i channels",
                                 p_pcm->channels );
     }
 
-    aout_BufferPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer );
+    aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_buffer );
 
     return MAD_FLOW_CONTINUE;
 }
@@ -240,14 +257,39 @@ enum mad_flow libmad_output( void *p_data, struct mad_header const *p_header,
 /*****************************************************************************
  * libmad_error: this function is called when an error occurs during decoding
  *****************************************************************************/
-enum mad_flow libmad_error( void *data, struct mad_stream *p_libmad_stream,
+enum mad_flow libmad_error( void *p_data, struct mad_stream *p_libmad_stream,
                             struct mad_frame *p_libmad_frame )
 {
-    mad_adec_thread_t *p_dec = (mad_adec_thread_t *) data;
-    enum mad_flow result = MAD_FLOW_CONTINUE;
+    mad_adec_thread_t *p_dec = (mad_adec_thread_t *) p_data;
+    enum mad_flow result;
+    struct mad_pcm *p_pcm;
 
     switch (p_libmad_stream->error)
     {             
+
+    case MAD_ERROR_BADDATAPTR:        /* bad main_data_begin pointer */
+        msg_Warn( p_dec->p_fifo, "lost synchronization" );
+
+        if( p_dec->output_format.i_rate &&
+            p_dec->output_format.i_physical_channels )
+        {
+            p_pcm = malloc( sizeof(struct mad_pcm) );
+            memset( p_pcm, 0, sizeof(struct mad_pcm) );
+            p_pcm->length = 32 * MAD_NSBSAMPLES( &p_libmad_frame->header );
+            p_pcm->channels = ( p_dec->output_format.i_physical_channels ==
+                                AOUT_CHAN_CENTER ) ? 1 : 2;
+            p_pcm->samplerate = p_dec->output_format.i_rate;
+            libmad_output( p_data, NULL, p_pcm );
+            free( p_pcm );
+        }
+        result = MAD_FLOW_CONTINUE;
+        break;
+
+    default:
+        result = MAD_FLOW_CONTINUE;
+        break;
+
+#if 0
     case MAD_ERROR_BUFLEN:                /* input buffer too small (or EOF) */
         msg_Err( p_dec->p_fifo, "input buffer too small (or EOF)" );
         result = MAD_FLOW_CONTINUE;
@@ -262,7 +304,6 @@ enum mad_flow libmad_error( void *data, struct mad_stream *p_libmad_stream,
         break;
     case MAD_ERROR_LOSTSYNC:            /* lost synchronization */
         msg_Err( p_dec->p_fifo, "lost synchronization" );
-        mad_stream_sync(p_libmad_stream);
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADLAYER:            /* reserved header layer value */
@@ -311,7 +352,7 @@ enum mad_flow libmad_error( void *data, struct mad_stream *p_libmad_stream,
         break;
     case MAD_ERROR_BADDATAPTR:        /* bad main_data_begin pointer */
         msg_Err( p_dec->p_fifo, "bad main_data_begin pointer" );
-        result = MAD_FLOW_STOP;
+        result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADPART3LEN:     /* bad audio data length */
         msg_Err( p_dec->p_fifo, "bad audio data length" );
@@ -333,10 +374,10 @@ enum mad_flow libmad_error( void *data, struct mad_stream *p_libmad_stream,
         msg_Err( p_dec->p_fifo, "unknown error occured stopping decoder" );
         result = MAD_FLOW_STOP;
         break;
+#endif
     }
     
     return (MAD_RECOVERABLE(p_libmad_stream->error)? result: MAD_FLOW_STOP);
-    //return (MAD_FLOW_CONTINUE);
 }
 
 /*****************************************************************************
@@ -351,7 +392,7 @@ enum mad_flow libmad_error( void *data, struct mad_stream *p_libmad_stream,
 
 
 /****************************************************************************
- * Print human readable informations about an audio MPEG frame.                                *
+ * Print human readable informations about an audio MPEG frame.
  ****************************************************************************/
 static void PrintFrameInfo(struct mad_header *Header)
 {