算法仿真平台搭建1-FFMPEG+RtspSever快速搭建一个RTSP服务器

一、前言

本文相关的全部源码和RtspSever库,我已打包上传,欢迎大家免费下载,testRTSPSever。
每一个嵌入式视觉算法工程师,都应该有一套属于自己的算法仿真和测试环境。可以方便地进行视频、图像等素材进行在线导入,可以方便地展示算法结果,可以快速地模拟应用场景,进行算法开发。在视频、图像文件等素材的在线导入模块,搭建一个属于自己的RTSP服务器,是一个理想的选择。
作为实时流媒体传输协议,RTSP服务器可无缝对接各类视觉采集设备,支持H.264/H.265编码格式的实时视频流传输,为算法验证提供稳定可靠的输入,降低算法开发过程中由于输入原因带来的困扰。

二、如何选择开源库

经过调研,使用C++搭建RTSP服务器,在安防领域使用频率最高的是Live555开源库。

2.1 Live555

Live555是一个为实时流媒体传输提供完整解决方案的跨平台C++开源框架,其特点可概括如下:

  • 完整实现RTSP(实时流控制协议)、RTP/RTCP(实时传输与控制协议)标准协议栈,支持HTTP、SIP等辅助协议扩展。
  • 原生支持H.264/H.265、MPEG、JPEG等20+种音视频格式,可通过派生类扩展新型编码。
  • 基于RTP协议实现<200ms级低延迟传输,支持自适应码率调节与网络抖动。
  • 支持搭建支持100+并发连接的RTSP服务器,应用于网络摄像头推流、视频会议系统。
  • 凭借<500KB的轻量化内存占用,适配智能家居、车载终端等资源受限场景。

功能越强大,其框架的开放程度也越高,但是,随之而来的学习成本也变高了。因此,在这里我没有选择Live555,而是选择了一个开放程度较低的RtspSever的开源项目。

2.2 RtspSever

在这里插入图片描述

RtspSever是C++11实现的RTSP服务器和推流器,源代码完全开放,可用于嵌入式的交叉编译,也可以在Windows下进编译开发。
在这里插入图片描述
RtspSever提供了一个例子,可以截取屏幕进行推流,这正好符合我的需求。因为,截取屏幕就肯定涉及到从内存中获取视频和图像,进行推流。

2.3 FFMPEG

对于视频的编码部分,我选择的是FFMPEG。FFMPEG是一个跨平台开源多媒体处理框架,由多个核心库组成,主要用于音视频编解码、封装转换、流媒体传输等场景。其核心功能与模块包括:

  • libavcode:
    提供音视频编解码功能,支持H.264、AAC等主流格式,支持GPU加速。

  • libavformat:
    处理音视频封装格式(如MP4、FLV),实现解封装(Demuxing)与封装(Muxing)。

  • libavfilter:
    支持音视频滤镜处理,例如添加水印、调整分辨率或音频变声。

  • 其他核心模块:
    libswscale:图像格式转换(如YUV与RGB互转);
    libavdevice:硬件设备采集与渲染(如摄像头、屏幕录制)
    libswresample:音频重采样与格式处理。

FFMPEG广泛应用于视频转码、直播推流、音视频编辑等领域,支持Windows、Linux、macOS等系统,并可通过命令行工具(ffmpeg、ffplay等)快速实现多媒体处理。
FFMPEG的安装和配置,在我的文章VS2022配置FFMPEG有详细介绍,这里不再重复说明。

三、代码详解

在确定好开源库后,接下来的事情就是开工撸代码了。超出了我的预期,我仅仅使用了不到200行的代码就完成了RTSP的服务器。

3.1 代码设计

  1. 初始化阶段

    • 创建RTSP服务器并绑定端口。
    • 定义媒体会话,配置H264视频源。
    • 初始化FFmpeg图像转换和H264编码器。
  2. 主循环阶段

    • 生成测试图像(绿色圆圈动画)。
    • 将BGR图像转换为NV12格式。
    • 使用H264编码器压缩视频帧。
    • 将编码后的数据通过RTSP协议推送。
    • 本地窗口显示实时画面。
  3. 资源释放

    • 退出循环后释放编码器、帧内存等资源。

代码逻辑流程如下图所示:

开始
初始化RTSP服务器
创建媒体会话并绑定H264源
配置FFmpeg转换和编码器
进入主循环
生成测试图像
BGR转NV12
H264编码
推送RTSP数据
显示本地预览
循环直到退出?
释放资源

3.2 代码详解

