changeset 2415:58ea110b4036

libmad (ARM) patch by jeroen.dobbelaere@acunia.com
author arpi
date Tue, 23 Oct 2001 12:03:41 +0000
parents 557a31eed636
children 25e7342b5171
files Makefile codec-cfg.c codec-cfg.h dec_audio.c etc/codecs.conf
diffstat 5 files changed, 163 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue Oct 23 12:02:45 2001 +0000
+++ b/Makefile	Tue Oct 23 12:03:41 2001 +0000
@@ -18,8 +18,8 @@
 # BINDIR = /usr/local/bin
 SRCS = xacodec.c cpudetect.c postproc/swscale.c postproc/postprocess.c mp_msg.c ac3-iec958.c find_sub.c dec_audio.c dec_video.c codec-cfg.c subreader.c linux/getch2.c linux/timer-lx.c linux/shmem.c xa/xa_gsm.c xa/rle8.c lirc_mp.c cfgparser.c mixer.c spudec.c
 OBJS = $(SRCS:.c=.o)
-CFLAGS = $(OPTFLAGS) -Ilibmpdemux -Iloader -Ilibvo $(CSS_INC) $(EXTRA_INC) # -Wall
-A_LIBS = -Lmp3lib -lMP3 -Llibac3 -lac3 $(ALSA_LIB) $(ESD_LIB)
+CFLAGS = $(OPTFLAGS) -Ilibmpdemux -Iloader -Ilibvo $(CSS_INC) $(EXTRA_INC) $(MADLIB_INC) # -Wall
+A_LIBS = -Lmp3lib -lMP3 -Llibac3 -lac3 $(ALSA_LIB) $(ESD_LIB) $(MADLIB_LIB)
 VO_LIBS = -Llibvo -lvo $(MLIB_LIB) $(X_LIBS)
 
 PARTS = libmpdemux mp3lib libac3 libmpeg2 opendivx libavcodec encore libvo libao2 drivers drivers/syncfb
--- a/codec-cfg.c	Tue Oct 23 12:02:45 2001 +0000
+++ b/codec-cfg.c	Tue Oct 23 12:03:41 2001 +0000
@@ -209,6 +209,7 @@
 		"hwac3",
 		"libvorbis",
 		"ffmpeg",
+		"libmad",
 		NULL
 	};
 	static char *videodrv[] = {
--- a/codec-cfg.h	Tue Oct 23 12:02:45 2001 +0000
+++ b/codec-cfg.h	Tue Oct 23 12:03:41 2001 +0000
@@ -29,6 +29,7 @@
 #define AFM_HWAC3 9
 #define AFM_VORBIS 10
 #define AFM_FFMPEG 11
+#define AFM_MAD 12
 
 #define VFM_MPEG 1
 #define VFM_VFW 2
--- a/dec_audio.c	Tue Oct 23 12:02:45 2001 +0000
+++ b/dec_audio.c	Tue Oct 23 12:03:41 2001 +0000
@@ -63,6 +63,55 @@
     extern int avcodec_inited;
 #endif
 
+
+
+#ifdef USE_LIBMAD
+#include <mad.h>
+static struct mad_stream mad_stream;
+static struct mad_frame  mad_frame;
+static struct mad_synth  mad_synth;
+
+
+// ensure buffer is filled with some data
+static void mad_prepare_buffer(sh_audio_t* sh_audio, struct mad_stream* ms, int length)
+{
+  if(sh_audio->a_in_buffer_len < length) {
+    int len = demux_read_data(sh_audio->ds, sh_audio->a_in_buffer+sh_audio->a_in_buffer_len, length-sh_audio->a_in_buffer_len);
+    sh_audio->a_in_buffer_len += len;
+  }
+}
+
+static void mad_postprocess_buffer(sh_audio_t* sh_audio, struct mad_stream* ms)
+{
+  int delta = (unsigned char*)ms->next_frame - (unsigned char *)sh_audio->a_in_buffer;
+  if(delta != 0) {
+    sh_audio->a_in_buffer_len -= delta;
+    memcpy(sh_audio->a_in_buffer, ms->next_frame, sh_audio->a_in_buffer_len);
+  }
+}
+
+
+static inline
+signed short mad_scale(mad_fixed_t sample)
+{
+  /* round */
+  sample += (1L << (MAD_F_FRACBITS - 16));
+
+  /* clip */
+  if (sample >= MAD_F_ONE)
+    sample = MAD_F_ONE - 1;
+  else if (sample < -MAD_F_ONE)
+    sample = -MAD_F_ONE;
+
+  /* quantize */
+  return sample >> (MAD_F_FRACBITS + 1 - 16);
+}
+#endif
+
+
+
+
+
 int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen);
 
 
@@ -191,6 +240,17 @@
   sh_audio->audio_out_minsize=AVCODEC_MAX_AUDIO_FRAME_SIZE;
   break;
 #endif
+
+#ifdef USE_LIBMAD
+ case AFM_MAD:
+   printf(__FILE__ ":%d:mad: setting minimum outputsize\n", __LINE__);
+   sh_audio->audio_out_minsize=4608;
+   if(sh_audio->audio_in_minsize<8192) sh_audio->audio_in_minsize=8192;
+   sh_audio->a_in_buffer_size=sh_audio->audio_in_minsize;
+   sh_audio->a_in_buffer=malloc(sh_audio->a_in_buffer_size);
+   sh_audio->a_in_buffer_len=0;
+   break;
+#endif
 }
 
 if(!driver) return 0;
