最近接触了一些视频流H264的编解码知识,之前项目使用的是FFMpeg多媒体库,利用CPU做视频的编码和解码,俗称为软编软解。该方法比较通用,但是占用CPU资源,编解码效率不高。一般系统都会提供GPU或者专用处理器来对视频流进行编解码,也就是硬件编码和解码,简称为硬编解码。苹果在iOS 8.0系统之前,没有开放系统的硬件编码解码功能,不过Mac OS系统一直有,被称为Video ToolBox的框架来处理硬件的编码和解码,终于在iOS 8.0后,苹果将该框架引入iOS系统。

由此,开发者便可以在iOS里面,调用Video Toolbox框架提供的接口,来对视频进行硬件编解码的工作,为VOIP视频通话,视频流播放等应用的视频编解码提供了便利。

(PS:按照苹果WWDC2014 513《direct access to media encoding and decoding》的描述,苹果之前提供的AVFoundation框架也使用硬件对视频进行硬编码和解码,但是编码后直接写入文件,解码后直接显示。Video Toolbox框架可以得到编码后的帧结构,也可以得到解码后的原始图像,因此具有更大的灵活性做一些视频图像处理。)

一:Video Toolbox视频编解码前后需要应用的数据结构

(1)CMSampleBuffer:存放编解码前后的视频图像的容器数据结构。

(2)CVPixelBuffer:编码前和解码后的图像数据结构。(像素缓存)

(3)CMBlockBuffer:编码后,结果图像的数据结构。

(4)CMTime、CMClock和CMTimebase:时间戳相关。时间以64-bit/32-bit的形式出现。

(5)CMVideoFormatDescription:图像存储方式,编解码器等格式描述。

1.1视频H264编解码前后数据结构示意图

如图1.1所示,

1:编解码前后的视频图像均封装在CMSampleBuffer中,

2:如果是编码后的图像,以CMBlockBuffe方式存储;

3:解码后的图像,以CVPixelBuffer存储。

4:CMSampleBuffer里面还有另外的时间信息CMTime和视频描述信息CMVideoFormatDesc。

二:硬解码使用方法。

通过如图2.1所示的一个典型应用,来说明如何使用硬件解码接口。该应用场景是从网络处传来H264编码后的视频码流,最后显示在手机屏幕上。

2.1 H264典型应用场景

1:将H264码流转换成解码前的CMSampleBuffer。

1.1:由图1.1所示,解码前的CMSampleBuffer = CMTime + FormatDesc + CMBlockBuffer。需要从H264的码流里面提取出以上的三个信息。最后组合成CMSampleBuffer,提供给硬解码接口来进行解码工作。

1.2:H264的码流由NALU单元组成,

  NALU单元包含视频图像数据和H264的参数信息。

  其中视频图像数据就是CMBlockBuffer,

  而H264的参数信息则可以组合成FormatDesc。

    具体来说参数信息包含SPS(Sequence Parameter Set)和PPS(Picture Parameter Set)。图2.2显示一个H264码流的结构。

2.2 H264码流结构

(1)提取sps和pps生成format description。

  a,每个NALU的开始码是0x00 00 01,按照开始码定位NALU。

  b,通过类型信息找到sps和pps并提取,开始码后第一个byte的后5位,7代表sps,8代表pps。

  c,CMVideoFormatDescriptionCreateFromH264ParameterSets函数来构建CMVideoFormatDescriptionRef。具体代码可以见demo。

(2)提取视频图像数据生成CMBlockBuffer。

  a,通过开始码,定位到NALU。

  b,确定类型为数据后,将开始码替换成NALU的长度信息(4 Bytes)。

  c,CMBlockBufferCreateWithMemoryBlock接口构造CMBlockBufferRef。具体代码可以见demo。

(3)根据需要,生成CMTime信息。(实际测试时,加入time信息后,有不稳定的图像,不加入time信息反而没有,需要进一步研究,这里建议不加入time信息)

根据上述得到CMVideoFormatDescriptionRef、CMBlockBufferRef和可选的时间信息,使用CMSampleBufferCreate接口得到CMSampleBuffer数据这个待解码的原始的数据。见图2.3的H264数据转换示意图。

2.3 H264码流转换CMSampleBuffer示意图

三:硬件解码图像显示。

硬件解码显示的方式有两种:

(1)通过系统提供的AVSampleBufferDisplayLayer来解码并显示。

AVSampleBufferDisplayLayer是苹果提供的一个专门显示编码后的H264数据的显示层,它是CALayer的子类,因此使用方式和其它CALayer类似。该层内置了硬件解码功能,将原始的CMSampleBuffer解码后的图像直接显示在屏幕上面,非常的简单方便。图2.4显示了这一解码过程。

2.4 AVSampleBufferDisplayLayer硬解压后显示图像

