DirctorShow 获取AVI文件的所有帧
2011-04-02 11:14
49 查看
首先很感谢
http://www.vckbase.com/document/viewdoc/?id=976
这位作者。谢谢他那么耐心的讲解
directorshow
提取
AVI
帧。我这篇文章是想再整理一下,希望能对初学者有帮助。
需要安装
DirectX9.0bSDK
,我安装了一个
exe
版本的。很奇怪,我去安装目录查了一下,只是一个
Doc
文件,之后又去下载了一个
DirectShowSDKinDirectX9.0b
版本的,结果看到我要的
Lib
和
Include
文件。我将他们放在
VC
安装目录,并在
VC
中加入他们的目录,方法是:菜单
->Tools->Options->Directories
中,在
show directories for
中选择
include files
在
Directories
中加入
Directorshow
的
include
文件路径。然后将
show directories for
选择
Library files
,相同的加入
lib
路径进去。好!配置环境好了。
建立一个
Dlg
文件工程。主要代码,大家还是下载上面那个链接中的源码。
需要修改的地方有:
1.
修改
bmp
文件保存路径。
void CFrameGrabberDlg::OnSaveBrowse()
{
char szDir[MAX_PATH];
BROWSEINFO bi;
ITEMIDLIST *pidl;
bi.hwndOwner = this->m_hWnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = szDir;
bi.lpszTitle = "
请选择受控的目录
";//strDlgTitle;
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.lParam = 0;
bi.iImage = 0;
pidl = SHBrowseForFolder(&bi);
if(pidl == NULL)
return;
if(!SHGetPathFromIDList(pidl, szDir))
return;
m_editSaveDir.Format("%s//",szDir);
UpdateData(FALSE);
}
2.
修改主要的函数
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;
double totalTime,dRate;
pDet->get_FrameRate(&dRate); //
获取帧播放的速率
pDet->get_StreamLength(&totalTime);
//
将第一帧保存为指定路径的位图文件
for(i=0;i<totalTime*dRate;i++)
{
CString str;
str.Format("%sbmpfile%d.bmp",m_editSaveDir,i);
double position = (double)(i/dRate);
CComBSTR saveBSTR(str);
hr = pDet->WriteBitmapBits(position, width, height, saveBSTR);
}
if (FAILED(hr))
return hr;
return S_OK;
}
就好了。黑体是修改了的。这样就完成了对
avi
每一帧的提取了。
http://www.vckbase.com/document/viewdoc/?id=976
这位作者。谢谢他那么耐心的讲解
directorshow
提取
AVI
帧。我这篇文章是想再整理一下,希望能对初学者有帮助。
需要安装
DirectX9.0bSDK
,我安装了一个
exe
版本的。很奇怪,我去安装目录查了一下,只是一个
Doc
文件,之后又去下载了一个
DirectShowSDKinDirectX9.0b
版本的,结果看到我要的
Lib
和
Include
文件。我将他们放在
VC
安装目录,并在
VC
中加入他们的目录,方法是:菜单
->Tools->Options->Directories
中,在
show directories for
中选择
include files
在
Directories
中加入
Directorshow
的
include
文件路径。然后将
show directories for
选择
Library files
,相同的加入
lib
路径进去。好!配置环境好了。
建立一个
Dlg
文件工程。主要代码,大家还是下载上面那个链接中的源码。
需要修改的地方有:
1.
修改
bmp
文件保存路径。
void CFrameGrabberDlg::OnSaveBrowse()
{
char szDir[MAX_PATH];
BROWSEINFO bi;
ITEMIDLIST *pidl;
bi.hwndOwner = this->m_hWnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = szDir;
bi.lpszTitle = "
请选择受控的目录
";//strDlgTitle;
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.lParam = 0;
bi.iImage = 0;
pidl = SHBrowseForFolder(&bi);
if(pidl == NULL)
return;
if(!SHGetPathFromIDList(pidl, szDir))
return;
m_editSaveDir.Format("%s//",szDir);
UpdateData(FALSE);
}
2.
修改主要的函数
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;
double totalTime,dRate;
pDet->get_FrameRate(&dRate); //
获取帧播放的速率
pDet->get_StreamLength(&totalTime);
//
将第一帧保存为指定路径的位图文件
for(i=0;i<totalTime*dRate;i++)
{
CString str;
str.Format("%sbmpfile%d.bmp",m_editSaveDir,i);
double position = (double)(i/dRate);
CComBSTR saveBSTR(str);
hr = pDet->WriteBitmapBits(position, width, height, saveBSTR);
}
if (FAILED(hr))
return hr;
return S_OK;
}
就好了。黑体是修改了的。这样就完成了对
avi
每一帧的提取了。
相关文章推荐
- Java 获取目录所有文件,删除文件。
- php获取目录所有文件并将结果保存到数组(实例)
- C#递归获取所有目录下的文件信息并生成对应的XML件
- php 获取目录下所有文件实现代码
- Python获取指定路径下所有文件的绝对路径
- linux下获取所有文件夹和文件,支持nfs和xfs
- 如何通过ADO,获取一个数据库文件里面所有的表?
- Linux 获取文件夹下的所有文件
- python 获取指定文件夹下所有文件名称并写入列表
- Android 获取本地所有音频文件
- C#.NET获取指定文件夹下所有的指定类型文件
- python如何获取一个文件夹内包括子文件夹所有文件的名字和路径
- java获取某个文件夹下的所有文件、删除文件
- linux 获取目录下的所有文件
- python获取指定路径下所有指定后缀文件的方法
- iOS小技巧 - 获取指定文件夹下的所有相对路径(包括子文件夹路径),并实现指定文件夹下的所有文件的全部移动
- C++获取某路径下所有文件名,ifstream打开某路径下的指定文件
- C++获取一个目录下的所有文件
- C#获取文件夹中所有文件的文件名
- C#控制台基础 directory获取一个文件夹中所有文件的绝对路径(不包括文件夹)