想要把android手机作为rtsp服务器推流,目前我看主要有个2个开源库可以参考
1.libstreaming
https://github.com/fyhertz/libstreaming
这是java写的
2.live555
这是C写的,有源码要编译
我主要看了libstreaming,这里我想记录下接入的过程及所遇到的问题,供需要的人参考
首先要理解RTSP这个协议,有个大神写的很详细,你看他的目录,不光有rtsp的系列文章,还有其他非常广的研究,很厉害
实现推流,主要就是2步,一RTSP协议几次握手,二RTP打包发送流
下面这个博主分析了libstreaming库里推流的基本流程
libstreaming局域网构建Android相机实时流媒体流程分析
看了libstreaming,肯定会发现另2个基于此库的android工程
Endoscope 我参考了这个
但接入libstreaming肯定还会遇到些问题,在下面这个博主文章里可以找到答案,其中一个就是无法推流大分辨率的问题
最后一个大问题,目前没在网上找到答案,经过我的研究也算解决,我这边简单说下问题及思路
一个android手机作为服务端推流,但无法在多个终端上同时播放,只要有第二个终端拉流就会导致第一个终端停止播放
1.先看RTSP的握手是否完成,是不是第2个终端发出请求后,第一个终端就发出“TEARDOWN”请求关闭
答案:不是
2.那就是打包视频流断了,没有继续给第一个终端推流
问题根源在MediaCodec在第二个终端请求进来时,又实例了个新对象,旧的MediaCodec无法再从Camera中获取帧数据,也就无法给第一个终端推流了
我的做法是,VideoStream类中对Camera类的调用和实现单独拉出来作为一个工具类来管理,不要每个终端过来请求时,就去实例化Camera类,
刚说的根源问题就是Camera的PreviewCallback又实例化了变成新的了,导致第一个MediaCodec无法获取到数据
在新的Camera管理类里创建一个MediaCodec的数组或Collection的实现类,每有一个终端接入就向数组里添加一个,最后Camera的PreviewCallback的回调中就给数组中每个MediaCodec塞数据,这样每个终端就能拉到流了
Camera.PreviewCallback callback = new Camera.PreviewCallback() {
long now = System.nanoTime() / 1000, oldnow = now, i = 0;
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
oldnow = now;
now = System.nanoTime() / 1000;
if (i++ > 3) {
i = 0;
//Log.d(TAG,"Measured: "+1000000L/(now-oldnow)+" fps.");
}
try {
for(MediaCodec mediaCodec:mediaCodecSet){
ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
int bufferIndex = mediaCodec.dequeueInputBuffer(500000);
if (bufferIndex >= 0) {
inputBuffers[bufferIndex].clear();
if (data == null)
Log.e(TAG, "Symptom of the \"Callback buffer was to small\" problem...");
else convertor.convert(data, inputBuffers[bufferIndex]);
mediaCodec.queueInputBuffer(bufferIndex, 0, inputBuffers[bufferIndex].position(), now, 0);
} else {
Log.e(TAG, "No buffer available !");
}
}
} finally {
mCamera.addCallbackBuffer(data);
}
}
};