显示的接口为[_avslayer enqueueSampleBuffer:sampleBuffer];

(2)通过VTDecompression接口来,将CMSampleBuffer解码成图像,将图像通过UIImageView或者OpenGL上显示。

a,初始化VTDecompressionSession,设置解码器的相关信息。初始化信息需要CMSampleBuffer里面的FormatDescription,以及设置解码后图像的存储方式。demo里面设置的CGBitmap模式,使用RGB方式存放。编码后的图像经过解码后,会调用一个回调函数,将解码后的图像交个这个回调函数来进一步处理。我们就在这个回调里面,将解码后的图像发给control来显示,初始化的时候要将回调指针作为参数传给create接口函数。最后使用create接口对session来进行初始化。

b,a中所述的回调函数可以完成CGBitmap图像转换成UIImage图像的处理,将图像通过队列发送到Control来进行显示处理。

c,调用VTDecompresSessionDecodeFrame接口进行解码操作。解码后的图像会交由a,b步骤设置的回调函数,来进一步的处理。

图2.5显示来硬解码的过程步骤。

2.5 VTDecompression硬解码过程示意图

四:硬编码使用方法。

硬编码的使用也通过一个典型的应用场景来描述。首先,通过摄像头来采集图像,然后将采集到的图像,通过硬编码的方式进行编码,最后编码后的数据将其组合成H264的码流通过网络传播。

1:摄像头采集数据。

摄像头采集,iOS系统提供了AVCaptureSession来采集摄像头的图像数据。设定好session的采集解析度。再设定好input和output即可。output设定的时候,需要设置delegate和输出队列。在delegate方法,处理采集好的图像。

注意,需要说明的是,图像输出的格式,是未编码的CMSampleBuffer形式。

2:使用VTCompressionSession进行硬编码。

(1)初始化VTCompressionSession。

  VTCompressionSession初始化的时候,一般需要给出width宽,height长,编码器类型kCMVideoCodecType_H264等。然后通过调用VTSessionSetProperty接口设置帧率等属性,demo里面提供了一些设置参考,测试的时候发现几乎没有什么影响,可能需要进一步调试。最后需要设定一个回调函数,这个回调是视频图像编码成功后调用。全部准备好后,使用VTCompressionSessionCreate创建session。

(2)提取摄像头采集的原始图像数据给VTCompressionSession来硬编码。

  摄像头采集后的图像是未编码的CMSampleBuffer形式,利用给定的接口函数CMSampleBufferGetImageBuffer从中提取出CVPixelBufferRef,使用硬编码接口VTCompressionSessionEncodeFrame来对该帧进行硬编码,编码成功后,会自动调用session初始化时设置的回调函数。

(3)利用回调函数,将因编码成功的CMSampleBuffer转换成H264码流,通过网络传播。

  基本上是硬解码的一个逆过程。解析出参数集SPS和PPS,加上开始码后组装成NALU。提取出视频数据,将长度码转换成开始码,组长成NALU。将NALU发送出去。

图2.6显示了整个硬编码的处理逻辑。

2.6硬编码处理流程示意图

demo 地址

参考网站

编解码链接

专业术语

1:码流(Data Rate)

  是指视频文件在单位时间内使用的数据流量,也叫码率,是视频编码中画面质量控制中最重要的部分。同样分辨率下,视频文件的码流越大,压缩比就越小,画面质量就越好。

2:   H264的码流由NALU单元组成,NALU单元包含视频图像数据和H264的参数信息。

2.1: H.264码流由视频编码层(Video Coding Layer,VCL)与网络提取层(Network Abstraction Layer,NAL)组成。

NAL全称Network Abstract Layer, 即网络抽象层。

在H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(VCL)和网络抽象层面(NAL)。

   其中,前者负责有效表示视频数据的内容,而后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。因此我们平时的每帧数据就是一个NAL单元(SPS与     PPS除外)。

3:  NAL:网络抽取层:SPS、PPS

序列参数集SPS(sequence Parameter Set):作用于一系列连续的编码图像

图像参数集PPS(Picture Parameter Set):作用于编码视频序列中一个或多个独立的图像;

4:I、P、B帧

  视频压缩中,每帧代表一幅静止的图像。而在实际压缩时,会采取各种算法减少数据的容量,其中IPB就是最常见的。

简单地说,I帧是关键帧,属于帧内压缩。就是和AVI的压缩是一样的。P是向前搜索的意思。B是双向搜索。他们都是基于I帧来压缩数据。

  I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)

    P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)

  B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累~。

采用的压缩方法: 分组:把几帧图像分为一组(GOP),为防止运动变化,帧数不宜取多。

1.定义帧:将每组内各帧图像定义为三种类型,即I帧、B帧和P帧;

2.预测帧:以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;

3.数据传输:最后将I帧数据与预测的差值信息进行存储和传输。

