利用ATL實現QuickTime多媒體檔案播放 (轉)
:namespace prefix = o ns = "urn:schemas--com::office" />
利用ATL實現QuickTime
多
摘要 本文主要介紹了平臺上Visual C++ 6利用ATL庫和QuickTime SDK開發播放QuickTime多媒體。為從事多媒體播放開發工作者提供借鑑和參考。
關鍵詞 多媒體 播放 QuickTime ATL
1 前言
在當今多媒體播放軟體主要有dia 、er和QuickTime。 Apple公司的QuickTime於1991年登臺亮相,是Apple公司面向專業影片編輯、網站建立和CD-ROM內容製作領域開發的多媒體技術平臺,QuickTime支援幾乎所有主流的個人平臺,是數字媒體領域事實上的工業標準,是建立3D動畫、實時效果、虛擬現實、A/V和其他數字流媒體的重要基礎。
由於眾多企業有對QuickTime player應用的需求,在國內外相關資料中有用Windows SDK或MFC的相關應用,本文試用小巧的ATL庫和QuickTime SDK開發定製QuickTime 多媒體播放軟體做了分析。
2 QuickTime Windows的開發概述
2.1開發前的準備
登陸Apple官方網站QuickTime SDK和了解有關技術資料。
由於QuickTime原先是為Mac OS設計,所以它裡面的許多概念和的都是面向Mac。
表1 Windows and QTML 術語比較
Windows 術語
QTML 對應術語
Message ( MSG )
Event ( EventRecord )
Graphics Device Interface (GDI)
QuickDraw
Device context ( DC )
Graphics port ( CGrafPort )
Window handle ( HWND )
Window pointer ( CWindowPtr )
Common Dialog Box Library
Standard File Package
對於一個原來是Windows程式設計師必須對於一些QuickTime概念有些最基本的瞭解才能比較快的掌握典型QuickTime Windows程式的開發。
2.2開發基本步驟
開發一個簡單的QuickTime Windows程式必須採取下面基本步驟加入到Windows應用中。
2.2.1在程式的開頭初始化QuickTime媒體層(InitializQTML)和QuickTime(EnterMovies)。
2.2.2和電影視窗建立圖形埠的關聯(CreatePortAssociation)。
2.2.3開啟電影(OpenMovieFile)和得到電影的控制程式碼(NewMovieFromFile)。
2.2.4建立在螢幕上顯示電影影像的(NewMovieController)。
2.2.5在Windows處理函式中,將接收的Windows訊息轉換為QTML事件(WinEventToMacEvent)並將它們傳到電影控制元件處理(MCIsPlayerEvent)。
2.2.6如果不在用到,釋放電影控制程式碼(DisposeMovie)和電影控制元件(DisPoseMovieController)。
2.2.7當銷燬視窗時,破壞電影圖形埠的關聯(DestroyPortAssociation)。
3 在ATL上實現播放
3.1用ATL建立Windows視窗
以CWindowImpl為基類,編寫自己的視窗類CQTVoWnd。並且定義宏來接收視窗訊息。
#define MY_QT_MSG_HANDLE(func)
{
BOOL bHandled = TRUE;
lResult;
func(uMsg,wParam,lParam,bHandled);
if(bHandled)
return TRUE;
}
class CQTVideoWnd:
public CWindowImpl
{
public:
CQTVideoWnd(HWND hParent, RECT& rc, IVideoPlayerNotifySink* pVPSink);
virtual ~ CQTVideoWnd();
public:
BEGIN_MSG_MAP(CVideoPlayerQT)
MY_QT_MSG_HANDLE (NewProc)
END_MSG_MAP()
protected:
LRESULT NewProc(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
……
CQuickTime m_QT;
……
}
CQuickTime為筆者呼叫QuickTime 的輔助類,後面將介紹。
NewProc成員函式根據接收不同的視窗訊息分別呼叫不同的成員函式處理。
LRESULT CQTVideoWnd::NewProc(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if(uMsg == WM_ERASEBKGND)
{
bHandled = FALSE;
LRESULT theResult = DefWindowProc(uMsg, wParam, lParam);
m_QT.ProcessMovieEvent (m_hWnd, uMsg, wParam, lParam);
return theResult;
}
else
{
m_QT.ProcessMovieEvent (m_hWnd, uMsg, wParam, lParam);
switch(uMsg)
{
case WM_CREATE:
OnCreate(uMsg, wParam, lParam,bHandled);
break;
case WM_PAINT:
OnPaint(uMsg, wParam, lParam,bHandled);
break;
case WM_DESTROY:
OnDestroy(uMsg, wParam, lParam,bHandled);
break;
default:
bHandled = FALSE;
break;
}
}
return 0;
}
其中OnCreate、OnPaint、OnDestroy等成員函式將根據2.2,分別呼叫輔助類CQuickTime處理。如
LRESULT CQTVideoWnd::OnCreate(UINT uMsg, WPARAM wParam , LPARAM lParam, BOOL& bHandled)
{
m_QT.OnMovieWindowCreate(m_hWnd,NULL);
return 0;
}
3.2 CQuickTime
CQuickTime為呼叫QuickTime API函式的輔助類。
3.2.1初始化和退出應用
InitializeQT和Tenate分別為初始化QuickTime媒體層和退出QuickTime媒體層。它們可以在程式的開始和結束。我們在CQTVideoWnd的建構函式和解構函式中呼叫它們。
BOOL CQuickTime::InitializeQT(IQTEventSink* pQTEventSink /*= NULL*/)
{
……
OSErr Err = noErr;
// Initialize QuickTime Media Layer
Err = InitializeQTML(0);
// Initialize QuickTime
if(Err == noErr)
{
Err = EnterMovies();
}
else
{
Err = QT_NOPLAYER;
}
if(Err == noErr)
{
//Because we can not distinguish the error from which
//So we marked SetMoviesErrorProc
// SetMoviesErrorProc(MoviesErrorProc,(long)this);
}
else
Err = QT_INITIAL_ERR;
……
return Err == noErr ? TRUE : FALSE;
}
如果要得到QuickTime的錯誤程式碼,我們可以在初始化完後呼叫SetMoviesErrorProc函式,但是假如一個應用中有多個QuickTime的電影。我們將不能區分錯誤來自哪個物件。
void CQuickTime::Terminate()
{
// Clean up
ExitMovies();
TerminateQTML();
DeInfo("CQuickTime::Terminate this = %p,m_pQTEventSink = %p",this,m_pQTEventSink);
}
3.2.2得到電影的控制程式碼
如果是本地檔案呼叫OpenLocalMovie,得到控制程式碼後儲存在成員變數裡m_Movie。該函式開啟電影后建立MovController。Apple公司推薦一般用Movie Controller來播放電影。
BOOL CQuickTime::OpenLocalMovie(LPCSTR fullPath)
{
_ASSERTE(fullPath && m_hViewWnd);
if(!fullPath || !m_hViewWnd)
return FALSE;
VIDEO_STATUE oldState = m_enState;
if ( strlen ((char*)fullPath ) != 0)
{
OSErr err;
short nTheFile = 0;
long lControllerFlags = 0L;
FSSpec File;
short nMovieResFile;
short nMovieResId;
char theFullPath[255];
// Close any previously opened movie
CloseMovie();
// make a copy of our full path name
strcpy ( (char *)theFullPath, (const char *) fullPath );
// convert theFullPath to pstring
c2pstr( (char*)theFullPath );
// Make a FSSpec with a pascal string filename
FSMakeFSSpec(0,0L,(unsigned char*)theFullPath, &sfFile);
// Set the port
SetGWorld((CGrafPtr)GetHWNDPort(m_hViewWnd), nil);
// Open the movie file
err = OpenMovieFile(&sfFile, &nMovieResFile, fsRdPerm);
if (err == noErr)
{
// Get the Movie from the file
nMovieResId = 0;
err = NewMovieFromFile(&m_Movie,nMovieResFile,
&nMovieResId,
nil,
newMovieActive, /* flags */
nil);
// Close the movie file
CloseMovieFile(nMovieResFile);
if (err == noErr)
{
SetMovieTimeScale(m_Movie,1000);
m_bBegine = TRUE;
// Create the movie controller
CreateNewMovieController(m_hViewWnd,m_Movie,&m_MC);
p2cstr((unsigned char*)theFullPath);
if(m_MC)
{
return TRUE;
}
}
}
}
CloseMovie();
return FALSE;
}
如果是URL檔案,呼叫OpenURLMovie,該函式跟OpenLocalMovie區別主要在於不用NewMovieFromFile而用NewMovieFromDataRef來得到控制程式碼。
一般電影在建立完Movie Controller後最好呼叫PrePrerollMovie。
void CQuickTime::CreateNewMovieController(HWND hwnd, Movie theMovie, MovieController *theMC)
{
……
PrePrerollMovie(theMovie, GetMovieTime(theMovie, NULL), GetMoviePreferredRate(theMovie), NewMoviePrePrerollCompleteProc(QTPrePrerollCompleteProc), (void *)m_hViewWnd);
}
3.2.3關閉電影
void CQuickTime::CloseMovie(void)
{
if (m_MC)
{
DisposeMovieController(m_MC);
}
if (m_Movie)
{
DisposeMovie(m_Movie);
}
m_Movie = NULL;
m_MC = NULL;
}
3.2.4建立和取消電影視窗關聯
int CQuickTime::OnMovieWindowCreate(HWND hWnd, CREATESTRUCT *lpCreateStruct)
{
if ( hWnd != NULL)
{
m_hViewWnd = hWnd; // the view's hwnd
// Create GrafPort HWND association
CreatePortAssociation(m_hViewWnd, NULL, kQTMLHandlePortEvents);
}
return 0;
}
void CQuickTime::OnMovieWindowDestroy()
{
if(m_Movie)
AbortPrePrerollMovie(m_Movie,noErr);
CGrafPtr windowPort = NULL;
// close any movies before destroying PortAssocation
CloseMovie();
// Destroy the view's GrafPort HWND association
if (m_hViewWnd)
windowPort = (CGrafPtr)GetHWNDPort(m_hViewWnd);
if (windowPort)
DestroyPortAssociation(windowPort);
}
3.2.5控制電影播放
筆者用控制MCDoAction來控制播放,這樣可以得到播放的狀態,當然也可以呼叫StartMovie、StopMovie等api函式。例如,
void CQuickTime::Play()
{
if(m_Movie)
{
MCDoAction (m_MC, mcActionPlay, (void *)GetMoviePreferredRate(m_Movie));
long controllerFlags;
MCGetControllerInfo(m_MC,&controllerFlags);
if((controllerFlags&mcInfoIsPlaying))
//Now this is playing state.
}
}
4 綜述
透過上面較為詳細的討論對於建立一個QuickTime的視窗,開啟和控制QuickTime電影檔案的播放的基本概念和基本過程,我認為QuickTime Player在Windows的平臺的應用將更為寬廣。同時為Apple公司在多媒體播放上的努力而致敬。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-962084/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 利用ATL製作程式多媒體封面元件 (轉)元件
- 解決MPLAYER播放不了多媒體檔案的方法。
- 在VB中用API實現多媒體 (轉)API
- C# DirectShow 播放多媒體C#
- Android -- 多媒體播放之MediaPlayer使用內部實現簡析Android
- CES展:FIC展示Linux多媒體播放器(轉)Linux播放器
- 通過 Git 來管理多媒體檔案Git
- 透過 Git 來管理多媒體檔案Git
- Android掃描多媒體檔案剖析Android
- ASP.NET利用HttpHandler實現多副檔名檔案下載ASP.NETHTTP
- 多媒體播放器哪款值得入手?播放器
- OmniPlayer Pro for Mac(全能多媒體播放器)Mac播放器
- XviD4PSP for mac多媒體檔案格式轉換器Mac
- 在C#中利用DirectX實現聲音播放(轉)C#
- Permute for mac(媒體檔案格式轉換器)Mac
- 利用IhttpHandler實現檔案下載HTTP
- 利用pearcmd實現裸檔案包含
- ZipArchive 實現媒體後者檔案資源打包下載Hive
- OpenHarmony 3.2 Beta多媒體系列——音影片播放框架框架
- OmniPlayer Pro for Mac(全能多媒體播放器)1.4.8Mac播放器
- ajax利用FormData、FileReader實現多檔案上傳php獲取ORMPHP
- Permute 3 for mac(媒體檔案格式轉換器)Mac
- Android多媒體之認識MP3與內建媒體播放(MediaPlayer)Android
- 試論多媒體技術與專案管理(轉)專案管理
- 自帶多媒體視訊播放器Infuse pro播放器
- 大型WAV檔案的播放 (轉)
- 利用 Webpack 實現小程式多專案管理Web專案管理
- 在ASP.NET中實現多檔案上傳 (轉)ASP.NET
- 開源專案如何利用社交媒體
- HttpFileCollection 實現多檔案上傳HTTP
- JMeter流媒體線上播放HLS外掛BlazeMeter - HLS Plugin實現視訊線上播放壓測JMeterPlugin
- asp.net利用jquery播放mp3檔案ASP.NETjQuery
- 支援M1、Infuse Pro for Mac「多媒體播放器」Mac播放器
- linux 利用rsync實現檔案增量同步Linux
- 利用rsync實現快速刪除海量檔案
- Java 在Word中嵌入多媒體(視訊、音訊)檔案Java音訊
- Linux下的多媒體軟體(轉)Linux
- Android 媒體播放框架MediaSession分析與實踐Android框架Session