分享
 
 
 

利用ATL实现QuickTime多媒体文件播放

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

利用ATL实现QuickTime

多媒体文件播放

摘要 本文主要介绍了Windows平台上Visual C++ 6利用ATL库和QuickTime SDK开发播放QuickTime多媒体软件。为从事多媒体播放开发工作者提供借鉴和参考。

关键词 多媒体 播放 QuickTime ATL

1 前言

在当今多媒体播放软件主要有Windows media player、Real player和QuickTime。 Apple公司的QuickTime于1991年登台亮相,是Apple公司面向专业视频编辑、Web网站创建和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为基类,编写自己的窗口类CQTVideoWnd。并且定义宏来接收窗口消息。

#define MY_QT_MSG_HANDLE(func)

{

BOOL bHandled = TRUE;

lResult;

func(uMsg,wParam,lParam,bHandled);

if(bHandled)

return TRUE;

}

class CQTVideoWnd:

public CWindowImpl<CVideoPlayerQT>

{

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 API的辅助类,后面将介绍。

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和Terminate分别为初始化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 object

//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();

DebugInfo("CQuickTime::Terminate this = %p,m_pQTEventSink = %p",this,m_pQTEventSink);

}

3.2.2得到电影的句柄

如果是本地文件调用OpenLocalMovie,得到句柄后保存在成员变量里m_Movie。该函数打开电影后创建Movie Controller。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 sfFile;

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_bBegineDownload = 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公司在多媒体播放上的努力而致敬。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有