shithub: aacdec

Download patch

ref: 33656858ad9f69ed9ea1e7fe565f1ce28987205c
parent: 2ac355532dc6bd13696bb8b06be924ed1a097d23
author: menno <menno>
date: Mon Apr 28 15:07:57 EDT 2003

new QCD MP4 plugin

--- /dev/null
+++ b/plugins/QCDMp4/AAC2Mp4Enc.c
@@ -1,0 +1,270 @@
+//-----------------------------------------------------------------------------
+//
+// File:	QCDEncodeDLL.cpp
+//
+// About:	See QCDOutputDLL.h
+//
+// Authors:	Written by Paul Quinn
+//
+//	QCD multimedia player application Software Development Kit Release 1.0.
+//
+//	Copyright (C) 1997-2002 Quinnware
+//
+//	This code is free.  If you redistribute it in any form, leave this notice 
+//	here.
+//
+//	This program is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+//
+//-----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <shlobj.h>
+#include <mp4.h>
+
+#include "QCDInputDLL.h"
+#include "QCDConvertDLL.h"
+#include "resource.h"
+#include "utils.h"
+#include "config.h"
+#include "aac2mp4.h"
+
+HWND			hwndConfigEnc;
+QCDModInitEnc	*QCDCallbacks_Enc;
+
+BOOL CALLBACK config_convert_proc(HWND hwndDlg, UINT message,
+                                 WPARAM wParam, LPARAM lParam);
+
+static char m_output_folder[MAX_PATH];// our output folder
+
+void config_enc_read()
+{
+	char output_folder[MAX_PATH];
+	output_folder[0] = 0;
+
+    RS(output_folder);
+
+	lstrcpy(m_output_folder, output_folder);
+}
+
+void config_enc_write()
+{
+	char output_folder[MAX_PATH];
+	lstrcpy(output_folder, m_output_folder);
+
+	WS(output_folder);
+}
+
+BOOL isFolder(char *folder)
+{
+	if(lstrlen(folder) > 0 && folder[1] == ':')
+		return TRUE;
+	else
+		return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+
+PLUGIN_API BOOL ENCODEDLL_ENTRY_POINT(QCDModInitEnc *ModInit, QCDModInfo *ModInfo)
+{
+	ModInit->version = PLUGIN_API_VERSION;
+	ModInfo->moduleString = "AAC to Mp4 Converter v1.0";
+
+	ModInit->toModule.ShutDown				= ShutDown_Enc;
+	ModInit->toModule.Open					= Open_Enc;
+	ModInit->toModule.Write					= Write_Enc;
+	ModInit->toModule.Stop					= Stop_Enc;
+	ModInit->toModule.GetCurrentPosition	= GetCurrentPosition_Enc;
+	ModInit->toModule.Configure				= Configure_Enc;
+	ModInit->toModule.About					= About_Enc;
+
+/* encoders can handle these calls if they wish,
+ * but they are generally not needed
+
+	ModInit->toModule.Flush				= Flush;
+	ModInit->toModule.Pause				= Pause;
+	ModInit->toModule.Drain				= Drain;
+	ModInit->toModule.SetVolume			= SetVolume;
+	ModInit->toModule.DrainCancel		= DrainCancel;
+
+*/
+
+	QCDCallbacks_Enc = ModInit;
+
+	hwndPlayer = (HWND)QCDCallbacks_Enc->Service(opGetParentWnd, 0, 0, 0);
+
+	QCDCallbacks_Enc->Service(opGetPluginSettingsFile, INI_FILE, MAX_PATH, 0);
+
+	//
+	// TODO: all your plugin initialization here
+	//
+	config_enc_read();
+
+	
+	// return TRUE for successful initialization
+	return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+
+void ShutDown_Enc(int flags)
+{
+	Stop_Enc(STOPFLAG_FORCESTOP);
+}
+
+//-----------------------------------------------------------------------------
+
+BOOL Open_Enc(LPCSTR medianame, WAVEFORMATEX *wf)
+{
+	char mp4FileName[256];
+	
+	if(StringComp(strrchr(medianame, '.'), ".aac", 4))
+	{
+		MessageBox(hwndPlayer, "Only AAC files can be converted into Mp4 Files!", "File Type Error", MB_OK);
+		return FALSE;
+	}
+	else if(!isFolder(m_output_folder) && MessageBox(hwndPlayer, "You should select a output folder!", "Error", MB_OK) == IDOK )
+	{
+		if(!IsWindow(hwndConfigEnc))
+			hwndConfigEnc = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_CONFIG_CONVERT), 
+				hwndPlayer, config_convert_proc);
+		ShowWindow(hwndConfigEnc, SW_SHOW);
+		return FALSE;
+	}
+	else
+	{
+		lstrcpy(mp4FileName, m_output_folder); // copy the folder path
+		lstrcat(mp4FileName, strrchr(medianame, '\\')); //copy the file name
+		lstrcpy(strrchr(mp4FileName, '.'), ".mp4"); // rename the file name to .mp4
+
+		if(covert_aac_to_mp4(medianame, mp4FileName))
+		{
+			MessageBox(hwndPlayer, "An error occured while converting AAC to MP4!", "An error occured!", MB_OK);
+			return FALSE;
+		}
+		else
+		{
+			QCDCallbacks_Enc->Service(opSetStatusMessage, "Converting OK", TEXT_TOOLTIP, 0);
+
+			return TRUE;
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+
+BOOL Write_Enc(WriteDataStruct* writeData)
+{
+	//
+	// TODO : Use the raw wave audio data passed from the player.
+	//
+	// Return value - one of the follwing:
+	//
+	// TRUE		- write succeeded
+	// FALSE	- write failed
+	//
+	// Note: this call can block (eg: to wait for available space to write)
+
+	return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+
+BOOL Stop_Enc(int flags)
+{
+	//
+	// TODO : Stop and close the output.
+	//
+	// Return TRUE for success, FALSE for failure
+
+	return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+
+BOOL GetCurrentPosition_Enc(UINT *position, int flags)
+{
+	// 
+	// TODO : set position to exact current playing position
+	// returned position needs to be latest marker sent to Write
+	// return TRUE for success
+
+	return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+
+BOOL CALLBACK config_convert_proc(HWND hwndDlg, UINT message,
+                                 WPARAM wParam, LPARAM lParam)
+{
+	char str_buffer[MAX_PATH];
+
+	switch (message) 
+	{
+    case WM_INITDIALOG:
+		if(isFolder(m_output_folder))// is a driver folder
+			SetDlgItemText(hwndDlg, IDC_OUTPUTFOLDER, m_output_folder);
+		else
+			SetDlgItemText(hwndDlg, IDC_OUTPUTFOLDER, "Select Output Folder");
+        return TRUE;
+
+    case WM_COMMAND:
+        switch (LOWORD(wParam))
+		{
+		case IDC_OUTPUTFOLDER:
+			{
+				char name[MAX_PATH];
+				BROWSEINFO bi;
+				ITEMIDLIST *idlist;
+				bi.hwndOwner = hwndDlg;
+				bi.pidlRoot = 0;
+				bi.pszDisplayName = name;
+				bi.lpszTitle = "Select a directory for saving mp4 files converted from aac files: ";
+				bi.ulFlags = BIF_RETURNONLYFSDIRS /*| BIF_USENEWUI*/;
+				bi.lpfn = NULL;
+				bi.lParam = 0;
+				
+				idlist = SHBrowseForFolder( &bi );
+				if(idlist)
+				{
+					SHGetPathFromIDList( idlist, m_output_folder);
+					SetDlgItemText(hwndDlg, IDC_OUTPUTFOLDER, m_output_folder);
+				}
+				return TRUE;
+			}
+        case IDOK:
+			GetDlgItemText(hwndDlg, IDC_OUTPUTFOLDER, str_buffer, MAX_PATH);
+			if(isFolder(str_buffer)) // is a driver foder
+				lstrcpy(m_output_folder, str_buffer);
+			else
+				m_output_folder[0] = 0;
+
+            /* save config */
+            config_enc_write();
+		default:
+			/* close the dialogbox */
+            DestroyWindow(hwndDlg);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+void Configure_Enc(int flags)
+{
+	if(!IsWindow(hwndConfigEnc))
+		hwndConfigEnc = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_CONFIG_CONVERT), 
+			hwndPlayer, config_convert_proc);
+	ShowWindow(hwndConfigEnc, SW_SHOWNORMAL);
+}
+
+//-----------------------------------------------------------------------------
+
+void About_Enc(int flags)
+{
+	if(!IsWindow(hwndAbout))
+		hwndAbout = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_ABOUT), 
+			hwndPlayer, about_dialog_proc);
+	ShowWindow(hwndAbout, SW_SHOWNORMAL);
+}
--- /dev/null
+++ b/plugins/QCDMp4/QCDConvertDLL.h
@@ -1,0 +1,40 @@
+//-----------------------------------------------------------------------------
+// 
+// File:	QCDEncodeDLL.h
+//
+// About:	QCD Player Output module DLL interface.  For more documentation, see
+//			QCDModOutput.h.
+//
+// Authors:	Written by Paul Quinn
+//
+//	QCD multimedia player application Software Development Kit Release 1.0.
+//
+//	Copyright (C) 1997-2002 Quinnware
+//
+//	This code is free.  If you redistribute it in any form, leave this notice 
+//	here.
+//
+//	This program is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+//
+//-----------------------------------------------------------------------------
+
+#include "QCDModEncode.h"
+
+#ifndef QCDENCODEDLL_H
+#define QCDENCODEDLL_H
+
+extern QCDModInitEnc	*QCDCallbacks_Enc;
+
+// Calls from the Player
+void ShutDown_Enc(int flags);
+BOOL Open_Enc(LPCSTR, WAVEFORMATEX *wf);
+BOOL Write_Enc(WriteDataStruct*);
+BOOL Stop_Enc(int flags);
+BOOL GetCurrentPosition_Enc(UINT *position, int flags);
+
+void Configure_Enc(int flags);
+void About_Enc(int flags);
+
+#endif //QCDOUTPUTDLL_H
\ No newline at end of file
--- /dev/null
+++ b/plugins/QCDMp4/QCDInputDLL.h
@@ -1,0 +1,52 @@
+//-----------------------------------------------------------------------------
+// 
+// File:	QCDInputDLL.h
+//
+// About:	QCD Player Input module DLL interface.  For more documentation, see
+//			QCDModInput.h.
+//
+// Authors:	Written by Paul Quinn and Richard Carlson.
+//
+//	QCD multimedia player application Software Development Kit Release 1.0.
+//
+//	Copyright (C) 1997-2002 Quinnware
+//
+//	This code is free.  If you redistribute it in any form, leave this notice 
+//	here.
+//
+//	This program is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef QCDInputDLL_H
+#define QCDInputDLL_H
+
+#include "QCDModInput.h"
+
+extern HINSTANCE		hInstance;
+extern HWND				hwndPlayer, hwndAbout;
+extern QCDModInitIn		sQCDCallbacks, *QCDCallbacks;
+
+// Calls from the Player
+int  GetMediaSupported(const char* medianame, MediaInfo *mediaInfo);
+int  GetTrackExtents(const char* medianame, TrackExtents *ext, int flags);
+int  GetCurrentPosition(const char* medianame, long *track, long *offset);
+
+void SetEQ(EQInfo*);
+void SetVolume(int levelleft, int levelright, int flags);
+
+int  Play(const char* medianame, int framefrom, int frameto, int flags);
+int  Pause(const char* medianame, int flags);
+int  Stop(const char* medianame, int flags);
+int  Eject(const char* medianame, int flags);
+
+int  Initialize(QCDModInfo *ModInfo, int flags);
+void ShutDown(int flags);
+void Configure(int flags);
+void About(int flags);
+
+#endif //QCDInputDLL_H
+
+INT_PTR CALLBACK about_dialog_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
--- /dev/null
+++ b/plugins/QCDMp4/QCDModDefs.h
@@ -1,0 +1,355 @@
+//-----------------------------------------------------------------------------
+//
+// File:	QCDModDefs.h
+//
+// About:	Module definitions file.  Miscellanious definitions used by different
+//			module types.  This file is published with the plugin SDKs.
+//
+// Authors:	Written by Paul Quinn and Richard Carlson.
+//
+// Copyright:
+//
+//	QCD multimedia player application Software Development Kit Release 1.0.
+//
+//	Copyright (C) 1997-2002 Quinnware
+//
+//	This code is free.  If you redistribute it in any form, leave this notice 
+//	here.
+//
+//	This program is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef QCDMODDEFS_H
+#define QCDMODDEFS_H
+
+#include <windows.h>
+
+#ifdef __cplusplus
+#define PLUGIN_API extern "C" __declspec(dllexport)
+#else
+#define PLUGIN_API __declspec(dllexport)
+#endif
+
+// Current plugin version
+#define PLUGIN_API_VERSION 250
+
+//-----------------------------------------------------------------------------
+
+typedef struct {
+	char				*moduleString;
+	char				*moduleExtensions;
+
+} QCDModInfo;
+
+//-----------------------------------------------------------------------------
+// Services (ops) provided by the Player
+//-----------------------------------------------------------------------------
+typedef enum 
+{									//*** below returns numeric info (*buffer not used)
+
+	opGetPlayerVersion = 0,			// high-order word = major version (eg 3.01 is 3), low-order word = minor (eg 3.01 = 1)
+	opGetParentWnd = 1,				// handle to player window
+	opGetPlayerInstance = 2,		// HINSTANCE to player executable
+
+	opGetPlayerState = 9,			// get current state of the player (returns: 1 = stopped, 2 = playing, 3 = paused, 0 = failed)
+	opGetNumTracks = 10,			// number of tracks in playlist
+	opGetCurrentIndex = 11,			// index of current track in playlist (0 based)
+	opGetNextIndex = 12,			// get index of next track to play (0 based), param1 = index start index. -1 for after current
+	opGetTrackNum = 13,				// get track number of index, param1 = index of track in playlist, -1 for current
+									//		- 'track number' is the number of the track in it's respective album, as opposed to playlist number
+									//		- the 'track number' for digital files will be 1, unless they are tagged with the CDDB identifier
+
+	opGetTrackLength = 14,			// get track length, param1 = index of track in playlist, -1 for current
+									//                   param2 = 0 for seconds, 1 for milliseconds
+	opGetTime = 15,					// get time on player, param1 = 0 for time displayed, 1 for track time, 2 for playlist time
+									//					   param2 = 0 for elapsed, 1 for remaining														   
+	opGetTrackState = 16,			// get whether track is marked, param1 = index of track, -1 for current
+	opGetPlaylistNum = 17,			// get playlist number of index, param1 = index of track in playlist, -1 for current
+	opGetMediaType = 18,			// get media type of track, param1 = index if track in playlist, -1 for current
+									//		- see MediaTypes below for return values
+
+	opGetAudioInfo = 19,			// get format info about currently playing track
+									//		- param1 = 0 for samplerate, 1 for bitrate, 2 for num channels
+
+	opGetOffline = 20,				// true if client is in Offline Mode
+	opGetVisTarget = 21,			// where is vis being drawn > 0 - internal to skin, 1 - external window, 2 - full screen
+	opGetAlwaysOnTop = 22,			// true if player is set to 'Always on Top'
+	opGetRepeatState = 23,			// returns: 0 - repeat off, 1 - repeat track, 2 - repeat all
+	opGetShuffleState = 27,			// returns: 0 - shuffle off, 1 - shuffle enabled
+
+	opGetTimerState = 24,			// low-order word: 0 - track ascend, 1 - playlist ascend, 2 - track descend, 3 - playlist descend
+									// hi-order word: 1 if 'show hours' is set, else 0
+
+	opGetVolume = 25,				// get master volume level (0 - 100), param1: 0 = combined, 1 = left, 2 = right
+	opSetVolume = 26,				// set master volume level, param1: vol level 0 - 100, param2: balance (-100 left, 0 center, 100 right)
+
+	opGetIndexFromPLNum = 28,		// get index from playlist number, param1 = playlist number
+
+	opGetChildWnd = 30,				// handle to the draggable window extension (only available on some skins) 
+	opGetExtVisWnd = 31,			// handle to the external visual window
+	opGetMusicBrowserWnd = 32,		// handle to the music browser window 
+	opGetSkinPreviewWnd = 33,		// handle to the skin preview window 
+	opGetPropertiesWnd = 34,		// handle to the player properties window 
+	opGetExtInfoWnd = 35,			// handle to the extended information window 
+	opGetAboutWnd = 36,				// handle to the about window 
+	opGetSegmentsWnd = 37,			// handle to the segments window 
+	opGetEQPresetsWnd = 38,			// handle to the EQ presets window 
+
+	opGetVisDimensions = 50,		// gets the width and height of visual window (param1 = -1 current vis window, 0 internal vis, 1 external vis, 2 full screen)
+									//		returns: HEIGHT in high word, WIDTH in low word 
+
+	opGetQueriesComplete = 60,		// get status on whether all tracks in playlist have been queryied for their info
+
+									// playlist manipulation
+	opDeleteIndex = 90,				// delete index from playlist (param1 = index)
+	opSelectIndex = 91,				// mark index as selected (param1 = index, param2 = 1 - set, 0 - unset)
+	opBlockIndex = 92,				// mark index as blocked (param1 = index, param2 = 1 - set, 0 - unset)
+
+	opGetMediaInfo = 99,			// get the CddbDisc object for the index specified, param1 = index of track, -1 for current
+									//		param2 = pointer to integer that receives track value
+									//		returns: pointer to CddbDisc object. Do not release or deallocate this pointer
+
+
+   									//*** below returns string info in buffer, param1 = size of buffer
+   									//*** returns 1 on success, 0 on failure
+
+	opGetTrackName = 100,			// get track name, param2 = index of track in playlist, -1 for current
+	opGetArtistName = 101,			// get artist name, param2 = index of track in playlist, -1 for current
+	opGetDiscName = 102,			// get disc name, param2 = index of track in playlist, -1 for current
+
+	opGetTrackFile = 103,			// file name of track in playlist, param2 = index of track in playlist, -1 for current
+	opGetSkinName = 104,			// get current skin name
+
+	opGetPluginFolder = 105,		// get current plugin folder
+	opGetPluginSettingsFile = 106,	// get settings file (plugins.ini) that plugin should save settings to
+	opGetPluginCacheFile = 107,		// get file that describes plugin validity, functions and names
+	opGetPlayerSettingsFile = 108,	// get settings file (qcd.ini) that player saves it settings to (should use for read-only)
+
+	opGetMusicFolder = 110,			// get current music folder
+	opGetPlaylistFolder = 111,		// get current playlist folder
+	opGetSkinFolder = 112,			// get current skin folder
+	opGetCDDBCacheFolder = 113,		// get current folder for CDDB cached info
+
+	opGetCurrentPlaylist = 114,		// get full pathname of playlist currently loaded 
+
+	opGetMediaID = 115,				// get media identifier, param2 = index of track in playlist, -1 for current
+									//		- for CD's it's the TOC - for anything else, right now it's 0      
+
+	opGetSupportedExtensions = 116,	// get file extensions supported by the player, param2 = 0 - get all extensions, 1 - get registered extensions
+									//		- returned extensions will be colon delimited
+
+
+   									//*** below buffer points to struct or other object
+   									//*** returns 1 on success, 0 on failure
+
+	opShowMainMenu = 120,			// Display Main QCD Menu (buffer = POINT* - location to display menu)
+	opGetMainMenu = 121,			// Returns copy of HMENU handle to QCD Menu (must use DestroyMenu on handle when complete)
+
+	opShowQuickTrack = 125,			// Display QuickTrack Menu (buffer = POINT* - location to display menu)
+
+	opGetEQVals = 200,				// get current EQ levels/on/off (buffer = EQInfo*)
+	opSetEQVals = 201,				// set EQ levels/on/off (buffer = EQInfo*)
+
+	opGetProxyInfo = 202,			// get proxy info (buffer = ProxyInfo*), returns 0 if proxy not in use
+
+
+									//*** below returns numeric info, buffer used
+
+	opGetIndexFromFilename = 210,	// get the index of a file that exists in current playlist (buffer = full path of file),
+									//		param1 = startindex (index to start searching on)
+                                    //		returns -1 if file not in playlist
+
+
+									//*** below send information to player
+									//*** returns 1 on success, 0 on failure
+
+	opSetStatusMessage = 1000,		// display message in status area (buffer = msg buffer (null term), param1 = text flags (see below))
+
+	opSetBrowserUrl = 1001,			// set music browser URL (buffer = url (null term))
+	                                //		null url buffer - closes browser
+	                                //		param1 = 0 - normal, 1 - force open
+
+	opSetAudioInfo = 1002,			// set the current music bitrate/khz (buffer = AudioInfo*, param1 = size of AudioInfo)
+
+	opSetTrackAlbum = 1003,			// update track ablum name (buffer = album (null term), param1 = (string ptr)file name), param2 = MediaTypes
+	opSetTrackTitle = 1004,			// update track title (buffer = title (null term), param1 = (string ptr)file name), param2 = MediaTypes
+	opSetTrackArtist = 1005,		// update track artist name (buffer = artist (null term), param1 = (string ptr)file name), param2 = MediaTypes
+
+	opSetTrackExtents = 1007,		// update track TrackExtents info (buffer = &TrackExtents), param1 = (string ptr)file name)
+	opSetTrackSeekable = 1008,		// update track seekable flag (buffer = (string ptr)file name), param1 = TRUE/FALSE
+	opSetPlayNext = 1009,			// set the next index to be played (buffer = NULL, param1 = index, index = -1 unsets playnext)
+	opSetIndexFilename = 1010,		// updates the filename (or stream) that an index in the current playlist refers to, buffer = new filename, param1 = index
+
+	opSetPlaylist = 1006,			// clear playlist, add files to playlist or reset playlist with new files 
+									//		buffer = file list (each file in quotes, string null terminated) Eg; buffer="\"file1.mp3\" \"file2.mp3\"\0" - NULL to clear playlist
+									//		param1 = (string ptr)originating path (can be NULL if paths included with files) 
+									//		param2 = 1 - clear playlist flag, 2 - enqueue to top
+
+	opInsertPlaylist = 1011,		// insert tracks into playlist 
+									//		buffer = file list (each file in quotes, string null terminated) Eg; buffer="\"file1.mp3\" \"file2.mp3\"\0"
+									//		param1 = (string ptr)originating path (can be NULL if paths included with files) 
+									//		param2 = index location to insert tracks (-1 to insert at end)
+
+	opMovePlaylistTrack = 1012,		// param1 = index of track to move, param2 = destination index (move shifts tracks between param1 and param2)
+	opSwapPlaylistTracks = 1013,	// param1 = index of first track, param2 = index of second track (swap only switches indecies param1 and param2)
+
+
+
+	opSetSeekPosition = 1100,		// seek to position during playback
+									//		buffer = NULL, param1 = position
+									//		param2 = 0 - position is in seconds, 1 - position is in milliseconds, 2 - position is in percent (use (float)param1))
+
+
+									//*** below configures custom plugin menu items for the 'plugin menu'
+									//*** Player will call plugin's configure routine with menu value when menu item selected
+									//*** returns 1 on success, 0 on failure
+
+	opSetPluginMenuItem = 2000,		// buffer = HINSTANCE of plugin, param1 = item id, param2 = (string ptr)string to display
+									//		- set param2 = 0 to remove item id from menu
+									//		- set param1 = 0 and param2 = 0 to remove whole menu
+	opSetPluginMenuState = 2001,	// buffer = HINSTANCE of plugin, param1 = item id, param2 = menu flags (same as windows menu flags - eg: MF_CHECKED)
+
+
+									//*** other services
+
+	opSafeWait = 10000				// plugin's can use this to wait on an object without worrying about deadlocking the player.
+									// this should only be called by the thread that enters the plugin, not by any plugin-created threads
+
+} PluginServiceOp;
+
+//-----------------------------------------------------------------------------
+// Info services api provided by the Player, called by Plugin.
+//-----------------------------------------------------------------------------
+typedef long (*PluginServiceFunc)(PluginServiceOp op, void *buffer, long param1, long param2);
+
+
+//-----------------------------------------------------------------------------
+typedef struct				// for Output Plugin Write callback
+{
+	void	*data;			// pointer to valid data
+	int		bytelen;		// length of data pointed to by 'data' in bytes
+	UINT	numsamples;		// number of samples represented by 'data'
+	UINT	bps;			// bits per sample
+	UINT	nch;			// number of channels
+	UINT	srate;			// sample rate
+
+	UINT	markerstart;	// Marker position at start of data (marker is time value of data) 
+							// (set to WAVE_VIS_DATA_ONLY to not have data sent to output plugins)
+	UINT	markerend;		// Marker position at end of data (not currently used, set to 0)
+} WriteDataStruct;
+
+//-----------------------------------------------------------------------------
+typedef struct			// for GetTrackExtents Input Plugin callback
+{
+	UINT track;			// for CD's, set the track number. Otherwise set to 1.
+	UINT start;			// for CD's or media that doesn't start at the beginning 
+						// of the file, set to start position. Otherwise set to 0.
+	UINT end;			// set to end position of media.
+	UINT unitpersec;	// whatever units are being used for this media, how many
+						// of them per second. 
+						// (Note: ((end - start) / unitpersecond) = file length
+	UINT bytesize;		// size of file in bytes (if applicable, otherwise 0).
+} TrackExtents;
+
+//-----------------------------------------------------------------------------
+typedef struct			// for opSetAudioInfo service
+{		
+    long struct_size;	// sizeof(AudioInfo)
+    long level;			// MPEG level (1 for MPEG1, 2 for MPEG2, 3 for MPEG2.5, 7 for MPEGpro)
+    long layer;			// and layer (1, 2 or 3)
+    long bitrate;		// audio bitrate in bits per second
+    long frequency;		// audio freq in Hz
+    long mode;			// 0 for stereo, 1 for joint-stereo, 2 for dual-channel, 3 for mono, 4 for multi-channel
+} AudioInfo;
+
+//-----------------------------------------------------------------------------
+// Equalizer Info
+//-----------------------------------------------------------------------------
+typedef struct			// for coming QCD version
+{
+	long struct_size;	// sizeof(EQInfo)
+	char enabled;		
+	char preamp;		// -128 to 127, 0 is even
+	char bands[10];		// -128 to 127, 0 is even
+} EQInfo;
+
+//-----------------------------------------------------------------------------
+typedef struct
+{
+	long struct_size;	// sizeof(ProxyInfo)
+	char hostname[200];
+	long port;
+	char username[100];
+	char password[100];
+} ProxyInfo;
+
+//-----------------------------------------------------------------------------
+typedef enum			// for MediaInfo.mediaType
+{ 
+	UNKNOWN_MEDIA = 0,
+	CD_AUDIO_MEDIA = 1,
+	DIGITAL_FILE_MEDIA = 2,
+	DIGITAL_STREAM_MEDIA = 3
+} MediaTypes;
+
+//-----------------------------------------------------------------------------
+#define MAX_TOC_LEN				2048
+typedef struct
+{
+	// media descriptors
+	CHAR		mediaFile[MAX_PATH];
+	MediaTypes	mediaType;
+
+	// cd audio media info
+	CHAR		cd_mediaTOC[MAX_TOC_LEN];
+	int			cd_numTracks;
+	int			cd_hasAudio;
+
+	// operation info
+	int			op_canSeek;
+
+	// not used
+	int			reserved[4];
+
+} MediaInfo;
+
+
+//-----------------------------------------------------------------------------
+// When subclassing the parent window, a plugin can watch for these messages
+// to react to events going on between plugins and player
+// DO NOT SEND THESE MESSAGES - can only watch for them
+
+// Plugin to Player Notifiers
+#define WM_PN_POSITIONUPDATE	(WM_USER + 100)	// playback progress updated
+#define WM_PN_PLAYSTARTED		(WM_USER + 101)	// playback has started
+#define WM_PN_PLAYSTOPPED		(WM_USER + 102) // playback has stopped by user
+#define WM_PN_PLAYPAUSED		(WM_USER + 103) // playback has been paused
+#define WM_PN_PLAYDONE			(WM_USER + 104) // playback has finished (track completed)
+#define WM_PN_MEDIAEJECTED		(WM_USER + 105) // a CD was ejected (lParam = (LPCSTR)medianame)
+#define WM_PN_MEDIAINSERTED		(WM_USER + 106) // a CD was inserted (lParam = (LPCSTR)medianame)
+#define WM_PN_INFOCHANGED		(WM_USER + 107) // track information was updated (lParam = (LPCSTR)medianame)
+#define WM_PN_TRACKCHANGED		(WM_USER + 109)	// current track playing has changed (relevant from CD plugin) (lParam = (LPCSTR)medianame)
+
+// Player to Plugin Notifiers
+#define WM_PN_PLAYLISTCHANGED	(WM_USER + 200) // playlist has changed in some way (add, delete, sort, shuffle, drag-n-drop, etc...)
+
+// For intercepting main menu display
+// (so you can get handle, modify, and display your own)
+#define WM_SHOWMAINMENU			(WM_USER + 20)
+
+//-----------------------------------------------------------------------------
+// To shutdown player, send this command
+#define WM_SHUTDOWN				(WM_USER + 5)
+
+//-----------------------------------------------------------------------------
+// opSetStatusMessage textflags
+#define TEXT_DEFAULT		0x0		// message scrolls by in status window
+#define TEXT_TOOLTIP		0x1		// message acts as tooltip in status window
+#define TEXT_URGENT			0x2		// forces message to appear even if no status window (using msg box)
+#define TEXT_HOLD			0x4		// tooltip message stays up (no fade out)
+
+
+#endif //QCDMODDEFS_H
\ No newline at end of file
--- /dev/null
+++ b/plugins/QCDMp4/QCDModEncode.h
@@ -1,0 +1,76 @@
+//-----------------------------------------------------------------------------
+//
+// File:	QCDModEncode.h
+//
+// About:	Encode plugin module interface.  This file is published with the 
+//			Encode plugin SDK.
+//
+// Authors:	Written by Paul Quinn
+//
+// Copyright:
+//
+//	QCD multimedia player application Software Development Kit Release 1.0.
+//
+//	Copyright (C) 1997-2002 Quinnware
+//
+//	This code is free.  If you redistribute it in any form, leave this notice 
+//	here.
+//
+//	This program is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef QCDMODENCODE_H
+#define QCDMODENCODE_H
+
+#include "QCDModDefs.h"
+
+// name of the DLL export for encode plugins
+#define ENCODEDLL_ENTRY_POINT	QEncodeModule
+
+// Stop will receive one of these flags
+#define STOPFLAG_FORCESTOP		0
+#define STOPFLAG_PLAYDONE		1
+
+// pause flags
+#define PAUSE_DISABLED			0	// Pause() call is to unpause playback
+#define PAUSE_ENABLED			1	// Pause() call is to pause playback
+
+//-----------------------------------------------------------------------------
+
+typedef struct 
+{
+	UINT				size;			// size of init structure
+	UINT				version;		// plugin structure version (set to PLUGIN_API_VERSION)
+	PluginServiceFunc	Service;		// player supplied services callback
+
+	struct
+	{
+		void *dummy;
+		void (*PositionUpdate)(UINT marker);
+		void *Reserved[2];
+	} toPlayer;
+
+	struct 
+	{
+		BOOL (*Open)(LPCSTR, WAVEFORMATEX *wf);
+		BOOL (*Write)(WriteDataStruct*);
+		BOOL (*Flush)(UINT marker);
+		BOOL (*Stop)(int flags);
+		BOOL (*Pause)(int flags);
+		BOOL (*Drain)(int flags);
+		void (*ShutDown)(int flags);
+
+		void (*Configure)(int flags);
+		void (*About)(int flags);
+
+		BOOL (*SetVolume)(int levelleft, int levelright, int flags);
+		BOOL (*GetCurrentPosition)(UINT *position, int flags);
+		BOOL (*DrainCancel)(int flags);
+		void *Reserved[8];
+	} toModule;
+} QCDModInitEnc;
+
+#endif //QCDMODENCODE_H
\ No newline at end of file
--- /dev/null
+++ b/plugins/QCDMp4/QCDModInput.h
@@ -1,0 +1,117 @@
+//-----------------------------------------------------------------------------
+//
+// File:	QCDModInput.h
+//
+// About:	Input plugin module interface.  This file is published with the 
+//			Input plugin SDK.
+//
+// Authors:	Written by Paul Quinn and Richard Carlson.
+//
+// Copyright:
+//
+//	QCD multimedia player application Software Development Kit Release 1.0.
+//
+//	Copyright (C) 1997-2002 Quinnware
+//
+//	This code is free.  If you redistribute it in any form, leave this notice 
+//	here.
+//
+//	This program is distributed in the hope that it will be useful,
+//	but WITHOUT ANY WARRANTY; without even the implied warranty of
+//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef QCDMODINPUT_H
+#define QCDMODINPUT_H
+
+#include "QCDModDefs.h"
+
+// name of the DLL export for input plugins
+#define INPUTDLL_ENTRY_POINT		QInputModule2	// (updated plugin api version 240+)
+
+// media insert flags
+#define MEDIAINSERT_PLAY			0x1
+#define MEDIAINSERT_ADDTRACKS		0x2
+#define MEDIAINSERT_ADDSEGMENTS		0x4
+#define MEDIAINSERT_CLEARPLAYLIST	0x8
+
+// Stop will receive one of these flags (pass to output plugin's stop())
+#define STOPFLAG_FORCESTOP			0	// stop occuring due to user action or other event
+#define STOPFLAG_PLAYDONE			1	// stop occuring due to playlist completion
+
+// play flags
+#define PLAYFLAG_PLAYBACK			0x0
+#define PLAYFLAG_ENCODING			0x1
+#define PLAYFLAG_SEEKING			0x2
+
+// Wave Marker flags
+#define WAVE_VIS_DATA_ONLY			-1	// set to WaveDataStruct.markerstart in OutputWrite() call have data only go to vis 
+										// and not to output plugin
+// pause flags
+#define PAUSE_DISABLED				0	// Pause() call is to unpause playback
+#define PAUSE_ENABLED				1	// Pause() call is to pause playback
+
+//-----------------------------------------------------------------------------
+// Input Module
+//-----------------------------------------------------------------------------
+typedef struct 
+{
+	unsigned int		size;			// size of init structure
+	unsigned int		version;		// plugin structure version (set to PLUGIN_API_VERSION)
+	PluginServiceFunc	Service;		// player supplied services callback
+
+	struct
+	{
+		void (*PositionUpdate)(unsigned int position);
+		void (*PlayStopped)(const char* medianame);					// notify player of play stop
+		void (*PlayStarted)(const char* medianame);					// notify player of play start
+		void (*PlayPaused)(const char* medianame, int flags);		// notify player of play pause
+		void (*PlayDone)(const char* medianame);					// notify player when play done
+		void (*PlayTrackChanged)(const char* medianame);			// notify player when playing track changes (cd audio relevant only)
+		void (*MediaEjected)(const char* medianame);				// notify player of media eject (cd audio relevant)
+		void (*MediaInserted)(const char* medianame, int flags);	// notify player of media insert (cd audio relevant)
+
+																	// output plugin calls
+		int  (*OutputOpen)(const char* medianame, WAVEFORMATEX*);	// open output for wave data
+		int  (*OutputWrite)(WriteDataStruct*);						// send PCM audio data to output 
+																		// (blocks until write completes, thus if output is paused can 
+																		// block until unpaused)
+		int  (*OutputDrain)(int flags);								// wait for all output to complete (blocking)
+		int  (*OutputDrainCancel)(int flags);						// break a drain in progress
+		int  (*OutputFlush)(unsigned int marker);						// flush output upto marker
+		int  (*OutputStop)(int flags);								// stop output
+		int  (*OutputPause)(int flags);								// pause output
+
+		int  (*OutputSetVol)(int levelleft, int levelright, int flags);
+		int  (*OutputGetCurrentPosition)(unsigned int *position, int flags);
+
+		void *Reserved[10];
+	} toPlayer;
+
+	struct 
+	{
+		int  (*Initialize)(QCDModInfo *modInfo, int flags);			// initialize plugin
+		void (*ShutDown)(int flags);								// shutdown plugin
+
+		int  (*Play)(const char* medianame, int playfrom, int playto, int flags);	// start playing playfrom->playto
+		int  (*Stop)(const char* medianame, int flags);				// stop playing
+		int  (*Pause)(const char* medianame, int flags);			// pause playback
+		int  (*Eject)(const char* medianame, int flags);			// eject media
+		void (*SetEQ)(EQInfo*);										// update EQ settings
+
+		int  (*GetMediaSupported)(const char* medianame, MediaInfo *mediaInfo);			// does plugin support medianame (and provides info for media)
+		int  (*GetTrackExtents)(const char* medianame, TrackExtents *ext, int flags);	// get media start, end & units
+		int  (*GetCurrentPosition)(const char* medianame, long *track, long *offset);	// get playing media's position
+
+		void (*Configure)(int flags);									// launch configuration
+		void (*About)(int flags);										// launch about info
+
+		void (*SetVolume)(int levelleft, int levelright, int flags);	// level 0 - 100
+
+		void *Reserved[10];
+	} toModule;
+
+} QCDModInitIn;
+
+#endif //QCDMODINPUT_H
--- /dev/null
+++ b/plugins/QCDMp4/QCDMp4.c
@@ -1,0 +1,1114 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: QCDMp4.c,v 1.1 2003/04/28 19:07:57 menno Exp $
+**/
+
+//#define DEBUG_OUTPUT
+#include "QCDInputDLL.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include <shellapi.h>
+#include <stdlib.h>
+#include <math.h>
+#include <faad.h>
+#include <mp4.h>
+
+#include "resource.h"
+#include "utils.h"
+#include "config.h"
+#include "aacinfo.h"
+
+static long priority_table[] = {
+    0,
+    THREAD_PRIORITY_HIGHEST,
+    THREAD_PRIORITY_ABOVE_NORMAL,
+    THREAD_PRIORITY_NORMAL,
+    THREAD_PRIORITY_BELOW_NORMAL,
+    THREAD_PRIORITY_LOWEST
+};
+static int res_id_table[] = {
+    IDC_16BITS,
+    IDC_24BITS,
+    IDC_32BITS,
+    0,
+    IDC_16BITS_DITHERED
+};
+static int res_table[] = {
+    16,
+    24,
+    32,
+    0,
+    16
+};
+
+typedef struct state
+{
+    /* general stuff */
+    faacDecHandle hDecoder;
+    int samplerate;
+    unsigned char channels;
+    int decode_pos_ms; // current decoding position, in milliseconds
+    int paused; // are we paused?
+    int seek_needed; // if != -1, it is the point that the decode thread should seek to, in ms.
+    char filename[_MAX_PATH];
+    int filetype; /* 0: MP4; 1: AAC */
+    int last_frame;
+
+    /* MP4 stuff */
+    MP4FileHandle mp4file;
+    int mp4track;
+    MP4SampleId numSamples;
+    MP4SampleId sampleId;
+
+    /* AAC stuff */
+    FILE *aacfile;
+    long filesize;
+    long bytes_read;
+    long bytes_into_buffer;
+    long bytes_consumed;
+    unsigned char *buffer;
+    long seconds;
+//    faadAACInfo aacInfo;
+} state;
+
+static state mp4state;
+
+HINSTANCE		hInstance;
+HWND			hwndPlayer, hwndConfig, hwndAbout;
+QCDModInitIn	sQCDCallbacks, *QCDCallbacks;
+BOOL			oldAPIs = 0;
+
+static int killPlayThread;
+HANDLE play_thread_handle = INVALID_HANDLE_VALUE; // the handle to the decode thread
+
+/* Function definitions */
+DWORD WINAPI MP4PlayThread(void *b); // the decode thread procedure
+DWORD WINAPI AACPlayThread(void *b); // the decode thread procedure
+
+#ifdef DEBUG_OUTPUT
+void in_mp4_DebugOutput(char *message)
+{
+    char s[1024];
+
+    sprintf(s, "%s: %s", mp4state.filename, message);
+    MessageBox(NULL, s, "Debug Message", MB_OK);
+}
+#endif
+
+static void show_error(HWND hwnd, char *message, ...)
+{
+    if (m_show_errors)
+        MessageBox(hwnd, message, "Error", MB_OK);
+}
+
+void config_read()
+{
+    char priority[10];
+    char resolution[10];
+    char show_errors[10];
+    char use_for_aac[10];
+
+    strcpy(show_errors, "1");
+    strcpy(priority, "3");
+    strcpy(resolution, "0");
+    strcpy(use_for_aac, "1");
+
+    RS(priority);
+	RS(resolution);
+	RS(show_errors);
+    RS(use_for_aac);
+
+    m_priority = atoi(priority);
+    m_resolution = atoi(resolution);
+    m_show_errors = atoi(show_errors);
+    m_use_for_aac = atoi(use_for_aac);
+}
+
+void config_write()
+{
+    char priority[10];
+    char resolution[10];
+    char show_errors[10];
+    char use_for_aac[10];
+
+    itoa(m_priority, priority, 10);
+    itoa(m_resolution, resolution, 10);
+    itoa(m_show_errors, show_errors, 10);
+    itoa(m_use_for_aac, use_for_aac, 10);
+
+    WS(priority);
+	WS(resolution);
+	WS(show_errors);
+	WS(use_for_aac);
+}
+
+//-----------------------------------------------------------------------------
+
+int WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, LPVOID pRes)
+{
+	if (fdwReason == DLL_PROCESS_ATTACH)
+		hInstance = hInst;
+	return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+//old entrypoint api
+PLUGIN_API BOOL QInputModule(QCDModInitIn *ModInit, QCDModInfo *ModInfo)
+{
+	ModInit->version					= PLUGIN_API_VERSION;
+	ModInit->toModule.ShutDown			= ShutDown;
+	ModInit->toModule.GetTrackExtents	= GetTrackExtents;
+	ModInit->toModule.GetMediaSupported = GetMediaSupported;
+	ModInit->toModule.GetCurrentPosition= GetCurrentPosition;
+	ModInit->toModule.Play				= Play;
+	ModInit->toModule.Pause				= Pause;
+	ModInit->toModule.Stop				= Stop;
+	ModInit->toModule.SetVolume			= SetVolume;
+	ModInit->toModule.About				= About;
+	ModInit->toModule.Configure			= Configure;
+	QCDCallbacks = ModInit;
+
+	/* read config */
+	QCDCallbacks->Service(opGetPluginSettingsFile, INI_FILE, MAX_PATH, 0);
+	config_read();
+
+	ModInfo->moduleString = "MPEG-4 General Audio Plugin v1.0";
+	ModInfo->moduleExtensions = m_use_for_aac ? "MP4:AAC" : "MP4";
+
+	hwndPlayer = (HWND)ModInit->Service(opGetParentWnd, 0, 0, 0);
+	mp4state.filename[0] = 0;
+	mp4state.seek_needed = -1;
+	mp4state.paused = 0;
+	play_thread_handle = INVALID_HANDLE_VALUE;
+
+	oldAPIs = 1;
+
+	return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+
+PLUGIN_API QCDModInitIn* INPUTDLL_ENTRY_POINT(QCDModInitIn *ModInit, QCDModInfo *ModInfo)
+{
+	sQCDCallbacks.version						= PLUGIN_API_VERSION;
+	sQCDCallbacks.toModule.Initialize			= Initialize;
+	sQCDCallbacks.toModule.ShutDown				= ShutDown;
+	sQCDCallbacks.toModule.GetTrackExtents		= GetTrackExtents;
+	sQCDCallbacks.toModule.GetMediaSupported	= GetMediaSupported;
+	sQCDCallbacks.toModule.GetCurrentPosition	= GetCurrentPosition;
+	sQCDCallbacks.toModule.Play					= Play;
+	sQCDCallbacks.toModule.Pause				= Pause;
+	sQCDCallbacks.toModule.Stop					= Stop;
+	sQCDCallbacks.toModule.SetVolume			= SetVolume;
+	sQCDCallbacks.toModule.About				= About;
+	sQCDCallbacks.toModule.Configure			= Configure;
+
+	QCDCallbacks = &sQCDCallbacks;
+	return &sQCDCallbacks;
+}
+
+//----------------------------------------------------------------------------
+
+int Initialize(QCDModInfo *ModInfo, int flags)
+{
+	hwndPlayer = (HWND)QCDCallbacks->Service(opGetParentWnd, 0, 0, 0);
+
+	mp4state.filename[0] = 0;
+	mp4state.seek_needed = -1;
+	mp4state.paused = 0;
+	play_thread_handle = INVALID_HANDLE_VALUE;
+
+	/* read config */
+	QCDCallbacks->Service(opGetPluginSettingsFile, INI_FILE, MAX_PATH, 0);
+    config_read();
+
+	ModInfo->moduleString = "MPEG-4 General Audio Plugin v1.0";
+	ModInfo->moduleExtensions = m_use_for_aac ? "MP4:AAC" : "MP4";
+
+	// insert menu item into plugin menu
+//	QCDCallbacks->Service(opSetPluginMenuItem, hInstance, IDD_CONFIG, (long)"Mp4 Plug-in");
+
+	return TRUE;
+}
+
+//----------------------------------------------------------------------------
+
+void ShutDown(int flags) 
+{
+	Stop(mp4state.filename, STOPFLAG_FORCESTOP);
+
+	// delete the inserted plugin menu
+//	QCDCallbacks->Service(opSetPluginMenuItem, hInstance, 0, 0);
+}
+
+//-----------------------------------------------------------------------------
+
+int GetMediaSupported(const char* medianame, MediaInfo *mediaInfo) 
+{
+	char *ch = strrchr(medianame, '.');
+
+	if (!medianame || !*medianame)
+		return FALSE;
+
+	if(!ch)
+		return (lstrlen(medianame) > 2); // no extension defaults to me (if not drive letter)
+
+   /* Finally fixed */
+    if(StringComp(ch, ".mp4", 4) == 0)
+    {
+		mediaInfo->mediaType = DIGITAL_FILE_MEDIA;
+		mediaInfo->op_canSeek = TRUE;
+		mp4state.filetype = 0;
+		return TRUE;
+	}
+	else if(StringComp(ch, ".aac", 4) ==0)
+	{
+		mediaInfo->mediaType = DIGITAL_FILE_MEDIA;
+		mediaInfo->op_canSeek = FALSE;
+		mp4state.filetype = 1;
+		return TRUE;
+	}
+	else
+		return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+
+int getsonglength(char *fn)
+{
+    long msDuration = 0;
+
+    if(StringComp(fn + strlen(fn) - 3, "MP4", 3) == 0)
+    {
+        int track;
+        MP4Duration length;
+        MP4FileHandle file;
+
+        file = MP4Read(fn, 0);
+        if (!file)
+            return 0;
+
+        if ((track = GetAACTrack(file)) < 0)
+        {
+            MP4Close(file);
+            return -1;
+        }
+
+        length = MP4GetTrackDuration(file, track);
+
+        msDuration = MP4ConvertFromTrackDuration(file, track,
+            length, MP4_MSECS_TIME_SCALE);
+
+        MP4Close(file);
+
+        return msDuration;
+    } 
+	else 
+	{
+//        faadAACInfo aacInfo;
+//        get_AAC_format(fn, &aacInfo);
+
+//        return aacInfo.length;
+        return 0;
+    }
+}
+
+int GetTrackExtents(const char* medianame, TrackExtents *ext, int flags)
+{
+	ext->track = 1;
+	ext->start = 0;
+	if( (ext->end = getsonglength(medianame)) < 0 )
+		return FALSE;
+	ext->bytesize = 0;
+	ext->unitpersec = 1000;
+
+	return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+
+BOOL CALLBACK config_dialog_proc(HWND hwndDlg, UINT message,
+                                 WPARAM wParam, LPARAM lParam)
+{
+    int i;
+
+    switch (message) 
+	{
+    case WM_INITDIALOG:
+		SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_SETRANGE, TRUE, MAKELONG(1,5)); 
+		SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_SETPOS, TRUE, m_priority);
+        SendMessage(GetDlgItem(hwndDlg, res_id_table[m_resolution]), BM_SETCHECK, BST_CHECKED, 0);
+        if (m_show_errors)
+            SendMessage(GetDlgItem(hwndDlg, IDC_ERROR), BM_SETCHECK, BST_CHECKED, 0);
+        if (m_use_for_aac)
+            SendMessage(GetDlgItem(hwndDlg, IDC_USEFORAAC), BM_SETCHECK, BST_CHECKED, 0);
+        return TRUE;
+
+    case WM_COMMAND:
+        switch (LOWORD(wParam)) 
+		{
+        case IDOK:
+            m_show_errors = SendMessage(GetDlgItem(hwndDlg, IDC_ERROR), BM_GETCHECK, 0, 0);
+            m_use_for_aac = SendMessage(GetDlgItem(hwndDlg, IDC_USEFORAAC), BM_GETCHECK, 0, 0);
+            m_priority = SendMessage(GetDlgItem(hwndDlg, IDC_PRIORITY), TBM_GETPOS, 0, 0);
+            for (i = 0; i < 5; i++)
+            {
+                if (SendMessage(GetDlgItem(hwndDlg, res_id_table[i]), BM_GETCHECK, 0, 0))
+                {
+                    m_resolution = i;
+                    break;
+                }
+            }
+
+            /* save config */
+            config_write();
+        case IDCANCEL:
+            DestroyWindow(hwndDlg);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+void Configure(int flags)
+{
+	if(!IsWindow(hwndConfig))
+		hwndConfig = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_CONFIG_INPUT), hwndPlayer, config_dialog_proc);
+	ShowWindow(hwndConfig, SW_SHOWNORMAL);
+}
+
+//-----------------------------------------------------------------------------
+// proc of "About Dialog"
+INT_PTR CALLBACK about_dialog_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+	static RECT rcLOGO, rcMail1, rcMail2/*, rcMail3*/;
+	POINT ptMouse;
+	static char szPluginVer[] = "QCD MP4 Input Plug-in v1.0\nCompiled on " __TIME__ ", " __DATE__;
+	static char szFLACVer[] = "Using: FAAD2 v "FAAD2_VERSION" by";
+
+	switch (uMsg)
+	{
+	case WM_INITDIALOG:
+	case WM_MOVE:
+		GetWindowRect(GetDlgItem(hwndDlg, IDC_LOGO), &rcLOGO);
+		GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL1), &rcMail1);
+		GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL2), &rcMail2);
+//		GetWindowRect(GetDlgItem(hwndDlg, IDC_MAIL2), &rcMail3);
+
+		SetDlgItemText(hwndDlg, IDC_PLUGINVER, szPluginVer);
+		SetDlgItemText(hwndDlg, IDC_FAADVER, szFLACVer);
+		
+		return TRUE;
+	case WM_MOUSEMOVE:
+		ptMouse.x = LOWORD(lParam);
+		ptMouse.y = HIWORD(lParam);
+		ClientToScreen(hwndDlg, &ptMouse);
+		if( (ptMouse.x >= rcLOGO.left && ptMouse.x <= rcLOGO.right && 
+			ptMouse.y >= rcLOGO.top && ptMouse.y<= rcLOGO.bottom) 
+			||
+			(ptMouse.x >= rcMail1.left && ptMouse.x <= rcMail1.right && 
+			ptMouse.y >= rcMail1.top && ptMouse.y<= rcMail1.bottom) 
+			||
+			(ptMouse.x >= rcMail2.left && ptMouse.x <= rcMail2.right && 
+			ptMouse.y >= rcMail2.top && ptMouse.y<= rcMail2.bottom) 
+/*			||
+			(ptMouse.x >= rcMail3.left && ptMouse.x <= rcMail3.right && 
+			ptMouse.y >= rcMail3.top && ptMouse.y<= rcMail3.bottom)*/ )
+			SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(32649)));
+		else
+			SetCursor(LoadCursor(NULL, IDC_ARROW));
+
+		return TRUE;
+	case WM_LBUTTONDOWN:
+		ptMouse.x = LOWORD(lParam);
+		ptMouse.y = HIWORD(lParam);
+		ClientToScreen(hwndDlg, &ptMouse);
+		if(ptMouse.x >= rcLOGO.left && ptMouse.x <= rcLOGO.right && 
+			ptMouse.y >= rcLOGO.top && ptMouse.y<= rcLOGO.bottom)
+			ShellExecute(0, NULL, "http://www.audiocoding.com", NULL,NULL, SW_NORMAL);
+		else if(ptMouse.x >= rcMail1.left && ptMouse.x <= rcMail1.right && 
+			ptMouse.y >= rcMail1.top && ptMouse.y<= rcMail1.bottom)
+			ShellExecute(0, NULL, "mailto:[email protected]", NULL,NULL, SW_NORMAL);
+		else if(ptMouse.x >= rcMail2.left && ptMouse.x <= rcMail2.right && 
+			ptMouse.y >= rcMail2.top && ptMouse.y<= rcMail2.bottom)
+			ShellExecute(0, NULL, "mailto:[email protected]", NULL,NULL, SW_NORMAL);
+/*		else if(ptMouse.x >= rcMail3.left && ptMouse.x <= rcMail3.right && 
+			ptMouse.y >= rcMail3.top && ptMouse.y<= rcMail3.bottom)
+			ShellExecute(0, NULL, "I don't know", NULL,NULL, SW_NORMAL);
+*/
+		return TRUE;
+	case WM_COMMAND:
+		switch(LOWORD(wParam))
+		{
+		case IDOK:
+		default:
+			DestroyWindow(hwndDlg);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+void About(int flags)
+{
+	if(!IsWindow(hwndAbout))
+		hwndAbout = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_ABOUT), hwndPlayer, about_dialog_proc); 
+	ShowWindow(hwndAbout, SW_SHOWNORMAL);
+}
+
+//-----------------------------------------------------------------------------
+
+int Play(const char* medianame, int playfrom, int playto, int flags)
+{
+	static WAVEFORMATEX wf;
+
+	if(flags == PLAYFLAG_ENCODING)
+	{
+		if(QCDCallbacks->toPlayer.OutputOpen(medianame, &wf))
+			Stop(medianame, STOPFLAG_FORCESTOP);
+		return FALSE;
+	}
+
+	if(stricmp(mp4state.filename, medianame) != 0)
+	{
+		sQCDCallbacks.toPlayer.OutputStop(STOPFLAG_PLAYDONE);
+		Stop(mp4state.filename, STOPFLAG_PLAYDONE);
+	}
+
+	if(mp4state.paused)
+	{
+		// Update the player controls to reflect the new unpaused state
+		sQCDCallbacks.toPlayer.OutputPause(0);
+		
+		Pause(medianame, PAUSE_DISABLED);
+		
+		if (playfrom >= 0)
+			mp4state.seek_needed = playfrom;
+	}
+	else if(play_thread_handle != INVALID_HANDLE_VALUE)
+	{
+		mp4state.seek_needed = playfrom;
+		return TRUE;
+	}
+	else
+	{
+#ifdef DEBUG_OUTPUT
+		in_mp4_DebugOutput("play");
+#endif
+		int thread_id;
+		int avg_bitrate, br, sr;
+		unsigned char *buffer;
+		int buffer_size;
+		faacDecConfigurationPtr config;	
+		
+		mp4state.channels = 0;
+		mp4state.samplerate = 0;
+		mp4state.filetype = 0;
+
+		strcpy(mp4state.filename, medianame);
+
+		if(StringComp(medianame + strlen(medianame) - 3, "AAC", 3) == 0)
+			mp4state.filetype = 1;
+		
+		mp4state.hDecoder = faacDecOpen();
+		if (!mp4state.hDecoder)
+		{
+			show_error(hwndPlayer, "Unable to open decoder library.");
+			return -1;
+		}
+		
+		config = faacDecGetCurrentConfiguration(mp4state.hDecoder);
+		config->outputFormat = m_resolution + 1;
+		faacDecSetConfiguration(mp4state.hDecoder, config);
+		
+		if (mp4state.filetype)
+		{
+			long pos, tmp, read, tagsize;
+			
+			//        get_AAC_format(mp4state.filename, &mp4state.aacInfo);
+			
+			mp4state.aacfile = fopen(mp4state.filename, "rb");
+			if (!mp4state.aacfile)
+			{
+				show_error(hwndPlayer, "Unable to open file.");
+				faacDecClose(mp4state.hDecoder);
+				return -1;
+			}
+			
+			pos = ftell(mp4state.aacfile);
+			fseek(mp4state.aacfile, 0, SEEK_END);
+			mp4state.filesize = ftell(mp4state.aacfile);
+			fseek(mp4state.aacfile, pos, SEEK_SET);
+			
+			if (!(mp4state.buffer=(unsigned char*)malloc(768*48)))
+			{
+				show_error(hwndPlayer, "Memory allocation error.");
+				faacDecClose(mp4state.hDecoder);
+				fclose(mp4state.aacfile);
+				return -1;
+			}
+			memset(mp4state.buffer, 0, 768*48);
+			
+			if (mp4state.filesize < 768*48)
+				tmp = mp4state.filesize;
+			else
+				tmp = 768*48;
+			read = fread(mp4state.buffer, 1, tmp, mp4state.aacfile);
+			if (read == tmp)
+			{
+				mp4state.bytes_read = read;
+				mp4state.bytes_into_buffer = read;
+			} 
+			else 
+			{
+				show_error(hwndPlayer, "Error reading from file.");
+				faacDecClose(mp4state.hDecoder);
+				fclose(mp4state.aacfile);
+				return -1;
+			}
+			
+			if (StringComp(mp4state.buffer, "ID3", 3) == 0)
+			{
+				/* high bit is not used */
+				tagsize = (mp4state.buffer[6] << 21) | (mp4state.buffer[7] << 14) |
+					(mp4state.buffer[8] <<  7) | (mp4state.buffer[9] <<  0);
+				
+				tagsize += 10;
+			} 
+			else 
+			{
+				tagsize = 0;
+			}
+			
+			if ((mp4state.bytes_consumed = faacDecInit(mp4state.hDecoder,
+				mp4state.buffer+tagsize, mp4state.bytes_into_buffer,
+				&mp4state.samplerate, &mp4state.channels)) < 0)
+			{
+				show_error(hwndPlayer, "Can't initialize library.");
+				faacDecClose(mp4state.hDecoder);
+				fclose(mp4state.aacfile);
+				return -1;
+			}
+			mp4state.bytes_consumed += tagsize;
+			mp4state.bytes_into_buffer -= mp4state.bytes_consumed;
+			
+			//        avg_bitrate = mp4state.aacInfo.bitrate;
+			avg_bitrate = 0;
+			
+//			module.is_seekable = 0;
+		} 
+		else 
+		{
+			mp4state.mp4file = MP4Read(mp4state.filename, 0);
+			if (!mp4state.mp4file)
+			{
+				show_error(hwndPlayer, "Unable to open file.");
+				faacDecClose(mp4state.hDecoder);
+				return -1;
+			}
+			
+			if ((mp4state.mp4track = GetAACTrack(mp4state.mp4file)) < 0)
+			{
+				show_error(hwndPlayer, "Unsupported Audio track type.");
+				faacDecClose(mp4state.hDecoder);
+				MP4Close(mp4state.mp4file);
+				return -1;
+			}
+			
+			buffer = NULL;
+			buffer_size = 0;
+			MP4GetTrackESConfiguration(mp4state.mp4file, mp4state.mp4track,
+				&buffer, &buffer_size);
+			if (!buffer)
+			{
+				faacDecClose(mp4state.hDecoder);
+				MP4Close(mp4state.mp4file);
+				return -1;
+			}
+			
+			if(faacDecInit2(mp4state.hDecoder, buffer, buffer_size,
+				&mp4state.samplerate, &mp4state.channels) < 0)
+			{
+				/* If some error initializing occured, skip the file */
+				faacDecClose(mp4state.hDecoder);
+				MP4Close(mp4state.mp4file);
+				return -1;
+			}
+			free(buffer);
+			
+			avg_bitrate = MP4GetTrackIntegerProperty(mp4state.mp4file, mp4state.mp4track,
+				"mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.avgBitrate");
+			
+			mp4state.numSamples = MP4GetTrackNumberOfSamples(mp4state.mp4file, mp4state.mp4track);
+			mp4state.sampleId = 1;
+			
+//			module.is_seekable = 1;
+		}
+		
+		if (mp4state.channels == 0)
+		{
+			show_error(hwndPlayer, "Number of channels not supported for playback.");
+			faacDecClose(mp4state.hDecoder);
+			if (mp4state.filetype)
+				fclose(mp4state.aacfile);
+			else
+				MP4Close(mp4state.mp4file);
+			return -1;
+		}
+		
+		// open outputdevice
+		wf.wFormatTag = WAVE_FORMAT_PCM;
+		wf.cbSize = 0;
+		wf.nChannels = mp4state.channels;
+		wf.wBitsPerSample = res_table[m_resolution];
+		wf.nSamplesPerSec = mp4state.samplerate;
+		wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
+		wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
+		if (!QCDCallbacks->toPlayer.OutputOpen(mp4state.filename, &wf))
+		{
+			show_error(hwndPlayer, "Error: Failed openning output plugin!");
+			faacDecClose(mp4state.hDecoder);
+			if (mp4state.filetype)
+				fclose(mp4state.aacfile);
+			else
+				MP4Close(mp4state.mp4file);
+			return -1; // cannot open sound device
+		}
+		
+		mp4state.paused			= 0;
+		mp4state.decode_pos_ms	= 0;
+		mp4state.seek_needed	= playfrom > 0 ? playfrom : -1;
+		
+		br = (int)floor(((float)avg_bitrate + 500.0)/1000.0);
+		sr = (int)floor((float)mp4state.samplerate/1000.0);
+		// show constant bitrate at first
+		{
+			AudioInfo cai;
+			cai.struct_size = sizeof(AudioInfo);
+			cai.frequency = sr * 1000;
+			cai.bitrate = br * 1000;
+			cai.mode = (mp4state.channels == 2) ? 0 : 3;
+			cai.layer = 0;
+			cai.level = 0;
+			QCDCallbacks->Service(opSetAudioInfo, &cai, sizeof(AudioInfo), 0);
+		}
+		
+		killPlayThread = 0;
+		
+		if (mp4state.filetype)
+		{
+			if ((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AACPlayThread,
+				(void *)&killPlayThread, 0, &thread_id)) == NULL)
+			{
+				show_error(hwndPlayer, "Cannot create playback thread");
+				faacDecClose(mp4state.hDecoder);
+				fclose(mp4state.aacfile);
+				return -1;
+			}
+		} 
+		else 
+		{
+			if ((play_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MP4PlayThread,
+				(void *)&killPlayThread, 0, &thread_id)) == NULL)
+			{
+				show_error(hwndPlayer, "Cannot create playback thread");
+				faacDecClose(mp4state.hDecoder);
+				MP4Close(mp4state.mp4file);
+				return -1;
+			}
+		}
+		
+		SetThreadAffinityMask(play_thread_handle, 1);
+		
+		if (m_priority != 3)
+			SetThreadPriority(play_thread_handle, priority_table[m_priority]);
+	}
+	return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+
+int Pause(const char* medianame, int flags)
+{
+#ifdef DEBUG_OUTPUT
+    in_mp4_DebugOutput("pause");
+#endif
+	if(QCDCallbacks->toPlayer.OutputPause(flags))
+	{
+		// send back pause/unpause notification
+		QCDCallbacks->toPlayer.PlayPaused(medianame, flags);
+		mp4state.paused = flags;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+
+void SetVolume(int levelleft, int levelright, int flags)
+{
+	QCDCallbacks->toPlayer.OutputSetVol(levelleft, levelright, flags);
+}
+
+//-----------------------------------------------------------------------------
+
+int GetCurrentPosition(const char* medianame, long *track, long *offset)
+{
+	return QCDCallbacks->toPlayer.OutputGetCurrentPosition((UINT*)offset, 0);
+}
+
+//-----------------------------------------------------------------------------
+
+int Stop(const char* medianame, int flags)
+{
+#ifdef DEBUG_OUTPUT
+    in_mp4_DebugOutput("stop");
+#endif
+	if(medianame && *medianame && stricmp(mp4state.filename, medianame) == 0)
+	{
+		sQCDCallbacks.toPlayer.OutputStop(flags);
+
+		killPlayThread = 1;
+		if(play_thread_handle != INVALID_HANDLE_VALUE)
+		{
+			if (WaitForSingleObject(play_thread_handle, INFINITE) == WAIT_TIMEOUT)
+			{
+//				MessageBox(hwndPlayer, "MP4 thread kill timeout", "debug", 0);
+				TerminateThread(play_thread_handle,0);
+			}
+			CloseHandle(play_thread_handle);
+			play_thread_handle = INVALID_HANDLE_VALUE;
+		}
+		
+		if (oldAPIs)
+			QCDCallbacks->toPlayer.PlayStopped(mp4state.filename);
+
+		mp4state.filename[0] = 0;
+		if(mp4state.hDecoder)
+			faacDecClose(mp4state.hDecoder);
+		if (mp4state.filetype)
+			fclose(mp4state.aacfile);
+		else
+			MP4Close(mp4state.mp4file);
+	}
+	
+	return TRUE;
+}
+
+DWORD WINAPI MP4PlayThread(void *b)
+{
+	BOOL done = FALSE, updatePos = FALSE;
+    int l;
+
+    void *sample_buffer;
+    unsigned char *buffer;
+    int buffer_size, ms;
+    faacDecFrameInfo frameInfo;
+
+#ifdef DEBUG_OUTPUT
+    in_mp4_DebugOutput("MP4PlayThread");
+#endif
+
+    mp4state.last_frame = 0;
+
+    while (!*((int *)b))
+    {
+        /* seeking */
+        if (!done && mp4state.seek_needed != -1)
+        {
+            MP4Duration duration;
+
+			QCDCallbacks->toPlayer.OutputFlush(mp4state.decode_pos_ms);
+            duration = MP4ConvertToTrackDuration(mp4state.mp4file,
+                mp4state.mp4track, mp4state.seek_needed, MP4_MSECS_TIME_SCALE);
+            mp4state.sampleId = MP4GetSampleIdFromTime(mp4state.mp4file,
+                mp4state.mp4track, duration, 0);
+
+            mp4state.decode_pos_ms = mp4state.seek_needed;
+			mp4state.seek_needed = -1;
+			updatePos = TRUE;
+        }
+		/* quit */
+		if (done)
+		{
+			if (QCDCallbacks->toPlayer.OutputDrain(0) && !(mp4state.seek_needed >= 0))
+			{
+				play_thread_handle = INVALID_HANDLE_VALUE;
+				QCDCallbacks->toPlayer.OutputStop(STOPFLAG_PLAYDONE);
+				QCDCallbacks->toPlayer.PlayDone(mp4state.filename);
+			}
+			else if (mp4state.seek_needed >= 0)
+			{
+				done = FALSE;
+				continue;
+			}
+			break;
+		}
+		/* decoding */
+		else
+		{
+
+            if (mp4state.last_frame)
+            {
+                done = TRUE;
+            } 
+			else 
+			{
+                int rc;
+
+                /* get acces unit from MP4 file */
+                buffer = NULL;
+                buffer_size = 0;
+
+                rc = MP4ReadSample(mp4state.mp4file, mp4state.mp4track,
+                    mp4state.sampleId++, &buffer, &buffer_size,
+                    NULL, NULL, NULL, NULL);
+                if (rc == 0 || buffer == NULL)
+                {
+                    mp4state.last_frame = 1;
+                    sample_buffer = NULL;
+                    frameInfo.samples = 0;
+                } 
+				else 
+				{
+                    sample_buffer = faacDecDecode(mp4state.hDecoder, &frameInfo,
+                        buffer, buffer_size);
+                }
+                if (frameInfo.error > 0)
+                {
+                    show_error(hwndPlayer, faacDecGetErrorMessage(frameInfo.error));
+                    mp4state.last_frame = 1;
+                }
+                if (mp4state.sampleId >= mp4state.numSamples)
+                    mp4state.last_frame = 1;
+
+                if (buffer) free(buffer);
+
+                if (!killPlayThread && (frameInfo.samples > 0))
+                {
+                    if (res_table[m_resolution] == 24)
+                    {
+                        /* convert libfaad output (3 bytes packed in 4) */
+                        char *temp_buffer = convert3in4to3in3(sample_buffer, frameInfo.samples);
+                        memcpy((void*)sample_buffer, (void*)temp_buffer, frameInfo.samples*3);
+                        free(temp_buffer);
+                    }
+
+                    ms = (int)floor(((float)frameInfo.samples*1000.0) /
+                        ((float)mp4state.samplerate*(float)frameInfo.channels));
+                    mp4state.decode_pos_ms += ms;
+
+                    l = frameInfo.samples * res_table[m_resolution] / 8;
+
+					if (updatePos)
+					{
+						QCDCallbacks->toPlayer.PositionUpdate(mp4state.decode_pos_ms);
+						updatePos = FALSE;
+					}
+                    {
+						WriteDataStruct wd;
+
+						wd.bytelen = l;
+						wd.data = sample_buffer;
+						wd.markerend = 0;
+						wd.markerstart = mp4state.decode_pos_ms;
+						wd.bps = res_table[m_resolution];
+						wd.nch = frameInfo.channels;
+						wd.numsamples = frameInfo.samples/frameInfo.channels;
+						wd.srate = mp4state.samplerate;
+
+						if (!QCDCallbacks->toPlayer.OutputWrite(&wd))
+							done = TRUE;
+                    }
+                }
+            }
+        }
+		Sleep(10);
+    }
+
+	// close up
+	play_thread_handle = INVALID_HANDLE_VALUE;
+
+	return 0;
+}
+
+DWORD WINAPI AACPlayThread(void *b)
+{
+	BOOL done = FALSE, updatePos = FALSE;
+    int l, ms;
+
+    void *sample_buffer;
+    faacDecFrameInfo frameInfo;
+
+#ifdef DEBUG_OUTPUT
+    in_mp4_DebugOutput("AACPlayThread");
+#endif
+
+    mp4state.last_frame = 0;
+
+    while (!*((int *)b))
+    {
+#if 0
+        /* seeking */
+        if (!done && mp4state.seek_needed != -1)
+        {
+            int ms;
+
+            /* Round off to a second */
+            ms = mp4state.seek_needed - (mp4state.seek_needed%1000);
+			QCDCallbacks->toPlayer.OutputFlush(mp4state.decode_pos_ms);
+            aac_seek(ms);
+            mp4state.decode_pos_ms = ms;
+            mp4state.seek_needed = -1;
+			updatePos = TRUE;
+        }
+#endif
+		/* quit */
+		if (done)
+		{
+			if (QCDCallbacks->toPlayer.OutputDrain(0) && !(mp4state.seek_needed >= 0))
+			{
+				QCDCallbacks->toPlayer.OutputStop(STOPFLAG_PLAYDONE);
+				QCDCallbacks->toPlayer.PlayDone(mp4state.filename);
+			}
+			else if (mp4state.seek_needed >= 0)
+			{
+				done = FALSE;
+				continue;
+			}
+			break;
+		}
+
+		/* decoding */
+		else
+		{
+            if (mp4state.last_frame)
+            {
+                done = TRUE;
+            } 
+			else 
+			{
+                long tmp, read;
+                unsigned char *buffer = mp4state.buffer;
+
+                do
+                {
+                    if (mp4state.bytes_consumed > 0)
+                    {
+                        if (mp4state.bytes_into_buffer)
+                        {
+                            memcpy(buffer, buffer+mp4state.bytes_consumed,
+                                mp4state.bytes_into_buffer);
+                        }
+
+                        if (mp4state.bytes_read < mp4state.filesize)
+                        {
+                            if (mp4state.bytes_read + mp4state.bytes_consumed < mp4state.filesize)
+                                tmp = mp4state.bytes_consumed;
+                            else
+                                tmp = mp4state.filesize - mp4state.bytes_read;
+                            read = fread(buffer + mp4state.bytes_into_buffer, 1, tmp, mp4state.aacfile);
+                            if (read == tmp)
+                            {
+                                mp4state.bytes_read += read;
+                                mp4state.bytes_into_buffer += read;
+                            }
+                        } 
+						else 
+						{
+                            if (mp4state.bytes_into_buffer)
+                            {
+                                memset(buffer + mp4state.bytes_into_buffer, 0,
+                                    mp4state.bytes_consumed);
+                            }
+                        }
+
+                        mp4state.bytes_consumed = 0;
+                    }
+
+                    if (mp4state.bytes_into_buffer < 1)
+                    {
+                        if (mp4state.bytes_read < mp4state.filesize)
+                        {
+                            show_error(hwndPlayer, faacDecGetErrorMessage(frameInfo.error));
+                            mp4state.last_frame = 1;
+                        } 
+						else
+						{
+                            mp4state.last_frame = 1;
+                        }
+                    }
+
+                    sample_buffer = faacDecDecode(mp4state.hDecoder, &frameInfo,
+                        buffer, mp4state.bytes_into_buffer);
+
+                    mp4state.bytes_consumed += frameInfo.bytesconsumed;
+                    mp4state.bytes_into_buffer -= mp4state.bytes_consumed;
+                } while (!frameInfo.samples && !frameInfo.error);
+
+                if (!killPlayThread && (frameInfo.samples > 0))
+                {
+                    if (res_table[m_resolution] == 24)
+                    {
+                        /* convert libfaad output (3 bytes packed in 4 bytes) */
+                        char *temp_buffer = convert3in4to3in3(sample_buffer, frameInfo.samples);
+                        memcpy((void*)sample_buffer, (void*)temp_buffer, frameInfo.samples*3);
+                        free(temp_buffer);
+                    }
+
+                    ms = (int)floor(((float)frameInfo.samples*1000.0) /
+                        ((float)mp4state.samplerate*(float)frameInfo.channels));
+                    mp4state.decode_pos_ms += ms;
+
+                    l = frameInfo.samples * res_table[m_resolution] / 8;
+
+					if (updatePos)
+					{
+						QCDCallbacks->toPlayer.PositionUpdate(mp4state.decode_pos_ms);
+						updatePos = FALSE;
+					}
+                    {
+						WriteDataStruct wd;
+
+						wd.bytelen = l;
+						wd.data = sample_buffer;
+						wd.markerend = 0;
+						wd.markerstart = mp4state.decode_pos_ms;
+						wd.bps = res_table[m_resolution];
+						wd.nch = frameInfo.channels;
+						wd.numsamples = frameInfo.samples/frameInfo.channels;
+						wd.srate = mp4state.samplerate;
+
+						if (!QCDCallbacks->toPlayer.OutputWrite(&wd))
+							done = TRUE;
+                    } 
+                }
+            }
+        } 
+		Sleep(10);
+    }
+
+	// close up
+	play_thread_handle = INVALID_HANDLE_VALUE;
+
+    return 0;
+}
--- /dev/null
+++ b/plugins/QCDMp4/QCDMp4.dsp
@@ -1,0 +1,183 @@
+# Microsoft Developer Studio Project File - Name="QCDMp4" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=QCDMp4 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "QCDMp4.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "QCDMp4.mak" CFG="QCDMp4 - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "QCDMp4 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "QCDMp4 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "QCDMp4 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /I "..\..\common\mp4v2" /I "..\..\common\mp4av" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+
+!ELSEIF  "$(CFG)" == "QCDMp4 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "..\..\common\mp4v2" /I "..\..\common\mp4av" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "QCDMp4 - Win32 Release"
+# Name "QCDMp4 - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\aac2mp4.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\AAC2Mp4Enc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\aacinfo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\config.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\QCDMp4.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\utils.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\aac2mp4.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\aacinfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\faad.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\mbs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QCDConvertDLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QCDInputDLL.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QCDModDefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QCDModEncode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\QCDModInput.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\utils.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\logo.bmp
+# End Source File
+# Begin Source File
+
+SOURCE=.\QCDMp4.rc
+# End Source File
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/plugins/QCDMp4/QCDMp4.dsw
@@ -1,0 +1,74 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "QCDMp4"=".\QCDMp4.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name libfaad
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libmp4av_st
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libmp4v2_st
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libfaad"="..\..\libfaad\libfaad.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libmp4av_st"="..\..\common\mp4av\libmp4av_st.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libmp4v2_st"="..\..\common\mp4v2\libmp4v2_st60.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+++ b/plugins/QCDMp4/QCDMp4.rc
@@ -1,0 +1,170 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Dutch (Netherlands) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NLD)
+#ifdef _WIN32
+LANGUAGE LANG_DUTCH, SUBLANG_DUTCH
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE MOVEABLE PURE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE MOVEABLE PURE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE MOVEABLE PURE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_CONFIG_INPUT DIALOG DISCARDABLE  0, 0, 151, 108
+STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Configuration"
+FONT 8, "MS Sans Serif"
+BEGIN
+    CONTROL         "Slider1",IDC_PRIORITY,"msctls_trackbar32",TBS_VERT | 
+                    TBS_NOTICKS | WS_TABSTOP,13,15,18,46
+    CONTROL         "16 bits",IDC_16BITS,"Button",BS_AUTORADIOBUTTON,77,18,
+                    37,10
+    CONTROL         "16 bits dithered",IDC_16BITS_DITHERED,"Button",
+                    BS_AUTORADIOBUTTON,77,29,64,10
+    CONTROL         "24 bits",IDC_24BITS,"Button",BS_AUTORADIOBUTTON,77,40,
+                    37,10
+    CONTROL         "32 bits",IDC_32BITS,"Button",BS_AUTORADIOBUTTON,77,51,
+                    37,10
+    CONTROL         "Show errors",IDC_ERROR,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,7,70,53,10
+    CONTROL         "Use for AAC",IDC_USEFORAAC,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,78,70,55,10
+    PUSHBUTTON      "Cancel",IDCANCEL,7,87,50,14
+    DEFPUSHBUTTON   "OK",IDOK,94,87,50,14
+    GROUPBOX        "Priority",IDC_STATIC,7,7,57,58
+    LTEXT           "Highest",IDC_STATIC,34,18,25,8
+    LTEXT           "Normal",IDC_STATIC,34,35,23,8
+    LTEXT           "Lowest",IDC_STATIC,34,52,24,8
+    GROUPBOX        "Resolution",IDC_STATIC,71,7,73,58
+END
+
+IDD_CONFIG_CONVERT DIALOG DISCARDABLE  0, 0, 306, 143
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "AAC to Mp4 Converter Setting"
+FONT 8, "MS Sans Serif"
+BEGIN
+    DEFPUSHBUTTON   "&OK",IDOK,127,122,50,14
+    PUSHBUTTON      "Select Oupput Folder",IDC_OUTPUTFOLDER,16,19,277,20
+    GROUPBOX        "Ouput Folder",IDC_STATIC,7,7,292,39
+    CONTROL         "You can convert AAC files to Mp4 files if you like.\n\nThis does not involve re-encoding, only the container format is changed.\n\nAdvantage Mp4 files are playable by a lot more players\nand they will have a lot of support in the future. ",
+                    IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,7,62,
+                    292,51
+END
+
+IDD_ABOUT DIALOG DISCARDABLE  0, 0, 191, 190
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About MPEG-4 Plug-in"
+FONT 8, "MS Sans Serif"
+BEGIN
+    DEFPUSHBUTTON   "OK",IDOK,69,168,50,14
+    CTEXT           "",IDC_PLUGINVER,29,94,133,16
+    CTEXT           "",IDC_FAADVER,39,144,111,8
+    LTEXT           "QCD Input Plug-in by",IDC_STATIC,61,118,67,8
+    CONTROL         105,IDC_LOGO,"Static",SS_BITMAP | SS_CENTERIMAGE | 
+                    SS_REALSIZEIMAGE,7,0,177,68
+    LTEXT           "Shao Hao",IDC_MAIL1,78,132,33,8
+    LTEXT           "M. Bakker",IDC_MAIL3,58,155,34,8
+    LTEXT           "menno",IDC_MAIL2,108,155,22,8
+    LTEXT           "&&",IDC_STATIC,96,155,8,8
+    CTEXT           "AudioCoding.com MPEG-4 General Audio player\nCopyright 2002 AudioCoding.com",
+                    IDC_STATIC,7,72,177,18
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO MOVEABLE PURE 
+BEGIN
+    IDD_CONFIG_INPUT, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 144
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 101
+    END
+
+    IDD_CONFIG_CONVERT, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 299
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 136
+    END
+
+    IDD_ABOUT, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 184
+        BOTTOMMARGIN, 183
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_LOGO                BITMAP  DISCARDABLE     "logo.bmp"
+#endif    // Dutch (Netherlands) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
--- /dev/null
+++ b/plugins/QCDMp4/QCDMp4.sln
@@ -1,0 +1,42 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "in_mp4", "in_mp4.vcproj", "{2D8F479D-A591-4502-9456-398425D5F834}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfaad", "..\..\libfaad\libfaad.vcproj", "{82CAD808-21AF-40A6-92EC-AE01AA67B413}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmp4v2_st", "..\..\common\mp4v2\libmp4v2_st60.vcproj", "{2398BB2F-FFF9-490B-B4CC-863F2D21AE46}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmp4av_st", "..\..\common\mp4av\libmp4av_st.vcproj", "{8CAC9E26-BAA5-45A4-8721-E3170B3F8F49}"
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		ConfigName.0 = Debug
+		ConfigName.1 = Release
+	EndGlobalSection
+	GlobalSection(ProjectDependencies) = postSolution
+		{2D8F479D-A591-4502-9456-398425D5F834}.0 = {82CAD808-21AF-40A6-92EC-AE01AA67B413}
+		{2D8F479D-A591-4502-9456-398425D5F834}.1 = {8CAC9E26-BAA5-45A4-8721-E3170B3F8F49}
+		{2D8F479D-A591-4502-9456-398425D5F834}.2 = {2398BB2F-FFF9-490B-B4CC-863F2D21AE46}
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{2D8F479D-A591-4502-9456-398425D5F834}.Debug.ActiveCfg = Debug|Win32
+		{2D8F479D-A591-4502-9456-398425D5F834}.Debug.Build.0 = Debug|Win32
+		{2D8F479D-A591-4502-9456-398425D5F834}.Release.ActiveCfg = Release|Win32
+		{2D8F479D-A591-4502-9456-398425D5F834}.Release.Build.0 = Release|Win32
+		{82CAD808-21AF-40A6-92EC-AE01AA67B413}.Debug.ActiveCfg = Debug|Win32
+		{82CAD808-21AF-40A6-92EC-AE01AA67B413}.Debug.Build.0 = Debug|Win32
+		{82CAD808-21AF-40A6-92EC-AE01AA67B413}.Release.ActiveCfg = Release|Win32
+		{82CAD808-21AF-40A6-92EC-AE01AA67B413}.Release.Build.0 = Release|Win32
+		{2398BB2F-FFF9-490B-B4CC-863F2D21AE46}.Debug.ActiveCfg = Debug|Win32
+		{2398BB2F-FFF9-490B-B4CC-863F2D21AE46}.Debug.Build.0 = Debug|Win32
+		{2398BB2F-FFF9-490B-B4CC-863F2D21AE46}.Release.ActiveCfg = Release|Win32
+		{2398BB2F-FFF9-490B-B4CC-863F2D21AE46}.Release.Build.0 = Release|Win32
+		{8CAC9E26-BAA5-45A4-8721-E3170B3F8F49}.Debug.ActiveCfg = Debug|Win32
+		{8CAC9E26-BAA5-45A4-8721-E3170B3F8F49}.Debug.Build.0 = Debug|Win32
+		{8CAC9E26-BAA5-45A4-8721-E3170B3F8F49}.Release.ActiveCfg = Release|Win32
+		{8CAC9E26-BAA5-45A4-8721-E3170B3F8F49}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
--- /dev/null
+++ b/plugins/QCDMp4/QCDMp4.vcproj
@@ -1,0 +1,200 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="in_mp4"
+	SccProjectName=""
+	SccLocalPath="">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory=".\Debug"
+			IntermediateDirectory=".\Debug"
+			ConfigurationType="2"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\include,..\..\common\mp4v2,..\..\common\mp4av"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderFile=".\Debug/in_mp4.pch"
+				AssemblerListingLocation=".\Debug/"
+				ObjectFile=".\Debug/"
+				ProgramDataBaseFileName=".\Debug/"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"
+				DebugInformationFormat="4"
+				CompileAs="0">
+				<IntelOptions
+					Optimization="0"
+					MinimalRebuild="1"
+					BasicRuntimeChecks="0"
+					RuntimeLibrary="1"
+					AllOptions="/c  /I &quot;..\..\include&quot; /I &quot;..\..\common\mp4v2&quot; /I &quot;..\..\common\mp4av&quot; /ZI /nologo /W3 /Od /D &quot;WIN32&quot; /D &quot;_DEBUG&quot; /D &quot;_WINDOWS&quot; /D &quot;_WINDLL&quot; /Gm /EHsc /MTd /YX&quot;StdAfx.h&quot; /Fp&quot;.\Debug/in_mp4.pch&quot; /Fo&quot;.\Debug/&quot; /Fd&quot;.\Debug/&quot; /Gd"/>
+			</Tool>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="ws2_32.lib odbc32.lib odbccp32.lib"
+				OutputFile=".\Debug/in_mp4.dll"
+				LinkIncremental="2"
+				SuppressStartupBanner="TRUE"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile=".\Debug/in_mp4.pdb"
+				SubSystem="2"
+				ImportLibrary=".\Debug/in_mp4.lib">
+				<IntelOptions
+					AllOptions="/NOLOGO /DLL /OUT:&quot;.\Debug/in_mp4.dll&quot; /INCREMENTAL ws2_32.lib odbc32.lib odbccp32.lib /DEBUG /PDB:&quot;.\Debug/in_mp4.pdb&quot; /SUBSYSTEM:WINDOWS /TLBID:1 /IMPLIB:&quot;.\Debug/in_mp4.lib&quot; /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"/>
+			</Tool>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="TRUE"
+				SuppressStartupBanner="TRUE"
+				TargetEnvironment="1"
+				TypeLibraryName=".\Debug/in_mp4.tlb"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1043"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory=".\Release"
+			IntermediateDirectory=".\Release"
+			ConfigurationType="2"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE">
+			<Tool
+				Name="VCCLCompilerTool"
+				GlobalOptimizations="TRUE"
+				InlineFunctionExpansion="1"
+				EnableIntrinsicFunctions="TRUE"
+				FavorSizeOrSpeed="1"
+				OptimizeForProcessor="2"
+				AdditionalIncludeDirectories="..\..\include,..\..\common\mp4v2,..\..\common\mp4av"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+				StringPooling="TRUE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="TRUE"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderFile=".\Release/in_mp4.pch"
+				AssemblerListingLocation=".\Release/"
+				ObjectFile=".\Release/"
+				ProgramDataBaseFileName=".\Release/"
+				WarningLevel="3"
+				SuppressStartupBanner="TRUE"
+				CompileAs="0">
+				<IntelOptions
+					Optimization="2"
+					GlobalOptimizations="1"
+					InlineFuncExpansion="1"
+					OmitFramePtrs="1"
+					StringPooling="1"
+					RuntimeLibrary="0"
+					BufferSecurityCheck="1"
+					FunctionLevelLinking="1"
+					AllOptions="/c  /I &quot;..\..\include&quot; /I &quot;..\..\common\mp4v2&quot; /I &quot;..\..\common\mp4av&quot; /nologo /W3 /O2 /Og /Ob1 /Oy /D &quot;WIN32&quot; /D &quot;NDEBUG&quot; /D &quot;_WINDOWS&quot; /D &quot;_WINDLL&quot; /GF /FD /EHsc /MT /GS /Gy /YX&quot;StdAfx.h&quot; /Fp&quot;.\Release/in_mp4.pch&quot; /Fo&quot;.\Release/&quot; /Fd&quot;.\Release/&quot; /Gd"/>
+			</Tool>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="ws2_32.lib"
+				OutputFile=".\Release/in_mp4.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="TRUE"
+				ProgramDatabaseFile=".\Release/in_mp4.pdb"
+				SubSystem="2"
+				ImportLibrary=".\Release/in_mp4.lib">
+				<IntelOptions
+					AllOptions="/NOLOGO /DLL /OUT:&quot;.\Release/in_mp4.dll&quot; /INCREMENTAL:NO ws2_32.lib /PDB:&quot;.\Release/in_mp4.pdb&quot; /SUBSYSTEM:WINDOWS /TLBID:1 /IMPLIB:&quot;.\Release/in_mp4.lib&quot; /MACHINE:I386 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"/>
+			</Tool>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="TRUE"
+				SuppressStartupBanner="TRUE"
+				TargetEnvironment="1"
+				TypeLibraryName=".\Release/in_mp4.tlb"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1043"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+			<File
+				RelativePath="aac2mp4.cpp"/>
+			<File
+				RelativePath="aacinfo.c"/>
+			<File
+				RelativePath=".\config.c"/>
+			<File
+				RelativePath=".\in_mp4.c"/>
+			<File
+				RelativePath=".\utils.c"/>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl">
+			<File
+				RelativePath="aac2mp4.h"/>
+			<File
+				RelativePath="aacinfo.h"/>
+			<File
+				RelativePath=".\config.h"/>
+			<File
+				RelativePath="..\..\include\faad.h"/>
+			<File
+				RelativePath=".\in2.h"/>
+			<File
+				RelativePath=".\out.h"/>
+			<File
+				RelativePath="resource.h"/>
+			<File
+				RelativePath=".\utils.h"/>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+			<File
+				RelativePath=".\in_mp4.rc"/>
+		</Filter>
+	</Files>
+	<Globals/>
+</VisualStudioProject>
--- /dev/null
+++ b/plugins/QCDMp4/aac2mp4.cpp
@@ -1,0 +1,313 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: aac2mp4.cpp,v 1.1 2003/04/28 19:07:57 menno Exp $
+**/
+
+#include <mpeg4ip.h>
+#include <mp4.h>
+#include <mp4av.h>
+
+#include "aac2mp4.h"
+
+int covert_aac_to_mp4(char *inputFileName, char *mp4FileName)
+{
+    int Mp4TimeScale = 90000;
+    int allMpeg4Streams = 0;
+    MP4FileHandle mp4File;
+    FILE* inFile;
+    const char *type;
+    MP4TrackId createdTrackId = MP4_INVALID_TRACK_ID;
+
+    mp4File = MP4Create(mp4FileName, 0, 0, 0);
+    if (mp4File)
+    {
+        MP4SetTimeScale(mp4File, Mp4TimeScale);
+    } else {
+        return 1;
+    }
+
+    inFile = fopen(inputFileName, "rb");
+
+	if (inFile == NULL)
+    {
+        MP4Close(mp4File);
+        return 2;
+    }
+
+    createdTrackId = AacCreator(mp4File, inFile);
+
+    if (createdTrackId == MP4_INVALID_TRACK_ID)
+    {
+        fclose(inFile);
+        MP4Close(mp4File);
+        return 3;
+    }
+
+    type = MP4GetTrackType(mp4File, createdTrackId);
+
+    if (!strcmp(type, MP4_AUDIO_TRACK_TYPE))
+    {
+        allMpeg4Streams &=
+            (MP4GetTrackAudioType(mp4File, createdTrackId)
+            == MP4_MPEG4_AUDIO_TYPE);
+    }
+
+    if (inFile)
+    {
+        fclose(inFile);
+    }
+
+    MP4Close(mp4File);
+    MP4MakeIsmaCompliant(mp4FileName, 0, allMpeg4Streams);
+
+    return 0;
+}
+
+#define ADTS_HEADER_MAX_SIZE 10 /* bytes */
+
+static u_int8_t firstHeader[ADTS_HEADER_MAX_SIZE];
+
+/* 
+ * hdr must point to at least ADTS_HEADER_MAX_SIZE bytes of memory 
+ */
+static bool LoadNextAdtsHeader(FILE* inFile, u_int8_t* hdr)
+{
+	u_int state = 0;
+	u_int dropped = 0;
+	u_int hdrByteSize = ADTS_HEADER_MAX_SIZE;
+
+	while (1) {
+		/* read a byte */
+		u_int8_t b;
+
+		if (fread(&b, 1, 1, inFile) == 0) {
+			return false;
+		}
+
+		/* header is complete, return it */
+		if (state == hdrByteSize - 1) {
+			hdr[state] = b;
+			if (dropped > 0) {
+				fprintf(stderr, "Warning: dropped %u input bytes\n", dropped);
+			}
+			return true;
+		}
+
+		/* collect requisite number of bytes, no constraints on data */
+		if (state >= 2) {
+			hdr[state++] = b;
+		} else {
+			/* have first byte, check if we have 1111X00X */
+			if (state == 1) {
+				if ((b & 0xF6) == 0xF0) {
+					hdr[state] = b;
+					state = 2;
+					/* compute desired header size */
+					hdrByteSize = MP4AV_AdtsGetHeaderByteSize(hdr);
+				} else {
+					state = 0;
+				}
+			}
+			/* initial state, looking for 11111111 */
+			if (state == 0) {
+				if (b == 0xFF) {
+					hdr[state] = b;
+					state = 1;
+				} else {
+					 /* else drop it */ 
+					dropped++;
+				}
+			}
+		}
+	}
+}
+
+/*
+ * Load the next frame from the file
+ * into the supplied buffer, which better be large enough!
+ *
+ * Note: Frames are padded to byte boundaries
+ */
+static bool LoadNextAacFrame(FILE* inFile, u_int8_t* pBuf, u_int32_t* pBufSize, bool stripAdts)
+{
+	u_int16_t frameSize;
+	u_int16_t hdrBitSize, hdrByteSize;
+	u_int8_t hdrBuf[ADTS_HEADER_MAX_SIZE];
+
+	/* get the next AAC frame header, more or less */
+	if (!LoadNextAdtsHeader(inFile, hdrBuf)) {
+		return false;
+	}
+	
+	/* get frame size from header */
+	frameSize = MP4AV_AdtsGetFrameSize(hdrBuf);
+
+	/* get header size in bits and bytes from header */
+	hdrBitSize = MP4AV_AdtsGetHeaderBitSize(hdrBuf);
+	hdrByteSize = MP4AV_AdtsGetHeaderByteSize(hdrBuf);
+	
+	/* adjust the frame size to what remains to be read */
+	frameSize -= hdrByteSize;
+
+	if (stripAdts) {
+		if ((hdrBitSize % 8) == 0) {
+			/* header is byte aligned, i.e. MPEG-2 ADTS */
+			/* read the frame data into the buffer */
+			if (fread(pBuf, 1, frameSize, inFile) != frameSize) {
+				return false;
+			}
+			(*pBufSize) = frameSize;
+		} else {
+			/* header is not byte aligned, i.e. MPEG-4 ADTS */
+			int i;
+			u_int8_t newByte;
+			int upShift = hdrBitSize % 8;
+			int downShift = 8 - upShift;
+
+			pBuf[0] = hdrBuf[hdrBitSize / 8] << upShift;
+
+			for (i = 0; i < frameSize; i++) {
+				if (fread(&newByte, 1, 1, inFile) != 1) {
+					return false;
+				}
+				pBuf[i] |= (newByte >> downShift);
+				pBuf[i+1] = (newByte << upShift);
+			}
+			(*pBufSize) = frameSize + 1;
+		}
+	} else { /* don't strip ADTS headers */
+		memcpy(pBuf, hdrBuf, hdrByteSize);
+		if (fread(&pBuf[hdrByteSize], 1, frameSize, inFile) != frameSize) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static bool GetFirstHeader(FILE* inFile)
+{
+	/* read file until we find an audio frame */
+	fpos_t curPos;
+
+	/* already read first header */
+	if (firstHeader[0] == 0xff) {
+		return true;
+	}
+
+	/* remember where we are */
+	fgetpos(inFile, &curPos);
+	
+	/* go back to start of file */
+	rewind(inFile);
+
+	if (!LoadNextAdtsHeader(inFile, firstHeader)) {
+		return false;
+	}
+
+	/* reposition the file to where we were */
+	fsetpos(inFile, &curPos);
+
+	return true;
+}
+
+MP4TrackId AacCreator(MP4FileHandle mp4File, FILE* inFile)
+{
+	// collect all the necessary meta information
+	u_int32_t samplesPerSecond;
+	u_int8_t mpegVersion;
+	u_int8_t profile;
+	u_int8_t channelConfig;
+
+	if (!GetFirstHeader(inFile)) {
+		return MP4_INVALID_TRACK_ID;
+	}
+
+	samplesPerSecond = MP4AV_AdtsGetSamplingRate(firstHeader);
+	mpegVersion = MP4AV_AdtsGetVersion(firstHeader);
+	profile = MP4AV_AdtsGetProfile(firstHeader);
+	channelConfig = MP4AV_AdtsGetChannels(firstHeader);
+
+	u_int8_t audioType = MP4_INVALID_AUDIO_TYPE;
+	switch (mpegVersion) {
+	case 0:
+		audioType = MP4_MPEG4_AUDIO_TYPE;
+		break;
+	case 1:
+		switch (profile) {
+		case 0:
+			audioType = MP4_MPEG2_AAC_MAIN_AUDIO_TYPE;
+			break;
+		case 1:
+			audioType = MP4_MPEG2_AAC_LC_AUDIO_TYPE;
+			break;
+		case 2:
+			audioType = MP4_MPEG2_AAC_SSR_AUDIO_TYPE;
+			break;
+		case 3:
+			return MP4_INVALID_TRACK_ID;
+		}
+		break;
+	}
+
+	// add the new audio track
+	MP4TrackId trackId = 
+		MP4AddAudioTrack(mp4File, 
+			samplesPerSecond, 1024, audioType);
+
+	if (trackId == MP4_INVALID_TRACK_ID) {
+		return MP4_INVALID_TRACK_ID;
+	}
+
+	if (MP4GetNumberOfTracks(mp4File, MP4_AUDIO_TRACK_TYPE) == 1) {
+		MP4SetAudioProfileLevel(mp4File, 0x0F);
+	}
+
+	u_int8_t* pConfig = NULL;
+	u_int32_t configLength = 0;
+
+	MP4AV_AacGetConfiguration(
+		&pConfig,
+		&configLength,
+		profile,
+		samplesPerSecond,
+		channelConfig);
+
+	if (!MP4SetTrackESConfiguration(mp4File, trackId, 
+	  pConfig, configLength)) {
+		MP4DeleteTrack(mp4File, trackId);
+		return MP4_INVALID_TRACK_ID;
+	}
+
+	// parse the ADTS frames, and write the MP4 samples
+	u_int8_t sampleBuffer[8 * 1024];
+	u_int32_t sampleSize = sizeof(sampleBuffer);
+	MP4SampleId sampleId = 1;
+
+	while (LoadNextAacFrame(inFile, sampleBuffer, &sampleSize, true)) {
+		if (!MP4WriteSample(mp4File, trackId, sampleBuffer, sampleSize)) {
+			MP4DeleteTrack(mp4File, trackId);
+			return MP4_INVALID_TRACK_ID;
+		}
+		sampleId++;
+		sampleSize = sizeof(sampleBuffer);
+	}
+
+	return trackId;
+}
--- /dev/null
+++ b/plugins/QCDMp4/aac2mp4.h
@@ -1,0 +1,36 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: aac2mp4.h,v 1.1 2003/04/28 19:07:57 menno Exp $
+**/
+
+#ifndef AAC2MP4_H__
+#define AAC2MP4_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int covert_aac_to_mp4(char *inputFileName, char *mp4FileName);
+MP4TrackId AacCreator(MP4FileHandle mp4File, FILE* inFile);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
--- /dev/null
+++ b/plugins/QCDMp4/aacinfo.c
@@ -1,0 +1,220 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: aacinfo.c,v 1.1 2003/04/28 19:07:57 menno Exp $
+**/
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "aacinfo.h"
+#include "utils.h"
+
+#define ADIF_MAX_SIZE 30 /* Should be enough */
+#define ADTS_MAX_SIZE 10 /* Should be enough */
+
+static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
+
+static int read_ADIF_header(FILE *file, faadAACInfo *info)
+{
+    int bitstream;
+    unsigned char buffer[ADIF_MAX_SIZE];
+    int skip_size = 0;
+    int sf_idx;
+
+    /* Get ADIF header data */
+    info->headertype = 1;
+
+    if (fread(buffer, 1, ADIF_MAX_SIZE, file) != ADIF_MAX_SIZE)
+        return -1;
+
+    /* copyright string */
+    if(buffer[0] & 0x80)
+        skip_size += 9; /* skip 9 bytes */
+
+    bitstream = buffer[0 + skip_size] & 0x10;
+    info->bitrate = ((unsigned int)(buffer[0 + skip_size] & 0x0F)<<19)|
+        ((unsigned int)buffer[1 + skip_size]<<11)|
+        ((unsigned int)buffer[2 + skip_size]<<3)|
+        ((unsigned int)buffer[3 + skip_size] & 0xE0);
+
+    if (bitstream == 0)
+    {
+        info->object_type =  ((buffer[6 + skip_size]&0x01)<<1)|((buffer[7 + skip_size]&0x80)>>7);
+        sf_idx = (buffer[7 + skip_size]&0x78)>>3;
+    } else {
+        info->object_type = (buffer[4 + skip_size] & 0x18)>>3;
+        sf_idx = ((buffer[4 + skip_size] & 0x07)<<1)|((buffer[5 + skip_size] & 0x80)>>7);
+    }
+    info->sampling_rate = sample_rates[sf_idx];
+
+    return 0;
+}
+
+static int read_ADTS_header(FILE *file, faadAACInfo *info)
+{
+    /* Get ADTS header data */
+    unsigned char buffer[ADTS_MAX_SIZE];
+    int frames, t_framelength = 0, frame_length, sr_idx = 0, ID;
+    int second = 0, pos;
+    float frames_per_sec = 0;
+    unsigned long bytes;
+    unsigned long *tmp_seek_table = NULL;
+
+    info->headertype = 2;
+
+    /* Read all frames to ensure correct time and bitrate */
+    for (frames = 0; /* */; frames++)
+    {
+        bytes = fread(buffer, 1, ADTS_MAX_SIZE, file);
+
+        if (bytes != ADTS_MAX_SIZE)
+            break;
+
+        /* check syncword */
+        if (!((buffer[0] == 0xFF)&&((buffer[1] & 0xF6) == 0xF0)))
+            break;
+
+        if (!frames)
+        {
+            /* fixed ADTS header is the same for every frame, so we read it only once */
+            /* Syncword found, proceed to read in the fixed ADTS header */
+            ID = buffer[1] & 0x08;
+            info->object_type = (buffer[2]&0xC0)>>6;
+            sr_idx = (buffer[2]&0x3C)>>2;
+            info->channels = ((buffer[2]&0x01)<<2)|((buffer[3]&0xC0)>>6);
+
+            frames_per_sec = sample_rates[sr_idx] / 1024.f;
+        }
+
+        /* ...and the variable ADTS header */
+        if (ID == 0)
+        {
+            info->version = 4;
+            frame_length = (((unsigned int)buffer[4]) << 5) |
+                ((unsigned int)buffer[5] >> 3);
+        } else { /* MPEG-2 */
+            info->version = 2;
+            frame_length = ((((unsigned int)buffer[3] & 0x3)) << 11)
+                | (((unsigned int)buffer[4]) << 3) | (buffer[5] >> 5);
+        }
+
+        t_framelength += frame_length;
+
+        pos = ftell(file) - ADTS_MAX_SIZE;
+
+        fseek(file, frame_length - ADTS_MAX_SIZE, SEEK_CUR);
+    }
+
+    if (frames > 0)
+    {
+        float sec_per_frame, bytes_per_frame;
+        info->sampling_rate = sample_rates[sr_idx];
+        sec_per_frame = (float)info->sampling_rate/1024.0;
+        bytes_per_frame = (float)t_framelength / (float)frames;
+        info->bitrate = 8 * (int)floor(bytes_per_frame * sec_per_frame);
+        info->length = (int)floor((float)frames/frames_per_sec)*1000;
+    } else {
+        info->sampling_rate = 4;
+        info->bitrate = 128000;
+        info->length = 0;
+        info->channels = 0;
+    }
+
+    return 0;
+}
+
+int get_AAC_format(char *filename, faadAACInfo *info)
+{
+    unsigned long tagsize;
+    FILE *file;
+    char buffer[10];
+    unsigned long file_len;
+    unsigned char adxx_id[5];
+    unsigned long tmp;
+
+    memset(info, 0, sizeof(faadAACInfo));
+
+    file = fopen(filename, "rb");
+
+    if(file == NULL)
+        return -1;
+
+    fseek(file, 0, SEEK_END);
+    file_len = ftell(file);
+    fseek(file, 0, SEEK_SET);
+
+    /* Skip the tag, if it's there */
+    tmp = fread(buffer, 10, 1, file);
+
+    if (StringComp(buffer, "ID3", 3) == 0)
+    {
+        /* high bit is not used */
+        tagsize = (buffer[6] << 21) | (buffer[7] << 14) |
+            (buffer[8] <<  7) | (buffer[9] <<  0);
+
+        fseek(file, tagsize, SEEK_CUR);
+        tagsize += 10;
+    } else {
+        tagsize = 0;
+        fseek(file, 0, SEEK_SET);
+    }
+
+    if (file_len)
+        file_len -= tagsize;
+
+    tmp = fread(adxx_id, 2, 1, file);
+    adxx_id[5-1] = 0;
+    info->length = 0;
+
+    /* Determine the header type of the file, check the first two bytes */
+    if (StringComp(adxx_id, "AD", 2) == 0)
+    {
+        /* We think its an ADIF header, but check the rest just to make sure */
+        tmp = fread(adxx_id + 2, 2, 1, file);
+
+        if (StringComp(adxx_id, "ADIF", 4) == 0)
+        {
+            read_ADIF_header(file, info);
+
+            info->length = (int)((float)file_len*8000.0/((float)info->bitrate));
+        }
+    } else {
+        /* No ADIF, check for ADTS header */
+        if ((adxx_id[0] == 0xFF)&&((adxx_id[1] & 0xF6) == 0xF0))
+        {
+            /* ADTS  header located */
+            fseek(file, tagsize, SEEK_SET);
+            read_ADTS_header(file, info);
+        } else {
+            /* Unknown/headerless AAC file, assume format: */
+            info->version = 2;
+            info->bitrate = 128000;
+            info->sampling_rate = 44100;
+            info->channels = 2;
+            info->headertype = 0;
+            info->object_type = 1;
+        }
+    }
+
+    fclose(file);
+
+    return 0;
+}
--- /dev/null
+++ b/plugins/QCDMp4/aacinfo.h
@@ -1,0 +1,40 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: aacinfo.h,v 1.1 2003/04/28 19:07:57 menno Exp $
+**/
+
+#ifndef AACINFO_INCLUDED
+#define AACINFO_INCLUDED
+
+typedef struct {
+    int version;
+    int channels;
+    int sampling_rate;
+    int bitrate;
+    int length;
+    int object_type;
+    int headertype;
+} faadAACInfo;
+
+int get_AAC_format(char *filename, faadAACInfo *info);
+
+static int read_ADIF_header(FILE *file, faadAACInfo *info);
+static int read_ADTS_header(FILE *file, faadAACInfo *info);
+
+#endif
--- /dev/null
+++ b/plugins/QCDMp4/config.c
@@ -1,0 +1,39 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: config.c,v 1.1 2003/04/28 19:07:57 menno Exp $
+**/
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include "config.h"
+
+char app_name[] = "QCDMp4";
+char INI_FILE[MAX_PATH];
+int m_priority = 3;
+int m_resolution = 0;
+int m_show_errors = 1;
+int m_use_for_aac = 1;
+
+void _r_s(char *name,char *data, int mlen)
+{
+	char buf[10];
+	strcpy(buf,data);
+	GetPrivateProfileString(app_name,name,buf,data,mlen,INI_FILE);
+}
+
--- /dev/null
+++ b/plugins/QCDMp4/config.h
@@ -1,0 +1,33 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: config.h,v 1.1 2003/04/28 19:07:57 menno Exp $
+**/
+
+extern char app_name[];
+extern char INI_FILE[];
+int m_priority;
+int m_resolution;
+int m_show_errors;
+int m_use_for_aac;
+
+#define RS(x) (_r_s(#x,x,sizeof(x)))
+#define WS(x) (WritePrivateProfileString(app_name,#x,x,INI_FILE))
+
+extern void _r_s(char *name,char *data, int mlen);
+
binary files /dev/null b/plugins/QCDMp4/logo.bmp differ
--- /dev/null
+++ b/plugins/QCDMp4/mbs.h
@@ -1,0 +1,81 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001-2002.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Dave Mackie		[email protected]
+ */
+
+#ifndef __MBS_INCLUDED__
+#define __MBS_INCLUDED__ 
+
+class CMemoryBitstream {
+public:
+	CMemoryBitstream() {
+		m_pBuf = NULL;
+		m_bitPos = 0;
+		m_numBits = 0;
+	}
+
+	void AllocBytes(u_int32_t numBytes);
+
+	void SetBytes(u_int8_t* pBytes, u_int32_t numBytes);
+
+	void PutBytes(u_int8_t* pBytes, u_int32_t numBytes);
+
+	void PutBits(u_int32_t bits, u_int32_t numBits);
+
+	u_int32_t GetBits(u_int32_t numBits);
+
+	void SkipBytes(u_int32_t numBytes) {
+		SkipBits(numBytes << 3);
+	}
+
+	void SkipBits(u_int32_t numBits) {
+		SetBitPosition(GetBitPosition() + numBits);
+	}
+
+	u_int32_t GetBitPosition() {
+		return m_bitPos;
+	}
+
+	void SetBitPosition(u_int32_t bitPos) {
+		if (bitPos > m_numBits) {
+			throw;
+		}
+		m_bitPos = bitPos;
+	}
+
+	u_int8_t* GetBuffer() {
+		return m_pBuf;
+	}
+
+	u_int32_t GetNumberOfBytes() {
+		return (GetNumberOfBits() + 7) / 8;
+	}
+
+	u_int32_t GetNumberOfBits() {
+		return m_numBits;
+	}
+
+protected:
+	u_int8_t*	m_pBuf;
+	u_int32_t	m_bitPos;
+	u_int32_t	m_numBits;
+};
+
+#endif /* __MBS_INCLUDED__ */ 
+
--- /dev/null
+++ b/plugins/QCDMp4/resource.h
@@ -1,0 +1,51 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by QCDMp4.rc
+//
+#define IDD_INFO                        101
+#define IDD_CONFIG                      102
+#define IDD_CONFIG_INPUT                102
+#define IDD_ABOUT                       103
+#define IDD_CONFIG_CONVERT              104
+#define IDB_LOGO                        105
+#define IDC_TYPE                        1000
+#define IDC_INFOTEXT                    1000
+#define IDC_DURATION                    1001
+#define IDC_BITRATE                     1002
+#define IDC_SAMPLERATE                  1003
+#define IDC_VTYPE                       1004
+#define IDC_PRIORITY                    1004
+#define IDC_VBITRATE                    1005
+#define IDC_ERROR                       1005
+#define IDC_VDURATION                   1006
+#define IDC_16BITS                      1006
+#define IDC_VSIZE                       1007
+#define IDC_24BITS                      1007
+#define IDC_CONVERT                     1007
+#define IDC_VFPS                        1008
+#define IDC_32BITS                      1008
+#define IDC_CONVERT2                    1008
+#define IDC_CHANNELS                    1009
+#define IDC_24BITS2                     1009
+#define IDC_16BITS_DITHERED             1009
+#define IDC_CONVERT1                    1009
+#define IDC_USERDATA                    1010
+#define IDC_USEFORAAC                   1011
+#define IDC_OUTPUTFOLDER                1014
+#define IDC_LOGO                        1019
+#define IDC_PLUGINVER                   1050
+#define IDC_FAADVER                     1051
+#define IDC_MAIL1                       1052
+#define IDC_MAIL2                       1053
+#define IDC_MAIL3                       1054
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        106
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1020
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
--- /dev/null
+++ b/plugins/QCDMp4/utils.c
@@ -1,0 +1,147 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: utils.c,v 1.1 2003/04/28 19:07:57 menno Exp $
+**/
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <mp4.h>
+#include <faad.h>
+#include "utils.h"
+
+int StringComp(char const *str1, char const *str2, unsigned long len)
+{
+    signed int c1 = 0, c2 = 0;
+
+    while (len--)
+    {
+        c1 = tolower(*str1++);
+        c2 = tolower(*str2++);
+
+        if (c1 == 0 || c1 != c2)
+            break;
+    }
+
+    return c1 - c2;
+}
+
+int GetAACTrack(MP4FileHandle infile)
+{
+    /* find AAC track */
+    int i, rc;
+	int numTracks = MP4GetNumberOfTracks(infile, NULL, 0);
+
+	for (i = 0; i < numTracks; i++)
+    {
+        MP4TrackId trackId = MP4FindTrackId(infile, i, NULL, 0);
+        const char* trackType = MP4GetTrackType(infile, trackId);
+
+        if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE))
+        {
+            unsigned char *buff = NULL;
+            int buff_size = 0;
+            mp4AudioSpecificConfig mp4ASC;
+
+            MP4GetTrackESConfiguration(infile, trackId, &buff, &buff_size);
+
+            if (buff)
+            {
+                rc = AudioSpecificConfig(buff, buff_size, &mp4ASC);
+                free(buff);
+
+                if (rc < 0)
+                    return -1;
+                return trackId;
+            }
+        }
+    }
+
+    /* can't decode this */
+    return -1;
+}
+
+int GetAudioTrack(MP4FileHandle infile)
+{
+    /* find AAC track */
+    int i;
+	int numTracks = MP4GetNumberOfTracks(infile, NULL, 0);
+
+	for (i = 0; i < numTracks; i++)
+    {
+        MP4TrackId trackId = MP4FindTrackId(infile, i, NULL, 0);
+        const char* trackType = MP4GetTrackType(infile, trackId);
+
+        if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE))
+        {
+            return trackId;
+        }
+    }
+
+    /* can't decode this */
+    return -1;
+}
+
+int GetVideoTrack(MP4FileHandle infile)
+{
+    /* find AAC track */
+    int i;
+	int numTracks = MP4GetNumberOfTracks(infile, NULL, 0);
+
+	for (i = 0; i < numTracks; i++)
+    {
+        MP4TrackId trackId = MP4FindTrackId(infile, i, NULL, 0);
+        const char* trackType = MP4GetTrackType(infile, trackId);
+
+        if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE))
+        {
+            return trackId;
+        }
+    }
+
+    /* can't decode this */
+    return -1;
+}
+
+LPTSTR PathFindFileName(LPCTSTR pPath)
+{
+    LPCTSTR pT;
+
+    for (pT = pPath; *pPath; pPath = CharNext(pPath)) {
+        if ((pPath[0] == TEXT('\\') || pPath[0] == TEXT(':')) && pPath[1] && (pPath[1] != TEXT('\\')))
+            pT = pPath + 1;
+    }
+
+    return (LPTSTR)pT;   // const -> non const
+}
+
+char *convert3in4to3in3(void *sample_buffer, int samples)
+{
+    int i;
+    long *sample_buffer24 = (long*)sample_buffer;
+    char *data = malloc(samples*3*sizeof(char));
+
+    for (i = 0; i < samples; i++)
+    {
+        data[i*3] = sample_buffer24[i] & 0xFF;
+        data[i*3+1] = (sample_buffer24[i] >> 8) & 0xFF;
+        data[i*3+2] = (sample_buffer24[i] >> 16) & 0xFF;
+    }
+
+    return data;
+}
--- /dev/null
+++ b/plugins/QCDMp4/utils.h
@@ -1,0 +1,34 @@
+/*
+** FAAD - Freeware Advanced Audio Decoder
+** Copyright (C) 2002 M. Bakker
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+** 
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** $Id: utils.h,v 1.1 2003/04/28 19:07:57 menno Exp $
+**/
+
+#ifndef UTILS_INCLUDED
+#define UTILS_INCLUDED
+
+#include <mp4.h>
+
+LPTSTR PathFindFileName(LPCTSTR pPath);
+int GetVideoTrack(MP4FileHandle infile);
+int GetAudioTrack(MP4FileHandle infile);
+int GetAACTrack(MP4FileHandle infile);
+int StringComp(char const *str1, char const *str2, unsigned long len);
+char *convert3in4to3in3(void *sample_buffer, int samples);
+
+#endif
\ No newline at end of file