阅读更多 背景:在已有的red5服务器环境下实现android客户端的视频直播

要实现客户端视频直播就先先对服务器端有所了解

Red5流媒体服务器是Adboe的产品,免费并且是开源的,与Flash搭配的时候可谓是天生一对,但使用Java和Android作为客户端调用却可谓一波三折。
Red5是一个采用Java开发开源的Flash流媒体服务器。它支持:把音频(MP3)和视频(FLV)转换成播放流; 录制客户端播放流(只支持FLV);共享对象;现场直播流发布;远程调用。Red5使用RSTP作为流媒体传输协议,在其自带的一些示例中演示了在线录制,flash流媒体播放,在线聊天,视频会议等一些基本功能。

服务器的相关配置
        webAppRootKey       /FlashMediaGateway [root@lapaccweb WEB-INF]# more red5-web.properties webapp.contextPath=/FlashMediaGatewaywebapp.virtualHosts=*:1935,*:443recordPath=/opt/Avaya/AccWeb/data/SessionRecording/playbackPath=/opt/Avaya/AccWeb/data/SessionRecording/absolutePath=true


android + red5 + rtmp_第1张图片


android + red5 + rtmp_第2张图片


android + red5 + rtmp_第3张图片





Adobe的Red5源代码里有一个RTMPClient的类,这个类在使用上其实不复杂,但却没办法成功调用。观察日志,发现是连接成功后在开始创建流的时候,服务端把连接断开了。我能想到的解释就是可能公司现在所使用的Red5服务器的版本与这个RTMPClient不兼容。

国外还有一个收费的RTMPClient,价值是395刀。具体网址和产品的名称我就不指出了,有心人肯定会找得到。这个客户端类库很强大,使用也很方便,我注册了一个试用的key,发现能和Red5服务器成功连接并且通讯良好。(国内有破解版)

之前用vlc和Vitamio尝试过,结果播放不了直播流,可能是我太笨了吧.
有可能的原因如下:
http://blog.csdn.net/qiuchangyong/article/details/18862247

利用LocalServerSocket采集视频数据的实时流数据,android自带的LocalServerSocket是和java 的serverSocket是不同的,因为LocalServerSocket的客户端和服务端都是必须在本机,所以我们可以在调用RecodMedia录制视频的时候建立客户端LocalSocket来向服务端发送数据,在服务端接收数据调用juv—rtmp—client将接收的数据打包成RTMP协议数据向流媒体服务器发送数据。
利用android自带的Camera来录制数据,这里主要用到了照相机的CallBack回调接口,在这个回调接口里面可以实时的接收照相机录制的视频数据,这里面录制的视频数据是YUV420SP格式的数据流,这是最原始的数据流,是无法显示的服务器界面的。将数据流转化成YUV420SP2RGB格式的数据,然后利用juv—rtmp—client向流媒体服务器发送数据。

juv—rtmp—client这个jar包封装了很多和流媒体服务器交互的方法,当然有视频数据传输格式。在流媒体服务提供了三种格式的传输方式:Record、Live、Append。

利用juv—rtmp—client有几个主要的类

其中最重要的几个类是NetConnection,NetStream, License,其中NetConnection,NetStream这两个类是负责创建连接和回调服务端的数据。而License则顾名思义是负责验证有没有授权。由于按照官方给出的使用说明,在使用前必须调用License.setKey()方法传入注册所得到的key。

