shithub: aacdec

Download patch

ref: e4b87483df3b5a4cb2a42d69fbfea649908aa71b
parent: 01584c198c3052681db9309914afd92543182ff8
author: menno <menno>
date: Tue Sep 2 16:12:18 EDT 2003

New xmms MP4 plugin from ciber-fred

diff: cannot open b/plugins/xmmsmp4/src//null: file does not exist: 'b/plugins/xmmsmp4/src//null' diff: cannot open b/plugins/xmmsmp4//null: file does not exist: 'b/plugins/xmmsmp4//null'
--- /dev/null
+++ b/plugins/xmmsmp4/src/Makefile.am
@@ -1,0 +1,10 @@
+libdir = `xmms-config --input-plugin-dir`
+
+lib_LTLIBRARIES = libmp4.la
+libmp4_la_CFLAGS = -I../mp4v2 -I../libmp4v2-include -I../libfaad-include `xmms-config --cflags` -DHAVE_GLIB_H=1
+
+libmp4_la_LDFLAGS = -module -avoid-version `xmms-config --libs` -lpthread -lstdc++ 
+
+libmp4_la_LIBADD = $(top_builddir)/libfaad/libfaad.la $(top_builddir)/mp4v2/libmp4v2.la
+
+libmp4_la_SOURCES = libmp4.c libmp4_utils.c libmp4_utils.h
--- /dev/null
+++ b/plugins/xmmsmp4/src/libmp4.c
@@ -1,0 +1,303 @@
+/*
+** a mp4 AAC audio player for XMMS by ciberfred
+**
+*/
+
+#include "mp4.h"
+#include <pthread.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+
+#include "faad.h"
+
+#include "xmms/plugin.h"
+#include "xmms/util.h"
+#include "xmms/configfile.h"
+#include "xmms/titlestring.h"
+
+#include "libmp4_utils.h"
+
+#define MP4_DESCRIPTION	"MP4 audio player - 1.2.7"
+#define MP4_VERSION	"mp4 audio player (v0.3) - 1 Aout 2003"
+#define MP4_ABOUT	"Written from scratch by ciberfred"
+
+static void	mp4_init(void);
+static void	mp4_about(void);
+static void	mp4_play(char *);
+static void	mp4_stop(void);
+static void	mp4_pause(short);
+static void	mp4_seek(int);
+static int	mp4_getTime(void);
+static void	mp4_cleanup(void);
+static void	mp4_getSongInfo(char *);
+static int	mp4_isFile(char *);
+
+static void	*mp4Decode(void *args);
+
+InputPlugin mp4_ip =
+  {
+    0,	// handle
+    0,	// filename
+    MP4_DESCRIPTION,
+    mp4_init,
+    mp4_about,
+    0,	// configuration
+    mp4_isFile,
+    0,	//scandir
+    mp4_play,
+    mp4_stop,
+    mp4_pause,
+    mp4_seek,
+    0,	// set equalizer
+    mp4_getTime,
+    0,	// get volume
+    0,
+    mp4_cleanup,
+    0,	// obsolete
+    0,	// send visualisation data
+    0,	// set player window info
+    0,	// set song title text
+    0,	// get song title text
+    mp4_getSongInfo, // info box
+    0,	// to output plugin
+  };
+
+
+static gboolean		bPlaying = FALSE;
+static pthread_t	decodeThread;
+static pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
+static int		seekPosition = -1;
+
+InputPlugin *get_iplugin_info(void)
+{
+  return(&mp4_ip);
+}
+
+static void mp4_init(void)
+{
+  memset(&decodeThread, 0, sizeof(pthread_t));
+  return;
+}
+
+static void mp4_play(char *filename)
+{
+  bPlaying = TRUE;
+  pthread_create(&decodeThread, 0, mp4Decode, g_strdup(filename));
+  return;
+}
+
+static void mp4_stop(void)
+{
+  if(bPlaying){
+    bPlaying = FALSE;
+    pthread_join(decodeThread, NULL);
+    memset(&decodeThread, 0, sizeof(pthread_t));
+    mp4_ip.output->close_audio();
+  }
+}
+
+static void *mp4Decode(void *args)
+{
+  unsigned long msDuration;
+  unsigned char	*buffer = NULL;
+  int		bufferSize = 0;
+  int		lastframe = 0;
+  faacDecHandle decoder;
+  MP4SampleId	numSamples;
+  MP4SampleId	sampleID=1;
+  MP4FileHandle mp4file;
+  MP4Duration	duration;
+  int		mp4track;
+  unsigned long	samplerate;
+  unsigned char channels;
+  unsigned int	avgBitrate;
+
+
+  pthread_mutex_lock(&mutex);
+  seekPosition = -1;
+  bPlaying = TRUE;
+  if(!(mp4file = MP4Read(args, 0))){
+    printf("can't open file: %s\n", args);
+    free(args);
+    bPlaying = FALSE;
+    pthread_mutex_unlock(&mutex);
+    pthread_exit(NULL);
+  }
+  if((mp4track = getAACTrack(mp4file)) < 0){
+// check here for others Audio format.....
+
+    g_print("Unsupported Audio track type\n");
+    free(args);
+    MP4Close(mp4file);
+    bPlaying = FALSE;
+    pthread_mutex_unlock(&mutex);
+    pthread_exit(NULL);
+  }
+  decoder = faacDecOpen();
+  MP4GetTrackESConfiguration(mp4file, mp4track, &buffer, &bufferSize);
+  if(!buffer){
+    free(args);
+    faacDecClose(decoder);
+    MP4Close(mp4file);
+    bPlaying = FALSE;
+    pthread_mutex_unlock(&mutex);
+    pthread_exit(NULL);
+  }
+  if(faacDecInit2(decoder, buffer, bufferSize, &samplerate, &channels)<0){
+    free(args);
+    faacDecClose(decoder);
+    MP4Close(mp4file);
+    bPlaying = FALSE;
+    pthread_mutex_unlock(&mutex);
+    pthread_exit(NULL);
+  }
+  free(buffer);
+  if(channels == 0){
+    g_print("Number of Channels not supported\n");
+    free(args);
+    faacDecClose(decoder);
+    MP4Close(mp4file);
+    bPlaying = FALSE;
+    pthread_mutex_unlock(&mutex);
+    pthread_exit(NULL);
+  }
+  mp4_ip.output->open_audio(FMT_S16_NE, samplerate, channels);
+  mp4_ip.output->flush(0);
+  g_print("MP4 flush\n");
+  duration = MP4GetTrackDuration(mp4file, mp4track);
+  msDuration = MP4ConvertFromTrackDuration(mp4file, mp4track, duration,
+					   MP4_MSECS_TIME_SCALE);
+  numSamples = MP4GetTrackNumberOfSamples(mp4file, mp4track);
+  //mp4_ip.set_info(args, msDuration, -1, samplerate/1000, channels);
+
+  while(bPlaying){
+    void		*sampleBuffer;
+    faacDecFrameInfo	frameInfo;    
+    int			rc;
+
+    if(seekPosition!=-1){
+      duration = MP4ConvertToTrackDuration(mp4file, mp4track,seekPosition*1000,
+					   MP4_MSECS_TIME_SCALE);
+      sampleID = MP4GetSampleIdFromTime(mp4file, mp4track, duration, 0);
+      mp4_ip.output->flush(seekPosition*1000);
+      seekPosition = -1;
+    }
+    buffer=NULL;
+    bufferSize=0;
+    if(sampleID > numSamples){
+      mp4_ip.output->close_audio();
+      free(args);
+      faacDecClose(decoder);
+      MP4Close(mp4file);
+      bPlaying = FALSE;
+      pthread_mutex_unlock(&mutex);
+      pthread_exit(NULL);
+    }
+    rc = MP4ReadSample(mp4file, mp4track, sampleID++, &buffer, &bufferSize,
+		       NULL, NULL, NULL, NULL);
+    //g_print("%d/%d\n", sampleID-1, numSamples);
+    if((rc==0) || (buffer== NULL)){
+      printf("read error\n");
+      sampleBuffer = NULL;
+      sampleID=0;
+      mp4_ip.output->buffer_free();
+      mp4_ip.output->close_audio();
+      free(args);
+      faacDecClose(decoder);
+      MP4Close(mp4file);
+      bPlaying = FALSE;
+      pthread_mutex_unlock(&mutex);
+      pthread_exit(NULL);
+    }
+    else{
+      sampleBuffer = faacDecDecode(decoder, &frameInfo, buffer, bufferSize);
+      if(frameInfo.error > 0){
+	printf("FAAD2 error : %s\n", faacDecGetErrorMessage(frameInfo.error));
+	mp4_ip.output->close_audio();
+	free(args);
+	faacDecClose(decoder);
+	MP4Close(mp4file);
+	bPlaying = FALSE;
+	pthread_mutex_unlock(&mutex);
+	pthread_exit(NULL);
+      }
+      if(buffer){
+	free(buffer); buffer=0;
+      }
+      while(bPlaying && mp4_ip.output->buffer_free()<frameInfo.samples<<1)
+	xmms_usleep(30000);
+    }
+    //mp4_ip.add_vis_pcm(mp4_ip.output->written_time(), FMT_S16_NE, channels, frameInfo.samples<<1, sampleBuffer);
+    mp4_ip.output->write_audio(sampleBuffer, frameInfo.samples<<1);
+  }
+  while(bPlaying && mp4_ip.output->buffer_free()){
+    xmms_usleep(10000);
+  }
+  mp4_ip.output->close_audio();
+  free(args);
+  faacDecClose(decoder);
+  MP4Close(mp4file);
+  bPlaying = FALSE;
+  pthread_mutex_unlock(&mutex);
+  pthread_exit(NULL);
+}
+
+static int	mp4_isFile(char *filename)
+{
+  char *extention = strrchr(filename, '.');
+  if (extention &&
+      !strcasecmp(extention, ".mp4") ||
+      !strcasecmp(extention, ".m4a")
+      ){
+    return (1);
+  }
+  return(0);
+}
+
+static void	mp4_about(void)
+{
+  static GtkWidget *aboutbox;
+
+  if(aboutbox!=NULL)
+    return;
+
+  aboutbox = xmms_show_message(
+			       "About MP4 AAC player plugin",
+			       "decoding engine : FAAD2 (30 July 2003)\n"
+			       "plugin version : 0.3 (ciberfred)/static",
+			       "Ok", FALSE, NULL, NULL);
+  gtk_signal_connect(GTK_OBJECT(aboutbox), "destroy",
+                     GTK_SIGNAL_FUNC(gtk_widget_destroyed),
+                     &aboutbox);
+}
+
+static void	mp4_pause(short flag)
+{
+  mp4_ip.output->pause(flag);
+}
+
+static void	mp4_seek(int time)
+{
+  seekPosition = time;
+  while(bPlaying && seekPosition!=-1) xmms_usleep(10000);
+}
+
+static int	mp4_getTime(void)
+{
+  if (!bPlaying){
+    return (-1);
+  }
+  else{
+    return (mp4_ip.output->output_time());
+  }
+}
+
+static void	mp4_cleanup(void)
+{
+}
+
+static void	mp4_getSongInfo(char *filename)
+{
+  getMP4info(filename);
+}
--- /dev/null
+++ b/plugins/xmmsmp4/src/libmp4_utils.c
@@ -1,0 +1,153 @@
+/*
+** some function for MP4 file based on libmp4v2 from mpeg4ip project
+*/
+#include <mp4.h>
+#include <faad.h>
+#include "libmp4_utils.h"
+
+
+const char *mp4AudioNames[]=
+  {
+    "MPEG-1 Audio Layers 1,2 or 3",
+    "MPEG-2 low biterate (MPEG-1 extension) - MP3",
+    "MPEG-2 AAC Main Profile",
+    "MPEG-2 AAC Low Complexity profile",
+    "MPEG-2 AAC SSR profile",
+    "MPEG-4 audio (MPEG-4 AAC)",
+    0
+  };
+
+const u_int8_t mp4AudioTypes[] =
+  {
+    MP4_MPEG1_AUDIO_TYPE,		// 0x6B
+    MP4_MPEG2_AUDIO_TYPE,		// 0x69
+    MP4_MPEG2_AAC_MAIN_AUDIO_TYPE,	// 0x66
+    MP4_MPEG2_AAC_LC_AUDIO_TYPE,	// 0x67
+    MP4_MPEG2_AAC_SSR_AUDIO_TYPE,	// 0x68
+    MP4_MPEG4_AUDIO_TYPE,		// 0x40
+    0
+  };
+
+/* MPEG-4 Audio types from 14496-3 Table 1.5.1 (from mp4.h)*/
+const char *mpeg4AudioNames[]=
+  {
+    "!!!!MPEG-4 Audio track Invalid !!!!!!!",
+    "MPEG-4 AAC Main profile",
+    "MPEG-4 AAC Low Complexity profile",
+    "MPEG-4 AAC SSR profile",
+    "MPEG-4 AAC Long Term Prediction profile",
+    "MPEG-4 AAC Scalable",
+    "MPEG-4 CELP",
+    "MPEG-4 HVXC",
+    "MPEG-4 Text To Speech",
+    "MPEG-4 Main Synthetic profile",
+    "MPEG-4 Wavetable Synthesis profile",
+    "MPEG-4 MIDI Profile",
+    "MPEG-4 Algorithmic Synthesis and Audio FX profile"
+  };
+
+int getAACTrack(MP4FileHandle file)
+{
+  int numTracks = MP4GetNumberOfTracks(file, NULL, 0);
+  int i=0;
+
+  for(i=0;i<numTracks;i++){
+    MP4TrackId trackID = MP4FindTrackId(file, i, NULL, 0);
+    const char *trackType = MP4GetTrackType(file, trackID);
+    if(!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)){//we found audio track !
+      int j=0;
+      u_int8_t audiotype = MP4GetTrackAudioType(file, trackID);
+      while(mp4AudioTypes[j]){ // what kind of audio is ?
+	if(mp4AudioTypes[j] == audiotype){
+	  if(mp4AudioTypes[j] == MP4_MPEG4_AUDIO_TYPE){//MPEG4 audio ok
+	    audiotype = MP4GetTrackAudioMpeg4Type(file, trackID);
+	    printf("%d-%s\n", audiotype, mpeg4AudioNames[audiotype]);
+	    return (trackID);
+	  }
+	  else{
+	    printf("%s\n", mp4AudioNames[j]);
+	    if (mp4AudioTypes[j]== MP4_MPEG2_AAC_LC_AUDIO_TYPE ||
+		mp4AudioTypes[j]== MP4_MPEG2_AAC_MAIN_AUDIO_TYPE ||
+		mp4AudioTypes[j]== MP4_MPEG2_AAC_SSR_AUDIO_TYPE)
+	      return(trackID);
+	    return(-1);
+	  }
+	}
+	j++;
+      }
+    }
+  }
+    return(-1);
+}
+
+int getAudioTrack(MP4FileHandle file)
+{
+  int numTracks = MP4GetNumberOfTracks(file, NULL,0);
+  int i=0;
+
+  for(i=0;i<numTracks;i++){
+    MP4TrackId trackID = MP4FindTrackId(file, i, NULL, 0);
+    const char *trackType = MP4GetTrackType(file, trackID);
+    if(!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)){
+      return(trackID);
+    }
+  }
+  return(-1);
+}
+
+int getVideoTrack(MP4FileHandle file)
+{
+  int numTracks = MP4GetNumberOfTracks(file, NULL, 0);
+  int i=0;
+
+  for(i=0;i<numTracks; i++){
+    MP4TrackId trackID = MP4FindTrackId(file, i, NULL, 0);
+    const char *trackType = MP4GetTrackType(file, trackID);
+    if(!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)){
+      return (trackID);
+    }
+  }
+  return(-1);
+}
+
+void getMP4info(char* file)
+{
+  MP4FileHandle	mp4file;
+  MP4Duration	trackDuration;
+  int numTracks;
+  int i=0;
+
+  if(!(mp4file = MP4Read(file,0)))
+    return;
+  //MP4Dump(mp4file, 0, 0);
+  numTracks = MP4GetNumberOfTracks(mp4file, NULL, 0);
+  printf("there is %d track(s)\n", numTracks);
+  for(i=0;i<numTracks;i++){
+    MP4TrackId trackID = MP4FindTrackId(mp4file, i, NULL, 0);
+    const char *trackType = MP4GetTrackType(mp4file, trackID);
+    printf("Track %d, %s", trackID, trackType);
+    if(!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)){//we found audio track !
+      int j=0;
+      u_int8_t audiotype = MP4GetTrackAudioType(mp4file, trackID);
+      while(mp4AudioTypes[j]){ // what kind of audio is ?
+	if(mp4AudioTypes[j] == audiotype){
+	  if(mp4AudioTypes[j] == MP4_MPEG4_AUDIO_TYPE){
+	    audiotype = MP4GetTrackAudioMpeg4Type(mp4file, trackID);
+	    printf(" %s", mpeg4AudioNames[audiotype]);
+	  }
+	  else{
+	    printf(" %s", mp4AudioNames[j]);
+	  }
+	  printf(" duration :%d",
+		 MP4ConvertFromTrackDuration(mp4file, trackID,
+					     MP4GetTrackDuration(mp4file,
+								 trackID),
+					     MP4_MSECS_TIME_SCALE));
+	}
+	j++;
+      }
+    }
+    printf("\n");
+  }
+  MP4Close(mp4file);
+}
--- /dev/null
+++ b/plugins/xmmsmp4/src/libmp4_utils.h
@@ -1,0 +1,9 @@
+#ifndef __MP4UTILS_H_
+#define __MP4UTILS_H_
+
+int getAACTrack(MP4FileHandle);
+int getAudioTrack(MP4FileHandle);
+int getVideoTrack(MP4FileHandle);
+void getMP4info(char*);
+
+#endif