用DirectShow抓取影片帧
2006-07-23 11:32:37 来源:WEB开发网第七步:调用IMediaDet::WriteBitmapBits方法将影片的帧保存为位图,若想指定保存哪一帧,只需要给第一个参数传递一个合适的时间即可。这里,我传递给第一个参数的时间为0,因此程序将保存影片第一帧的位图。
下面是GrabFramFromMovie函数的完整代码,其中,变量m_editOpenDir和m_editSaveDir分别指定了影片路径及保存的位图路径,请对照上面的步骤阅读:
HRESULT CFrameGrabberDlg::GrabFrameFromMovie()
{
HRESULT hr;
// 定义IMediaDet接口实例
CComPtr< IMediaDet > pDet;
hr = CoCreateInstance( CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER,
IID_IMediaDet, (void**) &pDet );
if (FAILED(hr))
return hr;
// 将影片文件名转换成BSTR类型
CComBSTR openBSTR(m_editOpenDir);
// 设置IMediaDet接口的文件关联
hr = pDet->put_Filename(openBSTR);
if (FAILED(hr))
return hr;
// 从影片中检索视频流和音频流
long lStreams;
hr = pDet->get_OutputStreams(&lStreams);
if (FAILED(hr))
return hr;
// 取出影片的视频流,因为帧的信息是保存在视频流中的
bool bFound = false;
for (int i=0; i<lStreams; i++)
{
GUID major_type;
hr = pDet->put_CurrentStream(i);
if (SUCCEEDED(hr))
hr = pDet->get_StreamType(&major_type);
if (FAILED(hr))
break;
if (major_type == MEDIATYPE_Video)
{
bFound = true;
break;
}
}
if (!bFound)
return VFW_E_INVALIDMEDIATYPE;
long width = 0, height = 0; // 存储位图的宽和高(单位:象素)
AM_MEDIA_TYPE mt;
hr = pDet->get_StreamMediaType(&mt);
if (SUCCEEDED(hr))
{
if ((mt.formattype == FORMAT_VideoInfo) &&
(mt.cbFormat >= sizeof(VIDEOINFOHEADER)))
{
// 得到VIDEOINFOHEADER结构指针,VIDEOINFOHEADER结构包含一些与视频
// 有关的信息,其中含有BITMAPINFORHEADER结构
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(mt.pbFormat);
width = pVih->bmiHeader.biWidth;
height = pVih->bmiHeader.biHeight;
}
else
hr = VFW_E_INVALIDMEDIATYPE;
MyFreeMediaType(mt); // 释放AM_MEDIA_TYPE结构
}
if (FAILED(hr))
return hr;
CComBSTR saveBSTR(m_editSaveDir);
// 将第一帧保存为指定路径的位图文件
hr = pDet->WriteBitmapBits(0, width, height, saveBSTR);
if (FAILED(hr))
return hr;
return S_OK;
}
三、程序运行:
程序运行后,选择一个影片,然后指定保存路径,点击“抓取”按钮,就可以将影片第一帧保存到指定路径下,我们也可以修改IMediaDet接口的WriteBitmapBits方法中的第一个参数来保存我们指定的帧。源代码的DEBUG文件夹下包含了一个测试影片,供测试使用。该程序在Windows XP、Visual C++ 6和DirectX 9.0b环境下编译并运行通过。
Tags:DirectShow 抓取 影片
编辑录入:爽爽 [复制链接] [打 印]更多精彩
赞助商链接