CameraVideoActivity
private void init() {aCamera = new AndroidCamera(CameraVideoActivity.this);hour = (TextView) findViewById(R.id.mediarecorder_TextView01);minute = (TextView) findViewById(R.id.mediarecorder_TextView03);second = (TextView) findViewById(R.id.mediarecorder_TextView05);mStart = (Button) findViewById(R.id.mediarecorder_VideoStartBtn);mStop = (Button) findViewById(R.id.mediarecorder_VideoStopBtn);mReturn = (Button) findViewById(R.id.mediarecorder_VideoReturnBtn);// 开始录像mStart.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (streaming == false) {aCamera.start();}aCamera.startVideo();isTiming = true;handler.postDelayed(task, 1000);// 设置按钮状态mStart.setEnabled(false);mReturn.setEnabled(false);mStop.setEnabled(true);}});mReturn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (RTMPConnectionUtil.netStream != null) {RTMPConnectionUtil.netStream.close();RTMPConnectionUtil.netStream = null;}if (aCamera != null) {aCamera = null;}finish();}});mStop.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubaCamera.stop();// 设置按钮状态mStart.setEnabled(true);mReturn.setEnabled(true);mStop.setEnabled(false);isTiming = false;}});}public class AndroidCamera extends AbstractCamera implementsSurfaceHolder.Callback, Camera.PreviewCallback {private SurfaceView surfaceView;private SurfaceHolder surfaceHolder;private Camera camera;private int width;private int height;private boolean init;int blockWidth;int blockHeight;int timeBetweenFrames; // 1000 / frameRateint frameCounter;byte[] previous;public AndroidCamera(Context context) {surfaceView = (SurfaceView) findViewById(R.id.mediarecorder_Surfaceview);surfaceView.setVisibility(View.VISIBLE);surfaceHolder = surfaceView.getHolder();surfaceHolder.addCallback(AndroidCamera.this);surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);width = 352 / 2;height = 288 / 2;init = false;Log.d("DEBUG", "AndroidCamera()");}private void startVideo() {Log.d("DEBUG", "startVideo()");RTMPConnectionUtil.ConnectRed5(CameraVideoActivity.this);RTMPConnectionUtil.netStream = new UltraNetStream(RTMPConnectionUtil.connection);RTMPConnectionUtil.netStream.addEventListener(new NetStream.ListenerAdapter() {@Overridepublic void onNetStatus(final INetStream source,final Map info) {Log.d("DEBUG", "Publisher#NetStream#onNetStatus: "+ info);final Object code = info.get("code");if (NetStream.PUBLISH_START.equals(code)) {if (CameraVideoActivity.aCamera != null) {RTMPConnectionUtil.netStream.attachCamera(aCamera, -1 /* snapshotMilliseconds */);Log.d("DEBUG", "aCamera.start()");aCamera.start();} else {Log.d("DEBUG", "camera == null");}}}});RTMPConnectionUtil.netStream.publish("anystringdata", NetStream.LIVE);}public void start() {camera.startPreview();streaming = true;}public void stop() {camera.stopPreview();streaming = false;}public void printHexString(byte[] b) {for (int i = 0; i < b.length; i++) {String hex = Integer.toHexString(b[i] & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}}}@Overridepublic void onPreviewFrame(byte[] arg0, Camera arg1) {// TODO Auto-generated method stub// if (!active) return;if (!init) {blockWidth = 32;blockHeight = 32;timeBetweenFrames = 100; // 1000 / frameRateframeCounter = 0;previous = null;init = true;}final long ctime = System.currentTimeMillis();/** 将采集的YUV420SP数据转换为RGB格式 */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 {Thread.sleep(Math.max(0, timeBetweenFrames - spent));} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {// TODO Auto-generated method stub// camera.startPreview();// camera.unlock();// Log.d("DEBUG", "surfaceChanged()");// startVideo();}@Overridepublic void surfaceCreated(SurfaceHolder holder) {// TODO Auto-generated method stubcamera = Camera.open();try {camera.setPreviewDisplay(surfaceHolder);camera.setPreviewCallback(this);Camera.Parameters params = camera.getParameters();params.setPreviewSize(width, height);camera.setParameters(params);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();camera.release();camera = null;}Log.d("DEBUG", "surfaceCreated()");}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {// TODO Auto-generated method stubif (camera != null) {camera.stopPreview();camera.release();camera = null;}}}/* 定时器设置,实现计时 */private Handler handler = new Handler();int s, h, m, s1, m1, h1;private Runnable task = new Runnable() {public void run() {if (isTiming) {handler.postDelayed(this, 1000);s++;if (s < 60) {second.setText(format(s));} else if (s < 3600) {m = s / 60;s1 = s % 60;minute.setText(format(m));second.setText(format(s1));} else {h = s / 3600;m1 = (s % 3600) / 60;s1 = (s % 3600) % 60;hour.setText(format(h));minute.setText(format(m1));second.setText(format(s1));}}}};


RTMPConnectionUtil
public static void ConnectRed5(Context context) {//License.setKey("63140-D023C-D7420-00B15-91FC7");connection = new UltraNetConnection();connection.configuration().put(UltraNetConnection.Configuration.INACTIVITY_TIMEOUT, -1);        connection.configuration().put(UltraNetConnection.Configuration.RECEIVE_BUFFER_SIZE, 256 * 1024);        connection.configuration().put(UltraNetConnection.Configuration.SEND_BUFFER_SIZE, 256 * 1024);//connection.client(new ClientHandler(context));connection.addEventListener(new NetConnectionListener());//Log.d("DEBUG", User.id + " - " + User.phone);connection.connect(red5_url);}


附带一款测试Red5用rtmp是否能够连接工具

博客地址:http://qiaoyihang.iteye.com/
  • android + red5 + rtmp_第4张图片
  • 大小: 152.1 KB
  • android + red5 + rtmp_第5张图片
  • 大小: 146.7 KB
  • android + red5 + rtmp_第6张图片
  • 大小: 152.4 KB
  • Red5用rtmp是否能够连接工具.rar (1.4 MB)
  • 下载次数: 43
  • 查看图片附件

更多相关文章

  1. android流媒体框架介绍
  2. Android数据存储方案ContentProvider存储数据
  3. android中共享全局数据的方法
  4. Django服务器与App(Android)客户端的简单实现
  5. android的5种数据存储方式
  6. Android服务器——TomCat服务器的搭建
  7. 在Android设备上搭建Web服务器的方法
  8. 【多端应用开发系列1.1.1 —— Android:使用新浪API V2】服务器Js

随机推荐

  1. Android高手进阶教程(三)之----Android(
  2. Android应用程序架构
  3. Android(安卓)RTC 自下而上分析
  4. Android(安卓)重点知识回顾
  5. android studio 更改快捷键为eclipse中习
  6. Android(安卓)Widgets
  7. 基于ffmpeg的Android播放器开源代码
  8. Android(安卓)如何在屏幕切换的时候页面
  9. Android平台安全分析
  10. AsynTask 异步任务