]> git.sesse.net Git - vlc/blobdiff - plugins/mad/mad_libmad.c
* ALL: got rid of p_object->p_this which is now useless.
[vlc] / plugins / mad / mad_libmad.c
index 9bd34295b2dee66a5517a84622d0b0fc90248380..e1abfc04592a4fa88e710e69c0cf90a8c72b25a6 100644 (file)
 #include <stdlib.h>                                      /* malloc(), free() */
 #include <string.h>                                              /* strdup() */
 
-#include <videolan/vlc.h>
-
-#include "audio_output.h"
-
-#include "stream_control.h"
-#include "input_ext-dec.h"
-
-#include "debug.h"
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
 
 /*****************************************************************************
  * Libmad includes files
@@ -40,6 +35,8 @@
 #include "mad_adec.h"
 #include "mad_libmad.h"
 
+static void PrintFrameInfo(struct mad_header *Header);
+
 /*****************************************************************************
  * libmad_input: this function is called by libmad when the input buffer needs
  * to be filled.
@@ -51,12 +48,12 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
     unsigned char     *ReadStart;
 
     if ( p_mad_adec->p_fifo->b_die == 1 ) {
-        intf_ErrMsg( "mad_adec error: libmad_input stopping libmad decoder" );
+        msg_Err( p_mad_adec->p_fifo, "libmad_input stopping libmad decoder" );
         return MAD_FLOW_STOP;
     }
 
     if ( p_mad_adec->p_fifo->b_error == 1 ) {
-        intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );
+        msg_Err( p_mad_adec->p_fifo, "libmad_input ignoring current audio frame" );
         return MAD_FLOW_IGNORE;
     }
 
@@ -80,11 +77,11 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
             Remaining=p_libmad_stream->bufend-p_libmad_stream->next_frame;
             if( p_mad_adec->buffer != p_libmad_stream->next_frame )
             {
-                FAST_MEMCPY( p_mad_adec->buffer, p_libmad_stream->next_frame,
-                             Remaining );
+                p_mad_adec->p_fifo->p_vlc->pf_memcpy( p_mad_adec->buffer,
+                                    p_libmad_stream->next_frame, Remaining );
             }
             ReadStart=p_mad_adec->buffer+Remaining;
-            ReadSize=(MAD_BUFFER_SIZE)-Remaining;
+            ReadSize=(MAD_BUFFER_MDLEN)-Remaining;
 
             /* Store time stamp of next frame */
             p_mad_adec->i_current_pts = p_mad_adec->i_next_pts;
@@ -92,7 +89,7 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
         }
         else
         {
-            ReadSize=(MAD_BUFFER_SIZE);
+            ReadSize=(MAD_BUFFER_MDLEN);
             ReadStart=p_mad_adec->buffer;
             Remaining=0;
             p_mad_adec->i_next_pts = 0;
@@ -109,26 +106,26 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
         {
             ReadSize = p_mad_adec->p_data->p_payload_end
                         - p_mad_adec->p_data->p_payload_start;
-            FAST_MEMCPY( ReadStart, p_mad_adec->p_data->p_payload_start,
-                         ReadSize );
+            p_mad_adec->p_fifo->p_vlc->pf_memcpy( ReadStart,
+                                p_mad_adec->p_data->p_payload_start, ReadSize );
             NextDataPacket( p_mad_adec->p_fifo, &p_mad_adec->p_data );
         }
         else
         {
-            FAST_MEMCPY( ReadStart, p_mad_adec->p_data->p_payload_start,
-                         ReadSize );
+            p_mad_adec->p_fifo->p_vlc->pf_memcpy( ReadStart,
+                         p_mad_adec->p_data->p_payload_start, ReadSize );
             p_mad_adec->p_data->p_payload_start += ReadSize;
         }
 
         if ( p_mad_adec->p_fifo->b_die == 1 )
         {
-            intf_ErrMsg( "mad_adec error: libmad_input stopping libmad decoder" );
+            msg_Dbg( p_mad_adec->p_fifo, "libmad_input stopping libmad decoder" );
             return MAD_FLOW_STOP;
         }
 
         if ( p_mad_adec->p_fifo->b_error == 1 )
         {
-            intf_ErrMsg( "mad_adec error: libmad_input ignoring current audio frame" );    
+            msg_Err( p_mad_adec->p_fifo, "libmad_input ignoring current audio frame" );    
             return MAD_FLOW_IGNORE;
         }
 
@@ -153,11 +150,9 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
  *{
  *   mad_adec_thread_t *p_mad_adec = (mad_adec_thread_t *) data;
  *
- *   intf_ErrMsg( "mad_adec: libmad_header samplerate %d", p_libmad_header->samplerate);
- *
- *   p_mad_adec->p_aout_fifo->i_rate = p_libmad_header->samplerate;
- *   mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
+ *   msg_Err( p_mad_adec->p_fifo, "libmad_header samplerate %d", p_libmad_header->samplerate);
  *
+ *   PrintFrameInfo(p_limad_mad_header)
  *   return MAD_FLOW_CONTINUE;
  *}
  */
@@ -171,8 +166,6 @@ enum mad_flow libmad_input(void *data, struct mad_stream *p_libmad_stream)
  * }
  */
 
