一、前言

现在各个监控大厂做的设备,基本上都会支持通过rtsp直接取流显示,而且做的比较好的还支持通过rtsp回放取流,基本上都会约定一个字符串的规则,每个厂家都是不一样的规则,比如回放对应的rtsp地址还要带上时间范围,回放肯定要指定一个开始时间和结束时间。这里需要特别提示的是,按道理rtsp是实时视频流,一般是没有时长的,而回放的rtsp视频流是带了时长的,所以可以通过seek来定位播放位置,这个就很方便用户在软件上任意拖动和切换播放位置,以前我一直以为rtsp实时视频流不可能有时长,原来是自己孤陋寡闻了,在通过一个老万音视频大佬的指点下才得知这个特性,这个特性当然需要设备厂家在后端实现支持。

有了回放可以切换播放进度位置这个特性,意味着回放这块不需要用GB28181国标去解析,直接构建对应的回放视频流字符串就可以,目前测试下来,正常播放和切换进度播放一点问题没有,唯独倍速播放有问题,目前看下来还是不支持倍速播放的,不知道是不是还有其他的机关要素控制比如参数啥的。其实取流回放的核心就是根据不同厂家拿到对应设备的rtsp字符串即可,解码那边要拿到时长,并当做文件处理,因为文件类型的可以切换播放进度。

二、效果图

三、体验地址

  1. 国内站点:https://gitee.com/feiyangqingyun
  2. 国际站点:https://github.com/feiyangqingyun
  3. 个人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
  4. 体验地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_demo。

