版本信息
x264(视频编码):好像没有版本号这一说
nasm(编译x264的依赖):nasm-2.14rc16
faac(音频编码):faac-1.29.9.2
编译的系统:centos
编译的NDK版本:17R
AndroidStudio:3.5
需要了解的背景
Nginx+Nginx-rtmp-module搭建RTMP视频直播服务器
环境搭建
AndroidStudio中新建C++的项目备用。
交叉编译x264
获取:git clone https://code.videolan.org/videolan/x264.git
进入到x264的目录,编写编译脚本build.sh,路径要和自己的环境匹配,不可照搬。
#!/bin/bash
PREFIX=./android/armeabi-v7a
NDK_ROOT=/ndk/android-ndk-r17c
TOOLCHAIN=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
FLAGS="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=17 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC"
./configure \
--prefix=$PREFIX \
--disable-cli \
--enable-static \
--enable-shared \
--enable-pic \
--host=arm-linux \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$NDK_ROOT/platforms/android-17/arch-arm \
--extra-cflags="$FLAGS"
make clean
make install
如果执行之后,Found no assembler. Minimum version is nasm-2.13 , 则先安装nasm
wget https://www.nasm.us/pub/nasm/releasebuilds/2.14rc16/nasm-2.14rc16.tar.bz2
进入nasm目录,依次执行
./configure
make
make install
安装玩nasm,重新执行sh build.sh 编译x264
如果编译时报错:
In file included from libavfilter/aeval.c:26:0:
./libavutil/avassert.h:30:20: fatal error: stdlib.h: No such file or directory
#include <stdlib.h>
^
出现这个错误是因为使用最新版的NDK造成的,最新版的NDk将头文件和库文件进行了分离,我们指定的sysroot文件夹下只有库文件,而头文件放在了NDK目录下的sysroot内,只需在--extra-cflags中添加 "-isysroot $NDK/sysroot" 即可,还有有关汇编的头文件也进行了分离,需要根据目标平台进行指定 "-I$NDK/sysroot/usr/include/arm-linux-androideabi",将 "arm-linux-androideabi" 改为需要的平台
编译成功,但是在AS中提示warning: skipping incompatible F:/NDK/LiveDemo/app/src/main/cpp/../../../libs/armeabi-v7a/libx264.so while searching for x264 说明编译的架构有问题,编译的.a文件和.so文件有问题 因为编译脚本中有注释内容,所以并没有走到指定交叉编译器的位置就停掉了, 用的是默认的GCC编译器, 编译出来是x86_64的平台,不是arm的平台
编译成功会在当前目录生成Android文件夹
进入Android文件夹,执行命令zip -r x264.zip armeabi-v7a/ 打压缩包, 下载faac.zip到Windows,将include文件夹放到AndroidStudio的cpp目录,将lib的内容放到AndroidStudio的libs/armeabi-v7a目录
交叉编译faac
获取faac, wget https://sourceforge.net/projects/faac/files/faac-src/faac-1.29/faac-1.29.9.2.tar.gz/download
进入到faac的目录,编写编译脚本build.sh,路径要和自己的环境匹配,不可照搬。
#!/bin/bash
PREFIX=`pwd`/android/armeabi-v7a
NDK_ROOT=/ndk/android-ndk-r17c
TOOLCHAIN=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi
FLAGS="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=17 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC"
export CC="$CROSS_COMPILE-gcc --sysroot=$NDK_ROOT/platforms/android-17/arch-arm"
export CFLAGS="$FLAGS"
./configure \
--prefix=$PREFIX \
--host=arm-linux \
--with-pic \
--enable-shared=no
make clean
make install
执行sh build.sh,会在当前目录生成Android文件夹
进入Android文件夹,执行命令zip -r faac.zip armeabi-v7a/ 打压缩包, 下载faac.zip到Windows,将include文件夹放到AndroidStudio的cpp目录,将lib的内容放到AndroidStudio的libs/armeabi-v7a目录
两个库引入完成之后, 项目应该是这样子的
引入RTMP库
下载rtmpdump http://rtmpdump.mplayerhq.hu/download/rtmpdump-2.3.tgz
将压缩包里面的librtmp拷贝到AndroidStudio项目的cpp目录下。
引入RTMP库之后的目录结构应该是这样婶的
图未截完。在librtmp中新建CMakeLists.txt编译脚本,此脚本是用于编译rtmp的,和cpp目录下的脚本不同, 会被cpp目录下的脚本引入。
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_CRYPTO")
add_library(
rtmp
STATIC
amf.c
hashswf.c
log.c
parseurl.c
rtmp.c
)
引入这三个库之后,需要将这三个库打包到native-lib.so中,编辑CMakeList.txt文件
cmake_minimum_required(VERSION 3.4.1)
add_subdirectory(${CMAKE_SOURCE_DIR}/librtmp)
add_library(
native-lib
SHARED
native-lib.cpp
VideoChannel.cpp
AudioChannel.cpp)
include_directories(src/main/cpp/include)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI}")
find_library(
log-lib
log)
target_link_libraries(
native-lib
rtmp
x264
faac
${log-lib})
修改app目录下的build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.myapplication"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
abiFilters "armeabi-v7a" // 仅支持此abi
}
}
ndk{
abiFilters 'armeabi-v7a' // 仅支持此abi
}
}
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"
}
}
}
sync之后rebuild项目, 能正常打包出debug.apk,则环境搭建成功。
流程梳理
视频推流流程图
音频推流流程
视频推流特点
I帧的第一个NALU单元包含编码器信息,这些信息放在SPS于PPS中,先发送包含sps和pps的packet
音频推流特点
只需要在开始推流音频前,将音频的信息封装成packet推过去,后面的音频流直接推过去即可。