一、RTSP协议简介
RTSP全称实时流协议(Real Time Streaming Protocol),它是一个网络控制协议,设计用于娱乐、会议系统中控制流媒体服务器。RTSP用于在希望通讯的两端建立并控制媒体会话,客户端通过发出VCR-style命令如play、record和pause等来实时控制媒体流。
RTSP处理流时会根据端点间可用带宽大小,将大数据切割成小分组,以使得客户端可以在播放一个分组的同时,可以解压第二个甚至同时下载第三个分组。这样一来,用户将不会感觉到数据间存在停顿。至于RTSP的特性,则主要体现在如下方面:
- 多服务器兼容 :媒体流可来自不同服务器
- 可协商 :客户端和服务器可协商feature支持程度
- HTTP亲和性 :尽可能重用HTTP概念,包括认证、状态码、解析等
- 易解析 :HTML或MIME解析器均可在RTSP中适用
- 易扩展 :新的方法或参数甚至协议本身均可添加或定制
- 防火墙亲和性 :传输层或应用层防火墙均可被协议较好处理
- 服务器控制 :控制概念易于理解,服务器不允许向客户端传输不能被客户端关闭的流
- 多场景适用 :RTSP提供帧级别精度,适用于更多媒体应用场景
RTSP组合使用了可靠传输协议TCP(控制)和高效传输协议UDP(内容)来串流内容给用户,即文件开始传输而客户端不用等待整个文件内容抵达就开始播放。其实不仅仅是点播服务,RTSP还支持传输不能以传统方式下载后播放的直播内容。
RTSP也并不负责数据传输,通常(非必须)是通过RTP(Real-time Transport Protocol)来完成,而RTP中,又通过RTCP负责完成同步、QOS管理等功能。具体应用中,它们三者的关系如下图所示:
RTSP:主要负责提供像播放、暂停、快进等操作,它负责定义具体的控制消息、操作方法、状态码等,此外还描述了与RTP间的交互操作。
RTP:传输音频/视频数据,如果是PLAY,Server发送到Client端,如果是RECORD,可以由Client发送到Server。整个RTP协议由两个密切相关的部分组成:RTP数据协议和RTP控制协议(RTCP)。
RTCP:服务质量的监视与反馈、媒体间的同步,以及多播组中成员的标识。在RTP会话期 间,各参与者周期性地传送RTCP包。RTCP包中含有已发送的数据包的数量、丢失的数据包的数量等统计资料,因此,各参与者可以利用这些信息动态地改变传输速率,甚至改变有效载荷类型。RTP和RTCP配合使用,它们能以有效的反馈和最小的开销使传输效率最佳化,因而特别适合传送网上的实时数据。
RTSP通信过程通常包括以下几个关键步骤:
- OPTIONS :客户端向服务器发送OPTIONS请求,以查询服务器支持的方法。
- DESCRIBE :客户端请求媒体描述信息,服务器返回SDP(Session Description Protocol)格式的描述。
- SETUP :为媒体流建立传输参数,如传输协议(RTP/RTCP)、端口等。
- PLAY :启动媒体流的播放,服务器开始发送RTP数据包。
- TEARDOWN :结束会话,释放资源。
二、Live555库移植到Android平台
1.Live555简介:
Live555库由多个核心模块组成,形成了一个完整的多媒体流媒体框架。其模块结构如下:
- BasicUsageEnvironment :提供基本的运行环境支持,包括任务调度、事件处理等。
- UsageEnvironment :扩展了BasicUsageEnvironment,支持更复杂的任务管理。
- Groupsock :提供底层网络通信支持,包括UDP和TCP。
- liveMedia :核心媒体处理模块,包含RTSP客户端/服务器、RTP封装/解析、媒体源处理等。
- ProxyServerMediaSession :用于构建代理服务器,实现媒体流的转发。
- RTSPServer :实现RTSP服务器端的功能,处理客户端的请求。
- SimpleRTPSink :用于将媒体数据通过RTP协议发送到客户端。
2.移植步骤:
(1)源码下载:https://download.live555.com/
注:需要使用到g++编译,提前安装:
sudo apt install g++-aarch64-linux-gnu
包括下载NDK: https://developer.android.google.cn/ndk/downloads?hl=cs 并解压到/opt/目录下,用于Android平台编译开源项目。
(2)增加对应平台的编译配置文件,例如复制config.armlinux一份命名为 config.aarch64-linux-gnu
修改其交叉编译工具为aarch64-linux-gnu-xx,当前不需要在 RTSP 通信中使用 SSL/TLS 加密功能,可以先禁用掉:
COMPILE_OPTS编译选项中添加:-DNO_OPENSSL=1 并清除 LIBS_FOR_CONSOLE_APPLICATION = -lssl -lcrypto 的依赖
另外Android NDK 工具链(通常是 GCC 或基于 LLVM 的 clang)的 C++ 标准库版本较旧,不支持这个 C++20 特性,禁用 C++ 标准库中的新特性:
COMPILE_OPTS编译选项中添加:-DNO_STD_LIB=1
完整的config.aarch64-linux-gnu配置文件内容:
# 定义 NDK 路径和工具链
NDK_PATH = /opt/android-ndk/android-ndk-r27d
TOOLCHAIN = $(NDK_PATH)/toolchains/llvm/prebuilt/linux-x86_64
SYSROOT = $(TOOLCHAIN)/sysroot
API_LEVEL = 31
# 交叉编译前缀(clang 的用法稍有不同,直接指定编译器全名)
CROSS_COMPILE = $(TOOLCHAIN)/bin/aarch64-linux-android$(API_LEVEL)-
# 编译选项:移除 -I/usr/local/include,添加 sysroot 和必要的宏
COMPILE_OPTS = $(INCLUDES) -I$(SYSROOT)/usr/include -I. -O2 \
-DSOCKLEN_T=socklen_t \
-DNO_SSTREAM=1 -DNO_OPENSSL=1 -DNO_STD_LIB=1 \
-D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 \
--sysroot=$(SYSROOT)
C = c
C_COMPILER = $(CROSS_COMPILE)clang
C_FLAGS = $(COMPILE_OPTS)
CPP = cpp
CPLUSPLUS_COMPILER = $(CROSS_COMPILE)clang++
CPLUSPLUS_FLAGS = $(COMPILE_OPTS) -Wall -DBSD=1
OBJ = o
LINK = $(CROSS_COMPILE)clang++ -o
LINK_OPTS = -static-libstdc++ # 静态链接 C++ 库,避免依赖 libc++_shared.so
CONSOLE_LINK_OPTS = $(LINK_OPTS)
LIBRARY_LINK = $(TOOLCHAIN)/bin/llvm-ar cr
LIBRARY_LINK_OPTS =
LIB_SUFFIX = a
LIBS_FOR_GUI_APPLICATION =
EXE =
(3)通过配置文件生成编译脚本:
./genMakefiles aarch64-linux-gnu
如果运行报错:bash: ./genMakefiles: cannot execute: required file not found
需要转换下文件格式(其他开源项目移植也要注意文件格式问题): dos2unix genMakefiles
(4)生成Makefile后就可以执行 make 编译得到如下静态库,再把对应模块的头文件拷贝出来引用即可:
./BasicUsageEnvironment/libBasicUsageEnvironment.a
./groupsock/libgroupsock.a
./liveMedia/libliveMedia.a
./UsageEnvironment/libUsageEnvironment.a
三、移植H.264视频编码器(x264)
1.x264简介:
H.264 是视频编码标准 , 由 ITU 和 MPEG 制订,而x264 是 H.264 格式的视频编解码库 , 由 C 语言实现 ;
2.移植步骤:
(1)下载x264源码:https://www.videolan.org/developers/x264.html ,解压后增加编译脚本build.sh:
#!/bin/bash
NDK=/opt/android-ndk/android-ndk-r27d
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
TARGET=aarch64-linux-android
API=31
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
export AR=$TOOLCHAIN/bin/llvm-ar
export AS=$TOOLCHAIN/bin/llvm-as
export LD=$TOOLCHAIN/bin/ld.lld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip
./configure \
--prefix=$(pwd)/android-build \
--host=$TARGET \
--sysroot=$TOOLCHAIN/sysroot \
--enable-static \
--enable-pic \
--disable-cli \
--disable-asm \
--extra-cflags="-fPIC -DANDROID" \
--extra-ldflags="-L$TOOLCHAIN/sysroot/usr/lib/$TARGET/$API"
make -j8
make install
echo "编译完成,输出目录:$(pwd)/android-build"
(3)执行build.sh后,得到对应静态库和头文件生成在android-build目录:
├── include
│ ├── x264_config.h
│ └── x264.h
└── lib
├── libx264.a
拷贝静态库和头文件出来引用即可。
四、移植三方开源rtsp server应用项目到Android平台
前面移植的live555、x264静态库就是为rtsp server应用所准备,按以下步骤将github上已有的开源项目适配Android平台:
(1)下载源码:https://github.com/xujie10101/liveRtspServer
(2)将之前编译得到的live555和x264静态库合入liveRtspServer源码
(3)适配Android原生的libtinyalsa来替代alsa-lib,用原生的libFraunhoferAAC来代替faac
(4)编写对应Android.bp,用于编译生成liveRtspServer可执行程序。
编译生成的 liveRtspServer 在RK3588s2 Android12平台运行效果:
RK3588s2:/ # liveRtspServer -v /dev/video20 -p 1234
video device: /dev/video20
port: 1234
Play this stream using the URL "rtsp://192.168.3.149:1234/live"
x264 [info]: using cpu capabilities: none!
x264 [info]: profile High 4:2:2, level 4.0, 4:2:2, 8-bit
x264 [info]: frame I:1 Avg QP:24.54 size: 59831
x264 [info]: frame P:1 Avg QP:23.89 size: 43090
x264 [info]: mb I I16..4: 18.5% 72.2% 9.2%
x264 [info]: mb P I16..4: 17.7% 38.0% 1.6% P16..4: 28.6% 9.2% 2.6% 0.0% 0.0% skip: 2.3%
x264 [info]: 8x8 transform intra:70.1% inter:80.6%
x264 [info]: coded y,uvDC,uvAC intra: 37.1% 84.4% 18.3% inter: 49.6% 89.6% 2.1%
x264 [info]: i16 v,h,dc,p: 32% 16% 9% 43%
x264 [info]: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 28% 12% 23% 5% 7% 10% 6% 5% 4%
x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 34% 12% 10% 5% 13% 11% 9% 4% 3%
x264 [info]: i8c dc,h,v,p: 49% 18% 26% 7%
x264 [info]: Weighted P-Frames: Y:100.0% UV:100.0%
x264 [info]: kb/s:12350.52
x264 [info]: using cpu capabilities: none!
x264 [info]: profile High 4:2:2, level 4.0, 4:2:2, 8-bit
目前只跑通测试了视频流,RK3588平台抓usb camera数据编码1080p h264传输只有5fps,需要移植类似ffmpeg支持硬件编码的库来替换x264,以提升码率。
另外多播还未跑通,以及音频需进一步调试。
适配Android的 liveRtspServer 工程已上传到github : git clone git@github.com:dragonforgithub/liveRtspServer.git