java jni librtmp_RTMPDump Android 端集成

RTMPDump 用来处理 RTMP 流媒体的开源工具包。能够单独使用 RTMP 通信,也可以集成到 FFmpeg 中通过 FFmpeg 接口来使用 RTMPDump。

介绍两种方式引入 RTMPDump 的方式,一种使用 NDK 提供的交叉编译工具来进行编译成静态库再引入,第二种源码集成。实际场景中可自行选择,如果源码不多的情况下推荐使用源码集成的方式。不过有时候我们需要大量引入 C/C++ 库,这个时候还是考虑使用静态库的方式,这样源文件就不显得很多。

交叉编译工具

使用 NDK 提供的交叉编译工具来生成静态库,首先我们下载源码,可以查看一下源码。一般开源项目都会提供 Makefile 或 CMake 编译脚本。RTMPDump 提供了 Makefile,不过它有两个,一个是根目录下,另一个在 librtmp 下。 先来看根目录下:

....

# 编译工具 gcc, 但是我在用 mac 时会使用 clang 替代,具体看我后面编译脚本。

CC=$(CROSS_COMPILE)gcc

# 链接器

LD=$(CROSS_COMPILE)ld

# 目标系统

SYS=posix

#SYS=mingw

# Openssl 加密,因为 RTMP 流媒体协议支持双向加密

CRYPTO=OPENSSL

#CRYPTO=POLARSSL

#CRYPTO=GNUTLS

LIBZ=-lz

LIB_GNUTLS=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ)

LIB_OPENSSL=-lssl -lcrypto $(LIBZ)

LIB_POLARSSL=-lpolarssl $(LIBZ)

CRYPTO_LIB=$(LIB_$(CRYPTO))

DEF_=-DNO_CRYPTO

CRYPTO_DEF=$(DEF_$(CRYPTO))

DEF=-DRTMPDUMP_VERSION=\"$(VERSION)\" $(CRYPTO_DEF) $(XDEF)

OPT=-O2

# 编译参数 XCFLAGS 会从外部指定.

CFLAGS=-Wall $(XCFLAGS) $(INC) $(DEF) $(OPT)

LDFLAGS=-Wall $(XLDFLAGS)

......

LIBRTMP=librtmp/librtmp.a

INCRTMP=librtmp/rtmp_sys.h librtmp/rtmp.h librtmp/log.h librtmp/amf.h

......

PROGS=rtmpdump rtmpgw rtmpsrv rtmpsuck

# 依赖两个目标:LIBRTMP 和 PROGS, 由于我们生成的是 Android 平台,所以这里我们不关心 PROGS,后面我会删掉这个目标。

all:$(LIBRTMP) $(PROGS)

$(PROGS): $(LIBRTMP)

# 安装,创建文件、复制文件到指定目录

install:$(PROGS)

-mkdir -p $(BINDIR) $(SBINDIR) $(MANDIR)/man1 $(MANDIR)/man8

cp rtmpdump$(EXT) $(BINDIR)

cp rtmpgw$(EXT) rtmpsrv$(EXT) rtmpsuck$(EXT) $(SBINDIR)

cp rtmpdump.1 $(MANDIR)/man1

cp rtmpgw.8 $(MANDIR)/man8

@cd librtmp; $(MAKE) install

clean:

rm -f *.o rtmpdump$(EXT) rtmpgw$(EXT) rtmpsrv$(EXT) rtmpsuck$(EXT)

@cd librtmp; $(MAKE) clean

FORCE:

# 执行 librtmp 目录下的 Makefile 文件.

$(LIBRTMP): FORCE

@cd librtmp; $(MAKE) all

# 调用编译器编译生成 rtmpdump.o

rtmpdump: rtmpdump.o

$(CC) $(LDFLAGS) -o $@$(EXT) $@.o $(LIBS)

....复制代码

librtmp 目录下的 Makefile.

......

# CC 编译器

CC=$(CROSS_COMPILE)gcc

# 链接器

LD=$(CROSS_COMPILE)ld

# ar 打包

AR=$(CROSS_COMPILE)ar

# 目标系统

SYS=posix

# OPENSSL 加密.

