SOC:RK3588
system:Android 13
SDK:Live555 MPP
Live555 是一个流媒体解决方案,用 C++ 编写的开源项目,具有跨平台特性,可运行在多种操作系统上。它实现了对标准流媒体传输协议的支持,包括 RTP/RTCP、RTSP 和 SIP
一.下载Live555
下载地址:http://www.live555.com/liveMedia/public/
1. 解压后修改config.linux
#配置自己的交叉编译器
CROSS_COMPILE?= /data/**/work/android-ndk-r21e/install/bin/aarch64-linux-android-
#配置编译选项
#D_FILE_OFFSET_BITS=64 //配置64位
#DNO_OPENSSL 要加上 不然MPP编译时会报错
COMPILE_OPTS = $(INCLUDES) -I/usr/local/include -static -I. -O2 -DSOCKLEN_T=socklen_t -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -DALLOW_RTSP_SERVER_PORT_REUSE=1 -DNO_OPENSSL
C = c
C_COMPILER = $(CROSS_COMPILE)gcc
C_FLAGS = $(COMPILE_OPTS) $(CPPFLAGS) $(CFLAGS)
CPP = cpp
CPLUSPLUS_COMPILER = $(CROSS_COMPILE)g++
#配置编译条件加上static,测试live555 demo 就不用推so库到板子上
CPLUSPLUS_FLAGS = $(COMPILE_OPTS) -Wall -DBSD=1 $(CPPFLAGS) $(CXXFLAGS) -static
OBJ = o
LINK = $(CROSS_COMPILE)g++ -o
LINK_OPTS = -L. $(LDFLAGS)
CONSOLE_LINK_OPTS = $(LINK_OPTS)
LIBRARY_LINK = $(CROSS_COMPILE)ar cr
LIBRARY_LINK_OPTS =
LIB_SUFFIX = a
#LIBS_FOR_CONSOLE_APPLICATION = -lssl -lcrypto
LIBS_FOR_GUI_APPLICATION =
EXE =
#安装目录
PREFIX=/data/huangjj/work/live555-master
主要修改以下这几个点
#配置自己的交叉编译器
CROSS_COMPILE?= /data/**/work/android-ndk-r21e/install/bin/aarch64-linux-android-
#配置编译选项
#D_FILE_OFFSET_BITS 配置64位
#DNO_OPENSSL 要加上 不然MPP编译时会报错
#配置编译条件加上static,测试live555 demo 就不用推库到板子上
CPLUSPLUS_FLAGS = $(COMPILE_OPTS) -Wall -DBSD=1 $(CPPFLAGS) $(CXXFLAGS) -static
#安装目录
PREFIX=/data/huangjj/work/live555-master
生效配置
./genMakefiles linux
编译安装
make -j16 && make install
//编译后生成的头文件目录
huangjj@wisdom-ad:~/work/live555-master$ ls include/
BasicUsageEnvironment groupsock liveMedia UsageEnvironment
//静态库
**@wisdom-ad:~/work/live555-master$ ls lib/
libBasicUsageEnvironment.a libgroupsock.a libliveMedia.a libUsageEnvironment.a
二,移植到MPP上
将上面生成的头文件目录和静态库 拷贝到test下
修改test/CMakeLists.txt
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index b5cc594f..1ba9149b 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -3,6 +3,15 @@
# mpp built-in unit test case
# ----------------------------------------------------------------------------
# macro for adding mpp sub-module unit test
+add_definitions(-DNO_OPENSSL=1)
+add_definitions(-DSOCKLEN_T=socklen_t)
+add_definitions(-DNO_SSTREAM=1)
+add_definitions(-D_LARGEFILE_SOURCE=1)
+add_definitions(-D_FILE_OFFSET_BITS=64)
+include_directories(UsageEnvironment)
+include_directories(BasicUsageEnvironment)
+include_directories(groupsock)
+include_directories(liveMedia)
macro(add_mpp_test module ext)
set(test_name ${module}_test)
set(file_name ${test_name}.${ext})
@@ -14,7 +23,12 @@ macro(add_mpp_test module ext)
option(${test_tag} "Build mpp ${module}.${ext} unit test" ${BUILD_TEST})
if(${test_tag})
add_executable(${test_name} ${file_name} mpp_event_trigger.c mpp_parse_cfg.c)
- target_link_libraries(${test_name} ${MPP_SHARED} utils)
+ target_link_libraries(${test_name} ${MPP_SHARED} utils
+ ${PROJECT_SOURCE_DIR}/test/libliveMedia.a
+ ${PROJECT_SOURCE_DIR}/test/libgroupsock.a
+ ${PROJECT_SOURCE_DIR}/test/libBasicUsageEnvironment.a
+ ${PROJECT_SOURCE_DIR}/test/libUsageEnvironment.a
+ )
set_target_properties(${test_name} PROPERTIES FOLDER "test")
install(TARGETS ${test_name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
#add_test(NAME ${test_name} COMMAND ${test_name})
@@ -22,28 +36,28 @@ macro(add_mpp_test module ext)
endmacro()
# mpp info test
-add_mpp_test(mpp_info c)
+# add_mpp_test(mpp_info c)
-# mpi decoder unit test
-add_mpp_test(mpi_dec c)
+# # mpi decoder unit test
+# add_mpp_test(mpi_dec c)
-# mpi decoder multi-thread input / output unit test
-add_mpp_test(mpi_dec_mt c)
+# # mpi decoder multi-thread input / output unit test
+# add_mpp_test(mpi_dec_mt c)
-# mpi decoder no-thread input / output unit test
-add_mpp_test(mpi_dec_nt c)
+# # mpi decoder no-thread input / output unit test
+# add_mpp_test(mpi_dec_nt c)
-# mpi encoder unit test
-add_mpp_test(mpi_enc c)
+# # mpi encoder unit test
+add_mpp_test(mpi_enc cpp)
# mpi encoder multi-thread input / output unit test
add_mpp_test(mpi_enc_mt cpp)
# new mpi rc unit test
-add_mpp_test(mpi_rc2 c)
+# add_mpp_test(mpi_rc2 c)
-# new dec multi unit test
-add_mpp_test(mpi_dec_multi c)
+# # new dec multi unit test
+# add_mpp_test(mpi_dec_multi c)
macro(add_legacy_test module)
set(test_name ${module}_test)
由于live555 是C++实现,记得mpi_enc_test.c改为CPP文件
之后MPP进行编译即可 ,编译会语法报错看着改就行
mpp/build/android/aarch64$ ./make-Android.bash --ndk /mnt/h/android-ndk-r21e/android-ndk-r21e/
test/ mpi_enc_test mpp/libmpp.so 就是编译后的结果推到板子上就行
到这一步我们就可以根据自己的需要开发RK3588 rtsp服务器了
三.修改Live555 testProgs /testOnDemandRTSPServer,修改demo获取h264数据的方式
testOnDemandRTSPServer是live555 提供的rtsp 推流的demo
通过读取test.264文件进行推流
{
char const* streamName = "h264ESVideoTest";
char const* inputFileName = "test.264";
ServerMediaSession* sms
= ServerMediaSession::createNew(*env, streamName, streamName,
descriptionString);
sms->addSubsession(H264VideoFileServerMediaSubsession
::createNew(*env, inputFileName, reuseFirstSource, getH264Buf));
rtspServer->addServerMediaSession(sms);
announceStream(rtspServer, sms, streamName, inputFileName);
}
跟踪代码是在liveMedia\ByteStreamFileSource.cpp里 使用fopen 打开文件
ByteStreamFileSource*
ByteStreamFileSource::createNew(UsageEnvironment& env, char const* fileName,
unsigned preferredFrameSize,
unsigned playTimePerFrame) {
FILE* fid = OpenInputFile(env, fileName);
if (fid == NULL) return NULL;
ByteStreamFileSource* newSource
= new ByteStreamFileSource(env, NULL,preferredFrameSize, playTimePerFrame);
newSource->fFileSize = GetFileSize(fileName, fid);
return newSource;
}
其他地方通过虚函数再调用到fileReadableHandler -> doGetNextFrame->fread获取数据
void ByteStreamFileSource::doReadFromFile() {
// Try to read as many bytes as will fit in the buffer provided (or "fPreferredFrameSize" if less)
if (fLimitNumBytesToStream && fNumBytesToStream < (u_int64_t)fMaxSize) {
fMaxSize = (unsigned)fNumBytesToStream;
}
if (fPreferredFrameSize > 0 && fPreferredFrameSize < fMaxSize) {
fMaxSize = fPreferredFrameSize;
}
#ifdef READ_FROM_FILES_SYNCHRONOUSLY
fFrameSize = fread(fTo, 1, fMaxSize, fFid);
#else
if (fFidIsSeekable) {
fFrameSize = fread(fTo, 1, fMaxSize, fFid);
} else {
// For non-seekable files (e.g., pipes), call "read()" rather than "fread()", to ensure that the read doesn't block:
fFrameSize = read(fileno(fFid), fTo, fMaxSize);
}
#endif
...
}
通过删掉ByteStreamFileSource mfd获取方式,添加通过传递一个函数回调,让live555 收到mpp编码的h264数据
void ByteStreamFileSource::doReadFromFile() {
...
if(mReader != NULL){
fFrameSize = mReader(fTo, fMaxSize );
}
...
}
将rtsp服务添加进 mpi_enc_test.c
//添加一个回调,用于传递mpp h264 编码后的数据
int getH264Buf(unsigned char *buf, int len)
{
...
buf = imageStream.readData();
return len;
}
//近过硬编码后将h264数据吸入队列里面
MPP_RET test_mpp_run(MpiEncMultiCtxInfo *info)
{
...
if (p->fp_output){
if(!imageStream.isFull()){
//写h264数据到buf
imageStream.writeData(&imagePool);
}else{
printf("isFull not write\n");
}
// fwrite(ptr,1 ,len,p->fp_output);
}
...
}
{
char const* streamName = "h264ESVideoTest";
char const* inputFileName = "test.264";
ServerMediaSession* sms
= ServerMediaSession::createNew(*env, streamName, streamName,
descriptionString);
sms->addSubsession(H264VideoFileServerMediaSubsession
::createNew(*env, inputFileName, reuseFirstSource, getH264Buf));
rtspServer->addServerMediaSession(sms);
announceStream(rtspServer, sms, streamName, inputFileName);
}
最后调试了一个早上才收到来自rtsp的数据:
局域网下自己测试发现有个2秒钟的延迟,目前还找不到原因
小白学习记录,非喜勿喷
有需要源码的 点赞 关注 收藏三连后可以私信我发源码