需要实现的功能:实时采集视频和声音,使用rtmp协议传输到流媒体服务器,流媒体使用的是开源的red5.
基本实现思路:
1、使用mediarecorder录像,路径设置为localsocket,这样可以在socket中获取实时视频流。视频格式设置的是H264,硬件是定制的,可以支持H264的硬编码,所以获取到的视频流应该是编码后的流。
2、在网上找到了一个juv-rtmp-client的包,可以将编码后的流通过rtmp协议发布到流媒体。
3、在浏览器使用播放器播放实时视频流。我找了一个开源的播放器,可以支持rtmp方式播放。
现在遇到的问题:
关于实时视频,我还找到了一个IVideoChat的示例项目,但是他是使用的Camera的预览回调获取的实时视频,关键代码如下:
public void onPreviewFrame(byte[] arg0, Camera arg1)
{
// TODO Auto-generated method stub
if (!active)
return;
if (!init)
{
blockWidth = 32;
blockHeight = 32;
timeBetweenFrames = 100; // 1000 / frameRate
frameCounter = 0;
previous = null;
init = true;
}
final long ctime = System.currentTimeMillis();
byte[] current = RemoteUtil.decodeYUV420SP2RGB(arg0, width, height);
try
{
final byte[] packet = RemoteUtil.encode(current, previous,
blockWidth, blockHeight, width, height);
fireOnVideoData(new MediaDataByteArray(timeBetweenFrames,
new ByteArray(packet)));
previous = current;
if (++frameCounter % 10 == 0)
previous = null;
} catch (Exception e)
{
e.printStackTrace();
}
final int spent = (int) (System.currentTimeMillis() - ctime);
try
{
Log.i(TAG, "锟竭程等达拷" + Math.max(0, timeBetweenFrames - spent)
+ " s");
Thread.sleep(Math.max(0, timeBetweenFrames - spent));
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
其中,fireOnVideoData这个方法,就是将编码后的视频通过rtmp发布到流媒体了。使用这种方式,我可以在浏览器上看到正确的实时画面,但是因为编码效率太低,视频很卡,并不实用。
我要做的,就是将mediarecorder获取到的H264视频流处理一下,然后调用fireOnVideoData这个方法发布出去。
关键代码大概是这样:
// 接收线程
Thread local_receive = new Thread()
{
public void run()
{
running = true;
try
{
is = mReceiveSocket.getInputStream();
byte buffer[] = new byte[4];
// Skip all atoms preceding mdat atom
while (true)
{
while (is.read() != 'm')
;
is.read(buffer, 0, 3);
if (buffer[0] == 'd' && buffer[1] == 'a'
&& buffer[2] == 't')
break;
}
byte[] current = new byte[10 * 1024];
while (running)
{
try
{
is.read(current);
fireOnVideoData(new MediaDataByteArray(
timeBetweenFrames, new ByteArray(current)));
} catch (Exception e)
{
e.printStackTrace();
}
}
} catch (IOException e)
{
Log.e(TAG, "Couldn't skip mp4 header :/");
return;
}
}
};
问题就出在这里了
is.read(current);
fireOnVideoData(new MediaDataByteArray(timeBetweenFrames, new ByteArray(current)));
我通过is.read(current)读取到视频数据之后,直接调用下面的方法,肯定是有问题的。所以发布出去的视频格式有问题,播不出来。
我想请问一下,我应该如何处理这个视频流呢?
比如我应该怎么样在读取到的byte数组中,找出一帧数据,可能再加上header获取其他什么的,或者或者,哎呀我也不知道,蛋疼啊。
另外,我找到了一个开源的视频通话软件源码,spydroid,他的实现大概也是这样的思路,只是他用的是rtsp协议,对视频流处理的代码没看懂。。。。
还请各位大神不吝赐教啊!!!!谢谢
------解决思路----------------------
听起来,IVideoChat的实现是比较靠谱的,通过preview的方式获得yuv格式的每一帧,然后压缩成视频格式发出去。
你的代码里面,is.read读取的是压缩后的格式,如果想从这里面获取到每一帧再转化成你要的格式,至少应该先解码吧,估计你还得用ffmpeg才能实现解码。
所以呀,还是用IVideoChat的实现靠谱。
------解决思路----------------------
http://blog.csdn.net/mirage520/article/details/7038633 看一下这里是否可以参考,一直都想弄,也没耐住心来搞这个
------解决思路----------------------
楼主,请加我qq:247804775,我告诉你怎么弄