四、功能特点

  1. 支持各种音视频文件、本地摄像头设备,各种视频流网络流。
  2. 支持开始播放、暂停播放、继续播放、停止播放、设置播放进度、倍速播放。
  3. 可设置音量、静音切换、抓拍图片、录像存储。
  4. 自动提取专辑信息比如标题、艺术家、专辑、专辑封面,自动显示专辑封面。
  5. 完美支持音视频同步和倍速播放。
  6. 解码策略支持速度优先、质量优先、均衡处理、最快速度。
  7. 支持手机视频旋转角度显示,比如一般手机拍摄的视频是旋转了90度的,解码显示的时候需要重新旋转90度才是正的。
  8. 自动转换yuv420格式,比如本地摄像头是yuyv422格式,有些视频文件是xx格式,统一将非yuv420格式转换,然后再进行处理。
  9. 支持硬解码dxva2、d3d11va等,性能极高尤其是大分辨率比如4K视频。
  10. 视频响应极低延迟0.2s左右,极速响应打开视频流0.5s左右,专门做了优化处理。
  11. 硬解码和GPU绘制组合,极低CPU占用,比海康大华等客户端更优。
  12. 支持视频流中的各种音频格式,AAC、PCM、G.726、G.711A、G.711Mu、G.711ulaw、G.711alaw、MP2L2等都支持,推荐选择AAC兼容性跨平台性最好。
  13. 视频存储支持yuv、h264、mp4多种格式,音频存储支持pcm、wav、aac多种格式。默认视频mp4格式、音频aac格式。
  14. 支持分开存储音频视频文件,也支持合并到一个mp4文件,默认策略是无论何种音视频文件格式存储,最终都转成mp4及aac格式,然后合并成音视频一起的mp4文件。
  15. 支持本地摄像头实时视频显示带音频输入输出,音视频录制合并到一个mp4文件。
  16. 支持H264/H265编码(现在越来越多的监控摄像头是H265视频流格式)生成视频文件,内部自动识别切换编码格式。
  17. 自动识别视频流动态分辨率改动,重新打开视频流。
  18. 支持用户信息中包含特殊字符(比如用户信息中包含+#@等字符)的视频流播放,内置解析转义处理。
  19. 纯qt+ffmpeg解码,非sdl等第三方绘制播放依赖,gpu绘制采用qopenglwidget,音频播放采用qaudiooutput。
  20. 同时支持ffmpeg2、ffmpeg3、ffmpeg4、ffmpeg5、ffmpeg6以及后续版本,全部做了兼容处理。如果需要支持xp需要选用ffmpeg3或ffmpeg2。
  21. 支持滤镜,源头带各种水印及图形效果,可以将OSD标签信息和各种图形信息写入到MP4文件。

五、相关代码

//地址参数结构体
struct UrlPara {
QString deviceIP; //通信地址
int devicePort; //通信端口
QString userName; //用户名称
QString userPwd; //用户密码 int channel; //通道编号
int streamType; //码流类型
QString companyName; //厂家标识
CompanyType companyType; //厂家类型 int videoType; //视频类型(0-实时/1-回放)
QDateTime dateTimeStart; //开始时间(回放专用)
QDateTime dateTimeEnd; //结束时间(回放专用) UrlPara() {
devicePort = 0;
channel = 0;
streamType = 0;
} //重载打印输出格式
friend QDebug operator << (QDebug debug, const UrlPara &urlPara) {
QStringList list;
list << QString("通信地址: %1").arg(urlPara.deviceIP);
list << QString("通信端口: %1").arg(urlPara.devicePort);
list << QString("用户名称: %1").arg(urlPara.userName);
list << QString("用户密码: %1").arg(urlPara.userPwd); list << QString("通道编号: %1").arg(urlPara.channel);
list << QString("码流类型: %1").arg(urlPara.streamType);
list << QString("厂家标识: %1").arg(urlPara.companyName);
list << QString("厂家类型: %1").arg(urlPara.companyType); #if (QT_VERSION >= QT_VERSION_CHECK(5,4,0))
debug.noquote() << list.join("\n");
#else
debug << list.join("\n");
#endif
return debug;
}
}; QString UrlHelper::getRtspUrl(const UrlPara &urlPara)
{
QString url;
//头部地址格式完全一致
QString head = QString("rtsp://%1:%2@%3:554").arg(urlPara.userName).arg(urlPara.userPwd).arg(urlPara.deviceIP);
if (urlPara.companyType == CompanyType_HaiKang) {
//实时预览格式 rtsp://admin:12345@192.168.1.128:554/Streaming/Channels/101?transportmode=unicast
//视频回放格式 rtsp://admin:12345@192.168.1.128:554/Streaming/tracks/101?starttime=20120802t063812z&endtime=20120802t064816z
//流媒体视频流 rtsp://172.6.24.15:554/Devicehc8://172.6.22.106:8000:0:0?username=admin&password=12345
//日期时间格式 ISO 8601 表示Zulu(GMT) 时间 YYYYMMDD”T”HHmmSS.fraction”Z”,
//unicast表示单播,multicast表示多播,默认单播可以省略
//101解析: 1是通道号 01是通道的码流编号 也可以是02 03
QString startTimeISO = urlPara.dateTimeStart.toString(Qt::ISODate);
startTimeISO.replace("-", "");
startTimeISO.replace(":", "");
startTimeISO.toLower(); QString endTimeISO = urlPara.dateTimeEnd.toString(Qt::ISODate);
endTimeISO.replace("-", "");
endTimeISO.replace(":", "");
endTimeISO.toLower(); //通道号和码流编号
QString info = QString("%1%2%3").arg(urlPara.channel).arg(0).arg(urlPara.streamType + 1);
//回放时间范围
QString time = QString("starttime=%1z&endtime=%2z").arg(startTimeISO).arg(endTimeISO);
//实时和回放地址格式不同
if (urlPara.videoType == 0) {
url = QString("%1/Streaming/Channels/%2").arg(head).arg(info);
} else if (urlPara.videoType == 1) {
url = QString("%1/Streaming/tracks/%2?%3").arg(head).arg(info).arg(time);
}
} else if (urlPara.companyType == CompanyType_DaHua) {
//实时预览格式 rtsp://192.168.1.128:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
//视频回放格式 rtsp://admin:12345@192.168.1.128:554/cam/playback?channel=1&subtype=0&starttime=2021_03_18_11_36_01&endtime=2021_03_18_12_05_01
QString startTimeStr = urlPara.dateTimeStart.toString("yyyy_MM_dd_HH_mm_ss");
QString endTimeStr = urlPara.dateTimeEnd.toString("yyyy_MM_dd_HH_mm_ss");
//通道号和码流编号
QString info = QString("channel=%1&subtype=%2").arg(urlPara.channel).arg(urlPara.streamType);
//回放时间范围
QString time = QString("starttime=%1&endtime=%2").arg(startTimeStr).arg(endTimeStr);
//实时和回放地址格式不同
if (urlPara.videoType == 0) {
url = QString("%1/cam/realmonitor?%2&unicast=true&proto=Onvif").arg(head).arg(info);
} else if (urlPara.videoType == 1) {
url = QString("%1/cam/playback?%2&%3").arg(head).arg(info).arg(time);
}
} else {
//实时预览格式 rtsp://admin:12345@192.168.1.128:554/live?channel=1&stream=1
//视频回放格式 rtsp://admin:12345@192.168.1.128:554/file?channel=1&start=1494485280&stop=1494485480
//先转换时间戳,1970年到该时间经过的秒数
qint64 startTimeSec = urlPara.dateTimeStart.toMSecsSinceEpoch() / 1000;
qint64 stopTimeSec = urlPara.dateTimeEnd.toMSecsSinceEpoch() / 1000;
//回放时间范围
QString time = QString("start=%1&stop=%2").arg(startTimeSec).arg(stopTimeSec);
//实时和回放地址格式不同
if (urlPara.videoType == 0) {
url = QString("%1/live?channel=%2&stream=%3").arg(head).arg(urlPara.channel).arg(urlPara.streamType);
} else if (urlPara.videoType == 1) {
url = QString("%1/file?channel=%2&%3").arg(head).arg(urlPara.channel).arg(time);
}
} //还有一种通用格式 rtsp://admin:12345@192.168.1.128:554/0 0-主码流 1-子码流
return url;
}

