前言
VideoToolBox是iOS8之后,苹果开发的用于硬解码编码H264/H265(iOS11以后支持)的API。
对于H264还不了解的童鞋一定要先看下这边的H264的简介。
H.264基础简介
编码流程
我们实现一个简单的Demo,从摄像头获取到视频数据,然后再编码成H264裸数据保存在沙盒中。
1. 创建初始化VideoToolBox
核心代码如下
1 | - (void)initVideoToolBox { |
初始化这里设置了编码类型kCMVideoCodecType_H264,
分辨率640 * 480,fps,GOP,码率。
2. 从摄像头获取视频数据丢给VideoToolBox编码成H264
初始化视频采集端核心代码如下
1 | //初始化摄像头采集端 |
这里需要注意设置的视频分辨率和编码器一致640 * 480. AVCaptureVideoDataOutput类型选用YUV420p。
摄像头数据回调部分
1 | - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{ |
3.框架中出现的数据结构
CMSampleBufferRef
存放一个或者多个压缩或未压缩的媒体数据;
下图列举了两种CMSampleBuffer。
CMTime
64位的value,32位的scale,media的时间格式;
CMBlockBuffer
这里可以叫裸数据;
CVPixelBuffer
包含未压缩的像素数据,图像宽度、高度等;
pixelBufferAttributes
CFDictionary包括宽高、像素格式(RGBA、YUV)、使用场景(OpenGL ES、Core Animation)
CVPixelBufferPool
CVPixelBuffer的缓冲池,因为CVPixelBuffer的创建和销毁开销很大
CMVideoFormatDescription
video格式,包括宽高、颜色空间、编码格式信息等;对于H264,还包含sps和pps数据;
编码完成后的数据写入H264
这里编码完成我们先判断的是否为I帧,如果是需要读取sps和pps参数集,为什么要这样呢?
我们先看一下一个裸数据H264(Elementary Stream)的NALU构成
H.264裸流中,不存在单独的SPS、PPS包或帧,而是附加在I帧前面,存储的一般形式为
00 00 00 01 SPS 00 00 00 01 PPS 00 00 00 01 I帧
前面的这些00 00数据称为起始码(Start Code),它们不属于SPS、PPS的内容。
SPS(Sequence Parameter Sets)和PPS(Picture Parameter Set):H.264的SPS和PPS包含了初始化H.264解码器所需要的信息参数,包括编码所用的profile,level,图像的宽和高,deblock滤波器等。
上面介绍了sps和pps是封装在CMFormatDescriptionRef中,所以我们得先CMFormatDescriptionRef中取出sps和pps写入h264裸流中。
这就不难理解写入H264的流程了。
代码如下
1 | // 编码完成回调 |
结束编码后销毁session
1 | - (void)EndVideoToolBox |
这样就完成了使用VideoToolbox 的H264编码。编码好的H264文件可以从沙盒中取出。
总结
仅仅看流程不看代码肯定是学不会框架的,自己动手编码试试吧!
Demo下载地址:iOS-VideoToolBox-demo