这篇文章主要针对《DirectShow中利用SampleGrabber捕获摄像头每一帧图像,并转为BMP文件信息写入内存》所写,记录了开发过程中遇到的比较深刻的问题。文中代码均来自上文。欢迎大家交流斧正。

P1:如何合理放置SampleGrabber在Filter Graph中的位置?

S1:在放置SampleGrabber位置时应该很小心,因为SampleGrabber通常是作为一个TransformFilter存在的,而不是一个RendererFilter存在。当然,它也能作为一个RendererFilter存在,但是这样一来就不能实现通常所要求的预览功能了。写法如下:

hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF, NULL, pGrabBase);  

那么应该怎样使得SampleGrabber和RendererFilter都得到Media Sample数据呢?容易发现,对于ICaptureGraphBuilder2::RenderStream(const GUID *pCategory,const GUID *pType,IUnknown *pSource,IBaseFilter *pIntermediate,IBaseFilter*pSink)的最后三个参数,pSource指向一个作为源头的SourceFilter或者输出Pin;pIntermediate指向一个中间Filter或者一个解压缩Filter(当然TransformFilter包括在内),可以为NULL;pSink指向一个RendererFilter或者一个MuxFilter,如果为空,将使用默认Filter。
   有了以上信息,我们不难把pIntermediate和我们的SampleGrabber Filter联系起来。所以可以如下写法:

 hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pBF, pGrabBase, m_pVMR);

这样一来,就能实现捕获和预览功能了。
  
P2: 如何合理copy回调函数BufferCB得到的内存数据,比如大小?
S2:
在FormatImage函数中,我们需要copy回调函数BufferCB得到的内存数据到一块内存中,进行处理。但是这个时候copy的大小就很重要了。不能大也不能小。这个地方其实不难想到大小是多少,但是容易犯“想当然”的错误。比如如下写法:

memset( m_pImgFileData, 0, nDataWidth*nImgHeight ) ;
memcpy( m_pImgFileData, lpImageData, nImgWidth*nImgHeight) ;

注意了,很多时候可能会想当然地认为nImgWidth*nImgHeight就是buffer的大小,其实不然。如果想如上写法,能得到一定的图片的信息,但是不完整。我当时就只能看到图片的下半部分。其实,在回调函数BufferCB中我们已经保存了这块buffer的大小:

if (!cb.pBuffer)
{
cb.pBuffer = new BYTE[lBufferSize];
cb.lBufferSize = lBufferSize;
}

正确的方法应该是直接使用已经保存起来的buffer大小去copy,如下:

memset( m_pImgFileData, 0, nDataWidth*nImgHeight ) ;
memcpy( m_pImgFileData, lpImageData, cb.lBufferSize) ;

P3:关于可能出现的内存泄露问题,比如BufferCB的内存管理问题?
S3:
之前在没有使用SampleGrabber时,程序不存在内存泄露的问题。但是用了之后就出现了泄露问题。说实话,我当时是一头雾水,就拼命地寻找哪块buffer或者哪个filter没有及时释放。在可能的地方都加上释放语句。结果最终证明这样做是错的,即是弄巧成拙。我的愚蠢做法如下:

BYTE* pImageData = new BYTE[cb.lBufferSize];
CopyMemory(pImageData, cb.pBuffer, cb.lBufferSize);
if (mCB.FormatImage(pImageData, 24,  cb.bih.biWidth, cb.bih.biHeight))
{
ScaleRgb24BmpData(TransformBuffer, 320, 240,( mCB.GetImgFileData()),cb.bih.biWidth, cb.bih.biHeight);
ZeroMemory(m_pData, BUFFER_SIZE);
CopyMemory(m_pData, TransformBuffer, BUFFER_SIZE);
}
//to free memory
cb.pBuffer = NULL;
delete pImageData;

看似没问题的代码,其实有一个很大的泄漏问题。我们注意到,在BufferCB中有这样的语句:

if (!cb.pBuffer)
{
cb.pBuffer = new BYTE[lBufferSize];
cb.lBufferSize = lBufferSize;
}

这就是说,如果cb.pBuffer为空的话,就会重新new一次,就会重新分配一块IBufferSize大小的内存。与此同时,你别以为之前那个cb.pBuffer所分配的内存已经回收了,它只是被只设置为NULL了而已!接着,你就会使用new出来的内存,之前的cb.pBuffer内存就泄露了。事实上,BufferCB函数会自己处理内存释放的问题,你不用瞎操心,要不然就画蛇添足了。所以做法应该是删除cb.pBuffer = NULL;这句。

