WEB开发网
开发学院软件开发VC 用DirectShow抓取影片帧 阅读

用DirectShow抓取影片帧

 2006-07-23 11:32:37 来源:WEB开发网   
核心提示: 第七步:调用IMediaDet::WriteBitmapBits方法将影片的帧保存为位图,若想指定保存哪一帧,用DirectShow抓取影片帧(3),只需要给第一个参数传递一个合适的时间即可,这里,源代码的DEBUG文件夹下包含了一个测试影片,供测试使用,我传递给第一个参数的时间为0,因此

第七步:调用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环境下编译并运行通过。

上一页  1 2 3 

Tags:DirectShow 抓取 影片

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接