-//#define MPG321_ROUTINES     1
-#ifdef MPG321_ROUTINES
 /*****************************************************************************
  * support routines borrowed from mpg321 (file: mad.c), which is distributed
  * under GPL license
@@ -197,16 +190,16 @@ struct audio_dither {
 * NAME:                prng()
 * DESCRIPTION: 32-bit pseudo-random number generator
 */
-static __inline__ unsigned long prng(unsigned long state)
+static inline unsigned long prng(unsigned long state)
 {
     return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
 }
 
 /*
-* NAME:                audio_linear_dither()
+* NAME:        mpg321_s24_to_s16_pcm()
 * DESCRIPTION: generic linear sample quantize and dither routine
 */
-static __inline__ signed int audio_linear_dither(unsigned int bits, mad_fixed_t sample,
+static inline signed int mpg321_s24_to_s16_pcm(unsigned int bits, mad_fixed_t sample,
                                     struct audio_dither *dither)
 {
     unsigned int scalebits;
@@ -258,12 +251,11 @@ static __inline__ signed int audio_linear_dither(unsigned int bits, mad_fixed_t
     /* scale */
     return output >> scalebits;
 }
-#else
 
 /*****************************************************************************
  * s24_to_s16_pcm: Scale a 24 bit pcm sample to a 16 bit pcm sample.
  *****************************************************************************/
-static __inline__ mad_fixed_t s24_to_s16_pcm(mad_fixed_t sample)
+static inline mad_fixed_t s24_to_s16_pcm(mad_fixed_t sample)
 {
   /* round */
   sample += (1L << (MAD_F_FRACBITS - 16));
@@ -277,7 +269,6 @@ static __inline__ mad_fixed_t s24_to_s16_pcm(mad_fixed_t sample)
   /* quantize */
   return sample >> (MAD_F_FRACBITS + 1 - 16);
 }
-#endif
 
 /*****************************************************************************
  * libmad_ouput: this function is called just after the frame is decoded
@@ -286,13 +277,10 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
 {
     mad_adec_thread_t *p_mad_adec= (mad_adec_thread_t *) data;
     byte_t *buffer=NULL;
-
     mad_fixed_t const *left_ch = p_libmad_pcm->samples[0], *right_ch = p_libmad_pcm->samples[1];
     register int nsamples = p_libmad_pcm->length;
     mad_fixed_t sample;
-#ifdef MPG321_ROUTINES
     static struct audio_dither dither;
-#endif
 
     /* Creating the audio output fifo.
      * Assume the samplerate and nr of channels from the first decoded frame is right for the entire audio track.
@@ -300,10 +288,11 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
     if (p_mad_adec->p_aout_fifo==NULL)
     {
        p_mad_adec->p_aout_fifo = aout_CreateFifo(
+                p_mad_adec->p_fifo,
                 AOUT_FIFO_PCM,              /* fifo type */
-                p_libmad_pcm->channels,     /* nr. of channels */
+                2, /*p_libmad_pcm->channels,*/     /* nr. of channels */
                 p_libmad_pcm->samplerate,   /* frame rate in Hz ?*/
-                ADEC_FRAME_SIZE,            /* frame size */
+                p_libmad_pcm->length*2,     /* length of output buffer *2 channels*/
                 NULL  );                    /* buffer */
 
        if ( p_mad_adec->p_aout_fifo == NULL )
@@ -311,14 +300,16 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
                return( -1 );
        }
 
