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

小白学习记录,非喜勿喷

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

### RK3588平台硬编码实现方法及配置教程 #### 一、RK3588硬件编解码特性概述 RK3588处理器内置强大的多媒体处理单元,支持多种视频格式的高效硬件编解码功能。该芯片集成了Media Process Platform (MPP),能够显著提升视频编解码效率并降低CPU占用率[^1]。 #### 二、环境准备 为了能够在RK3588上顺利实施硬编码操作,需先完成如下准备工作: - 安装Linux操作系统,并确保已安装必要的依赖库如FFmpeg等工具; - 下载并编译适用于RK3588架构版本的FFmpeg源代码包;此过程可能涉及到交叉编译设置等问题,请参照官方文档指导进行相应调整[^4]; ```bash sudo apt-get update && sudo apt-get install -y build-essential yasm cmake libtool autoconf pkg-config git wget nasm git clone https://github.com/FFmpeg/FFmpeg.git ffmpeg-rk3588 cd ffmpeg-rk3588 ./configure --target-os=linux --arch=aarch64 --enable-cross-compile ...其他选项... make -j$(nproc) sudo make install ``` #### 三、编写硬编码脚本 创建一个简单的Python脚本来调用FFmpeg命令行工具执行实时采集图像帧并通过RTMP协议送至服务器端口。这里给出一段基本示例代码用于说明如何构建这样的应用程序逻辑结构: ```python import os from subprocess import Popen, PIPE def start_rtsp_push(rtsp_url='rtmp://your.server.address/live/stream'): command = [ 'ffmpeg', '-f', 'v4l2', # 使用V4L2设备作为输入源 '-i', '/dev/video0', # 指定摄像头路径 '-c:v', 'h264_mmal', # 启动H.264硬件加速编码器 '-b:v', '2M', # 设置比特率为2Mbps '-f', 'flv', # 输出FLV封装格式的数据给RTMP服务端 rtsp_url # RTMP目标地址 ] process = Popen(command, stdout=PIPE, stderr=PIPE) if __name__ == '__main__': try: start_rtsp_push() while True: pass except KeyboardInterrupt: print('停止') ``` 上述程序片段展示了通过`subprocess.Popen()`函数启动外部进程的方式运行FFmpeg命令来捕获来自USB摄像机的画面数据,并将其转换成适合网络传输的形式发送出去。 #### 四、优化与调试建议 当遇到性能瓶颈或质量问题时可以考虑以下几个方面来进行针对性改进: - 尝试不同的分辨率和帧速率组合找到最佳平衡点; - 修改量化参数控制压缩比例从而影响画质清晰度; - 更改GOP大小以适应不同应用场景需求; - 利用GPU资源进一步减轻CPU负担提高整体吞吐量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hmbbPdx_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值