《AV Foundation开发秘籍——实践掌握iOS & OS X应用的视听处理技术》阅读指南

博客同步更新:http://caixindong.leanote.com

前言

因为工作涉及到一些音视频编解码的东西,所以花了点时间学习了音视频在iOS这个平台的相关开发和实现。AVFoundation是iOS音视频开发的一个利器,它是苹果是对iOSMAC OX这两个平台音视频操作的抽象和封装,而且支持硬编码,通过AVFoundation,我们可以很快地写出一个播放器、简易的人脸识别应用或者与摄像头相关的一些应用。欲善其事必利其器,《AV Foundation开发秘籍——实践掌握iOS & OS X应用的视听处理技术》这本书就是学习AV Foundation的利器。通过一段时间的阅读,我整理出一份读书笔记,一些关键点我会标注对应页码和参考资料,想学习这方面的读者可以先阅读这份指南,来个快速入门,先在脑中先形成一定的框架,再带着归纳好的知识点去读这本书,哪些需要详读,哪些需要略读,心里都有底,阅读效率至少提高一倍,也能保证对知识的记忆度保持在70%以上。

总概图

AVFoundation.png

阅读指南

数字媒体压缩

色彩二次抽样 P11~12

是通过色彩二次抽样来进行压缩,视频数据使用的是YUV颜色模式(大部分人认为是RGB模式),Y代表亮度,UV代表颜色。
将一张图片分离亮度通道和色彩通道,发现图片的大部分细节保存在亮度通道,这是因为人眼对亮度的敏感度高于颜色,所以我们可以大幅减少存储在每个像素中的颜色信息,而不至于图片的质量严重受损,这个减少颜色数据的过程就称为色彩二次抽样。
为了维持图片质量,每个像素点都需要各自的亮度值,却不一定需要色度值。

编解码器压缩 P13

指编码器和解码器,使用高级压缩算法对音视频进行压缩编码,还可以将压缩文件解码成合适播放和编辑的文件。
压缩分为无损压缩和有损压缩,常见的zipgzip压缩都是无损压缩。有损压缩的目的是使用psycho-acousticpsycho-visual模式作为一种方法来减少媒体内容中的冗余数据。

视频编解码器 P13~14

H.264视频格式标准,遵循早期MEPG-1MEPG-2标准,通过两个维度缩小视频文件的尺寸:
空间:压缩独立视频帧,也叫帧内压缩。帧内压缩通过消除包含在每个独立帧内的色彩及结构中的冗余信息来进行压缩,它是有损压缩。通过这个过程创建的帧叫作I-framesI-frames也叫关键帧,每个GOP都正好有一个I-frames,它尺寸最大,解压也最快
时间:通过以组为单位的视频帧压缩冗余数据,也叫帧间压缩。很多帧组合在一起作为GOP,对于GOP所存在的时间维度的冗余可以被消除。GOP包含三种不同类型帧,除了上面讲到的I-frames,还有P-framesB-framesP-frames又叫预测帧,是基于最近的I-framesP-frames的可预测的图片进行编码得到。B-frames又叫双向帧,是基于前后的帧信息进行编码得到,几乎不需要存储空间,但解压过程比较耗时间。

音频编解码器 P15

AACH.264标准相应的音频处理方式,AVFoundationCore Audio支持MP3数据解码,但不支持对其进行编码。

音频

配置音频

获取音频session(每个app只有一个)->配置(设置分类P22,想更进一步的自定义,可以设置options或mode)->激活

播放音频AVAudioPlayer