CRYPTO=OPENSSL

#CRYPTO=GNUTLS

DEF_POLARSSL=-DUSE_POLARSSL

DEF_OPENSSL=-DUSE_OPENSSL

DEF_GNUTLS=-DUSE_GNUTLS

DEF_=-DNO_CRYPTO

REQ_GNUTLS=gnutls,hogweed,nettle

REQ_OPENSSL=libssl,libcrypto

PUB_GNUTLS=-lgmp

LIBZ=-lz

LIBS_posix=

LIBS_darwin=

LIBS_mingw=-lws2_32 -lwinmm -lgdi32

LIB_GNUTLS=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ)

LIB_OPENSSL=-lssl -lcrypto $(LIBZ)

LIB_POLARSSL=-lpolarssl $(LIBZ)

PRIVATE_LIBS=$(LIBS_$(SYS))

CRYPTO_LIB=$(LIB_$(CRYPTO)) $(PRIVATE_LIBS)

CRYPTO_REQ=$(REQ_$(CRYPTO))

CRYPTO_DEF=$(DEF_$(CRYPTO))

PUBLIC_LIBS=$(PUB_$(CRYPTO))

......

SHARED=yes

......

DEF=-DRTMPDUMP_VERSION=\"$(VERSION)\" $(CRYPTO_DEF) $(XDEF)

OPT=-O2

CFLAGS=-Wall $(XCFLAGS) $(INC) $(DEF) $(OPT) $(SO_DEF)

LDFLAGS=$(XLDFLAGS)

OBJS=rtmp.o log.o amf.o hashswf.o parseurl.o

# 生成 librtmp.a 以及动态库

all:librtmp.a $(SO_LIB)

clean:

rm -f *.o *.a *.$(SOX) *$(SO_EXT) librtmp.pc

# 目标依赖于 OBJS

librtmp.a: $(OBJS)

$(AR) rs $@ $?

librtmp$(SO_EXT): $(OBJS)

$(CC) $(SO_LDFLAGS) $(LDFLAGS) -o $@ $^ $> $(CRYPTO_LIB)

ln -sf $@ librtmp.$(SOX)

# 生成目标的规则.

log.o: log.c log.h Makefile

rtmp.o: rtmp.c rtmp.h rtmp_sys.h handshake.h dh.h log.h amf.h Makefile

amf.o: amf.c amf.h bytes.h log.h Makefile

hashswf.o: hashswf.c http.h rtmp.h rtmp_sys.h Makefile

parseurl.o: parseurl.c rtmp.h rtmp_sys.h log.h Makefile

librtmp.pc: librtmp.pc.in Makefile

sed -e "s;@prefix@;$(prefix);" -e "s;@libdir@;$(libdir);" \

-e "s;@VERSION@;$(VERSION);" \

-e "s;@CRYPTO_REQ@;$(CRYPTO_REQ);" \

-e "s;@PUBLIC_LIBS@;$(PUBLIC_LIBS);" \

-e "s;@PRIVATE_LIBS@;$(PRIVATE_LIBS);" librtmp.pc.in > $@

install:install_base $(SO_INST)

install_base:librtmp.a librtmp.pc

-mkdir -p $(INCDIR) $(LIBDIR)/pkgconfig $(MANDIR)/man3 $(SODIR)

cp amf.h http.h log.h rtmp.h $(INCDIR)

cp librtmp.a $(LIBDIR)

cp librtmp.pc $(LIBDIR)/pkgconfig

cp librtmp.3 $(MANDIR)/man3

......复制代码

整体流程大概分析一下,告诉了我们编译规则和依赖,以及安装目录。那么接下来编写 NDK 交叉编译脚本,基于 Mac 平台编写,linux 更改一下工具链位置。

# 交叉编译工具链,基于 ndk-r17c

# 你的交叉编译工具链位置,这里使用的是独立工具链生成.

TOOLCHAIN= /XX/standalone-toolchain/armv7a-standalone-toolchain

# 加入到系统路径

export PATH=$PATH:$TOOLCHAIN/bin

# 目标

target_host=arm-linux-androideabi

# 编译目标品台 api 版本

ANDROID_API=21

