Android流媒體開發之路二:NDK C++開發Android端RTMP直播推流程序

NDK C++開發Android端RTMP直播推流程序

通過一番折騰,成功把RTMP直播推流代碼,經過NDK交叉編譯的方式,移植到了Android下,從而實現了Android端採集攝像頭和麥克縫數據,而後進行h264視頻編碼和aac音頻編碼,併發送到RTMP服務器,從而實現Android攝像頭直播。程序名爲NdkRtmpEncoder,在這裏把整個過程,和大致框架介紹一下,算是給須要的人引路。html

開發思路

首先,爲何要用NDK來作,由於本身以前就已經實現過RTMP推流、RTMP播放、RTSP轉碼等等各類c++實現的流媒體項目,有很成熟的代碼模塊。既然Android有NDK,能夠JNI的方式複用以前的成熟代碼,大大拓展和加快項目實現,那爲何不這樣去作呢。和其餘平臺同樣,要實現採集攝像頭推送直播流,須要實現如下幾點linux

  • 獲取Android攝像頭數據
  • 對攝像頭數據進行h264編碼
  • 編碼後數據以RTMP協議封裝數據並推送

下面分開來說開發思路:android

  1. Android端採集攝像頭原始數據,能夠在Java層經過Camera2獲取數據,也能夠用NativeCamera經過NDK來獲取,不事後者須要的版本高一些,我考慮了一下,仍是決定經過Java層獲取數據,而後再交給下層處理。
  2. h264編碼,能夠經過AndroidMediaCodec進行硬件編碼,也能夠經過x264進行軟件編碼,這裏由於要複用之前的代碼,決定使用軟件編碼來驗證
  3. RTMP協議封裝,這部分代碼,直接使用以前的C++代碼便可,自己就是平臺無關的,NDK也是linux環境開發,socket網絡通訊都是相通的。具體能夠參考我以前的文章「C++實現RTMP協議發送H.264編碼及AAC編碼的音視頻

程序框架

根據個人開發思路,程序框架就顯而易見了:c++

這裏省略了部份內容,好比在so動態庫之上,有一層封裝模塊,供Activity調用服務器

  1. Java層的主要作數據採集。對攝像頭,經過Camera2接口,獲取到更新的Surface,並轉交給Opengl.EGL進行繪製,數據被繪製到TextureView的SurfaceTexture上,同時將RGB原始數據回調給Activity,由Activity把數據轉交給動態庫。 關於Camera2接口獲取攝像頭數據,能夠參考以前的文章「Android流媒體開發之路一:Camera2採集攝像頭原始數據並手動預覽」,不一樣的是,那篇文章裏直接使用ImageReader的Surface,這裏使用的是自定義的Surface。網絡

  2. 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腳本進行編譯。框架

1. 工具鏈方式

對第一種方式來講其實比較簡單,安裝好交叉編譯工具鏈以後,配置一下環境,就能夠編譯了。好比以下配置socket

這樣基本就能夠了,固然不一樣項目可能還須要進一步的修改配置,make以前須要執行configure等,但大體如此。

2. ndk-build方式

對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。(轉載請註明做者和出處~)

相關文章
相關標籤/搜索