RK3588 MPP使用Live555 进行推流

SOC:RK3588

system:Android 13

SDK:Live555 MPP

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

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

小白学习记录,非喜勿喷

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

相关推荐
冷眼看人间恩怨31 分钟前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
红龙创客41 分钟前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin43 分钟前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
yuanbenshidiaos2 小时前
c++---------数据类型
java·jvm·c++
十年一梦实验室3 小时前
【C++】sophus : sim_details.hpp 实现了矩阵函数 W、其导数,以及其逆 (十七)
开发语言·c++·线性代数·矩阵
taoyong0013 小时前
代码随想录算法训练营第十一天-239.滑动窗口最大值
c++·算法
这是我583 小时前
C++打小怪游戏
c++·其他·游戏·visual studio·小怪·大型·怪物
fpcc3 小时前
跟我学c++中级篇——C++中的缓存利用
c++·缓存
呆萌很3 小时前
C++ 集合 list 使用
c++
诚丞成4 小时前
计算世界之安生:C++继承的文水和智慧(上)
开发语言·c++