/* 头文件引入 */
#include <fstream>
#include <iostream>
#include <queue>
#include <mutex>
#include <atomic>
#include <thread>
#include <winsock2.h>          // Windows网络库
#include <iphlpapi.h>          // IP辅助库
#pragma comment(lib, "ws2_32.lib")   // 链接Winsock库
#pragma comment(lib, "iphlpapi.lib") // 链接IP辅助库extern "C" { // FFmpeg库使用C语言接口
#include <libavcodec/avcodec.h>   // 音视频编解码
#include <libavformat/avformat.h> // 媒体格式处理
#include <libswscale/swscale.h>   // 图像缩放与格式转换
}#include "xop/RtspServer.h"   // RTSP服务器库
#include "net/Timer.h"        // 定时器
#include "opencv2/opencv.hpp" // OpenCV图像处理库
int main() {/* RTSP服务配置 */std::string suffix = "live"; // 流后缀std::string ip = "192.168.1.14"; // 服务器IPstd::string port = "554";        // RTSP默认端口std::string rtsp_url = "rtsp://" + ip + ":" + port + "/" + suffix; // 完整URL/* 初始化事件循环和RTSP服务器 */std::shared_ptr<xop::EventLoop> event_loop(new xop::EventLoop()); // 创建事件循环std::shared_ptr<xop::RtspServer> server = xop::RtspServer::Create(event_loop.get()); // 创建RTSP服务器实例if (!server->Start("0.0.0.0", atoi(port.c_str()))) { // 启动服务器(监听所有网卡)printf("RTSP Server启动失败,端口:%s\n", port.c_str());return 0;}/* 创建媒体会话 */xop::MediaSession* session = xop::MediaSession::CreateNew("live"); // 创建会话session->AddSource(xop::channel_0, xop::H264Source::CreateNew()); // 添加H264源// 客户端连接/断开回调session->AddNotifyConnectedCallback([](xop::MediaSessionId sessionId, std::string peer_ip, uint16_t peer_port) {printf("客户端连接: IP=%s 端口=%hu\n", peer_ip.c_str(), peer_port);});session->AddNotifyDisconnectedCallback([](...) { /* 类似处理断开事件 */ });xop::MediaSessionId session_id = server->AddSession(session); // 注册会话std::cout << "播放地址: " << rtsp_url << std::endl;/* 视频参数配置 */const int frame_width = 512, frame_height = 512;/* FFmpeg图像转换配置 */SwsContext* sws_ctx = sws_getContext( // 创建颜色空间转换上下文frame_width, frame_height, AV_PIX_FMT_BGR24,  // 输入参数(BGR格式)frame_width, frame_height, AV_PIX_FMT_NV12,   // 输出参数(NV12格式)SWS_BILINEAR, nullptr, nullptr, nullptr);     // 转换算法AVFrame* sws_frame = av_frame_alloc(); // 分配转换后的帧内存// ...(设置sws_frame参数并分配缓冲区)/* H264编码器初始化 */const AVCodec* encoder = avcodec_find_encoder(AV_CODEC_ID_H264); // 查找编码器AVCodecContext* enc_ctx = avcodec_alloc_context3(encoder); // 创建编码器上下文enc_ctx->width = frame_width;  // 分辨率enc_ctx->height = frame_height;enc_ctx->time_base = {1, 25};  // 时间基(25FPS)// ...(其他编码参数设置)avcodec_open2(enc_ctx, encoder, nullptr); // 打开编码器/* 主循环 */while (true) {// 生成测试图像(绿色圆圈)cv::Mat frame = cv::Mat::zeros(frame_height, frame_width, CV_8UC3);// ...(绘制动态圆圈)/* BGR转NV12 */sws_scale(sws_ctx, bgr_frame->data, ..., sws_frame->data, ...); /* H264编码 */avcodec_send_frame(enc_ctx, sws_frame); // 发送帧到编码器while (avcodec_receive_packet(enc_ctx, enc_pkt) == 0) { // 接收编码后的包// 封装视频帧并推送到RTSP服务器xop::AVFrame videoFrame = {0};// ...(填充数据并调用PushFrame)}cv::imshow("server", frame); // 显示本地预览cv::waitKey(3); // 等待3ms}/* 资源释放 */av_packet_free(&enc_pkt);av_frame_free(&sws_frame);// ...(其他资源清理)
}

3.3、关键API说明表格

3.3.1. sws_getContext()