//END ICTwangbiao

SampleGrabber开发问题与解决方案相关推荐

  1. 微软一站式开发技术框架解决方案 年内展望

    微软一站式开发技术框架解决方案 (CodeFx) 自成立至今已有半年.在这半年里,我们完成了130个代码示例,主要覆盖了COM.数据访问.库加载.进程间通信.Office开发.WinForms等技术. ...

  2. GIS项目中数据开源、工具开源、开发开源的解决方案

    GIS项目中数据开源.工具开源.开发开源的解决方案 参考文章: (1)GIS项目中数据开源.工具开源.开发开源的解决方案 (2)https://www.cnblogs.com/naaoveGIS/p/ ...

  3. CodeFx: 微软一站式开发技术框架解决方案 2009-7-30 新增sample code简介

    微软一站式开发技术框架解决方案 2009年7月30号更新: http://cfx.codeplex.com/Wiki/View.aspx?title=All-In-One%20Code%20Frame ...

  4. ARKit从入门到精通(11)-ARKit开发常见问题及解决方案

    转载请注明出处:ARKit从入门到精通(11)-ARKit开发常见问题及解决方案 本文主要介绍ARKit开发过程中一些常见问题 1.ARKit框架无法导入问题 2.ARKit运行黑屏或者白屏问题:Un ...

  5. UI开发的终极解决方案

    2019独角兽企业重金招聘Python工程师标准>>> 呵呵,有点标题党的意思,但是如果你正在寻找UI解决方案,你一定不会白来的. 虽然没有直接开发前台界面,但是好呆也看了这么些年, ...

  6. 开发跨平台应用解决方案-uniapp 真心不错,支持一波

    开发跨平台应用解决方案-uniapp 真心不错,支持一波 参考文章: (1)开发跨平台应用解决方案-uniapp 真心不错,支持一波 (2)https://www.cnblogs.com/simao/ ...

  7. web app开发利器 - iscroll4 解决方案

    web app开发利器 - iscroll4 解决方案 参考文章: (1)web app开发利器 - iscroll4 解决方案 (2)https://www.cnblogs.com/aaronjs/ ...

  8. Android 9.0/P 开发问题及解决方案汇总

    Android 9.0/P 开发问题及解决方案汇总 参考文章: (1)Android 9.0/P 开发问题及解决方案汇总 (2)https://www.cnblogs.com/renhui/p/979 ...

  9. net-snmp开发代理常见问题解决方案

    转自:http://www.aichengxu.com/view/43967 net-snmp开发代理常见问题解决方案,有需要的朋友可以参考下. snmpd启动方式: ./snmpd-Lsd-Lf/d ...

最新文章

  1. PyTorch 常用代码段示例整理
  2. EZ430 Chronos 自带程序源码:test 示范程序
  3. django网上商城_网上商城开源项目合集
  4. PDF文件加密有什么方法?如何给PDF文件加密
  5. NSubstitute完全手册索引
  6. oracle两个约束,Oracle中的约束介绍(2)
  7. Silverlight 4 初学者的10大经典问答
  8. Ora-01008错误:oracle 并非所有变量都已绑定的原因
  9. vue2.0 $set()的用法
  10. 连接局域网打印机简易教程
  11. python爬虫网页崩溃怎么处理_《Python网络爬虫》1.2 爬取网页的异常处理
  12. Android 蓝牙开发 BLE(低功耗) 摩拜单车共享汽车开门实例
  13. 驱动VS1003要注意的事项
  14. 26个顶尖战略咨询公司常用分析模型详解!
  15. 专利缴费后如何获取发票
  16. Dropwizard框架新手学习教程(详细版)
  17. CentOS 7使用samba共享文件夹
  18. 大白话说网络(四)-----应用层常用协议介绍
  19. 微软原版Windows XP Pro With SP3 VOL MSDN原版镜像
  20. LinkedIn领英在什么情况下容易被封,提前学习避免进坑

热门文章

  1. 黑产工具情报的分析方式浅析
  2. 463个生活小窍门 找找你需要的!(1-200)
  3. HTC M8t unlock Bootloader/Root/S-OFF/解网络锁笔记
  4. vue2 provide和inject的使用
  5. 錦匯行商業管理公司对于西昌商铺一条街公开秩序管理方案
  6. 《大明王朝》掠之于官
  7. 一款简易低成本智能割草机的制作——硬件篇
  8. 浏览器的作用不只是搜索、浏览网页,它还隐藏着这些功能
  9. 手机上面正常显示网页大小
  10. 蛮力法的相关问题总结