Android端实现基于RTMP的音视频推流

版本信息

x264(视频编码):好像没有版本号这一说

nasm(编译x264的依赖):nasm-2.14rc16

faac(音频编码):faac-1.29.9.2

编译的系统:centos

编译的NDK版本:17R

AndroidStudio:3.5

 

需要了解的背景

Nginx+Nginx-rtmp-module搭建RTMP视频直播服务器

H264基本原理

带你吃透RTMP

AAC解码算法原理详解

 

环境搭建

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推过去,后面的音频流直接推过去即可。

源码见附件。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值