您的位置:首页 > 其它

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
每一帧的提取了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  avi include null library bi exe