首先跟大家说下我做的一个拍传项目:
这个拍传的项目呢,是通过获取Camera的预览帧数据,然后经过H264的编码,然后发送到服务器端进行的,协议是公司自己制定的协议。
获取预览帧的接口是:
- private byte[] prewframe;
- @Override
- public void onPreviewFrame(byte[] data, Camera arg1) {
- prewframe = data;
- }
复制代码
在里面我就是这样做,然后在surfaceChanged中启动一个编码线程一个数据发送线程,编码线程不断的循环编码prewframe原始数据,编码之后通过本地数据报包传递给数据报包接受线程,然后通过Socket将数据发送出去。
编码线程的核心代码如下:
- while(isPrewRunning)
- {
- buffer = changeYUV420SP2P(prewframe,prewframe.length);
- iLen = H264Encoder.encode(handle, buffer, buffer.length, outBuf, outBuf.length);
- dataPacket.setLength(iLen);
- udpSocket.send(dataPacket);
- Log.e("SendLen", ""+iLen);
- try {
- sender.setSendBufferSize(iLen);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
复制代码
首先跟大家说下,我为什么这样做!
原因非常简单,保证传输给观看段的是最新采集到的图像,弊端是观看段看的时候界面会非常的不流畅。
为什么呢?
onPrewFrame中prewframe只指向了最新采集到得图片数据,那么咱们假设下:
假设这个时候编码线程正在编码的是100帧,进入H264Encoder.encoder的时候编码的是第100帧,编码完后,再循环在编码,这个时候prewframe指向的是第101帧吗?铁定不是的,prewframe也许已经指向了105帧,中间的4帧都被我忽略不计了,
那么服务器端观看视频的流畅性就完全的取决于编码器的效率了。
可惜啊,我这边的编码器的效率真是底下,1秒才2帧。
后来参考了几个同类型的软件,人家做的都是保证流畅优先,因此这2天我煞费苦心决定采取缓冲机制来一帧都不丢的传输H264编码数据。
先给大家说下我是怎么弄的吧?
我还是借助DatagramSocket和DatagramPacket来实现的,原理和核心思路请参见:
http://www.shouyanwang.org/thread-43-1-1.html
在onPrewFrame中我获取到了预览帧数据后就直接通过DatagramSocket的send来进行发送
- try {
- outBuf = tempBuf;
- dataPacket.setLength(tempBuf.length);
- dataPacket.setData(outBuf, 0, outBuf.length);
- udpSocket.send(dataPacket);
- // Log.e("", "length:"+tempBuf.length);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
复制代码
接受后呢,就直接的编码发送,这样做呢?
有一个很有意思的问题:
数据发送端发送速度肯定会远远的高于数据接收端,因为接受端要接受数据并进行编码,那么底层是怎么来存储那些还没有进行编码的数据的呢,采用的是什么缓冲机制?
正确的情况下咱们应该怎么弄?
其实应该借助SDCARD来进行存储,在onPrewFrame中咱们获取到了预览帧的数据之后,就只管将数据存储在缓存文件中,然后咱们再开一个线程,不断的从这个缓存文件中读取预览帧数据编码发送就行了,存取为异步操作.
Android存在这样的机制吗?
借助FileDescripter能够实现这种效果吗?
????这方面的高手能够帮助分析一下吗?
本文转载自:http://www.shouyanwang.org/thread-64-1-1.html