帮酷LOGO
0 0 评论
文章标签:内存  视频  MEMO  捕获  sam  Frames  模式    


Screenshot - vidcap.jpg

介绍

我找到了一个项目,从外部视频设备到内存缓冲区,找不到我需要的一个项目。 Code an视频处理框架,通过 DirectShow 获取帧,并使用简单方法来获取原始数据的帧抓取器,不提供数据流的首选缓冲模式。 它的中一些只在on和 Windows 2000上进行测试,最新的一个返回 1999或者捕获视频文件中的样本。

我在电脑上安装 Vista,并安装 Windows SDK用于Vista和 DirectX SDK 2007. 现在直接显示是 Windows SDK的一部分,如果你想使用 ISampleGrabber 进行原始数据捕获,你需要安装 DirectX SDK。 i的MFC MFC,在缓冲模式下,用 GDI+ 文件捕获原始图像数据,捕获原始图像数据,以缓冲模式捕获原始图像数据,以方式显示。 使用该应用程序,你可以轻松地从图像/视频处理任务( 视频编解码器开发,运动估计,边缘检测) 开始。 我在我的人脸检测程序中使用了这个,我将稍后发布。

背景

你需要对直接显示编程有一个了解。 查看 上面 所提及的文章或者 Windows Vista SDK帮助。 需要了解com技术- have了解文章,介绍简介以及如何使用它。

使用代码

单击将枚举可用视频设备的enum 按钮并选择一个。 在毫秒( 默认为 1000,每秒捕获数据) 中指定希望的原始图像数据捕获间隔,单击 Run button。 左上方的小 static 将会预览视频输出,中心大的会显示捕获的原始图像。 拍照时,鼠标左键双击中心捕获窗口,捕获的图像将保存在磁盘上,并将捕获的图像保存到磁盘,其中X 是映像的编号。

为了实现代码重用,我在单独的文件中提供了示例抓取器和视频捕获实现。 我使用了来自SDK示例( SDKSamplesMultimediaDirectShowCapturePlayCap )的视频捕获例程。 我将它们封装在易于使用外部应用程序的功能中,并且还添加了视频设备枚举:

  • void vcGetCaptureDevices(CComboBox& adaptersBox);
  • HRESULT vcCaptureVideo(HWND msgWindow, HWND prvWindow, unsignedint devIndex = 1);
  • void vcStopCaptureVideo();

vcGetCaptureDevices() 枚举视频设备并将它的添加到 ComboBoxvcCaptureVideo() 使用 msgWindow 应用程序对 prvWindow 启动视频预览,该应用程序将处理过滤图通知消息。 devIndex 是捕获数据的视频设备的索引。 vcStopCaptureVideo 停止捕获视频数据。
vcCaptureVideo 函数中添加过滤器图形的示例抓取器如下所示:

