[移动直播技术分享]
###1. 推流端 直播技术的流程大致可以分为几个步骤:数据采集、数据处理、视频编码、封包发送、云端(服务端)(转码、录制、分发)、播放器。
数据采集:通过摄像头和麦克风获得实时的音视频数据;
数据处理:将数据采集的输入流进行实时滤镜,得到我们美化之后的音视频数据, 视频包括各种处理滤镜,美颜,动态贴纸等, 音频包括降噪, 放大等处理;
音视频编码:编码分为软编码和硬编码。现在直播默认的编码都是 H.264
。软编码是利用 CPU
进行编码,硬编码就是使用 GPU
进行编码。软编码支持现在所有的系统版本。由于苹果在 iOS8
才开放硬编码的 API
,故硬编码只支持 iOS8
以上的系统;
封包发送:现在直播推流中,一般采用的格式是 FLV
, 然后利用 ffmpeg
或者 librtmp
进行传输, 这两者封包的处理是不一样的,我们采用的是 ffmpeg
, 所以没有对 librtmp
进行深入的研究;
云端(服务端):进行流的转码、分发和录制;
播放器:负责拉流、解码、播放。
乱谈:杂谈
移动端直播采集摄像头,麦克风的数据。
图像采集: 设置一下前置摄像头 后置摄像头. 配置一下采集的参数, 图像数据的长宽, fps, 输出的方向, 横屏竖屏等. 然后从回调中取到数据就行了。
_videoCamera.outputImageOrientation = videoCameraOrientation;
// 设置拍摄帧频
_videoCamera.frameRate = _fps;
音频采集: 前期不需要音频数据处理需求的时候, 配置一下音频采集的采样频率, 采样精度, 声道就行了.
_audioFormat0.mSampleRate = 44100.00;
_audioFormat0.mFormatID = kAudioFormatLinearPCM;
_audioFormat0.mBitsPerChannel = 16;
如果不需要处理音视频数据的话。 采集这一块是很简单的。只要调用系统的 AVCaptureSession
, 拿到音视频数据之后 直接丢给编码器编码就行了。
图像: 不过如果需要 美白, 水印, 裁剪等一些处理效果. 就必须处理拿到的 buffer, 这个时候还要考虑到拿到的数据是 YUV 还是 RGB .
iOS 上是不能对 YUV 格式直接进行 美颜处理的。只能是 RGB 格式, 这个算是坑。 所以后来就选择使用了 GPUImage
库. 调用 GPUImage
来进行采集和 美白, 水印, 裁剪的处理, 然后取出来进行编码上传, 另一方面显示在预览画面上。
声音: 增益降噪等, 直接从 speex
项目中抽出来的声音处理代码.然后调用, 处理。 有混音的需求, 类似在直播的时候播放背景音乐. 简单的采集就不行了. 这个时候就需要使用 Audio Unit
来实现音频数据的混音, 而还需要将混音的背景音乐转成 PCM
数据, 拷贝一份送入混音. 原来的数据送入播放器。
软编码就是利用CPU资源来压缩音视频数据,硬编码与之相反。
软编码: 现在广泛采用FFmpeg库结合编码库来实现,FFmpeg
+ x264
来编码视频数据YUV/RGB输出H264数据,
FFmpeg+fdk_aac
来编码音频数据PCM输出AAC数据。
硬编码: iOS 8之后开放了硬解码和硬编码API, 所以基本上都是选择 VideoToolBox
和 AudioToolBox
进行图像和音频的硬编码.
将音频,视频打包成packet。
因为我们先做的播放器.播放器采用 FFMPEG
进行数据的接收. 推流端也就默认使用了 FFMPEG
进行数据的封包发送。
封包的时候要注意, 编码的数据, 是有 Sps
Pps
数据的
根据所选流媒体协议,发送相应指令连接服务器,连接服务器成功后,就可以发送packet数据了。
我们用的是 RTMP
, 服务端会进行 转码, 录制, 转 HLS
的操作。
拉流端
拉流,就是从流媒体服务器获取音频,视频数据。
一、解析协议
播放器端根据URL解析所用的流媒体协议(RTMP,HLS)。
二、解封装
解封装,就是demux的过程,从容器格式(FLV,TS)中,分离出音视频数据。
三、解码
解码,就是把获取到的数据解压缩,恢复成原始数据。解码就是将H264变成YUV,AAC变成PCM。
解码可以使用软解码,硬解码。
软解码就是利用CPU资源去解压缩数据,采用的方式是FFmpeg解码。
硬解码,对于iOS平台来说,可以使用VideoToolbox.Framework(该框架只能在iOS 8.0及以上系统使用) 硬解码视频数据。Android平台上,可以使用MediaCodec来硬解码视频数据。
四、渲染数据
采用OpenGL渲染YUV数据,呈现视频画面。将PCM送入设备的硬件资源播放,产生声音。
iOS播放流式音频,使用Audio Queue 的方式,即,利用AudioToolbox.Framework 框架
附1: 音频基础知识。
SDK
, 为了兼容编码, 现在推流的音频采样率为 32 kHz.附2: 图像基础知识。
YUV
分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色. YUV格式有两大类:planar和packed。 对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。 对于packed的YUV格式,每个像素点的Y,U,V是连续交叉存储的.
YUV 标准的 I420 一帧的大小 size=width×heigth×1.5 Byte
iOS 上有两种 YUV 存储格式 NV12 和 NV21, 是一种two-plane模式,即Y和UV分为两个Plane,但是UV(CbCr)为交错存储.
RGB
三基色排列, ARGB
或者 BGRA
每个像素用32位表示,RGB分量各使用8位(剩下的8位用于表示Alpha通道值), 一帧的大小 size=width×heigth×4 Byte.