在VS2012环境下使用DirectShow+X264+Mp4Encoder录制、编码、合成MP4视频

在我之前的一篇博客“使用DirectShow+VS2012预览、录制摄像头视频,播放本地视频”中,我使用了一种效率不高的方法来进行摄像头视频的预览和录制,而且录制的视频所占用的磁盘空间还很大(40秒的视频有110多兆), 为了提高项目的实用性,我得寻找一种视频编码技术。后来通过查找资料发现了一种开源的x264编码技术,然后以“Directshow+x264”为关键词在网上搜索相关的资料,搜索到一位名叫“快乐阿门”的博主的一系列文章(https://blog.csdn.net/klamen)。我程序编写的思路以及具体代码都是以他为主要参考的。由于我只需要录制视频而不需要录制音频,所以我只分析了他文章中的视频部分。下面我以他的程序为对比详细地讲述一下我的编程过程。

“快乐阿门”的思路是先利用 ISampleGrabber 来获取摄像头中视频流的数据,并且通过ISampleGrabber::SetCallback()设置回调函数,在被调用函数中将每帧数据存入队列。然后另开辟一个线程,在线程中将每帧数据取出并转换成YUV420格式,再使用x264进行编码,最后使用Mp4Encoder(这是一个合成MP4文件的函数,函数名字是自己取的)将x264类型的数据合成MP4文件。

按照他的思路,我也开始尝试这样编写,但是发现有两个问题无法解决。

第一:每帧视频数据的入队和出队不在同一个线程中,而且每帧的数据的大小又不尽相同,从而无法使用数组来保存数据。如果只记录存放数据缓冲区的地址,又会有很大的隐患。
第二:下面这个被回调函数的形参我不知道是如何传递进来的,分别逐步调试他和我的程序时发现他的第一个形参是一个非0值,而我的就是0。这样就导致在我将视频帧写入MP4文件时帧间隔为0,从而视频迅速放完。

HRESULT STDMETHODCALLTYPE CAudioSampleGrabber::BufferCB(double SampleTime, BYTE *pBuffer, long BufferLen)

对于第一个问题,“快乐阿门”使用的是c++的STL,但是由于我是初学,还没有深入学习STL,所以无法解决。

对于第二个问题,目前我还没有看懂他的代码是怎样实现的,在网上查找资料也没有结果。

由于无法解决这两个问题,我决定换一种思路:利用定时器而不是通过设置回调函数来处理数据。当定时时间到了之后,利用 ISampleGrabber 抓取一帧数据,然后将其转换为YUV420格式,进而使用x264编码,最后写入MP4文件中。

这种做法的好处就是视频帧数据现取现用,内存开销小;不需要开辟新线程,程序简单。

不足之处就是,定时器中需要处理的东西较多,对电脑的配置要求较高,视频的帧数也不能的太大,因为定时时间等于1000(ms)/fps,如果帧数过大,可能会导致本次定时器溢出后的代码还没执行完毕,又来了新的溢出。

我所用的摄像头分辨率是1280*720,fps为15,录制的效果不错。

附上我的工程文件:https://pan.baidu.com/s/1m1ZgK6gjbFXacKFZWTRlbg 
提取码:wx0d 
 

最后,非常感谢“快乐阿门”博主!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值