最近接触了一些视频流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. Flutter学习笔记(21)--TextField文本框组件和Card卡片组件

    如需转载,请注明出处:Flutter学习笔记(21)--TextField文本框组件和Card卡片组件 今天来学习下TextField文本框组件和Card卡片组件. 只要是应用程序就少不了交互,基本上 ...

  2. xpath中normalize-space的用法【转载】

    下面这个菜单中,要点击“货运表现”,我们来看一下xpath, 菜单中的所有项的id都是“vertab”,所以不能用id来定位,那么先用文本的xpath试试 //a[text()='货运表现'] 发现定 ...

  3. c语言的输出

    Cpp是c plus plus Cpp c++的源文件 c++支持c语言的语法 %x是十六进制x后面输出小写%X输出的结果是大写. %o是八进制. %lf是双精度double,默认小数点后六位,输出最 ...

  4. 掌握 Maven 私服

    前言 在 Java EE 开发中,我们使用 Maven 构建工具主要来管理项目的第三方库的依赖,以及公司内部其他项目服务的依赖.因此 Maven 私服就是必不可少的一环,本文主要对 Maven 私服的 ...

  5. Spring学习之旅(五)--AOP

    什么是 AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是 OOP(Object-Oriented Programing,面向对象编程)的补充和完善. OO ...

  6. d3.js制作连线动画图和编辑器

    此文章为原创文章,原文地址:https://www.cnblogs.com/eagle1098/p/11431679.html 连线动画图 编辑器 效果如上图所示.本项目使用主要d3.jsv4制作,分 ...

  7. Contour 学习笔记(一):使用 Contour 接管 Kubernetes 的南北流量

    原文链接:Contour 学习笔记(一):使用 Contour 接管 Kubernetes 的南北流量 在 Kubernetes 中运行大规模以 Web 为中心的工作负载,最关键的需求之一就是在 L7 ...

  8. jvm系列(六):Java服务GC参数调优案例

    本文介绍了一次生产环境的JVM GC相关参数的调优过程,通过参数的调整避免了GC卡顿对JAVA服务成功率的影响. 这段时间在整理jvm系列的文章,无意中发现本文,作者思路清晰通过步步分析最终解决问题. ...

  9. JDBC之批量处理

    JDBC之批量处理 一.批量处理JDBC语句提高处理速度 当需要成批插入或者更新记录时.可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理.通常情况下比单独提交处理更有效率 ...

  10. (七)分布式通信----Netty实现NIO通信

    目录 1. 消息监听器 2. 指令执行器 3. 消息发送器 4. 客户端工厂 5. 序列化工具 6. 通信主机 项目文件结构图 通信主机: 1. 消息监听器(黄色框) 这部分由 Netty 实现,Ne ...