一直想学习实时视频聊天的技术,虽然到现在也没有完全搞明白各种编码格式,但搞清楚怎怎么编解码H264视频,怎么编解码AAC格式音频就够了,就能实现一个最基本的视频聊天/会议系统。什么RTMP,HLS统统可以不管他,不过,不管的前提是你得自己封装视音频流。由于固执的认为只有本地化编解码才是效率最高的,所以没有打算使用ffmpeg来编解码,虽然ffmpeg在iOS上已经使用硬编码了。当然,如果在windows上开发,ffmpeg会简单一些,也可以使用x264和AAC的独立库。视音频流准确说说应该是视音频帧,中间是分割好的一段段数据。
从相机采集视频帧->调整单帧相片编码格式->编码成H264视频帧->发送到服务器->服务器转发到对端->对端接收数据->解码并显示
从麦克风采集音频->编码成AAC->发送到服务器->服务器转发到对端->对端接收数据->解码并播放
从相机采集视频:具体代码不贴了,到处都是。
调整单帧相片编码格式 :有些Android相机输出的照片格式是YV12格式,而MediaCodec需要的是NV12格式,所以需要转换,转换代码如下:
public byte[] YV12toYUV420PackedSemiPlanar(final byte[] input, final byte[] output, final int width, final int height) {
finalint frameSize = width * height;
finalint qFrameSize = frameSize / 4;
System.arraycopy(input, 0, output, 0, frameSize);// Y
for (int i = 0; i < qFrameSize; i++) {
output[alignedFrameSize + i * 2] = input[frameSize + i + qFrameSize];// Cb (U)
output[alignedFrameSize + i * 2 + 1] = input[frameSize + i];// Cr (V)
}
return output;
}
这个地方注意,真正用在产品里需要使用openGLES来转码,CPU转码效率太低。
编码成H264视频帧:Android编码使用MediaCodec,iOS编码使用VideoToolBox。具体代码参考度娘。
发送到服务器:传输协议使用自定义协议,为了代码通用性,使用标准TCP socket C实现底层通信框架,兼容Windows,Linux,Android,iOS。
服务器转发到对端:服务器是在Linux C socket实现,理论上只要CPU,内存,网络带宽足够,可并发千万用户同时在线。
对端接收数据:接收数据也是使用标准TCP socket C实现。
解码并显示:Android解码使用MediaCodec,iOS解码使用VideoToolBox。具体代码参考度娘。
音频采集传输和视频一样。
00018
网友评论