通过一番折腾,成功把RTMP直播推流代码,经过NDK交叉编译的方式,移植到了Android下,从而实现了Android端采集摄像头和麦克缝数据,而后进行h264视频编码和aac音频编码,并发送到RTMP服务器,从而实现Android摄像头直播。程序名为NdkRtmpEncoder,在这里把整个过程,和大致框架介绍一下,算是给须要的人引路。html
首先,为何要用NDK来作,由于本身以前就已经实现过RTMP推流、RTMP播放、RTSP转码等等各类c++实现的流媒体项目,有很成熟的代码模块。既然Android有NDK,能够JNI的方式复用以前的成熟代码,大大拓展和加快项目实现,那为何不这样去作呢。和其余平台同样,要实现采集摄像头推送直播流,须要实现如下几点linux
下面分开来说开发思路:android
根据个人开发思路,程序框架就显而易见了:c++
这里省略了部份内容,好比在so动态库之上,有一层封装模块,供Activity调用服务器
Java层的主要作数据采集。对摄像头,经过Camera2接口,获取到更新的Surface,并转交给Opengl.EGL进行绘制,数据被绘制到TextureView的SurfaceTexture上,同时将RGB原始数据回调给Activity,由Activity把数据转交给动态库。 关于Camera2接口获取摄像头数据,能够参考以前的文章“Android流媒体开发之路一:Camera2采集摄像头原始数据并手动预览”,不一样的是,那篇文章里直接使用ImageReader的Surface,这里使用的是自定义的Surface。网络
C++层实现对原始数据进行编码,并按照RTMP数据包进行封装,而后推送到RTMP服务器。这部分能够参考之前的文章“C++实现RTMP协议发送H.264编码及AAC编码的音视频”。架构
这部分也是主要工做之一,c++代码要想在Android上使用,必须编译成动态库,而后让APP经过JNI来调用。本质上,Android也是linux嘛,因此跟其余嵌入式arm-linux的交叉编译方式,本质上是差很少的,固然,前提是系统内布置好交叉编译环境。熟悉NDK的应该都知道,Google提供了完整的编译工具链,也包括SDK,下载地址在这里:“NDK Downloads”。我是在Ubuntu Linux上来作的,因此选择“Linux 64-bit(x86)”版本,记得Linux环境必须是64位,否则你什么都编译不了。并发
解压后其实就能够开始了。不过这里仍是有两种编译方式:第一种就是相似其余arm-linux环境,配置好交叉编译工具链环境,而后直接按照普通的linux编译方式进行编译;第二种是编写Android.mk文件,而后用NDK里提供的ndk-build脚本进行编译。框架
对第一种方式来讲其实比较简单,安装好交叉编译工具链以后,配置一下环境,就能够编译了。好比以下配置socket
这样基本就能够了,固然不一样项目可能还须要进一步的修改配置,make以前须要执行configure等,但大体如此。
对Android.mk来讲,跟Makefile差异是很大的,有它本身的语法,它在整个编译过程当中的位置,可能更接近于automake工具里Makefile.am。关于它的语法,参见我下面的mk文件,作了一些注释,能够帮助理解,具体的语法能够参考官方网站Android Developer。我在这里把我rtmp_enc_sdk.so动态库的Android.mk的主要内容贴出来,你们可做参考。
模式基本是同样的,按照这个模板,修改为你本身项目里使用并不困难。
不论是Java层仍是C++层的代码其实都很多,不过以前几篇文章里已经有关于他们的逻辑结构和实现方法的介绍,有兴趣的能够参考,按照文章里写的架构去理解,相信均可以实现。我这里把Java层对摄像头捕获到数据之后的处理逻辑的代码贴一下。
1 当TextureView有效以后,开始建立工做。首先要生成一个OES SurfaceTexture,后面要把它传递给Camera2接口,用于接收摄像头画面,以后开始建立RTMP推流模块调用线程,并建立摄像头捕获模块,和渲染模块
2 当OESTexture画面有效以后,获取摄像头画面的实际分辨率,以及旋转矩阵,画面旋转信息等,封装在一块儿,交给EGLRender,通知渲染模块进行画面渲染
3 渲染模块绘制完数据后,读取RGB原始数据并回调,在这里交给Rtmp发送线程,调用动态库,完成最后h264编码,并推送到RTMP服务器,这下面就是c++层so动态库作的事情了
在手机端RTMP推流画面:
在PC上用flash播放RTMP直播画面:
haibindev.cnblogs.com,合做请联系QQ。(转载请注明做者和出处~)