视频直播,主要涉及到采集、预处理、编码、传输、服务器转码、解码这样一个流程。
一、视频采集:采集主要包含图像采集和音频采集;
图像采集设置前置摄像头、后置摄像头,并配置采集的参数、图像数据的长宽、fps、输出的方向、横屏竖屏等,然后从回调中取到数据。
音频采集和编码主要面临的挑战在于:噪声消除(Denoise)、回声消除(AEC)算法等。
前期不需要音频数据处理需求的时候,只需配置音频采集的采样频率、采样精度和声道。
二、预处理:分为音频处理和视频处理两个方面。
音频处理是直播难点之一,尤其主播离手机有一段距离,直播环境会有噪音,所以直播的音频处理是整体降噪的过程。增益降噪等处理可直接从speex项目中抽出来的声音处理代码,然后调用、处理。如有类似在直播的时候播放背景音乐的混音需求,就需要使用Audio Unit来实现音频数据的混音,而还需要将混音的背景音乐转成PCM数据,拷贝一份送入混音,原来的数据送入播放器。
滤镜、美颜功能是直播标配,如果需要美白、水印、裁剪等处理效果,就必须处理拿到的buffer,这个时候还要考虑到拿到的数据是YUV还是RGB。iOS上是不能对YUV格式直接进行美颜处理,只能是RGB格式。可选择使用GPUImage库,调用GPUImage来进行采集和美白、水印、裁剪的处理,然后取出来进行编码上传,并显示在预览画面上。
三、编码:
软编码:现在广泛采用FFmpeg库结合编码库来实现,FFmpeg+x264来编码视频数据YUV/RGB输出H264数据,FFmpeg+fdk_aac来编码音频数据PCM输出AAC数据。
硬编码:iOS 8之后开放了硬解码和硬编码AP,所以基本上都是选择VideoToolBox和AudioToolBox进行图像和音频的硬编码。
四、传输:又拍云播放器采用FFMPEG进行数据的接收,推流端默认使用FFMPEG进行数据的封包发送。
相对来说,封包最主要注意的一个点是时间戳。因为用的AVPacket封包,每个包都会有一个DST(Decode Time Stamp)、PST(Presentation Time Stamp)参数,从字面上可以理解,就是解码时间和显示时间,在没有B帧存在的情况下DTS的顺序和PTS的顺序应该是一样的。这块还涉及到重连和丢帧,用户的网络情况波动断开了,会进行重连。重连失败之后才会发送失败回调。丢帧是一个弱网情况的策略,根据音视频数据的缓冲区大小来判断是否丢帧,丢帧会优先丢非关键帧,保留关键帧,而一旦需要丢关键帧的时,关键帧后的非关键帧也会一起丢掉直到下一个关键帧,来保证画面不会花屏。
五、服务端
现在主流的两种推送协议是RTMP和HLS,两者的优缺点我就不在这里做比较了。又拍直播云采用用的是RTMP协议。
六、播放器
播放器主要负责拉流、解码、播放。
1.解析协议
播放器端根据URL解析所用的流媒体协议(RTMP,HLS)。
2.解封装
解封装,就是demux的过程,从容器格式(FLV,TS)中,分离出音视频数据。
3.解码
解码,就是把获取到的数据解压缩,恢复成原始数据。解码就是将H264变成YUV,AAC变成PCM。解码可以使用软解码,硬解码。
4.渲染数据
采用OpenGL渲染YUV数据,呈现视频画面。将PCM送入设备的硬件资源播放,产生声音。
iOS播放流式音频,使用Audio Queue的方式,即利用AudioToolbox.framework框架。