//...hr = sgAddSampleGrabber(g_pGraph);if (FAILED(hr)) {
 Msg(TEXT("Couldn't add the SampleGrabber filter to the graph! hr=0x%x"), hr);
 return hr;
}
hr = sgSetSampleGrabberMediaType();if (FAILED(hr)) {
 Msg(TEXT("Couldn't set the SampleGrabber media type! hr=0x%x"), hr);
 return hr;
}
IBaseFilter* pGrabber = sgGetSampleGrabber();// Render the preview pin on the video capture filter// Use this instead of g_pGraph->RenderFilehr = g_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
 pSrcFilter, pGrabber/*NULL*/, NULL);if (FAILED(hr)) {
 Msg(TEXT("Couldn't render the video capture stream. hr=0x%xrn")
 TEXT("The capture device may already be in use by another application.
 rnrn")
 TEXT("The sample will now close."), hr);
 pSrcFilter->Release();
 return hr;
}
hr = sgGetSampleGrabberMediaType();//...

相应的sg* 函数位于 samplegrab.cpp 中:

HRESULT sgAddSampleGrabber(IGraphBuilder *pGraph)
{
 // Create the Sample Grabber. HRESULT hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
 IID_IBaseFilter, (void**) & pGrabberFilter);
 if (FAILED(hr)) {
 return hr;
 }
 hr = pGraph->AddFilter(pGrabberFilter, L"Sample Grabber");
 if (FAILED(hr)) {
 return hr;
 }
 pGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber);
 return hr;
}
HRESULT sgSetSampleGrabberMediaType()
{
 AM_MEDIA_TYPE mt;
 ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
 mt.majortype = MEDIATYPE_Video;
 mt.subtype = MEDIASUBTYPE_RGB24;
 HRESULT hr = pGrabber->SetMediaType(&mt);
 if (FAILED(hr)) {
 return hr;
 }
 //Do not stop the graph after one shot hr = pGrabber->SetOneShot(FALSE);
 //Use buffered mode hr = pGrabber->SetBufferSamples(TRUE);
 return hr;
}
IBaseFilter* sgGetSampleGrabber()
{
 return pGrabberFilter;
}
HRESULT sgGetSampleGrabberMediaType()
{
 AM_MEDIA_TYPE mt;
 HRESULT hr = pGrabber->GetConnectedMediaType(&mt);
 if (FAILED(hr)) {
 return hr;
 }
 VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER *)mt.pbFormat;
 gChannels = pVih->bmiHeader.biBitCount/8;
 gWidth = pVih->bmiHeader.biWidth;
 gHeight = pVih->bmiHeader.biHeight;
 sgFreeMediaType(mt);
 return hr;
}

在运行按钮按常规 CVidCapDlg::OnBnClickedRunButton() 实现视频预览和捕获的初始化,这是根据在主题"。使用样本抓取器"中描述的使用示例捕获器筛选器来查询捕获的原始图像数据的首选方法。

要获取原始图像数据,请使用来自 samplegrab.h的以下函数:

  • unsignedchar* sgGrabData();
  • Gdiplus::Bitmap* sgGetBitmap();
  • long sgGetBufferSize();

第一个返回带有原始图像数据的缓冲区指针,如果示例抓取器尚未准备就绪,则返回 NULL。 注意,示例抓取器筛选器填充了图像倒置的缓冲区,作为底层位图。 sgGetBitmap() 返回在 sgGrabData() 调用或者 NULL 之后填充原始图像数据的GDI+ bitmap,如果数据未被捕获则返回。 我使用 sgFlipUpDown() 函数在将原始图像复制到 bitmap 之前翻转原始图像。 如果要将原始图像绘制到窗口中,请先调用这些函数,然后再调用 sgGrabData() 对象将它的绘制到窗口中,稍后再调用。 要获取原始图像的缓冲区长度,请调用 sgGetBufferSize()

抓取的代码如下所示:

unsignedchar* sgGrabData()
{
 HRESULT hr;
 if (pGrabber == 0)
 return0;
 long Size = 0;
 hr = pGrabber->GetCurrentBuffer(&Size, NULL);
 if (FAILED(hr))
 return0;
 elseif (Size!= pBufferSize) {
 pBufferSize = Size;
 if (pBuffer!= 0)
 delete[] pBuffer;
 pBuffer = newunsignedchar[pBufferSize];
 }
 hr = pGrabber->GetCurrentBuffer(&pBufferSize, (long*)pBuffer);
 if (FAILED(hr))
 return0;
 else {
 sgFlipUpDown(pBuffer);
 return pBuffer;
 }
}

要确定图像大小,请调用以下函数:

  • unsignedint sgGetDataWidth();
  • unsignedint sgGetDataHeight();
  • unsignedint sgGetDataChannels();


文章标签:  模式  PRE  sam  视频  cap  MEMO  内存  

Copyright © 2011 HelpLib All rights reserved.    知识分享协议 京ICP备05059198号-3  |  如果智培  |  酷兔英语