-        intf_ErrMsg("mad_adec debug: in libmad_output aout fifo created");
+        msg_Dbg( p_mad_adec->p_fifo, "aout fifo created");
     }
 
     if (p_mad_adec->p_aout_fifo->i_rate != p_libmad_pcm->samplerate)
     {
-       intf_ErrMsg( "mad_adec: libmad_output samplerate is changing from [%d] Hz to [%d] Hz, sample size [%d], error_code [%0x]",
-                   p_mad_adec->p_aout_fifo->i_rate, p_libmad_pcm->samplerate,
-                    p_libmad_pcm->length, p_mad_adec->libmad_decoder->sync->stream.error);
+       msg_Warn( p_mad_adec->p_fifo, "samplerate is changing from [%d] Hz "
+                  "to [%d] Hz, sample size [%d], error_code [%0x]",
+                  p_mad_adec->p_aout_fifo->i_rate, p_libmad_pcm->samplerate,
+                  p_libmad_pcm->length,
+                  p_mad_adec->libmad_decoder->sync->stream.error );
        p_mad_adec->p_aout_fifo->i_rate = p_libmad_pcm->samplerate;
     }
 
@@ -332,55 +323,61 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
         p_mad_adec->p_aout_fifo->date[p_mad_adec->p_aout_fifo->i_end_frame]
                 = LAST_MDATE;
     }
-    mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
+//    mad_timer_add(&p_mad_adec->libmad_timer,p_libmad_header->duration);
 
-    buffer = ((byte_t *)p_mad_adec->p_aout_fifo->buffer) + (p_mad_adec->p_aout_fifo->i_end_frame * MAD_OUTPUT_SIZE);
+    buffer = ((byte_t *)p_mad_adec->p_aout_fifo->buffer) + (p_mad_adec->p_aout_fifo->i_end_frame * (p_libmad_pcm->length*4));
 
     while (nsamples--)
     {
-#ifdef MPG321_ROUTINES
-        sample = audio_linear_dither(16, *left_ch++, &dither);
-#else
-       sample = s24_to_s16_pcm(*left_ch++);
-#endif
-
+        switch (p_mad_adec->audio_scaling)
+        {
+          case MPG321_SCALING:
+               sample = mpg321_s24_to_s16_pcm(16, *left_ch++, &dither);
+          break;
+          case FAST_SCALING: /* intended fall through */
+          default:
+               sample = s24_to_s16_pcm(*left_ch++);
+          break;
+                         }
+
+        /* left audio channel */
 #ifndef WORDS_BIGENDIAN
         *buffer++ = (byte_t) (sample >> 0);
         *buffer++ = (byte_t) (sample >> 8);
 #else
-       *buffer++ = (byte_t) (sample >> 8);
-       *buffer++ = (byte_t) (sample >> 0);
+         *buffer++ = (byte_t) (sample >> 8);
+         *buffer++ = (byte_t) (sample >> 0);
 #endif
-       if (p_libmad_pcm->channels == 2) {
-
-           /* right audio channel */
-#ifdef MPG321_ROUTINES
-            sample = audio_linear_dither(16, *right_ch++, &dither);
-#else
-            sample = s24_to_s16_pcm(*right_ch++);
-#endif
-
+       if (p_libmad_pcm->channels == 2)
+        {
+                   /* right audio channel */
+            switch (p_mad_adec->audio_scaling)
+            {
+              case MPG321_SCALING:
+                   sample = mpg321_s24_to_s16_pcm(16, *right_ch++, &dither);
+              break;
+              case FAST_SCALING: /* intended fall through */
+              default:
+                   sample = s24_to_s16_pcm(*right_ch++);
+              break;
+                         }
+        }
+        /* else reuse left_ch */
 #ifndef WORDS_BIGENDIAN
-            *buffer++ = (byte_t) (sample >> 0);
-            *buffer++ = (byte_t) (sample >> 8);
+        *buffer++ = (byte_t) (sample >> 0);
+        *buffer++ = (byte_t) (sample >> 8);
 #else
-            *buffer++ = (byte_t) (sample >> 8);
-            *buffer++ = (byte_t) (sample >> 0);
+        *buffer++ = (byte_t) (sample >> 8);
+        *buffer++ = (byte_t) (sample >> 0);
 #endif                                         
-        }
-       else {
-           /* Somethimes a single channel frame is found, while the rest of the movie are
-             * stereo channel frames. How to deal with this ??
-             * One solution is to silence the second channel.
-             */
-            *buffer++ = (byte_t) (0);
-            *buffer++ = (byte_t) (0);
-       }
     }