01:***VideoToolbox硬编码H.264的更多相关文章

  1. 使用VideoToolbox硬编码H.264<转>

    文/落影loyinglin(简书作者)原文链接:http://www.jianshu.com/p/37784e363b8a著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. ======= ...

  2. iOS VideoToolbox硬编H.265(HEVC)H.264(AVC):2 H264数据写入文件

    本文档为iOS VideoToolbox硬编H.265(HEVC)H.264(AVC):1 概述续篇,主要描述: CMSampleBufferRef读取实际数据 序列参数集(Sequence Para ...

  3. 【流媒体】 Android 实时视频编码—H.264硬编码

    [流媒體] Android 实时视频编码—H.264硬编码 SkySeraph Apr 4th 2012 Email:skyseraph00@163.com 1  硬编码 & 软编码 硬编码: ...

  4. iOS VideoToolbox硬编H.265(HEVC)H.264(AVC):1 概述

    本文档尝试用Video Toolbox进行H.265(HEVC)硬件编码,视频源为iPhone后置摄像头.去年做完硬解H.264,没做编码,技能上感觉有些缺失.正好刚才发现CMFormatDescri ...

  5. iOS硬解H.264:-VideoToolboxDemo源码分析[草稿]

    来源:http://www.cnblogs.com/michaellfx/p/understanding_-VideoToolboxDemo.html iOS硬解H.264:-VideoToolbox ...

  6. How to use VideoToolbox to decompress H.264 video stream

    来源:http://stackoverflow.com/questions/29525000/how-to-use-videotoolbox-to-decompress-h-264-video-str ...

  7. Android 实时视频编码—H.264硬编码

    from://http://www.cnblogs.com/skyseraph/archive/2012/04/04/2431771.html 1  硬编码 & 软编码 硬编码:通过调用And ...

  8. iOS VideoToolbox硬编H.265(HEVC)H.264(AVC):4 同步编码

    本文档描述Video Toolbox实现同步编码的办法. Video Toolbox在头文件描述了编码方式为异步,实际开发中也确实为异步. This function may be called as ...

  9. iOS使用VideoToolbox硬编码录制H264视频

    http://blog.csdn.net/shawnkong/article/details/52045894

随机推荐

  1. C++实现微信WeChat网页接口推送股票报警消息

    QStockView微信推送股票报警 1.功能简介 最近很多用户反馈,软件只能在电脑上使用,不能在手机上使用.所以增加了微信推送报警的功能,电脑端的报警提示消息可以通过微信同步发送到手机微信.这样即可 ...

  2. tab栏切换制作

    tab栏切换制作 先上图 要求1:默认状态,第一个选项卡被选中,展示第一个选项卡的内容 策略:第一个选项卡默认有被选中的样式,第一个选项卡对应的display: block,其他的dispaly设为n ...

  3. Shrio使用Jwt达到前后端分离

    概述 前后端分离之后,因为HTTP本身是无状态的,Session就没法用了.项目采用jwt的方案后,请求的主要流程如下:用户登录成功之后,服务端会创建一个jwt的token(jwt的这个token中记 ...

  4. 根据屏幕分辨率判断当前手机型号(swift4.1)

    import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoa ...

  5. 第一个基于ArcGIS的Android应用

     使用Android Studio创建第一个工程 打开Android Studio,新建工程.在Application name处填写项目名称,company domain是公司地址,将来作为包名,点 ...

  6. .net core 单元测试之 JustMock第二篇

    JustMock标记方法 上篇文章在举例子的时候使用了returns的标记方法,JustMock还有很多标记方法: CallOriginal 跟Behaviors里的CallOriginal差不多意思 ...

  7. C笔记_常用快捷键

    1.第一部分 Ctrl + up/down 以光标所在行为中心上下移动文本: Ctrl + left/right 左右跳过一个单词或符号: Ctrl + end 跳至文本末尾: Ctrl + dele ...

  8. Python实现的一些常见简单问题(持续更新)

    提纲: 1.汉诺塔 2.找到某个范围内的所有质数 3.杨辉三角 4.用闭包实现一个计数器,调用一次计数器加1 5.将类构造成可迭代对象,实现斐波那契数列 ...... 1.汉诺塔(汉诺塔) 用递归函数 ...

  9. Setup Factory 9 简单打包

    由于项目资源太大,使用VS自带打包工具无法实现需求,所以Setup Factory 9进行打包生成多个文件的方案,下面记录使用方法: 一:这里点击下载:下载,提取码:tt7a 二:下载完安装需要注册码 ...

  10. poj 1797Heavy Transportation(dijkstra变形)

    题目链接:http://poj.org/problem?id=1797 题意:有n个城市,m条道路,在每条道路上有一个承载量,现在要求从1到n城市最大承载量,而最大承载量就是从城市1到城市n所有通路上 ...