采集音频和摄像头视频并实时H264编码及AAC编码

0. 前言

  我在前两篇文章中写了DirectShow捕获音视频然后生成avi,再进行264编码的方法。那种方法有一些局限性,不适合实时性质的应用,如:视频会议、视频聊天、视频监控等。本文所使用的技术,适用于这种实时性的应用,通过处理采集出来的音视频的每一帧,实现实时编码,实时输出。这是我做直播系列应用的一部分,目前的情况是输入端采用DirectShow技术捕获音视频,然后对视频进行h.264编码,对音频进行aac编码,输出端则是生成文件,接下来还要进一步扩展输入端和输出端,以支持文件、桌面输入,RTSP、RTMP、HTTP等流式协议输出。

 

1. 简单介绍

  首先是捕获,这里采用了DirectShow的方式,对它进行了一定程度的封装,包括音视频。好处是直接使用native api,你可以做想做的任何修改,坏处是,不能跨平台,采集音视频这种应用,linux平台也是需要滴呀。有跨平台的做法,对视频,可以使用OpenCV,对音频,可以使用OpenAL或PortAudio等,这样就行了。

  编码可以选择的余地比较大,对视频来讲,有H264, MPEG-4, WebM/VP8, Theora等,音频有Speex, AAC, Ogg/Vorbis等,它们都有相应的开源项目方案,我采用的是x264进行H264编码,libfaac进行aac编码,之后是否更改编码方案,等具体项目需求再说了。这里提一下WebM,Google牵头的项目,完全开放和自由,使用VP8和Vorbis编码,webm(mkv)封装,有多家巨头支持,目的是想要取代当前的H264视频编码,号称比后者更加优秀,我没有测试过实际效果。不过有商业公司牵头就是不一样,各项支持都很全面,有时间了关注一下。

 

2. 逻辑和流程

  基本的思想是实现dshow ISampleGrabberCB接口,通过回调来保存每一个buffer。除了界面线程和dshow自己的线程之外,我们启动了两个线程,AudioEncoderThread和VideoEncoderThread,分别从SampleGrabber中取出数据,调用编码器进行编码,编码后的文件可以直接输出。看图:

     

  程序是用VS2010构建的,看张工程截图:

      

  Base下面的是对系统API的一些简单封装,主要是线程和锁。我这里简单也封装的了一下dshow的捕获过程,包括graph builder的创建,filter的连接等。directshow是出了名的难用,没办法,难用也得用。因为是VS2010,调用的Windows SDK 7.1中的dshow,没有qedit.h这个文件,而它正式定义ISampleGrabberCB的。不急,系统中还是有qedit.dll的,我们要做的就是从Windows SDK 6.0中,把它拷过来,然后在stdafx.h中加入这几行代码,就可以了

1 #pragma include_alias( "dxtrans.h", "qedit.h" )2 #define __IDxtCompositor_INTERFACE_DEFINED__3 #define __IDxtAlphaSetter_INTERFACE_DEFINED__4 #define __IDxtJpeg_INTERFACE_DEFINED__5 #define __IDxtKey_INTERFACE_DEFINED__6 #include "qedit.h"

 

3. 音视频编码

  相关文件:

      

  Encoder下就是音视频编码相关的代码。X264Encoder封装了调用x264编码器的操作,FAACEncoder封装了调用libfaac编码器的操作,VideoEncoderThread和AudioEncoderThread负责主要的流程。下面我把关键代码贴出来,大家可以参考一下。

  A. 视频编码线程

  主要流程是首先初始化x264编码器,然后开始循环调用DSVideoGraph,从SampleGrabber中取出视频帧,调用x264进行编码,流程比较简单,调用的频率就是你想要获取的视频帧率。要注意的一点是,x264进行编码比较耗时,在计算线程Sleep时间时,要把这个过程消耗的时间算上,以免采集的视频帧率错误。

  B. 音频编码线程

  主要流程和视频编码线程相同,也是初始化FAAC编码器,然后循环调用DSAudioGraph,从SampleGrabber中取出视频帧,调用faac进行编码。和视频不同的是,音频的sample的频率是非常快的,所以几乎要不断的进行采集,但前提是SampleGrabber中捕获到新数据了才行,不然你的程序cpu就100%了,下面代码中IsBufferAvailaber()就是做这个检测的。

  调用faac进行编码的时候,有点需要注意,大家特别注意下,不然编码出来的音频会很不正常,搞不好的话会很头疼的。先看下faac.h的相关接口

1 faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate, unsigned int numChannels,2                   unsigned long *inputSamples, unsigned long *maxOutputBytes);3 4 int FAACAPI faacEncEncode(faacEncHandle hEncoder, int32_t * inputBuffer, unsigned int samplesInput,5              unsigned char *outputBuffer, unsigned int bufferSize);

  faacEncEncode第三个参数指的是传入的sample的个数,这个值要和调用faacEncOpen返回的inputSamples相等。要做到这点,就要在dshow中设置好buffsize,公式是:

BufferSize = aac_frame_len * channels * wBytesPerSample// aac_frame_len = 1024

 

4. 程序界面

  运行中

     

  捕获完成后生成aac 和 264文件

     

  生成的aac文件用MediaInfo读出来的编码格式

     

  生成的264文件用MediaInfo读出来的编码格式

     

  用mp4box封装一下,把264和aac存放到mp4容器文件中,就可以在播放器中播放了

     

 