建议调用prepareToPlay方法,他会取得需要的音频硬件并预加载Audio Queue的缓冲器,
stoppause的区别:在外部用户看来,两者没区别,通过这两种方法停止的音频都会继续播放,它们的区别体现在底层上面,调用stop会撤销调用prepareToPlay时所做的设置
pan修改音道,volume修改音量,rate修改音速(先设置enable
默认的音频会话配置SoloAmbient不满足音频播放器的需求,所以需要对它进行配置,配置为Playback分类,此外还在info.plist文件配置UIBackgroundModes添加audioP30
通过监听AVAudioSessionInterruptionNotification来处理中断事件(P31~33)
通过监听AVAudioSessionRouteChangeNotification来处理线路变化(例如拔出耳机停止音乐播放,基于内容保密)(P33~35

录制音频AVAudioRecorder

创建AVAudioRecorder需要指定存储音频文件的url、录音配置dictionary
录音配置:
AVFormatIDKey用于定义写入内容的音频格式,指定的音频格式要与存储文件的文件类型兼容(P37
AVSampleRateKey用于定义录音的采样率,标识音频信号每一秒的采样数,使用低采样率,文件较小,但音质较低,使用高采用率则反之,一般标准是8000、16000、22050、44100
AVNumberOfChannelsKey用于定义记录音频内容的通道数,默认值为1,表示使用单声道录制,设置为2表示使用立体声录制
CAF文件是最好的容器格式,他与内容无关并可以保存Core Audio支持的任何音频格式。
建议调用prepareToRecord,做一些初始化,将录制启动的延时降到最低
stoppauseAVAudioPlayer区别不一样,stop会结束当前录音并回调[- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag]
获取声音计量(平均分贝和分值分贝,-160~0dB)时,要设置meteringEnable为YES,而且每次获取分贝值都需要先调用updateMeters才能保证读取的值最新

资源与元数据

参考资料

AVAsset

AVAsset本身不是媒体资源,它是媒体的容器,它由一个或多个带有描述自身元数据的媒体组成。所有资源抽象化为AVAsset,它是一个抽象类,不能直接实例化。
AVFoundation中有一个专门的类 承载多媒体中的tracks:AVAssetTrack,一般的视频至少有2个track,一个播放声音,一个播放画面,还可以是文本、副标题或隐藏字幕等媒体文件
AVAsset创建时就是对基础URL文件进行处理,这里有一个特殊的设计,就是AVAsset延迟载入资源的属性,只有请求属性的时候才载入,这个有利于快速创建资源,但也造成一个问题,就是访问属性时没有预先加载,这个获取属性的过程是同步的,会阻塞线程,所以一般用异步的方式查询资源的属性。

媒体元数据

AVFoundation中主要媒体格式都可以嵌入描述其内容(例如组织格式)的元数据
Apple环境下主要的媒体格式:QuickTime(mov)、MPEG-4 video(MP4和m4v)、MPEG-4 audio(m4a)、MPEG-Layer III audio(mp3)
QuickTime是跨平台的媒体架构,定义.mov文件的内部结构,它有atoms的数据结构(树状结构)组成,QuickTime文件结构图(P55 图3-2);
MPEG-4是定义MP4文件格式的规范,他直接派生与QuickTime文件格式,也是有atoms这种数据结构组成,文件结构图(P56 图3-3),它存在多种文件扩展名:.mp4、.m4v、.m4p、.m4b(P57
MP3不使用容器格式,而使用编码音频数据,可选的元数据位于文件开头,因为专利原因,AVFoundation无法支持对MP3数据进行编码,允许读取,但无法写入

使用元数据

AVAssetAVAssetTrack都可以实现查询元数据的功能,有两种元数据的键:common键空间、availableMetadataFormatsAVMetadataItem提供读取具体的元数据的接口

视频播放

AVPlayer

AVPlayer只管理一个单独资源的播放,提供一个子类AVQueuePlayer来管理一个资源队列,用于播放多个媒体资源或者循环播放
AVPlayerLayer将播放的内容渲染到图层上,提供几种gravity用于设置视频显示状态(P87
AVAsset只包含资源的静态信息,仅用它无法实现播放,所以需要AVPlayerItemAVPlayerItemTrack来构建相应的动态内容
AVAsset—>AVPlayerItem(KVO)—>AVPlayer—>AVPlayerLayer

CMTimer

更可靠的时间展示格式,以分数的形式展示,value是分子,timescale是分母
typedef struct { CMTimeValue value; CMTimeScale timescale; CMTimeFlags flags; CMTimeEpoch epoch; } CMTime CMTimeMake ( int64_t value, //表示 当前视频播放到的第几桢数 int32_t timescale //每秒的帧数 );
时间 = value/timescale
CMTime CMTimeMakeWithSeconds( Float64 seconds, //第几秒的截图,是当前视频播放到的帧数的具体时间 int32_t preferredTimeScale //首选的时间尺度 "每秒的帧数" );

AVKit

提供了AVPlayerViewController实现播放器的功能,支持iOS 8以上。使用的话直接实例化,并给它的player(AVPlayer)赋值,添加到视图就可以。

媒体捕获AVCaptureSession

关键类

AVCaptureSessionAVCaptureDeviceAVCaptureDeviceInputAVCaptureOutputAVCaptureConnectionAVCaptureVideoPreviewLayer
AVCaptureSession是核心类,用于连接和管理输入和输出的资源
AVCaptureDevice是物理捕获设备的抽象表示,可以通过[+defaultDeviceWithMediaType]获取系统默认的捕获设备,传入AVMediaTypeVideo获取后置摄像头(默认)参考资料
AVCaptureDeviceInput是捕获会话的输入,AVCaptureDevice没办法直接添加到session,需要先将他封装到AVCaptureDeviceInput才能添加
AVCaptureOutput是一个抽象基类,用于从捕获会话得到数据寻找输出目的地,框架定义了一些高级拓展类AVCaptureStillImageOutput(输出为图片)和AVCaptureMovieFileOutput(输出为视频文件),也定义了一些底层拓展类AVCaptureAudioDataOutputAVCaptureVideoDataOutput,使用它们可以直接访问硬件捕获到的数字样本,可以对音频和视频流进行实时处理
AVCaptureConnection是输入输出类之间的连接,当session添加input和ouput后会自动生成AVCaptureConnection,它可让开发者对信号流进行底层控制
AVCaptureVideoPreviewLayer对捕获的数据进行实时预览,它是CALayer的子类
媒体捕获大致过程:实例化AVCaptureSession,设置AVCaptureDeviceAVCaptureDeviceInput,session添加input,设置AVCaptureOutput,session添加output,session启动

高级捕获

视频缩放

设置AVCaptureDevice的videoZoomFactor可以设置缩放参数,一般通过device的activeFormat.videoMaxZoomFactor是否大于1来判断设备是否支持缩放,希望平滑缩放可以调用device的[-rampToVideoZoomFactor:(CGFloat)factor withRate:(float)rate],放大factor传最大缩放,缩小factor传1,设置缩放时device也要lockForConfiguration

人脸识别

定义一个AVCaptureMetadataOutput,添加到session上,它输出的是元数据,接着设置元数据的类型metadataObjectTypesAVMetadataObjectTypeFace,那捕获到的元数据都是AVMetadataFaceObject类型,设置AVCaptureMetadataOutput的delegate[-setMetadataObjectsDelegate:(id)objectsDelegate queue:(dispatch_queue_t)objectsCallbackQueue],一旦有人脸就会通过[AVCaptureMetadataOutputObjectsDelegate -captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection]回调获取人脸元数据,元数据包含人脸很多信息,例如faceID、范围。

视频处理

参考资料1
参考资料2
通过AVCaptureVideoDataOutput的回调方法可以获取视频帧数据,每个视频帧都会包装在CMSampleBuffer中。(未编码)
CMSampleBuffer = CVPixelBuffer(视频帧原始像素数据)+ CMFormatDescription(格式描述信息)+时间信息 + 附加的元数据

读取和写入媒体

关键类

AVAssetReaderOutputAVAssetReaderAVAssetWriterInputAVAssetWriter
AVAssetReader用于从AVAsset实例读取媒体样本,通过会配置一个或多个AVAssetReaderOutput,将媒体文件读成CMSampleBuffer,可以配置编码设置(解压)
AVAssetWriter用于对媒体资源(CMSampleBuffer)进行编码并写入到容器文件,通常会配置一个或多个AVAssetWriterInput,可以配置编码设置(压缩),会用到一个专门的适配器对象AVAssetWriterInputPixelBufferAdaptor,这个类会在附加视频样本时提供最优性能,AVAssetWriter分为实时操作和离线操作(拉模式)

你可能感兴趣的:(《AV Foundation开发秘籍——实践掌握iOS & OS X应用的视听处理技术》阅读指南)