安卓直播的推流和播放

为啥想写这篇博客呢,也是因为自己这一周开发走过不少坎坷路途,希望对有同样需求的同志们有些许帮助。说说最近的项目,需要远程控制一个硬件设备,通过互联网传送指令,后来硬是加上远程监控,所以就有了接下来的纠结。需要在远程控制端加上个播放流媒体的功能,执行端需要调用摄像头进行推流。我也是调研很多,以前也没做过相关的,最终选择使用RTMP协议推流,nginx服务器转发流媒体,远程采用Vitamio播放RTMP流。

实现方法

推流端publisher
执行端要加上推流,找了很久最终选择github上一位大神分享的免费RTMP推流SDK,android_rtmppush_sdk下载地址,但是我遇到个问题,我需要的是横屏推流和小窗口嵌入界面,仔细看了他附带demo中的代码终于找到方法。我们知道从摄像头提取的数据先得转换成yuv格式(yuv420 = _swEncH264.swapNV21toI420(YUV, W, H)根据手机ImageFormat设置NV21或YV12来选择swap函数),然后裁剪(demo中使用获取相机默认的尺寸,然后设置成推流的宽高比例),相机返回尺寸默认是宽度大于高度的,作者为了实现竖屏推流将宽设置小于高,但是在处理的时候都是将参数倒过来用,之后还将yuv数据旋转270度(后置摄像头需要旋转90度)。sdk中集成了yuv数据的90度和270度旋转的方法(SWVideoEncoder类中YUV420pRotate90、YUV420pRotate270方法),当然也可以自己写,但是效率啥的这里应该更好。
回到我的项目,我需要的是前置摄像头横屏推流,这里在xml布局文件中加了个SurfaceView,设置大小为推流视频分辨率尺寸或者等比放大。横屏推流就不需要旋转yuv数据角度,直接赋值_yuvEdit = yuvData就好,根据需求旋转90或270度(试过这sdk中只有这两种旋转方式),例如_yuvEdit = _swEncH264.YUV420pRotate90(yuvData, W,H) (W>H默认相机获取图形分辨率宽大于高)。在进行编码时候的宽高是发送推流后显示的宽高_swEncH264 = new SWVideoEncoder(W, H, F, B)。
倘若需要横竖屏推流切换的话,应该在编码前进行手机重力感应进行方向判断(demo中有getWindowManager().getDefaultDisplay().getRotation()函数返回屏幕方向,但遇到某些定制平板横竖底层调转了,要自己调试一下,或者手动设置角度),然后相应旋转yuv数据,编码输出相应尺寸。
调用前置摄像头经常需要镜像处理,发一段yuv数据镜像转换的函数

public void Mirror(byte[] src, int w, int h) {//src是原始yuv数组
        int i;
        int index;
        byte temp;
        int a, b;
        //mirror y
        for (i = 0; i < h; i++) {
            a = i * w;
            b = (i + 1) * w - 1;
            while (a < b) {
                temp = src[a];
                src[a] = src[b];
                src[b] = temp;
                a++;
                b--;
            }
        }
        //mirror u
        index = w * h;//U起始位置
        for (i = 0; i < h / 2; i++) {
            a = i * w / 2;
            b = (i + 1) * w / 2 - 1;
            while (a < b) {
                temp = src[a + index];
                src[a + index] = src[b + index];
                src[b + index] = temp;
                a++;
                b--;
            }
        }
        //mirror v
        index = w * h / 4 * 5;//V起始位置
        for (i = 0; i < h / 2; i++) {
            a = i * w / 2;
            b = (i + 1) * w / 2 - 1;
            while (a < b) {
                temp = src[a + index];
                src[a + index] = src[b + index];
                src[b + index] = temp;
                a++;
                b--;
            }
        }
    }

服务端nginx
服务端采用的是nginx作为流媒体服务器,下载的是带rtmp模块的服务器,nginx-rtmp-win32下载地址,监听端口(网络端口、RTMP端口)可以在/conf/nginx.conf里面修改,开启服务器后,可以在http://ip:8080/index.html访问查看连接的视频流影像,在http://ip:8080/stat 访问连接设备状态(其中ip本地可以选择localhost,远程访问需要公网ip)。
播放端player
远程控制端进行直播拉流播放,ijkplayer挺好用,可是我这边总是编译不了,最后选择vitamio插件,VitamioSDK下载地址 ,怎么加入它的sdk就不说了,说说怎么调用,布局文件中加入

.vov.vitamio.widget.VideoView
     android:id="@+id/vv"
     android:layout_width="640px"
     android:layout_height="480px"
     android:layout_centerHorizontal="true" />

在清单文件中加入

不声明没法使用播放器,注意之后使用的videoview类是import vitamio插件里面的类,安卓自带的那个不能播放rtmp流。
在activity中加入

if (Vitamio.isInitialized(this)) {
    mVideoView = (VideoView) findViewById(R.id.vv);
    mVideoView.setVideoPath(url_path);
    mVideoView.setBufferSize(512);
    mVideoView.requestFocus();
    mVideoView.start();
    mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){
        @Override
        public void onPrepared(MediaPlayer mediaPlayer) {
            mediaPlayer.setPlaybackSpeed(1.0f);
        }
    });
}

我这里使用的只是基本功能,比如控制条、缓冲等待显示、亮度调节、声音调节等等功能,都能在官方文档中找到。
RTMP延迟
RTMP流的播放延迟也是让我抓狂,分享一点思路吧。从两个方面:推流端,sdk中在Thread _h264EncoderThread中有个for循环,循环500次每次Thread.sleep(10),总共5000(5秒)的固定缓冲池蓄积时间,然后再取数据发送给服务器,这在弱网环境下比较有效果,直播显得连贯,但是在网络较好的情况下这五秒是无法逾越的延迟,可以适当调小一些,我发的视频流分辨率也不高,调到2.5秒在wifi下推流发现丝毫不影响;Vitamio启动播放也耗时不少,因为我需要的是远程点播,可以在程序启动时早早实例化videoview,并且把缓冲区设置小一些,之后再调用start()方法,网速好的话延迟能控制在3秒以内,弱网丢包重传会很慢,累积延迟,可以设置超时强制重连刷新。
特别感谢
最后感谢CSDN博客的博主huaxun66,正是参考他的方法才能实现我的功能,也要感谢android_rtmppush_sdk作者Alex.CR,还有Vitamio团队的播放器。

参考

[1]http://blog.csdn.net/huaxun66/article/details/53427771
[2]http://blog.csdn.net/beyond_cn/article/details/12998247
[3]http://blog.csdn.net/holo_easydarwin/article/details/51147379
[4]http://jingyan.baidu.com/article/c910274b9e1963cd361d2d04.html
[5]http://blog.sina.com.cn/s/blog_13951ca9d0102wl37.html

你可能感兴趣的:(安卓,android,rtmp直播,nginx,vitamio,横屏推流)