📄 videoplay.cpp
字号:
// VideoPlay.cpp: implementation of the CVideoPlay class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "VideoPlay.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CVideoPlay::CVideoPlay(HWND hwnd)
{
pigb = NULL;
pimc = NULL;
pimex = NULL;
pivw = NULL;
pmp = NULL;
pVCap = NULL;
CappFg = NULL;
CapPigb = NULL;
m_hwnd=hwnd;
}
CVideoPlay::~CVideoPlay()
{
HELPER_RELEASE(pivw);
HELPER_RELEASE(pigb);
HELPER_RELEASE(pimc);
HELPER_RELEASE(pimex);
HELPER_RELEASE(pmp);
HELPER_RELEASE(CapPigb);
HELPER_RELEASE(CappFg);
HELPER_RELEASE(pVCap);
}
//实时捕捉图像的播放
void CVideoPlay::RealPlay()
{
HRESULT hr;
//创建捕捉过滤器图表
CHECK_ERROR(CoCreateInstance((REFCLSID)CLSID_CaptureGraphBuilder,NULL,
CLSCTX_INPROC, (REFIID)IID_ICaptureGraphBuilder,(void **)&CapPigb),
"CoCreateInstance Error");
//创建过滤器图表
CHECK_ERROR(hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (LPVOID *)&CappFg),"Cannot instantiate filtergraph");
//将捕捉过滤器图表和过滤器图表进行关联
hr = CapPigb->SetFiltergraph(CappFg);
if (hr != NOERROR)
{
MessageBox(m_hwnd,"Cannot give graph to builder","Error",MB_OK);
return;
}
int uIndex=0;
//创建视频设备枚举器
ICreateDevEnum *pCreateDevEnum;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pCreateDevEnum);
//创建一个类型枚举器,指向系统的视频设备列表
IEnumMoniker *pEm;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pEm, 0);
HELPER_RELEASE(pCreateDevEnum);
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
//枚举每个视频设备
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
{
//生成并初始化管理该设备的过滤器
hr = pM->BindToObject(0, 0, IID_IBaseFilter, (void**)&pVCap);
if(pVCap== NULL)
{
MessageBox(m_hwnd,"Cannot get the capture filterr","Error",MB_OK);
return;
}
HELPER_RELEASE(pM);
uIndex++;
}
HELPER_RELEASE(pEm);
if(pVCap)
hr = CappFg->AddFilter(pVCap, NULL); //添加过滤器到Filter Graph中
if (hr != NOERROR)
{
MessageBox(m_hwnd,"Cannot add vidcap to filtergraph","Error",MB_OK);
return;
}
//连接源过滤器和提交过滤器
hr = CapPigb->RenderStream(&PIN_CATEGORY_PREVIEW,pVCap,NULL, NULL);
if (hr != S_OK)
{
MessageBox(m_hwnd,"This graph cannot preview properly","Error",MB_OK);
return;
}
//在过滤器图表中查找一个与捕捉有关的接口
hr = CapPigb->FindInterface(&PIN_CATEGORY_PREVIEW,pVCap,IID_IVideoWindow,(void **)&pivw);
if (hr != NOERROR)
{
MessageBox(m_hwnd,"cannot find Video Window properly","Error",MB_OK);
return;
}
else
{
DisplayVideoWin(); //显示视频播放窗口
}
//查询数据流控制接口
hr =CappFg->QueryInterface(IID_IMediaControl, (void **)&pimc);
if (SUCCEEDED(hr))
{
hr = pimc->Run(); //播放视频
}
else
{
MessageBox(m_hwnd,"Cannot run preview graph","Error",MB_OK);
return;
}
}
//显示视频播放窗口
void CVideoPlay::DisplayVideoWin()
{
RECT grc;
if(pivw)
{
//设置窗口所有者
pivw->put_Owner((OAHWND)m_hwnd);
//设置窗口尺寸
pivw->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
//设置窗口位置
::GetClientRect(m_hwnd, &grc);;
pivw->SetWindowPosition(grc.left, grc.top, grc.right, grc.bottom);
//显示窗口
pivw->put_Visible(OATRUE);
}
}
//停止播放视频
void CVideoPlay::StopPlay()
{
if(pimc)
{
//停止播放视频
pimc->Stop();
HELPER_RELEASE(pimc);
}
if (pivw)
{
//关闭视频播放窗口
pivw->put_Visible(OAFALSE);
pivw->put_Owner(NULL);
HELPER_RELEASE(pivw);
}
HELPER_RELEASE(CapPigb);
HELPER_RELEASE(CappFg);
HELPER_RELEASE(pVCap);
}
//播放视频文件
void CVideoPlay::PlayFromFile(CString szFile)
{
WCHAR wFile[MAX_PATH];
HRESULT hr;
MultiByteToWideChar( CP_ACP, 0, szFile.GetBuffer(_MAX_PATH), -1, wFile, MAX_PATH );
szFile.ReleaseBuffer();
//创建过滤器图表生成器接口
CHECK_ERROR(::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pigb),"CoCreateInstance Error") ;
//查询数据流控制接口
pigb->QueryInterface(IID_IMediaControl, (void **)&pimc);
//查询过滤器图表事件接口
hr=pigb->QueryInterface(IID_IMediaEventEx, (void **)&pimex);
//查询视频播放窗口接口
pigb->QueryInterface(IID_IVideoWindow, (void **)&pivw);
//查询数据流位置接口
hr=pigb->QueryInterface(IID_IMediaPosition, (void**) &pmp);
//为指定的多媒体文件创建一个过滤器图表进行处理
hr = pigb->RenderFile(wFile, NULL);
//得到视频文件的播放时间
if (SUCCEEDED(hr))
hr=pmp->get_Duration(&tLength);
//显示视频播放窗口
DisplayVideoWin();
if (SUCCEEDED(hr))
pimc->Run(); //播放视频
pimex->SetNotifyWindow((OAHWND)m_hwnd, WM_PLAYOVER, 0);
}
int CVideoPlay::PlayOver()
{
long evCode,evParam1,evParam2;
HRESULT hr;
if(pimex)
{
while (SUCCEEDED(pimex->GetEvent(&evCode, &evParam1, &evParam2, 0)))
{ // Spin through the events
hr = pimex->FreeEventParams(evCode, evParam1, evParam2);
if (EC_COMPLETE == evCode)
{ // Finished
if (pivw)
{ // Relinquish ownership (IMPORTANT!) after hiding
pivw->put_Visible(OAFALSE);
pivw->put_Owner(NULL);
HELPER_RELEASE(pivw);
} // Relinquish ownership (IMPORTANT!) after hiding
// HELPER_RELEASE(pif);
HELPER_RELEASE(pigb);
HELPER_RELEASE(pimc);
HELPER_RELEASE(pmp);
HELPER_RELEASE(pimex);
return 0;
break;
}
}
}
return -1;
}
//继续播放
void CVideoPlay::ResumePlay()
{
HRESULT hr;
//得到当前播放位置
hr = pmp->get_CurrentPosition(&tCurrent);
if (SUCCEEDED(hr))
{
// 如果已在播放文件的最后(播放时间剩下不到1分钟),当前位置回到文件头
if ((tRemain=tLength - tCurrent) < 1)
pmp->put_CurrentPosition(0);
//不在文件尾,当前位置不变
else
pmp->put_CurrentPosition(tCurrent);
}
if(pimc)
pimc->Run(); //继续播放文件
}
//暂停播放
void CVideoPlay::PausePlay()
{
if(pimc)
pimc->Pause();
}
//搜索视频设备,并返回视频设备名列表
void CVideoPlay::FindDevice(CStringList &DevName)
{
HRESULT hr;
int uIndex=0;
//创建一个系统设备枚举器接口
ICreateDevEnum *pCreateDevEnum;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pCreateDevEnum);
//创建一个类型枚举器,指向系统的视频设备列表
IEnumMoniker *pEm;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pEm, 0);
HELPER_RELEASE(pCreateDevEnum);
if(pEm)
{
pEm->Reset();
ULONG cFetched;
IMoniker *pM;
//枚举每个视频设备
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
{
IPropertyBag *pBag;
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr))
{
VARIANT var;
var.vt = VT_BSTR;
//得到视频设备的友好名称
hr = pBag->Read(L"FriendlyName", &var, NULL);
if (hr == NOERROR)
{
CString achName;
WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, achName.GetBuffer(50),80,NULL, NULL);
achName.ReleaseBuffer();
//将设备名添加到设备名列表末尾
DevName.AddTail(achName);
SysFreeString(var.bstrVal);
}
HELPER_RELEASE(pBag);
}
HELPER_RELEASE(pM);
uIndex++;
}
HELPER_RELEASE(pEm);
}
}
CVideoPlay::CVideoPlay()
{
pigb = NULL;
pimc = NULL;
pimex = NULL;
pivw = NULL;
pmp = NULL;
pVCap = NULL;
CappFg = NULL;
CapPigb = NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -