公司动态

海思Hi3516平台Live555 RTSP服务器移植实战指南

📅 2026/9/3 9:00:51
海思Hi3516平台Live555 RTSP服务器移植实战指南
简介本资源是面向嵌入式音视频开发工程师与海思平台移植实践者的live555 RTSP服务器移植工程包聚焦于海思Hi3516ARM Cortex-A7平台的完整适配落地解决在国产安防芯片上构建低延迟、高稳定视频流转发服务的核心难题。压缩包共47个文件涵盖11个编译目标文件.o、8个头文件.h/.hh、7个C源码.c、4个C源码.cpp及关键构建脚本Makefile、makecompile、replace.csh和调试工具gdb-arm-hisiv300-linux、gdbserver总大小4.21MB其中DynamicRTSPServer、H264VideoLiveServerMediaSubsession、LiveDeviceSource等模块已针对海思共享内存数据获取与RTP封装完成定制化改造。已有1817人学习下载资源提供可直接编译运行的交叉编译工程结构、海思专用线程/信号处理机制rtsp_threads.c/h、rtsp_signal.c/h、初始化与销毁流程rtsp_init/fini.c/h及典型H.264流媒体子会话实现大幅降低从零移植门槛助力开发者快速验证RTSP推流、调试内存拷贝瓶颈并开展性能优化。1. 项目概述为什么要在海思3516上折腾Live555如果你手头正好有一块海思Hi3516的开发板想在上面实现一个RTSP流媒体服务器把板子上的摄像头画面或者编码后的视频流推出去那么“Live555海思平台移植”这个项目就是你绕不开的一道坎。这活儿我干过不止一次从Hi3516A到Hi3516DV300都折腾过过程说不上多复杂但里头的坑和门道没踩过的人还真容易迷糊。简单来说Live555是一个用C编写的开源流媒体处理库功能非常纯粹和经典它实现了RTSP/RTP/RTCP等流媒体协议栈。你可以基于它用相对较少的代码快速搭建起一个RTSP服务器Server或客户端Client。而海思Hi3516系列芯片是安防监控、物联网摄像头等领域最常见的SoC之一它内置了强大的视频编码器H.264/H.265但通常不直接提供完整的、可编程的RTSP服务器实现。官方的MPP媒体处理平台样例里往往只给到网络发送裸码流的demo。所以把Live555移植到海思平台上本质就是让Live555这个“协议大脑”去驱动海思的“编码肌肉”从而输出标准的、能被VLC、FFmpeg、EasyPlayer等通用播放器识别的RTSP视频流。这个项目的价值非常直接它让你的海思设备从一个单纯的“编码盒子”变成了一个标准的网络流媒体源。无论是用于设备调试、方案验证还是集成到更大的视频系统中都提供了极大的便利。适合谁呢首先是海思平台的嵌入式开发工程师其次是做IPC网络摄像机、NVR网络视频录像机或智能视频分析设备的开发者甚至是对流媒体协议感兴趣的嵌入式爱好者都可以通过这个项目深入理解从编码到网络传输的完整链条。2. 核心思路与方案选型为什么是Live555还有其他选择吗决定移植Live555之前我们得先盘算一下手头的选项。在海思平台上实现RTSP服务大体有三条路使用海思SDK自带的网络传输模块海思MPP样本里通常有sample_venc结合socket发送码流的例子。但这只是简单的TCP/UDP传输需要自己实现RTSP信令交互、RTP打包、SDP描述等一整套复杂逻辑相当于重新造轮子对大多数项目来说性价比极低。集成其他RTSP服务器库比如gStreamer的rtspserver、MediaMTX原rtsp-simple-server或者一些商业库。gStreamer功能强大但体系庞大交叉编译和裁剪对嵌入式平台是个挑战MediaMTX用Go编写虽然部署简单但在资源受限的海思平台上运行一个Go程序可能不是最优解。移植Live555这是最经典、最轻量级的选择。Live555代码风格古老但稳定核心库体积小功能专注就是RTSP/RTP/RTCP交叉编译相对容易。更重要的是它在嵌入式领域有广泛的成功应用案例社区里能找到的参考也多。所以选择Live555进行移植是基于以下几个核心考量轻量、专注、可控、有迹可循。你不需要一个全功能的媒体框架你只需要一个可靠的协议栈把海思编码器产生的H.264/H.265码流按照标准规范打包发送出去。Live555完美契合这个需求。整个移植工作的核心思路可以概括为“搭桥”。我们需要在海思的编码数据输出端通常是通过HI_MPI_VENC_GetStream获取码流帧和Live555的媒体输入源之间搭建一座数据桥梁。具体来说就是实现一个Live555框架下的FramedSource子类。这个子类负责从海思的编码缓冲区中“拉取”或“等待”视频帧数据然后以Live555能理解的方式比如通过afterGetting回调提交给下游的RTPSink进行RTP打包和发送。同时我们还需要一个ServerMediaSubsession的子类来管理这个自定义的Source并将其纳入RTSP会话的生命周期管理中。3. 环境准备与源码获取工欲善其事必先利其器动手之前先把“战场”布置好。这里主要分两部分海思开发环境和Live555源码。3.1 海思SDK与交叉编译工具链这是基础中的基础。你需要从海思官方或你的方案商获取对应你芯片型号的SDK包比如Hi3516EV200_SDK_Vx.x.x.x。解压后重点关注以下内容osdrv/opensource/toolchain/这里面放着交叉编译工具链。对于Hi3516通常是arm-hisiv300-linux或arm-hisiv400-linux工具链路径类似arm-hisiv300-linux/bin/arm-hisiv300-linux-gcc。你需要将其加入系统的PATH环境变量。export PATH/your_sdk_path/osdrv/opensource/toolchain/arm-hisiv300-linux/bin:$PATHmpp/媒体处理平台MPP的头文件和库文件。后续我们编译自己的应用程序和Live555时需要链接这些库如libmpi.a,libive.a,libhigo.a等。sample/参考样例特别是sample_venc。这是我们理解如何获取编码码流的关键。注意不同版本SDK的目录结构可能有细微差异请以你手中的实际SDK为准。确保你的Ubuntu编译主机或其他Linux发行版已经安装了基本的开发工具如make,g用于本地编译Live555的生成工具。3.2 Live555源码下载与本地配置Live555官网live555.com提供了源码压缩包。下载最新稳定版即可。我们先在本地x86电脑上进行一些预处理。wget http://www.live555.com/liveMedia/public/live555-latest.tar.gz tar -xzf live555-latest.tar.gz cd live555在编译给海思用的库之前我们需要先用本地编译器生成一些必要的工具如genWatchTables这些工具在配置阶段会被使用。执行./genMakefiles linux make -j4这一步会在本地生成live555ProxyServer等测试程序我们主要目的是生成那些工具。编译完成后先别急着清理我们接下来要修改配置用于交叉编译。4. 交叉编译Live555库关键配置与编译脚本这是移植的核心步骤之一。Live555使用一个名为config.*的文件来定义编译环境。我们需要为海思平台创建一个新的配置。创建海思平台配置文件 在Live555源码根目录复制一个现有的配置模板比如config.linux命名为config.hi3516。cp config.linux config.hi3516编辑config.hi3516文件 这个文件需要根据你的交叉编译工具链和海思SDK路径进行修改。以下是一个针对arm-hisiv300-linux的配置示例关键修改处已加注释# 定义交叉编译工具前缀 COMPILE_OPTS $(INCLUDES) -I. -I/your_sdk_path/mpp/include -I/your_sdk_path/mpp/include/hi_common -I/your_sdk_path/mpp/include/hi_mpi -O2 -DSOCKLEN_Tsocklen_t -DNO_SSTREAM1 -D_LARGEFILE_SOURCE1 -D_FILE_OFFSET_BITS64 -fPIC # 将g替换为交叉编译器的g C_COMPILER arm-hisiv300-linux-gcc C_FLAGS $(COMPILE_OPTS) CPLUSPLUS_COMPILER arm-hisiv300-linux-g CPLUSPLUS_FLAGS $(COMPILE_OPTS) -Wall -DBSD1 # 链接器也使用交叉编译器的 LINK arm-hisiv300-linux-g -o LINK_OPTS -L/your_sdk_path/mpp/lib -lmpi -lhdmi -lhigo -lhi_common -lhi_memory -lpthread -ldl CONSOLE_LINK_OPTS $(LINK_OPTS) LIBRARY_LINK arm-hisiv300-linux-g -o # 指定库文件后缀和生成命令 LIBRARY_LINK_OPTS -shared -Wl,-soname,$(NAME).so $(LINK_OPTS) LIB_SUFFIX .so SHORT_LIB_SUFFIX .so # 关键指定ranlib为交叉编译工具链中的避免链接错误 RANLIB arm-hisiv300-linux-ranlib重要解释-I参数添加了海思MPP的头文件路径这样Live555代码里才能找到海思的数据类型和函数声明。-L和-l参数指定了海思MPP库的路径和需要链接的库。-lmpi是最核心的媒体处理接口库。-fPIC生成位置无关代码这是编译动态库所必需的。RANLIB这个很容易被忽略。如果使用交叉编译工具链必须指定对应的ranlib否则在生成静态库.a文件时会报错。生成交叉编译的Makefile并编译./genMakefiles hi3516 # 使用我们刚创建的config.hi3516 make -j4如果一切顺利你会在当前目录下看到为ARM平台生成的库文件libBasicUsageEnvironment.so,libgroupsock.so,libliveMedia.so,libUsageEnvironment.so以及一些可执行文件如testProgs/testOnDemandRTSPServer。提取必要的头文件和库 编译成功后建议将生成的四个动态库.so文件和Live555的核心头文件位于include/目录下以及BasicUsageEnvironment/include/,groupsock/include/,liveMedia/include/,UsageEnvironment/include/整理到一个独立的目录中方便后续你的应用程序链接。例如创建一个live555_for_hi3516文件夹里面包含include和lib两个子目录。实操心得第一次交叉编译很大概率会失败常见错误包括找不到海思的头文件、链接时找不到海思的库、或者ranlib错误。请务必静下心来根据错误信息逐行检查config.hi3516中的路径和工具名是否正确。另外海思SDK不同版本库名可能有变化如果遇到undefined reference toHI_MPI_XXX这类错误去/your_sdk_path/mpp/lib目录下看看实际的库文件名是什么相应修改LINK_OPTS。5. 实现海思码流Source连接数据与协议的关键桥梁现在来到了最核心的编码部分创建自定义的FramedSource。这是Live555获取媒体数据的源头我们需要在这里对接海思的编码输出。5.1 设计数据流模型海思获取编码码流的典型方式是在一个循环中调用HI_MPI_VENC_GetStream它会阻塞直到有一帧编码数据准备好。而Live555的FramedSource是通过事件驱动doGetNextFrame函数来被动获取数据的。这里存在一个生产-消费模型的差异。通常有两种处理方式阻塞等待模式在doGetNextFrame里直接调用HI_MPI_VENC_GetStream直到拿到一帧数据然后返回。这种方式简单但会阻塞Live555的事件循环如果获取帧耗时过长会影响RTSP协议响应和其他会话的处理。缓冲区信号量模式推荐创建一个独立的线程或复用海思的编码线程专门负责循环调用HI_MPI_VENC_GetStream将获取到的码流帧放入一个环形缓冲区。doGetNextFrame则从缓冲区中取数据如果缓冲区为空则设置一个定时器延迟重试或者利用信号量/条件变量让doGetNextFrame等待。这种方式更高效解耦了数据生产和协议处理。我们采用第二种模式。设计一个类HisiH264FramedSource它继承自FramedSource并内部管理一个缓冲区队列和一个数据生产线程。5.2 关键代码结构解析以下是一个高度简化的代码框架用于说明核心逻辑// HisiH264FramedSource.hh #ifndef _HISI_H264_FRAMED_SOURCE_HH #define _HISI_H264_FRAMED_SOURCE_HH #include FramedSource.hh #include pthread.h #include queue // 定义一个结构体存放从海思获取的一帧数据 typedef struct { unsigned char* data; // 码流数据指针 unsigned int size; // 数据长度 unsigned long long pts; // 时间戳 bool isKeyFrame; // 是否为关键帧(I帧) } HisiFrameData; class HisiH264FramedSource: public FramedSource { public: static HisiH264FramedSource* createNew(UsageEnvironment env, int vencChn); // ... 其他接口 protected: HisiH264FramedSource(UsageEnvironment env, int vencChn); virtual ~HisiH264FramedSource(); private: // 重写父类虚函数当Live555需要数据时调用 virtual void doGetNextFrame(); // 一个静态函数或成员函数作为数据生产线程的入口 static void* dataFeederThread(void* clientData); void feedData(); // 实际的数据填充循环 // 处理从海思获取的原始帧进行H.264 NALU分割等预处理 void processHisiFrame(const VENC_STREAM_S stStream); private: int fVencChn; // 海思编码通道号 pthread_t fFeederTid; // 数据生产线程ID std::queueHisiFrameData fFrameQueue; // 帧数据队列 pthread_mutex_t fMutex; // 保护队列的互斥锁 pthread_cond_t fCond; // 条件变量用于线程同步 EventTriggerId fEventTriggerId; // Live555内部事件触发器ID bool fIsFeeding; // 线程控制标志 }; #endif// HisiH264FramedSource.cpp #include HisiH264FramedSource.hh #include hi_comm_venc.h #include mpi_venc.h #include unistd.h // 线程函数不断从海思编码通道获取数据 void* HisiH264FramedSource::dataFeederThread(void* clientData) { HisiH264FramedSource* source (HisiH264FramedSource*)clientData; source-feedData(); return NULL; } void HisiH264FramedSource::feedData() { VENC_STREAM_S stStream; VENC_PACK_S* pstPack; HI_S32 s32Ret; while (fIsFeeding) { // 1. 清空上次的数据结构 memset(stStream, 0, sizeof(VENC_STREAM_S)); // 2. 阻塞获取码流超时时间可根据需要设置 s32Ret HI_MPI_VENC_GetStream(fVencChn, stStream, HI_TRUE); if (s32Ret ! HI_SUCCESS) { usleep(10000); // 获取失败短暂休眠避免CPU空转 continue; } // 3. 处理获取到的码流帧 processHisiFrame(stStream); // 4. 释放海思的码流缓冲区非常重要否则会内存泄漏 s32Ret HI_MPI_VENC_ReleaseStream(fVencChn, stStream); if (s32Ret ! HI_SUCCESS) { // 记录错误日志 } } } void HisiH264FramedSource::processHisiFrame(const VENC_STREAM_S stStream) { pthread_mutex_lock(fMutex); // 遍历一帧中的所有包海思一帧可能分多个包传输 for (int i 0; i stStream.u32PackCount; i) { pstPack stStream.pstPack[i]; HisiFrameData frame; frame.size pstPack-u32Len - pstPack-u32Offset; // 有效数据长度 frame.data new unsigned char[frame.size]; // 拷贝数据注意偏移量u32Offset memcpy(frame.data, pstPack-pu8Addr pstPack-u32Offset, frame.size); frame.pts pstPack-u64PTS; frame.isKeyFrame (pstPack-DataType.enH264EType H264E_NALU_ISLICE); // 判断I帧 fFrameQueue.push(frame); } // 通知等待数据的线程即doGetNextFrame pthread_cond_signal(fCond); pthread_mutex_unlock(fMutex); } void HisiH264FramedSource::doGetNextFrame() { pthread_mutex_lock(fMutex); if (fFrameQueue.empty()) { // 队列为空设置一个延迟事件比如20ms后再次尝试 nextTask() envir().taskScheduler().scheduleDelayedTask(20000, (TaskFunc*)FramedSource::afterGetting, this); pthread_mutex_unlock(fMutex); return; } HisiFrameData frame fFrameQueue.front(); fFrameQueue.pop(); pthread_mutex_unlock(fMutex); // 检查输出缓冲区是否足够大 if (frame.size fMaxSize) { fFrameSize fMaxSize; fNumTruncatedBytes frame.size - fMaxSize; // 可以选择只拷贝部分或者处理错误 } else { fFrameSize frame.size; fNumTruncatedBytes 0; } // 将数据拷贝到Live555提供的缓冲区fTo memcpy(fTo, frame.data, fFrameSize); // 设置帧信息 fPresentationTime frame.pts; // 注意时间戳单位转换海思是微秒Live555需要秒 // fDurationInMicroseconds ... // 可以根据帧率计算每帧持续时间 // 关键标记是否为关键帧影响RTP打包 if (frame.isKeyFrame) { // 可能需要设置一些内部标志具体取决于后续的Sink如何处理 } // 释放我们分配的内存 delete[] frame.data; // 通知Live555数据已就绪进行后续处理RTP打包等 afterGetting(this); }5.3 实现ServerMediaSubsession有了FramedSource我们还需要一个ServerMediaSubsession来创建和管理它。这个类负责在RTSP客户端发起SETUP请求时创建对应的RTPSink和我们的HisiH264FramedSource并将它们关联起来。// HisiH264ServerMediaSubsession.hh #include H264VideoFileServerMediaSubsession.hh class HisiH264ServerMediaSubsession: public H264VideoFileServerMediaSubsession { public: static HisiH264ServerMediaSubsession* createNew(UsageEnvironment env, int vencChn); protected: HisiH264ServerMediaSubsession(UsageEnvironment env, int vencChn); virtual ~HisiH264ServerMediaSubsession(); // 重写关键函数返回我们自定义的FramedSource virtual FramedSource* createNewStreamSource(unsigned clientSessionId, unsigned estBitrate); // 重写此函数创建对应的RTPSink virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource); private: int fVencChn; };在createNewStreamSource函数中直接return HisiH264FramedSource::createNew(envir(), fVencChn);即可。6. 整合与主程序搭建让服务器跑起来现在我们需要一个主程序初始化海思的MPP系统、启动编码然后创建Live555的RTSP服务器。初始化海思MPP这部分代码可以参考海思的sample_venc。主要步骤包括HI_MPI_SYS_Init()系统初始化。HI_MPI_VPSS_Init()/HI_MPI_VENC_Init()初始化VPSS和VENC模块。配置并启动VI视频输入、VPSS视频处理、VENC视频编码绑定关系让原始图像经过处理最终被编码成H.264码流。创建RTSP服务器#include liveMedia.hh #include BasicUsageEnvironment.hh #include HisiH264ServerMediaSubsession.hh int main(int argc, char** argv) { // 1. 初始化海思MPP系统省略详细代码 // ... // 2. 创建Live555调度器和环境 TaskScheduler* scheduler BasicTaskScheduler::createNew(); UsageEnvironment* env BasicUsageEnvironment::createNew(*scheduler); // 3. 创建RTSPServer监听554端口 RTSPServer* rtspServer RTSPServer::createNew(*env, 554, NULL); if (rtspServer NULL) { *env Failed to create RTSP server: env-getResultMsg() \n; exit(1); } // 4. 创建我们的媒体会话子会话假设使用编码通道0 ServerMediaSession* sms ServerMediaSession::createNew(*env, live, Hisi Live Stream, Session from Hi3516); sms-addSubsession(HisiH264ServerMediaSubsession::createNew(*env, 0)); // vencChn 0 rtspServer-addServerMediaSession(sms); // 5. 打印访问URL char* url rtspServer-rtspURL(sms); *env Play this stream using the URL: \ url \\n; delete[] url; // 6. 进入事件循环永不返回 env-taskScheduler().doEventLoop(); return 0; // 实际上不会执行到这里 }编译你的应用程序 编写一个Makefile链接海思的MPP库和你编译好的Live555库。CC arm-hisiv300-linux-gcc CXX arm-hisiv300-linux-g CFLAGS -I./live555_for_hi3516/include -I/your_sdk_path/mpp/include -O2 -fPIC LDFLAGS -L./live555_for_hi3516/lib -L/your_sdk_path/mpp/lib LIBS -lliveMedia -lgroupsock -lBasicUsageEnvironment -lUsageEnvironment -lmpi -lhdmi -lhigo -lhi_common -lhi_memory -lpthread -ldl -lstdc TARGET hisi_rtsp_server SRCS main.cpp HisiH264FramedSource.cpp HisiH264ServerMediaSubsession.cpp OBJS $(SRCS:.cpp.o) all: $(TARGET) $(TARGET): $(OBJS) $(CXX) $(LDFLAGS) -o $ $^ $(LIBS) .cpp.o: $(CXX) $(CFLAGS) -c $ -o $ clean: rm -f $(OBJS) $(TARGET)7. 部署、测试与问题排查实录将编译生成的hisi_rtsp_server可执行文件以及Live555的四个动态库lib*.so拷贝到海思板子的文件系统中例如/usr/lib/或与可执行文件同目录。确保库文件路径能被系统找到可通过设置LD_LIBRARY_PATH环境变量。在板子上运行./hisi_rtsp_server如果看到输出Play this stream using the URL: rtsp://板子IP:554/live说明服务器启动成功。7.1 测试方法使用VLC测试在PC上打开VLC选择“媒体” - “打开网络串流”输入rtsp://板子IP:554/live点击播放。使用FFplay测试在命令行输入ffplay -rtsp_transport tcp rtsp://板子IP:554/live。使用tcp传输可以避免UDP在复杂网络环境下的丢包问题便于初步调试。使用openRTSP测试Live555自带工具可以将流保存为文件。./openRTSP -v -t rtsp://板子IP:554/live test.264。7.2 常见问题与排查技巧以下是我在多次移植中遇到的典型问题及解决方案整理成了速查表问题现象可能原因排查思路与解决方案服务器启动失败提示“Failed to create RTSP server”1. 554端口被占用。2. 动态库未找到或加载失败。1. 使用netstat -tlnp查看端口占用换用其他端口如8554。2. 检查LD_LIBRARY_PATH或直接将.so库放到/lib或/usr/lib下。用ldd hisi_rtsp_server查看所有依赖库是否都能找到。VLC能连接但无法播放黑屏或瞬间断开1. SDP信息错误如编码类型、分辨率、帧率不匹配。2.FramedSource没有正确提供关键帧I帧。3. 时间戳fPresentationTime设置错误。1. 在HisiH264ServerMediaSubsession::createNewRTPSink中确保H264VideoRTPSink的profile-level-id和packetization-mode参数正确。可以在doGetNextFrame里打印前几个字节确认是H.264 NALU起始码0x00 0x00 0x00 0x01。2. 确保processHisiFrame中正确识别了I帧H264E_NALU_ISLICE并且在doGetNextFrame后RTPSink能知道这是关键帧。对于H.264关键帧的第一个NALU必须是SPS然后是PPS接着是IDR Slice。确保你的数据队列是按这个顺序提供数据的。3. 海思的PTS是微秒需要转换为秒fPresentationTime frame.pts / 1000000.0。播放卡顿延迟大1. 数据生产编码跟不上消费网络发送。2. 网络带宽不足或UDP丢包严重。3. 缓冲区队列设计不合理积压太多帧。1. 降低编码分辨率或帧率或检查海思编码通道是否配置正确。2. 尝试在VLC或ffplay中使用-rtsp_transport tcp选项。在Live555端可以调整OutPacketBuffer::maxSize默认约600KB增大网络缓冲区。3. 在FramedSource中设置合理的队列长度当队列过长时丢弃非关键帧确保实时性。内存泄漏运行一段时间后程序崩溃1.HI_MPI_VENC_ReleaseStream未调用。2.HisiFrameData中的data指针未释放。3. Live555内部对象未正确销毁。1.绝对确保每次HI_MPI_VENC_GetStream后都必须有对应的HI_MPI_VENC_ReleaseStream这是海思MPP的硬性要求。2. 在doGetNextFrame中memcpy完成后立即delete[] frame.data。3. 程序通常不会正常退出但如果需要需在析构函数中停止数据线程清空队列并调用Medium::close()。交叉编译链接失败提示海思MPI函数未定义1. 链接库顺序不对。2. 库路径错误或库文件缺失。3. 使用了错误的工具链。1. 调整Makefile中-l的顺序被依赖的库放在后面。尝试将-lmpi等海思库放在命令末尾。2. 使用-L明确指定海思库的绝对路径。用arm-hisiv300-linux-nm -D libmpi.so7.3 性能优化与稳定性建议线程安全是重中之重fFrameQueue的读写push和pop必须用互斥锁pthread_mutex_t保护。条件变量pthread_cond_t用于高效同步生产者和消费者。错误处理要健壮HI_MPI_VENC_GetStream可能返回错误网络也可能断开。你的代码需要能处理这些异常比如记录日志、尝试恢复编码通道、或者优雅地关闭会话。SPS/PPS的发送H.264的SPS和PPS参数集需要在会话开始时以及每个关键帧之前发送。Live555的H264VideoRTPSink通常能处理但你需要确保你的FramedSource在流开始时能提供这些NALU。海思编码器在创建通道后可以通过HI_MPI_VENC_GetH264SpsPps等函数主动获取。码流控制如果网络带宽有限可以考虑在FramedSource中根据网络状况动态调整海思编码器的码率通过HI_MPI_VENC_SetRcParam实现简单的码流控制。移植完成后你得到的不仅仅是一个能在海思3516上运行的RTSP服务器更是一套深入理解嵌入式流媒体系统数据流、线程同步和协议栈的实践经验。这套框架稍作修改同样可以应用于其他平台或者扩展支持H.265、音频流等功能。本文还有配套的精品资源点击获取