# 指定编译器 cflags 编译参数

export XCFLAGS="-isysroot ${TOOLCHAIN}/sysroot -isystem ${TOOLCHAIN}/sysroot/usr/include/${target_host} -D__ANDROID_API__=${ANDRO$

# 交叉编译工具,使用的是 NDK 提供的

export CROSS_COMPILE=${TOOLCHAIN}/bin${target_host}-

# 使用 clang 编译器

CC=$target_host-clang

AR=$target_host-ar

LD=$target_host-ld

make clean

# 安装,指定 SYS 为 android, prefix 安装路径, 不指定 CRYPTO=, 不生成共享库 SHARED ,去掉 ssl 加密

make install SYS=android prefix=`pwd`/install CC=$CC AR=$AR LD=$LD CRYPTO= SHARED= XDEF=-DNO_SSL复制代码chmod +x librtmp_build.sh

./librtmp_build.sh

复制代码

生成的目录

0e3098785551bd0fe0300e1128ea21d2.png

在 Android Studio 中使用

新建一个 CXX 工程,然后将编译出来头文件和静态库文件拷贝到项目中,如图

11d9d0da2ba89d1e189143a6f450cdbc.png

CMakeLists.txt 配置文件

cmake_minimum_required(VERSION 3.4.1)

include_directories(${CMAKE_SOURCE_DIR}/include/librtmp)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}")

add_library(

native-lib

SHARED

native-lib.cpp )

target_link_libraries(

native-lib

log

rtmp

)

复制代码

测试获取 RTMPDump 版本

#include

#include

#include "rtmp.h"

extern "C" JNIEXPORT jstring JNICALL

Java_com_hxj_rtmpdumpdemo_MainActivity_stringFromJNI(

JNIEnv *env,

jobject /* this */) {

char *str = "hello xxx";

char version[100];

sprintf(version, "rtmpdump version: %d", RTMP_LibVersion());

return env->NewStringUTF(version);

}

复制代码

引入源码的方式

前面大概介绍了下 Makefile 规则,引入源码的只需要将 librtmp 目录下的源码引入,根目录下生成一些工具,而我们不必关心。

# librtmp 目录下的 Makefile.

# 依赖的目标.

OBJS=rtmp.o log.o amf.o hashswf.o parseurl.o

# 生成 librtmp.a 以及动态库

all:librtmp.a $(SO_LIB)

# 目标依赖于 OBJS

librtmp.a: $(OBJS)

$(AR) rs $@ $?

# 生成目标的规则.

log.o: log.c log.h Makefile

rtmp.o: rtmp.c rtmp.h rtmp_sys.h handshake.h dh.h log.h amf.h Makefile

amf.o: amf.c amf.h bytes.h log.h Makefile

hashswf.o: hashswf.c http.h rtmp.h rtmp_sys.h Makefile

parseurl.o: parseurl.c rtmp.h rtmp_sys.h log.h Makefile

复制代码

可以知道我们需要那些文件,这里其实就是所有的.h 和 .c 文件。 这里我们新建一个目录 sources 用来存放.h 和 .c 文件,可以使用如下命令拷贝

注意 librtmp 路径

cp -rf ../librtmp/*.h ../librtmp/*.c ./sources

复制代码

在工程新建一个目录 librtmp,然后拷贝源文件进入

5aaaf89ff9c2011be8db338b076c5388.png

修改 CMakeLists.txt 文件

cmake_minimum_required(VERSION 3.4.1)

include_directories(${CMAKE_SOURCE_DIR}/librtmp)

set(src_dir ${CMAKE_SOURCE_DIR}/librtmp)

file(GLOB srcs ${src_dir}/*.c)

# 或者使用 aux_source_directory 替代 set 和 file 两个指令.

# aux_source_directory(${CMAKE_SOURCE_DIR}/librtmp srcs)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_CRYPTO")

add_library(

native-lib

SHARED

native-lib.cpp

${srcs}

)

target_link_libraries(

native-lib

log

)

复制代码

由于 RTMPDump 使用到了 openssl, 我这里没有选择使用所以通过编译指令去掉。否则会报错,读者可以去掉试试。

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_CRYPTO")

复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值