Qt/C++编写监控实时显示和取流回放工具(回放支持切换进度)的更多相关文章

  1. 目前使用过的各大厂商rtsp取流的url

    目前使用过的各大厂商取流规则是在实际的工作中遇到的相关视频接入问题,通过rtsp协议接入视频数据的一些记录,其中的图片可能来源于网络,内容部分来源于网络,本人仅仅是对相关内容作了汇总. 海康RTSP取 ...

  2. 各大厂RTSP取流的URI

    目前使用过的各大厂商取流规则是在实际的工作中遇到的相关视频接入问题,通过rtsp协议接入视频数据的一些记录,其中的图片可能来源于网络,内容部分来源于网络,本人仅仅是对相关内容作了汇总. 海康RTSP取 ...

  3. 海康RTSP取流URL格式

    预览取流url [海康威视]举例说明: 主码流取流: rtsp://admin:12345@192.0.0.64:554/h264/ch1/main/av_stream 子码流取流: rtsp://a ...

  4. Qt 实时显示系统时间

    前言 我们用一个label控件来实时显示系统时间,用到 QTimer 和 QDateTime 这个两个类. 正题 头文件: #ifndef MAINWINDOW_H #define MAINWINDO ...

  5. 使用 Qt 获取 UDP 数据并显示成图片(2)

    本文首发于 BriFuture 的 个人博客 在我的前一篇文章 使用 Qt 获取 UDP 数据并显示成图片 中,我讲了如何用 Python 模拟发送数据,如何在 Qt 中高效的接收 UDP 数据包并将 ...

  6. 基于MATLAB的GUI(Graphical User Interface)音频实时显示设计

    摘要:本文章的设计主要讲基于matlab的gui音频实时显示设计,此次设计的gui相当于一个简洁的音乐播放器,界面只有”录音“和”播放“两个控件,哈哈,够简洁吧.通过”录音“按钮可以实现声音从电脑的声 ...

  7. [Swift通天遁地]四、网络和线程-(8)下载图片并实时显示下载进度

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  8. [Swift通天遁地]四、网络和线程-(9)上传图片并实时显示上传进度

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  9. 6.MIL采集和实时显示

    前面讲到的都是离线的图像获取方法,实际中我们做机器视觉都是在线采集图像和处理,处理结果决定了计算机要给出的控制信号如电机运动等,这样就实现了实时视觉反馈运动.MIL中的采集需要Matrox采集板卡的支 ...

  10. Qt+imx6编写的楼宇对讲管理平台

    第一个初步版本. 1:楼宇对讲模块.住户报警模块.门禁控制模块.系统设置模块. 2:实时对讲信息卡片式展示,通话记录表格展示. 3:设备面板展示,实时显示上下线报警等信息. 4:设备查询.记录查询.运 ...

