iOS开发笔记程序员iOS Developer

硬件编码相关知识(H264,H265)

2017-10-15  本文已影响558人  小东邪啊

硬件编码相关知识(H264,H265)

阅读人群:研究硬件编码器应用于iOS开发中,从0研究关于硬件编解码,码流中解析数据结构

内容概述:关于H264,H265的背景,数据结构,在iOS开发中编解码的应用

博客地址: 硬件编码相关知识

简书地址: 硬件编码相关知识

一. 背景及概述

1. 在升级 iOS 11 之后,iPhone 7 及更新的设备内的照片存储将不再用 JPEG 了,而采用了一种新的图片格式 HEIF(发音同 heef),在 iOS 中对应的文件后缀为 .heic ,其编码用的是 HEVC(这个发不了音,哈哈哈)格式,又称 H.265 (这个就很熟悉了 H.264 的下一代),同时视频也用 HEVC 作为编码器,对应的文件后缀还是 .mov 。
2. 这里要注意他们俩的关系, HEIF 是图片格式,而 HEVC 是编码格式(类似 H.264,VP8),HEIF 是图片容器(类似于视频的 mkv,mp4 后缀),而用 HEVC 进行编码的 HEIF 图片就是后缀为 .heic 的图片,也是苹果主要使用的格式。
3. HEIF 全称 High Efficiency Image Format (HEIF)。是由 Moving Picture Experts Group 制定的,存储图片和图片序列的格式。下图是形容HEIF的一句英文诗,JPEG很大,但是HEIF很小。
HEIFHEIF
4. 优点
5. 文件组成
6. 兼容

一般情况下,用户是对这个格式无感知的,因为只有在新款支持硬解码的 iOS 手机内部是以 heif & hevc 格式来存储照片和视频的,而在用户通过 Airdrop或者数据线传送到电脑上的时候,对不兼容的设备会自动转换到 JPEG 的格式。所以也不会影响你使用微信,微博等软件。

二. 视频编解码

1.软编与硬编概念
2. h.264编码原理

H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面,我理解的他的理论依据是:参照一段时间内图像的统计结果表明,在相邻几幅图像画面中,一般有差别的像素只有10%以内的点,亮度差值变化不超过2%,而色度差值的变化只有1%以内。所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像帧A,随后的B帧就不编码全部图像,只写入与A帧的差别,这样B帧的大小就只有完整帧的1/10或更小!B帧之后的C帧如果变化不大,我们可以继续以参考B的方式编码C帧,这样循环下去。这段图像我们称为一个序列(序列就是有相同特点的一段数据),当某个图像与之前的图像变化很大,无法参考前面的帧来生成,那我们就结束上一个序列,开始下一段序列,也就是对这个图像生成一个完整帧A1,随后的图像就参考A1生成,只写入与A1的差别内容。

在H264协议里定义了三种帧,完整编码的帧叫I帧,参考之前的I帧生成的只包含差异部分编码的帧叫P帧,还有一种参考前后的帧编码的帧叫B帧。

H264采用的核心算法是帧内压缩和帧间压缩,帧内压缩是生成I帧的算法,帧间压缩是生成B帧和P帧的算法。

3. 对序列的说明

在H264中图像以序列为单位进行组织,一个序列是一段图像编码后的数据流,以I帧开始,到下一个I帧结束。

一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。

一个序列就是一段内容差异不太大的图像编码后生成的一串数据流。当运动变化比较少时,一个序列可以很长,因为运动变化少就代表图像画面的内容变动很小,所以就可以编一个I帧,然后一直P帧、B帧了。当运动变化多时,可能一个序列就比较短了,比如就包含一个I帧和3、4个P帧。

4. 对三种帧的介绍

I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧。一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。

5.对压缩算法得说明

h264的压缩方法:

6. DTS和PTS的不同

DTS主要用于视频的解码,在解码阶段使用.PTS主要用于视频的同步和输出.在display的时候使用.在没有B frame的情况下.DTS和PTS的输出顺序是一样的。

EX:下面给出一个GOP为15的例子,其解码的参照frame及其解码的顺序都在里面:


GOPGOP

如上图:I frame 的解码不依赖于任何的其它的帧.而p frame的解码则依赖于其前面的I frame或者P frame.B frame的解码则依赖于其前的最近的一个I frame或者P frame 及其后的最近的一个P frame.

三. IOS系统 H.264视频硬件编解码说明

1.对VideoToolbox的介绍

在iOS中,与视频相关的接口有5个,从顶层开始分别是 AVKit - AVFoundation - VideoToolbox - Core Media - Core Video

其中VideoToolbox可以将视频解压到CVPixelBuffer,也可以压缩到CMSampleBuffer。

如果需要使用硬编码的话,在5个接口中,就需要用到AVKit,AVFoundation和VideoToolbox。在这里我就只介绍VideoToolbox。

2.VideoToolbox中的对象
CVPixelBufferCVPixelBuffer CVPixelBufferPoolCVPixelBufferPool CMTimeCMTime
3. 硬解码

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


NAL单元NAL单元

要完成以上功能需要经过以下几个步骤:

1> 将 H.264码流转换为 CMSampleBuffer

我们知道,CMSampleBuffer = CMTime + FormatDesc + CMBlockBuffer . 需要从H264的码流里面提取出以上的三个信息。最后组合成CMSampleBuffer,提供给硬解码接口来进行解码工作。

在H.264的语法中,有一个最基础的层,叫做Network Abstraction Layer, 简称为NAL。H.264流数据正是由一系列的NAL单元(NAL Unit, 简称NAUL)组成的。

NALUNALU

H264的码流由NALU单元组成,一个NALU可能包含有:

H264的码流H264的码流

流数据中,属性集合可能是这样的:

属性集合属性集合

经过处理之后,在Format Description中则是:

Format DescriptionFormat Description

要从基础的流数据将SPS和PPS转化为Format Desc中的话,需要调用CMVideoFormatDescriptionCreateFromH264ParameterSets()方法

对于流数据来说,一个NAUL的Header中,可能是0x00 00 01或者是0x00 00 00 01作为开头(两者都有可能,下面以0x00 00 01作为例子)。0x00 00 01因此被称为开始码(Start code).

NALU headerNALU header

总结以上知识,我们知道H264的码流由NALU单元组成,NALU单元包含视频图像数据和H264的参数信息。其中视频图像数据就是CMBlockBuffer,而H264的参数信息则可以组合成FormatDesc。具体来说参数信息包含SPS(Sequence Parameter Set)和PPS(Picture Parameter Set).如下图显示了一个H.264码流结构:

H.264码流H.264码流

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

CMSampleBufferCreateCMSampleBufferCreate
2> 将 CMSampleBuffer显示出来

显示的方式有两种:

4.硬编码

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

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

参考:H264介绍HEIF & HEVC 你知道多少?

上一篇下一篇

猜你喜欢

热点阅读