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