时间: 2024-09-17 10:44:45

采集音频和摄像头视频并实时H264编码及AAC编码的相关文章

Visual C++编程实现摄像头视频捕捉

前言 DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布.DirectShow为多媒体流的捕捉和回放提供了强有力的支持.用DirectShow开发应用程序,我们可以很方便地从支持WDM驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中. DirectShow是基于COM的,为了编写DirectShow应用程序,需要了解COM客户程序编写的基础知识.DirectShow提供了大量的接口,但在编程中发现还是不够方便,如

摄像头视频流-QCamera与OpenGL显示摄像头视频

问题描述 QCamera与OpenGL显示摄像头视频 用QCamera做了个摄像头视频采集程序, 现在想将视频显示在OpenGL的模型上应该怎么处理呀 看帖子一般OpenGL都是使用纹理贴图来完成, opencv的话有cvQueryFrame命令 问题是QCamera 貌似没有 类似返回每帧图片的命令呀 该如何操作 求大神指点 解决方案 我最近也在为这个事情苦恼,支持一下 解决方案二: 这是要沉了么...... 解决方案三: 这是要沉了么......

i etty ervlet-Servlet如何传输视频流(视频的实时传输)

问题描述 Servlet如何传输视频流(视频的实时传输) 各位大神,我在tiny6410上移植了i-Jetty作为嵌入式web服务器,新建Servlet用于处理http请求,可以处理一些简单的数据交互,现在想基于这个开发实时视频监控,用Servlet传输视频流,请问哪位大神做过,可以给点建议?太太太感谢了... 解决方案 Servlet 能处理实时视频流,如H.264吗?就算可以,用 6410 做为服务器,性能呢? 解决方案二: 之前看到有人用CGI开启线程,调用摄像头,进行编码,并且传输视频流

怎样实现对h.264接收的视频进行实时播放

问题描述 我现在在弄一个实时视频播放,采用java开发,由采集器上送rtp视频报文,报文中视频格式为h.264,我已经编写java代码实现了h.264的解码,现在要找一个开源的播放器实现在浏览器上实时播放采集的视频,请问我应该怎样实现,有demo的最好. 解决方案 解决方案二:哪个大神帮帮忙啊解决方案三:顶,同问!!解决方案四:同问,,,,,,,解决方案五:http://blog.csdn.net/sweetwxh/article/details/6555199

求助:安卓手机vnc远程树莓派无法用opencv显示摄像头视频窗口

问题描述 求助:安卓手机vnc远程树莓派无法用opencv显示摄像头视频窗口 使用python,用opencv和usb摄像头实时图像处理并显示,在电脑上用远程桌面可以正常运行,但是在手机上无法运行,如截图.请问如何解决? 解决方案

android摄像头-Android摄像头视频帧数据保存

问题描述 Android摄像头视频帧数据保存 用Android手机自带的camera,采集视频信息,得到每帧中心点的像素值,写入到txt文档中,现在出现一个奇怪的问题:在onCreate()方法中,先创建好空的txt文档,用于后面的数据写入,视频处理后的帧率也快些,但是得到的数据与实际的有很大的出入:而在onPreviewFrame()方法中,读取每帧的时候重复创建空的txt文档,帧率是稍微降低些,但是数据更合理,不知道其中什么原因导致的.,各位大神,拜托了!(这个Android底层有关系么?)

Win8/Win7系统使用摄像头视频出现波纹闪烁怎么解决?

  Win8/Win7系统使用摄像头视频出现波纹闪烁怎么解决?          方法一: 1. Win+Q调出搜索应用界面,找到相机; 2. 选择屏幕下方的摄像头选项,选择"更多"; 3. 更多选项里闪烁的频率的默认为60HZ,调节为50HZ之后波纹消失. 方法二: 1. 若已安装QQ,可在QQ视频设置里进行调节,聊天窗口打开"视频设置"; 2. 打开"画质调节"; 3. "电力线频率(防闪烁)(P)",默认也是60HZ,修

win7系统笔记本用摄像头视频聊天画面不清晰怎么办

  win7系统笔记本用摄像头视频聊天画面不清晰怎么办 1.焦聚问题,通过手动调节镜头圈来调节;镜头脏了,用全棉的布轻微擦拭即可.当然有些免驱动的摄像头上面的小镜头还是具备一定的调节功能的,尝试旋转摄像头镜头外面的圈看看能否旋转; 2.检查看看摄像头的驱动是否装好,easy capture卸载掉再重装试试. 上述就是关于win7系统电脑摄像头不清晰的解决办法,按照以上的方法来,相信就可以轻松解决摄像头模糊不清的问题了.

视频转换成H264格式图文教程

H.264是MPEG-4标准所定义的最新格式,同时也是技术含量最高.代表最新技术水平的视频编码格式之一,有的也称(AVC). 使用软件MediaCoder可以将视频转换成H264视频格式,它是一个免费的软件,你可以先到百度搜索下载. 启动MediaCoder,主界面如下图所示,请在主界面中,点击左上角的"+"号选择要转换的视频,然后,请参考下图中红色标出的视频配置进行设置: 在上图中,我们将视频格式设置为H.264.二次编码.编码器使用x264.规格为Baseline等,这些设置是根据