@@ -488,6 +548,37 @@
   break;
 }
 #endif
+
+#ifdef USE_LIBMAD
+ case AFM_MAD:
+   {
+     printf(__FILE__ ":%d:mad: initialising\n", __LINE__);
+     mad_frame_init(&mad_frame);
+     mad_stream_init(&mad_stream);
+
+     printf(__FILE__ ":%d:mad: preparing buffer\n", __LINE__);
+     mad_prepare_buffer(sh_audio, &mad_stream, sh_audio->a_in_buffer_size);
+     mad_stream_buffer(&mad_stream, (unsigned char*)(sh_audio->a_in_buffer), sh_audio->a_in_buffer_len);
+     mad_stream_sync(&mad_stream);
+     mad_synth_init(&mad_synth);
+
+     if(mad_frame_decode(&mad_frame, &mad_stream) == 0)
+       {
+	 printf(__FILE__ ":%d:mad: post processing buffer\n", __LINE__);
+	 mad_postprocess_buffer(sh_audio, &mad_stream);
+       }
+     else
+       {
+	 printf(__FILE__ ":%d:mad: frame decoding failed\n", __LINE__);
+       }
+     
+     sh_audio->channels=2; // hack
+     sh_audio->samplerate=mad_frame.header.sfreq;
+     sh_audio->i_bps=mad_frame.header.bitrate;
+     printf(__FILE__ ":%d:mad: continuing\n", __LINE__);
+     break;
+   }
+#endif
 }
 
 if(!sh_audio->channels || !sh_audio->samplerate){
@@ -741,6 +832,42 @@
         break;
       }
 #endif
+
+#ifdef USE_LIBMAD
+    case AFM_MAD:
+      {
+	mad_prepare_buffer(sh_audio, &mad_stream, sh_audio->a_in_buffer_size);
+	mad_stream_buffer(&mad_stream, sh_audio->a_in_buffer, sh_audio->a_in_buffer_len);
+	if(mad_frame_decode(&mad_frame, &mad_stream) == 0)
+	  {
+	    mad_synth_frame(&mad_synth, &mad_frame);
+	    mad_postprocess_buffer(sh_audio, &mad_stream);
+	    
+	    /* and fill buffer */
+	    
+	    {
+	      int i;
+	      int end_size = mad_synth.pcm.length;
+	      signed short* samples = (signed short*)buf;
+	      if(end_size > maxlen/4)
+		end_size=maxlen/4;
+	      
+	      for(i=0; i<mad_synth.pcm.length; ++i) {
+		*samples++ = mad_scale(mad_synth.pcm.samples[0][i]);
+		*samples++ = mad_scale(mad_synth.pcm.samples[0][i]);
+		//		*buf++ = mad_scale(mad_synth.pcm.sampAles[1][i]);
+	      }
+	      len = end_size*4;
+	    }
+	  }
+	else
+	  {
+	    printf(__FILE__ ":%d:mad: frame decoding failed\n", __LINE__);
+	  }
+	
+	break;
+      }
+#endif
     }
     return len;
 }
@@ -770,8 +897,16 @@
 	case AFM_HWAC3:
           sh_audio->a_in_buffer_len=0;        // reset ACM/DShow audio buffer
           break;
+
+#ifdef USE_LIBMAD
+	case AFM_MAD:
+	  mad_prepare_buffer(sh_audio, &mad_stream, sh_audio->a_in_buffer_size);
+	  mad_stream_buffer(&mad_stream, sh_audio->a_in_buffer, sh_audio->a_in_buffer_len);
+	  mad_stream_sync(&mad_stream);
+	  mad_postprocess_buffer(sh_audio, &mad_stream);
+	  break;
         }
-	
+#endif	
 }
 
 void skip_audio_frame(sh_audio_t *sh_audio){
@@ -796,6 +931,18 @@
 		    demux_read_data(sh_audio->ds,NULL,skip);
 		    break;
 		}
+#ifdef USE_LIBMAD
+	      case AFM_MAD:
+		{
+		  mad_prepare_buffer(sh_audio, &mad_stream, sh_audio->a_in_buffer_size);
+		  mad_stream_buffer(&mad_stream, sh_audio->a_in_buffer, sh_audio->a_in_buffer_len);
+		  mad_stream_skip(&mad_stream, 2);
+		  mad_stream_sync(&mad_stream);
+		  mad_postprocess_buffer(sh_audio, &mad_stream);
+		  break;
+		}
+#endif
+
                 default: ds_fill_buffer(sh_audio->ds);  // skip PCM frame
               }
 }
--- a/etc/codecs.conf	Tue Oct 23 12:02:45 2001 +0000
+++ b/etc/codecs.conf	Tue Oct 23 12:03:41 2001 +0000
@@ -590,6 +590,17 @@
   dll "mp3lib (mpglib)"
   flags seekable
 
+;MAD library
+audiocodec mad
+  info "MAD MPEG layer-2, layer-3"
+  status working
+  comment "Optimized for ARM"
+  format 0x50
+  format 0x55
+  driver libmad
+  dll "libmad"
+  flags seekable
+
 audiocodec ffmp3
   info "FFmpeg layer-123 audio decoder - integer only"
   status working