RK3588 MPP使用Live555 进行推流

SOC:RK3588

system:Android 13

SDK:Live555 MPP

Live555 是一个流媒体解决方案,用 C++ 编写的开源项目,具有跨平台特性,可运行在多种操作系统上。它实现了对标准流媒体传输协议的支持,包括 RTP/RTCP、RTSP 和 SIP

一.下载Live555

官网地址:http://www.live555.com/

下载地址: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秒钟的延迟,目前还找不到原因

小白学习记录,非喜勿喷

有需要源码的 点赞 关注 收藏三连后可以私信我发源码

相关推荐
TDTC_XQ6 小时前
模板类的写法
linux·c++
CCCCCCCCharlie7 小时前
深入解析I/O底层:文件描述符与缓冲区真相
linux·开发语言·c++·算法
自信150413057597 小时前
重生之从0开始学习c++之string(下)
c++·学习·stl
wuminyu8 小时前
Continuation::freeze与thaw的x86_64汇编Stack Chunk拆解源码分析
java·linux·c语言·汇编·jvm·c++
kunicoding8 小时前
C++ 策略模式实战:写一个可以“一键换输出“的日志系统
开发语言·c++·策略模式
xiaoye-duck9 小时前
《C++ 项目:手写大模型接入 SDK》项目背景、目标及名词解释
服务器·网络·c++·语言模型
艾莉丝努力练剑9 小时前
【AI大模型接入SDK】ChatServer接口设计规范
网络·c++·人工智能·学习·大模型·设计规范
纪念 2299 小时前
C++算法(三)
开发语言·c++·算法
AbandonForce9 小时前
递归、搜索与回溯:从板书到二叉树解题方法
c++·算法·决策树
艾莉丝努力练剑10 小时前
【AI大模型接入SDK】ChatServer HTTP接口模块实现总览
网络·c++·人工智能·网络协议·学习·http·架构