前言
最近一直打算搞搞移动端的直播,基本的路数已经跑通,本着造福大众的想法,我打算将一些接触过的知识都记录下来,方便后人学习,当然主要是方便自己回顾。
效果
原理
我不是搞前端的,对HTTP的一些标准也不是特别了解,关于HTTP Server Push的说法也是在查找资料的过程中发现的官方说法。因此拿来使用,既形象也正式。
最早接触这种使用方式,应该还是在外培训的时候,当时我上的培训班是嵌入式相关的,其中有一个比较大的实验就是使用linux 下的V4L2编程接口,获取摄像头的数据,编码成合适格式,然后通过socket发送出去,从而在客户端的浏览器中可以形成图片流,看起来就像视频一样。
主要技术点:
- 获取原始摄像头数据
- 编码成合适的格式
- socket发送出去
其中前两步是基础,最后一步是实现的核心。而且按照这个思路只要你的开发运行环境满足条件,那么不管是ARM开发板,还是我们的手机都可以实现这个功能。下面的说明以安卓手机为例来介绍。
实现
1. 获取摄像头数据
在手机上获取摄像头数据是非常简单的,public void onPreviewFrame(byte[] data, Camera camera)
。在这个回调方法中会返回原始的摄像头数据,通常都是NV21格式,这个格式是所有安卓设备都支持的,其它格式需要设备支持才可以使用。
2. 编码成合适的格式
这一步就是对格式进行转换,比如NV21转换为JPEG,我们这里的需求可以直接使用安卓提供的方法,如果在您的使用场景中没有现成的方法,或者您有别的需求,那么需要您自己实现转换的方法。
YuvImage yuv = new YuvImage(data, ImageFormat.NV21, prevSizeW, prevSizeH, null);
Rect r = new Rect(0, 0, prevSizeW, prevSizeH);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuv.compressToJpeg(r, 100, baos);
3.socket发送出去
基本的socket使用还是很简单的,我们这里比较麻烦的地方,就是我们需要借助浏览器对HTTP标准的支持,因此我们的HTTP响应包不能随便搞,我们要按标准来,这样浏览器才可以按标准对我们发出的数据包进行相应的解析。
我们首先在手机建立一个socket的服务器,监听8888端口,等待客户端浏览器的访问,等客户端浏览器访问我们的服务器时,我们需要通过响应包来告知客户端浏览器我们将要以HTTP Server Push的方式进行数据的发送。
第一个响应包:HTTP header + frameHeader + JPEG data
后续的响应包:frameHeader + JPEG data
#响应格式的一些定义
private String header = "HTTP/1.1 200 OK\r\n" +
"Connection: close\r\n" +
"Server: Net-camera-1-0\r\n" +
"Cache-Control: no-store, no-cache, must-revalidate, pre-check=0,post-check=0, max-age=0\r\n" +
"Pragma: no-cache\r\n" +
"Content-Type:multipart/x-mixed-replace;boundary=www.shutup.com\r\n\r\n";
private String frameHeader = "--www.shutup.com\r\n" +
"Content-Type: image/jpeg\r\n" +
"Content-Length: %d\r\n\r\n";
wireshark tcp flow
坑
目前发现摄像头数据的方向不对劲。。。
参考
httpwebresponse-with-mjpeg-and-multipart-x-mixed-replace-boundary-myboundary