参数类型说明
srcWint源图像宽度
srcHint源图像高度
srcFormatAVPixelFormat源像素格式(如AV_PIX_FMT_BGR24)
dstWint目标图像宽度
dstHint目标图像高度
dstFormatAVPixelFormat目标像素格式(如AV_PIX_FMT_NV12)
flagsint缩放算法(如SWS_BILINEAR)
srcFilterSwsFilter*源滤波器(通常为nullptr)
dstFilterSwsFilter*目标滤波器(通常为nullptr)
paramconst double*算法参数(通常为nullptr)
功能创建图像缩放/格式转换上下文
返回值SwsContext*转换上下文句柄

3.3. 2. avcodec_find_encoder()

参数类型说明
idenum AVCodecID编码器ID(如AV_CODEC_ID_H264)
功能根据ID查找已注册的编码器
返回值const AVCodec*编码器指针(失败返回NULL)

3.3.3. avcodec_open2()

参数类型说明
avctxAVCodecContext*编码器上下文
codecconst AVCodec*目标编码器
optionsAVDictionary**附加选项(通常为nullptr)
功能使用指定编码器初始化上下文
返回值int0成功,负数错误码

四、测试

运行程序,使用VLC进行拉流测试:
在这里插入图片描述
延时有点大,但是,视频流还是很稳定的。有懂的小伙伴,可以在评论区留言,怎么解决这个延时的问题。

五、小结

  • 对小白来说,开源库,选择好入门的,封装程度高的。
  • 可以做下一步了,在开发板完成RTSP流的接收和解码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/71045.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型WebUI:Gradio全解12——LangChain原理、架构和组件(2)

大模型WebUI:Gradio全解12——LangChain原理、架构和组件(2) 前言12. LangChain原理及agents构建Gradio UI12.2 学习资料12.2.1 学习文档12.2.2 用途示例12.2.3 OpenAI和DeepSeek例程1. OpenAI示例2. DeepSeek例程参考文献前言 本系列文章主要介绍WEB界面工具Gradio。Gradi…

盛京开源社区加入 GitCode,书写东北开源生态新篇章

在数字化转型与开源技术蓬勃发展的浪潮下&#xff0c;开源社区已成为推动技术创新的核心力量。盛京开源社区&#xff08;SJOSC&#xff09;作为沈阳地区的开源交流平台&#xff0c;始终致力于连接开发者、企业及高校&#xff0c;构建区域技术生态圈。 现在&#xff0c;盛京开源…

安装Git(小白也会装)

一、官网下载&#xff1a;Git 1.依次点击&#xff08;红框&#xff09; 不要安装在C盘了&#xff0c;要炸了&#xff01;&#xff01;&#xff01; 后面都 使用默认就好了&#xff0c;不用改&#xff0c;直接Next&#xff01; 直到这里&#xff0c;选第一个 这两种选项的区别如…

Vue.js计算属性