+
     /* DEBUG */
+    /*
     if (p_libmad_pcm->channels == 1) {
-       intf_ErrMsg( "mad debug: libmad_output channels [%d]", p_libmad_pcm->channels);
+       msg_Dbg( p_mad_adec->p_fifo, "libmad_output channels [%d]", p_libmad_pcm->channels);
     }
+    */
 
     vlc_mutex_lock (&p_mad_adec->p_aout_fifo->data_lock);
     p_mad_adec->p_aout_fifo->i_end_frame = (p_mad_adec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
@@ -400,88 +397,88 @@ enum mad_flow libmad_error(void *data, struct mad_stream *p_libmad_stream, struc
     switch (p_libmad_stream->error)
     {             
     case MAD_ERROR_BUFLEN:                /* input buffer too small (or EOF) */
-        intf_ErrMsg("libmad error: input buffer too small (or EOF)");
+//X        intf_ErrMsg("libmad error: input buffer too small (or EOF)");
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BUFPTR:                /* invalid (null) buffer pointer */
-        intf_ErrMsg("libmad error: invalid (null) buffer pointer");
+//X        intf_ErrMsg("libmad error: invalid (null) buffer pointer");
         result = MAD_FLOW_STOP;
         break;
     case MAD_ERROR_NOMEM:                 /* not enough memory */
-        intf_ErrMsg("libmad error: invalid (null) buffer pointer");
+//X        intf_ErrMsg("libmad error: invalid (null) buffer pointer");
         result = MAD_FLOW_STOP;
         break;
     case MAD_ERROR_LOSTSYNC:            /* lost synchronization */
-        intf_ErrMsg("libmad error: lost synchronization");
+//X        intf_ErrMsg("libmad error: lost synchronization");
         mad_stream_sync(p_libmad_stream);
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADLAYER:            /* reserved header layer value */
-        intf_ErrMsg("libmad error: reserved header layer value");
+//X        intf_ErrMsg("libmad error: reserved header layer value");
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADBITRATE:        /* forbidden bitrate value */
-        intf_ErrMsg("libmad error: forbidden bitrate value");
+//X        intf_ErrMsg("libmad error: forbidden bitrate value");
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADSAMPLERATE: /* reserved sample frequency value */
-        intf_ErrMsg("libmad error: reserved sample frequency value");
+//X        intf_ErrMsg("libmad error: reserved sample frequency value");
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADEMPHASIS:     /* reserved emphasis value */
-        intf_ErrMsg("libmad error: reserverd emphasis value");
+//X        intf_ErrMsg("libmad error: reserverd emphasis value");
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADCRC:                /* CRC check failed */
-        intf_ErrMsg("libmad error: CRC check failed");
+//X        intf_ErrMsg("libmad error: CRC check failed");
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADBITALLOC:     /* forbidden bit allocation value */
-        intf_ErrMsg("libmad error: forbidden bit allocation value");
+//X        intf_ErrMsg("libmad error: forbidden bit allocation value");
         result = MAD_FLOW_IGNORE;
         break;
     case MAD_ERROR_BADSCALEFACTOR:/* bad scalefactor index */
-        intf_ErrMsg("libmad error: bad scalefactor index");
+//X        intf_ErrMsg("libmad error: bad scalefactor index");
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADFRAMELEN:     /* bad frame length */
-        intf_ErrMsg("libmad error: bad frame length");
+//X        intf_ErrMsg("libmad error: bad frame length");
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADBIGVALUES:    /* bad big_values count */
-        intf_ErrMsg("libmad error: bad big values count");
+//X        intf_ErrMsg("libmad error: bad big values count");
         result = MAD_FLOW_IGNORE;
         break;
     case MAD_ERROR_BADBLOCKTYPE:    /* reserved block_type */
-        intf_ErrMsg("libmad error: reserverd block_type");
+//X        intf_ErrMsg("libmad error: reserverd block_type");
         result = MAD_FLOW_IGNORE;
         break;
     case MAD_ERROR_BADSCFSI:            /* bad scalefactor selection info */
-        intf_ErrMsg("libmad error: bad scalefactor selection info");
+//X        intf_ErrMsg("libmad error: bad scalefactor selection info");
         result = MAD_FLOW_CONTINUE;
         break;
     case MAD_ERROR_BADDATAPTR:        /* bad main_data_begin pointer */
-        intf_ErrMsg("libmad error: bad main_data_begin pointer");
+//X        intf_ErrMsg("libmad error: bad main_data_begin pointer");
         result = MAD_FLOW_STOP;
         break;
     case MAD_ERROR_BADPART3LEN:     /* bad audio data length */
-        intf_ErrMsg("libmad error: bad audio data length");
+//X        intf_ErrMsg("libmad error: bad audio data length");
         result = MAD_FLOW_IGNORE;
         break;
     case MAD_ERROR_BADHUFFTABLE:    /* bad Huffman table select */
-        intf_ErrMsg("libmad error: bad Huffman table select");
+//X        intf_ErrMsg("libmad error: bad Huffman table select");
         result = MAD_FLOW_IGNORE;
         break;
     case MAD_ERROR_BADHUFFDATA:     /* Huffman data overrun */
-        intf_ErrMsg("libmad error: Huffman data overrun");
+//X        intf_ErrMsg("libmad error: Huffman data overrun");
         result = MAD_FLOW_IGNORE;
         break;
     case MAD_ERROR_BADSTEREO:         /* incompatible block_type for JS */
-        intf_ErrMsg("libmad error: incompatible block_type for JS");
+//X        intf_ErrMsg("libmad error: incompatible block_type for JS");
         result = MAD_FLOW_IGNORE;
         break;
     default:
-        intf_ErrMsg("libmad error: unknown error occured stopping decoder");
+//X        intf_ErrMsg("libmad error: unknown error occured stopping decoder");
         result = MAD_FLOW_STOP;
         break;
     }
@@ -500,3 +497,73 @@ enum mad_flow libmad_error(void *data, struct mad_stream *p_libmad_stream, struc
  */
 
 
+
+/****************************************************************************
+ * Print human readable informations about an audio MPEG frame.                                *
+ ****************************************************************************/
+static void PrintFrameInfo(struct mad_header *Header)
+{
+       const char      *Layer,
+                       *Mode,
+                       *Emphasis;
+
+       /* Convert the layer number to it's printed representation. */
+       switch(Header->layer)
+       {
+               case MAD_LAYER_I:
+                       Layer="I";
+                       break;
+               case MAD_LAYER_II:
+                       Layer="II";
+                       break;
+               case MAD_LAYER_III:
+                       Layer="III";
+                       break;
+               default:
+                       Layer="(unexpected layer value)";
+                       break;
+       }
+
+       /* Convert the audio mode to it's printed representation. */
+       switch(Header->mode)
+       {
+               case MAD_MODE_SINGLE_CHANNEL:
+                       Mode="single channel";
+                       break;
+               case MAD_MODE_DUAL_CHANNEL:
+                       Mode="dual channel";
+                       break;
+               case MAD_MODE_JOINT_STEREO:
+                       Mode="joint (MS/intensity) stereo";
+                       break;
+               case MAD_MODE_STEREO:
+                       Mode="normal LR stereo";
+                       break;
+               default:
+                       Mode="(unexpected mode value)";
+                       break;
+       }
+
+       /* Convert the emphasis to it's printed representation. */
+       switch(Header->emphasis)
+       {
+               case MAD_EMPHASIS_NONE:
+                       Emphasis="no";
+                       break;
+               case MAD_EMPHASIS_50_15_US:
+                       Emphasis="50/15 us";
+                       break;
+               case MAD_EMPHASIS_CCITT_J_17:
+                       Emphasis="CCITT J.17";
+                       break;
+               default:
+                       Emphasis="(unexpected emphasis value)";
+                       break;
+       }
+
+//X    intf_ErrMsg("statistics: %lu kb/s audio mpeg layer %s stream %s crc, "
+//X                    "%s with %s emphasis at %d Hz sample rate\n",
+//X                    Header->bitrate,Layer,
+//X                    Header->flags&MAD_FLAG_PROTECTION?"with":"without",
+//X                    Mode,Emphasis,Header->samplerate);
+}