随机推荐

  1. JDBC后端实现查询功能逻辑

    // 包名 package com.zhulx.JDBC; // 导入实例类 import com.zhulx.pojo.Account; import java.sql.*; import java ...

  2. 神经网络之卷积篇:详解经典网络(Classic networks)

    详解经典网络 首先看看LeNet-5的网络结构,假设有一张32×32×1的图片,LeNet-5可以识别图中的手写数字,比如像这样手写数字7.LeNet-5是针对灰度图片训练的,所以图片的大小只有32× ...

  3. [GXYCTF2019]BabyUpload 1

    打开靶机,上传文件抓包 后缀不能带ph,大小写也无法绕过,意味着phtml后缀也无法上传 对后缀只过滤ph,我们转变思路上传图片马,用.htaccess使图片马以php格式打开 上传图片马 上传失败, ...

  4. BUUCTF BUU SQL COURSE 1

    方法一:手工注入 启动靶机 寻找注入点,使用burp抓包得到传参页面 得到注入点 /backend/content_detail.php?id=1 用and 1 =1 和 and 1 =2 判断存在s ...

  5. Python 实现Excel XLS和XLSX格式相互转换

    在日常工作中,我们经常需要处理和转换不同格式的Excel文件,以适应不同的需求和软件兼容性.Excel文件的两种常见格式是XLS(Excel 97-2003)和XLSX(Excel 2007及以上版本 ...

  6. 神经网络之卷积篇:详解残差网络为什么有用?(Why ResNets work?)

    详解残差网络为什么有用? 为什么ResNets能有如此好的表现,来看个例子,它解释了其中的原因,至少可以说明,如何构建更深层次的ResNets网络的同时还不降低它们在训练集上的效率.通常来讲,网络在训 ...

  7. 你真的理解 Kubernetes 中的 requests 和 limits 吗?

    在 Kubernetes 集群中部署资源的时候,你是否经常遇到以下情形: 经常在 Kubernetes 集群种部署负载的时候不设置 CPU requests 或将 CPU requests 设置得过低 ...

  8. 云原生周刊:Microcks 成为 CNCF 沙箱项目

    开源项目推荐 Kubent Kube No Trouble (kubent) 是一个简单的工具,该工具将能够根据您部署资源的方式检测已弃用的 API. kdoctor kdoctor 是一个数据面测试 ...

  9. Mongo oplog理解

    转载请注明出处: oplog(操作日志)是MongoDB中用于记录所有写操作的日志.它是一个特殊的集合,存储在副本集的主节点中.oplog用于确保副本集中的副节点与主节点的数据保持一致.当主节点执行写 ...

  10. 痞子衡嵌入式:瑞萨RA系列FSP固件库分析之外设驱动

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是瑞萨RA系列FSP固件库里的外设驱动. 上一篇文章 <瑞萨RA8系列高性能MCU开发初体验>,痞子衡带大家快速体验了一下瑞萨 ...