计算属性​ 基础示例​ 模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。比如说,我们有这样一个包含嵌套数组的对象: js const author = reactive({name: John Doe,books: [Vue 2 - Advanced Guide,Vue 3 - Bas…

代码审计入门学习

简介 HadSky轻论坛程序为个人原创PHP系统&#xff0c;作者为蒲乐天&#xff0c;后端基于puyuetianPHP框架驱动&#xff0c;前端基于 puyuetianUI框架驱动&#xff0c;默认编辑器为puyuetianEditor富文本编辑器&#xff0c;其他非原创框架及驱动JQuery.js 及Font-Awesome字体库…

测试金蝶云的OpenAPI

如何使用Postman测试K3Cloud的OpenAPI 1. 引言 在本篇博客中&#xff0c;我将带你逐步了解如何使用Postman测试和使用K3Cloud的OpenAPI。内容包括下载所需的SDK文件、配置文件、API调用及测试等步骤。让我们开始吧&#xff01; 2. 下载所需的SDK文件 2.1 获取SDK 首先&…

【愚公系列】《Python网络爬虫从入门到精通》034-DataFrame简单数据计算整理

标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度…

服务端驱动UI架构解析:React Server Components与流式渲染的革命

引言&#xff1a;重新定义前后端边界 Shopify采用React Server Components后&#xff0c;动态模块加载速度提升340%&#xff0c;客户端Bundle减少62%。Discord重构消息流服务&#xff0c;通过流式渲染使首屏TTI从4.2s降至1.1s。Vercel生产数据显示&#xff0c;混合渲染技术让L…

顶顶通呼叫中心中间件(mod_cti基于FreeSWITCH)-大模型电话机器人

语音流直接对接Realtime API 多模态大模型 直接把音频流输出给大模型&#xff0c;大模型返回音频流。 顶顶通CTI对Realtime API 的支持 提供了以下2个APP可对接任意 •cti_audio_stream 通过TCP推流和播放流&#xff0c;适合用于人机对话场景。 •cti_unicast_start 通过旁…

绕过 RAG 实时检索瓶颈,缓存增强生成(CAG)如何助力性能突破?

编者按&#xff1a; 你是否曾经遇到过这样的困扰&#xff1a;在开发基于 RAG 的应用时&#xff0c;实时检索的延迟让用户体验大打折扣&#xff1f;或者在处理复杂查询时&#xff0c;检索结果的不准确导致回答质量不尽如人意&#xff1f; 在当前大语言模型应用大规模落地的背景下…

后端返回文件流,前端导出excel文件

1、当后端接口返回文件流时&#xff0c;需前端导出excel文件&#xff0c;在请求中添加 responseType: blob限制条件&#xff0c;根据返回的文件流导出 封装的方法&#xff1a; /** * 公共的导出excel方法 * param {*} content 后端接口返回的二进制文件 * param {*} name 导出…

基于django图书信息管理系统的搭建(增删改查)

✍django项目搭建教程 ☞ ----------------- 教程 本文主要讲解django如何连接数据库MySQL并且可视化展示&#xff0c;实现增删改查功能 目录 一. 创建django应用 二. 数据库配置 三. 查看数据库 四. 编写代码 4.1视图函数 4.2 配置URL 4.3创建模板文件 4.…

鸿蒙NEXT开发-元服务和服务卡片的开发

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 目录 1. 元服务基本概念 1.1 基本介绍 1.2 元…

HBuilder X中,uni-app、js的延时操作及定时器

完整源码下载 https://download.csdn.net/download/luckyext/90430165 在HBuilder X中&#xff0c;uni-app、js的延时操作及定时器可以用setTimeout和setInterval这两个函数来实现。 1.setTimeout函数用于在指定的毫秒数后执行一次函数。 例如&#xff0c; 2秒后弹出一个提…

IP属地是通过卫星定位的吗?如何保护用户隐私

在数字时代&#xff0c;网络空间成为了人们日常生活不可或缺的一部分。随着社交媒体、在线服务等平台的兴起&#xff0c;用户IP属地信息的重要性日益凸显。然而&#xff0c;关于IP属地是如何确定的&#xff0c;尤其是是否通过卫星定位这一问题&#xff0c;却常常引发公众的疑问…

DMA发送全部历史记录数据到串口

背景 博主参与的项目中&#xff0c;有个读取全部历史记录的功能&#xff0c;如果下位机在主程序中将全部历史记录单纯地通过串口传输会比较占用cpu资源&#xff0c;影响主程序中别的功能。最后商量得出以下实现方案&#xff1a; 定义两个发送缓冲区DMATxbuf1和DMATxbuf2&…

华为云之使用鲲鹏弹性云服务器部署Node.js环境【玩转华为云】

华为云之使用鲲鹏弹性云服务器部署Node.js环境【玩转华为云】 一、本次实践介绍1.1 实践环境简介1.3 本次实践完成目标 二、 相关服务介绍2.1 华为云ECS云服务器介绍2.2 Node.js介绍 三、环境准备工作3.1 预置实验环境3.2 查看预置环境信息 四、登录华为云4.1 登录华为云4.2 查…

记录深度学习中有用的终端命令

1 查看 CUDA 版本 如果你安装了 CUDA 开发工具包&#xff0c;你可以使用 nvcc 命令来查看 CUDA 的版本。 打开终端&#xff08;或命令提示符&#xff09;&#xff0c;运行&#xff1a; nvcc --version 2. 监控 GPU 状态 使用 nvidia-smi 命令&#xff0c;nvidia-smi 是一个…

PyCharm中通过命令行执行`pip`命令下载到哪里了:虚拟环境目录下

PyCharm中通过命令行执行pip命令下载到哪里了:虚拟环境目录下 在PyCharm中通过命令行执行pip命令安装工具包,包的下载位置取决于多种因素 虚拟环境 如果项目使用了虚拟环境(通常是推荐的做法): Windows:虚拟环境通常位于项目目录下的.venv文件夹(默认情况)或你指定…

PS修复画笔工具

修复画笔工具&#xff1a; 修复画笔工具J&#xff1a;仿制图章工具适配颜色功能&#xff08;模式 正常&#xff1a;仿制图章工具适配颜色功能。替换&#xff1a;仿制图章工具&#xff09;&#xff08;扩散&#xff08;羽化&#xff09;&#xff1a;越高&#xff0c;周围颜色融合…