安卓直播推流專欄博客總結
0 . 資源和源碼地址 :
- 資源下載地址 : 資源下載地址 , 服務器搭建 , x264 , faac , RTMPDump , 源碼及交叉編譯庫 , 本專欄 Android 直播推流源碼 ;
- GitHub 源碼地址 : han1202012 / RTMP_Pusher
1. 搭建 RTMP 服務器 : 下面的博客中講解了如何在 VMWare 虛擬機中搭建 RTMP 直播推流服務器 ;
2. 準備視頻編碼的 x264 編碼器開源庫 , 和 RTMP 數據包封裝開源庫 :
-
【Android RTMP】RTMPDumb 源碼導入 Android Studio ( 交叉編譯 | 配置 CMakeList.txt 構建腳本 )
-
【Android RTMP】Android Studio 集成 x264 開源庫 ( Ubuntu 交叉編譯 | Android Studio 導入函數庫 )
3. 講解 RTMP 數據包封裝格式 :
4. 圖像數據採集 : 從 Camera 攝像頭中採集 NV21 格式的圖像數據 , 並預覽該數據 ;
-
【Android RTMP】Android Camera 視頻數據採集預覽 ( 視頻採集相關概念 | 攝像頭預覽參數設置 | 攝像頭預覽數據回調接口 )
-
【Android RTMP】Android Camera 視頻數據採集預覽 ( NV21 圖像格式 | I420 圖像格式 | NV21 與 I420 格式對比 | NV21 轉 I420 算法 )
-
【Android RTMP】Android Camera 視頻數據採集預覽 ( 圖像傳感器方向設置 | Camera 使用流程 | 動態權限申請 )
5. NV21 格式的圖像數據編碼成 H.264 格式的視頻數據 :
-
【Android RTMP】x264 編碼器初始化及設置 ( 獲取 x264 編碼參數 | 編碼規格 | 碼率 | 幀率 | B幀個數 | 關鍵幀間隔 | 關鍵幀解碼數據 SPS PPS )
-
【Android RTMP】x264 圖像數據編碼 ( Camera 圖像數據採集 | NV21 圖像數據傳到 Native 處理 | JNI 傳輸字節數組 | 局部引用變量處理 | 線程互斥 )
-
【Android RTMP】x264 圖像數據編碼 ( NV21 格式中的 YUV 數據排列 | Y 灰度數據拷貝 | U 色彩值數據拷貝 | V 飽和度數據拷貝 | 圖像編碼操作 )
6. 將 H.264 格式的視頻數據封裝到 RTMP 數據包中 :
-
【Android RTMP】RTMPDump 封裝 RTMPPacket 數據包 ( 封裝 SPS / PPS 數據包 )
-
【Android RTMP】RTMPDump 封裝 RTMPPacket 數據包 ( 關鍵幀數據格式 | 非關鍵幀數據格式 | x264 編碼後的數據處理 | 封裝 H.264 視頻數據幀 )
-
【Android RTMP】RTMPDump 推流過程 ( 獨立線程推流 | 創建推流器 | 初始化操作 | 設置推流地址 | 啓用寫出 | 連接 RTMP 服務器 | 發送 RTMP 數據包 )
7. 階段總結 : 阿里雲服務器中搭建 RTMP 服務器 , 並使用電腦軟件推流和觀看直播內容 ;
-
【Android RTMP】RTMP 直播推流 ( 阿里雲服務器購買 | 遠程服務器控制 | 搭建 RTMP 服務器 | 服務器配置 | 推流軟件配置 | 直播軟件配置 | 推流直播效果展示 )
-
【Android RTMP】RTMP 直播推流階段總結 ( 服務器端搭建 | Android 手機端編碼推流 | 電腦端觀看直播 | 服務器狀態查看 )
8. 處理 Camera 圖像傳感器導致的 NV21 格式圖像旋轉問題 :
-
【Android RTMP】NV21 圖像旋轉處理 ( 問題描述 | 圖像順時針旋轉 90 度方案 | YUV 圖像旋轉細節 | 手機屏幕旋轉方向 )
-
【Android RTMP】NV21 圖像旋轉處理 ( 圖像旋轉算法 | 後置攝像頭順時針旋轉 90 度 | 前置攝像頭順時針旋轉 90 度 )
9. 下面這篇博客比較重要 , 裏面有一個快速搭建 RTMP 服務器的腳本 , 強烈建議使用 ;
10. 編碼 AAC 音頻數據的開源庫 FAAC 交叉編譯與 Android Studio 環境搭建 :
-
【Android RTMP】音頻數據採集編碼 ( 音頻數據採集編碼 | AAC 高級音頻編碼 | FAAC 編碼器 | Ubuntu 交叉編譯 FAAC 編碼器 )
-
【Android RTMP】音頻數據採集編碼 ( FAAC 頭文件與靜態庫拷貝到 AS | CMakeList.txt 配置 FAAC | AudioRecord 音頻採樣 PCM 格式 )
11. 解析 AAC 音頻格式 :
12 . 將麥克風採集的 PCM 音頻採樣編碼成 AAC 格式音頻 , 並封裝到 RTMP 包中 , 推流到客戶端 :
-
【Android RTMP】音頻數據採集編碼 ( FAAC 音頻編碼參數設置 | FAAC 編碼器創建 | 獲取編碼器參數 | 設置 AAC 編碼規格 | 設置編碼器輸入輸出參數 )
-
【Android RTMP】音頻數據採集編碼 ( FAAC 編碼器編碼 AAC 音頻解碼信息 | 封裝 RTMP 音頻數據頭 | 設置 AAC 音頻數據類型 | 封裝 RTMP 數據包 )
-
【Android RTMP】音頻數據採集編碼 ( FAAC 編碼器編碼 AAC 音頻採樣數據 | 封裝 RTMP 音頻數據頭 | 設置 AAC 音頻數據類型 | 封裝 RTMP 數據包 )
上一篇博客 【Android RTMP】RTMPDumb 源碼導入 Android Studio 工程 ( 交叉編譯 | 配置 CMakeList.txt 構建腳本 ) 中 , 集成了 RTMPDump , 用於 RTMP 數據編解碼及傳輸 , 本篇博客中主要講解將圖像編碼爲視頻的開源庫 x264 , 集成到 Android 項目中 ;
RTMPDump 和 x264 庫都可以集成到 FFMPEG 中 , FFMPEG 中也提供類似功能 , 但是其執行效率性能要低於 RTMPDump 和 x264 開源庫 ;
一、 x264 簡介
x264 簡介 :
① H.264 標準 : H.264 是視頻編碼標準 , 由 ITU 和 MPEG 制訂 ;
② x264 開源庫 : x264 是 H.264 格式的視頻編解碼庫 , 由 C 語言實現 ;
③ 官方頁面 : 訪問 x264 官網頁面 , 該開源庫是由 VLC 同一個團隊維護的 ;
④ 直接下載 : 上述官網頁面建議不好訪問 , 可以 點擊此處直接下載 , 也可以在博客資源中下載 ;
⑤ Android 使用方式 : x264 庫很大 , 必須交叉編譯成 ARM 架構的函數庫 ( 動態庫 / 靜態庫 ) 導入到 Android Studio 中才能使用 ;
不像 RTMPDump 只有 個 C 代碼 , 可以直接放在 Android Studio 工程中進行編譯 ;
二、 x264 交叉編譯
參考博客 : 有些配置 , 參考之前寫的 NDK 交叉編譯相關的博客 ;
【Android NDK 開發】NDK 交叉編譯 ( Ubuntu 中交叉編譯動態庫 | Android Studio 中配置使用第三方動態庫 )
【Android NDK 開發】Ubuntu 函數庫交叉編譯 ( Android 動態庫交叉編譯 | Android 靜態庫交叉編譯 )
【Android FFMPEG 開發】FFMPEG 交叉編譯配置 ( 下載 | 配置腳本 | 輸出路徑 | 函數庫配置 | 程序配置 | 組件配置 | 編碼解碼配置 | 交叉編譯配置 | 最終腳本 )
1 . 準備編譯環境 : 按照 交叉編譯環境 操作 , 先把 NDK 環境搭建好 ;
2 . 拷貝源碼到 Ubuntu : 將 last_x264.tar.bz2 拷貝到 Ubuntu 中的 /root/rtmp/ 目錄下 ;
3 . 解壓源碼 :
tar xvf last_x264.tar.bz2
4 . 配置 Makefile 文件 ( 僅做參考 ) : 與 FFMPEG 編譯內容類似 , 不一一配置了 , 直接執行 shell 腳本自動配置 ;
--prefix
: 指定代碼安裝目錄 ;
--cross-prefix
: 指定交叉編譯頭 ;
--sysroot
: 配置頭文件與庫文件查找目錄 ;
5 . 交叉編譯 Shell 腳本內容 : 根據之前的 FFMPEG 編譯 Shell 腳本修改一下即可 , 只是 ./configure
生成 Makefile 的選項不同 , 其它都相同 ; 在 x264 源碼目錄 x264-master 下 , 創建 build.sh , 並拷貝上述內容 ;
#!/bin/bash
# NDK 根目錄
NDK_ROOT=/root/NDK/android-ndk-r17c
# TOOLCHAIN 變量指向 gcc g++ 等交叉編譯工具所在的目錄
TOOLCHAIN=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
# gcc 編譯器參數
FLAGS="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -isystem $NDK_ROOT/sources/android/support/include -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC"
# 編譯結果輸出路徑
PREFIX=./android/armeabi-v7a
./configure \
--prefix=$PREFIX \
--disable-cli \
--enable-static \
--enable-pic \
--host=arm-linux \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$NDK_ROOT/platforms/android-21/arch-arm \
--extra-cflags="$FLAGS"
# 清除之前的編譯內容
make clean
# 開啓新的 FFMPEG 編譯安裝過程
make install
6 . 修改腳本權限 : chmod -R 777 build.sh
命令 , 修改 build.sh 腳本權限 ;
root@octopus:~/rtmp/x264-master# ls
AUTHORS build.sh config.guess configure doc example.c filters Makefile tools x264.c x264dll.c x264res.rc
autocomplete.c common config.sub COPYING encoder extras input output version.sh x264cli.h x264.h
root@octopus:~/rtmp/x264-master# chmod -R 777 build.sh
7 . 執行編譯腳本 : 執行 ./build.sh
編譯腳本 , 編譯後 , 生成的結果如下 ;
三、 Android Studio 導入函數庫
1 . 拷貝文件 : 拷貝上面編譯好的頭文件與函數庫到 Android Studio 工程中 , 沒有目錄的創建目錄 ;
2 . 編輯 build.gradle 構建腳本 : 只在生成的代碼基礎上 , 添加了 abiFilters ‘armeabi-v7a’ 內容 ;
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "kim.hsl.rtmp"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
abiFilters 'armeabi-v7a'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
3 . 編輯 CMakeList.txt 構建腳本 : 這是 src/main/cpp 下的 CMakeList.txt 構建腳本 ;
cmake_minimum_required(VERSION 3.4.1)
# 鏈接 src/main/cpp/librtmp 目錄下的構建腳本
add_subdirectory(librtmp)
add_library( # 函數庫名稱
native-lib
# 動態庫類型
SHARED
# 源文件
native-lib.cpp )
find_library( # 日誌庫
log-lib
log )
# 設置頭文件搜索路徑
include_directories(include)
# 通過設置編譯選項, 設置函數庫的搜索路徑
# 此處的 ANDROID_ABI 是在
# build.gradle android->defaultConfig->externalNativeBuild->cmake
# 下的 abiFilters 中設置
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}")
target_link_libraries( # 鏈接動態庫
native-lib
# 編譯的 rtmp 靜態庫
rtmp
${log-lib} )
四、 交叉編譯版本
1 . 交叉編譯 Android 庫版本 : 在 Ubuntu 中進行交叉編譯時 , 使用的是 android-21 版本的函數庫與頭文件 ,
# 截取的兩個配置片段
FLAGS="...-D__ANDROID_API__=21..."
./configure \
...
--sysroot=$NDK_ROOT/platforms/android-21/arch-arm \
...
2 . Android APP 中的最低版本 : Android 項目中的 build.gradle 中配置對應的最低兼容版本 , 也要是 21 版本 ;
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "kim.hsl.rtmp"
// 核心 ---------------------------------
minSdkVersion 21
// 核心 ---------------------------------
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
abiFilters 'armeabi-v7a'
}
}
}
...
}
...
Ubuntu 中的交叉編譯版本 , 與 Android 應用的最低兼容版本 , 一定要保持一致 ;
五、 GitHub 項目地址
GitHub 地址 : han1202012 / RTMP_Pusher