📄 libmp4.c
字号:
/*
* MP4/AAC decoder for xmms
*
* OPTIONNAL need
* --------------
* libid3 (3.8.x - www.id3.org)
*/
#include <pthread.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
#if defined(HAVE_BMP)
#include <bmp/plugin.h>
#include <bmp/util.h>
#include <bmp/configfile.h>
#include <bmp/titlestring.h>
#else
#include <xmms/plugin.h>
#include <xmms/util.h>
#include <xmms/configfile.h>
#include <xmms/titlestring.h>
#endif /*HAVE_BMP*/
#include "neaacdec.h"
#include "mp4ff.h"
#define MP4_DESCRIPTION "MP4 & MPEG2/4-AAC audio player - 1.2.x"
#define MP4_VERSION "ver. 0.5-faad2-version - 22 August 2004"
#define MP4_ABOUT "Written by ciberfred"
#define BUFFER_SIZE FAAD_MIN_STREAMSIZE*64
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_getSongTitle(char *, char **, int *);
static void mp4_getSongInfo(char *);
static int mp4_isFile(char *);
static void* mp4Decode(void *);
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
mp4_getSongTitle, // get song title text
mp4_getSongInfo, // info box
0, // to output plugin
};
typedef struct _mp4cfg{
gshort file_type;
#define FILE_UNKNOW 0
#define FILE_MP4 1
#define FILE_AAC 2
} Mp4Config;
static Mp4Config mp4cfg;
static gboolean bPlaying = FALSE;
static pthread_t decodeThread;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static int seekPosition = -1;
// Functions from mp4_utils.c
extern int getAACTrack(mp4ff_t *infile);
extern mp4ff_callback_t *getMP4FF_cb(FILE *mp4file);
extern char *getMP4title(mp4ff_t *infile, char *filename);
extern void getMP4info(char* filename, FILE *mp4file);
InputPlugin *get_iplugin_info(void)
{
return(&mp4_ip);
}
static void mp4_init(void)
{
memset(&decodeThread, 0, sizeof(pthread_t));
mp4cfg.file_type = FILE_UNKNOW;
seekPosition = -1;
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 int mp4_isFile(char *filename)
{
if(filename){
gchar* extention;
extention = strrchr(filename, '.');
if(extention &&
(!strncasecmp(extention, ".mp4", 4) || // official extention
!strncasecmp(extention, ".m4a", 4) || // Apple mp4 extention
!strncasecmp(extention, ".aac", 4) // old MPEG2/4-AAC extention
)){
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",
"libfaad2-" FAAD2_VERSION "\n"
"plugin version: " MP4_VERSION "\n"
MP4_ABOUT,
"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)
{
}
void mp4_get_file_type(FILE *mp4file)
{
unsigned char header[10] = {0};
fseek(mp4file, 0, SEEK_SET);
fread(header, 1, 8, mp4file);
if(header[4]=='f' &&
header[5]=='t' &&
header[6]=='y' &&
header[7]=='p'){
mp4cfg.file_type = FILE_MP4;
}else{
mp4cfg.file_type = FILE_AAC;
}
}
static void mp4_getSongTitle(char *filename, char **title, int *len) {
FILE* mp4file;
(*title) = NULL;
(*len) = -1;
if((mp4file = fopen(filename, "rb"))){
mp4_get_file_type(mp4file);
fseek(mp4file, 0, SEEK_SET);
if(mp4cfg.file_type == FILE_MP4){
mp4ff_callback_t* mp4cb;
mp4ff_t* infile;
gint mp4track;
mp4cb = getMP4FF_cb(mp4file);
if ((infile = mp4ff_open_read_metaonly(mp4cb)) &&
((mp4track = getAACTrack(infile)) >= 0)){
(*title) = getMP4title(infile, filename);
double track_duration = mp4ff_get_track_duration(infile, mp4track);
unsigned long time_scale = mp4ff_time_scale(infile, mp4track);
unsigned long length = (track_duration * 1000 / time_scale);
(*len) = length;
}
if(infile) mp4ff_close(infile);
if(mp4cb) g_free(mp4cb);
}
else{
// Check AAC ID3 tag...
}
fclose(mp4file);
}
}
static void mp4_getSongInfo(char *filename)
{
FILE* mp4file;
if((mp4file = fopen(filename, "rb"))){
if (mp4cfg.file_type == FILE_UNKNOW)
mp4_get_file_type(mp4file);
fseek(mp4file, 0, SEEK_SET);
if(mp4cfg.file_type == FILE_MP4)
getMP4info(filename, mp4file);
else if(mp4cfg.file_type == FILE_AAC)
/*
* check the id3tagv2
*/
;
fclose(mp4file);
}
}
static void *mp4Decode(void *args)
{
FILE* mp4file;
pthread_mutex_lock(&mutex);
seekPosition = -1;
bPlaying = TRUE;
if(!(mp4file = fopen(args, "rb"))){
g_print("MP4!AAC - Can't open file\n");
g_free(args);
bPlaying = FALSE;
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
mp4_get_file_type(mp4file);
fseek(mp4file, 0, SEEK_SET);
if(mp4cfg.file_type == FILE_MP4){// We are reading a MP4 file
mp4ff_callback_t* mp4cb;
mp4ff_t* infile;
gint mp4track;
mp4cb = getMP4FF_cb(mp4file);
if(!(infile = mp4ff_open_read(mp4cb))){
g_print("MP4 - Can't open file\n");
goto end;
}
if((mp4track = getAACTrack(infile)) < 0){
/*
* TODO: check here for others Audio format.....
*
*/
g_print("Unsupported Audio track type\n");
g_free(args);
fclose(mp4file);
bPlaying = FALSE;
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}else{
NeAACDecHandle decoder;
unsigned char *buffer = NULL;
guint bufferSize = 0;
gulong samplerate;
guchar channels;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -