首页 > 其他分享 >Qt编写监控实时显示和取流回放工具(回放支持切换进度)

Qt编写监控实时显示和取流回放工具(回放支持切换进度)

时间:2023-06-21 14:23:57浏览次数:40  
标签:取流 rtsp Qt 回放 视频流 支持 格式 播放

一、前言

现在各个监控大厂做的设备,基本上都会支持通过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:[email protected]:554/Streaming/Channels/101?transportmode=unicast
        //视频回放格式 rtsp://admin:[email protected]: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:[email protected]: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:[email protected]:554/live?channel=1&stream=1
        //视频回放格式 rtsp://admin:[email protected]: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:[email protected]:554/0  0-主码流 1-子码流
    return url;
}

标签:取流,rtsp,Qt,回放,视频流,支持,格式,播放
From: https://www.cnblogs.com/feiyangqingyun/p/17496108.html

相关文章

  • QT转换GMT时间
    故事背景:需要把"Apr1201:03:172023GMT"转化为"yyyy年MM月dd日hh:mm:ss",直接看代码QStringgtm_time="Apr1201:03:172023GMT";QLocalelocale=QLocale::English;QDateTimecur_time=locale.toDateTime(gtm_time,"MMMddh......
  • qt中添加多个UI界面,并在其他文件中调用该UI界面
    一、概述qt创建一个新项目时,会创建一个属于mainwindow'的主ui界面,这时如果想要创建多个窗口,可以有三种方法。第一种:使用代码创建一个新窗口,优点是灵活,缺点是麻烦,其中控件和布局都需要代码来创建。第二种:在ui设计界面使用tabwidget控件来达到多个窗口的效果,不过这种方法只能......
  • 多路Qt串口通信源码C++语言接口自定义协议帧Qt读写配置文件ini出售: 可变长定长通信接
    多路Qt串口通信源码C++语言接口自定义协议帧Qt读写配置文件ini出售:可变长定长通信接口协议实现Qt多路串口发送接收SerialProtocol.rar工控自定义报文可用于嵌入式,单片机,ARM,DSP等常见的串口通信中,出售在应用实践中编写总结的源代码,实现自定义的串口通信协议,包括报文头部、长度......
  • Qt编写曲线图柱状图源码 1:可设置X轴Y轴范围值 2:可设置背
    Qt编写曲线图柱状图源码1:可设置X轴Y轴范围值2:可设置背景颜色+文本颜色+网格颜色3:可设置三条曲线颜色+颜色集合4:可设置是否显示定位十字线,可分别设置横向和纵向5:可设置十字线的宽度和颜色6:可设置是否显示数据点以及数据点的大小7:可设置是否填充背景形成面积图8:可设置模......
  • Qt编写安防楼宇对讲管理平台源码 1. 同时集成了楼宇对讲、住户报
    Qt编写安防楼宇对讲管理平台源码1.同时集成了楼宇对讲、住户报警、门禁控制、公共报警、视频监控等模块。2.系统管理部分包括系统配置、对讲配置、住户配置、公共配置、监控配置、地图管理、视频联动、用户管理、区域管理。3.图形化的实时对讲、室内报警、门禁设备界面,非常大......
  • Qt编写控件组态属性设计器源码属性设计器产品不包括里面控件的源码
    Qt编写控件组态属性设计器源码属性设计器产品不包括里面控件的源码1.自动加载插件文件中的所有控件生成列表,默认自带的控件超过120个。2.拖曳到画布自动生成对应的控件,所见即所得。3.右侧中文属性栏,改变对应的属性立即应用到对应选中控件,直观简洁,非常适合小白使用。4.独创属性......
  • Qt 常用函数
    forever死循环宏定义,和while(1)类似,其底层使用for(;;)实现,使用方法如下:forever{ //...}foreachQStringListstrList;QStringstr;foreach(str,strList) qDebug()<<str;常用数学函数Qt中的<QtAlgorithms>、<QtGlobal>、<QtMath>提供了一些常用......
  • Qt 常用全局宏定义
    本文主要积累一些常用宏定义,有些定义在头文件QtGlobal中。QT_VERSION,QT_VERSION_CHECK//主要用于条件编译设置,根据Qt版本不同编译不同的代码//我这里用的Qt版本是5.12.2,因此软件走的分支是isHighVer=false;//示例代码:#ifQT_VERSION>=QT_VERSION_CHECK(5,12,2)......
  • 【Qt5学习笔记】使用ui界面编一个入门级的小项目(保姆级教程,多图警告)
    前言我发现自己之前可能是有点走偏了,花了两天时间看书几乎一无所获,书上都是代码实现,还没有相应的注释…今天我用ui设计师界面来进行编程,写一个小界面。界面功能1.计算加法;2.可以弹窗;3.使用布局,美化界面;4.退出按钮;界面预览实现1.建立一个QtWidgetsApplication可以参考QT5项目......
  • Qt5.9.1的下载和安装注意事项
    下载地址qt5.9downlaod安装过程编译器是可选的若本地环境没有VisualStdio,就不要勾选关于它的编译器。一般至少要勾选MingGW编译器......