• 53阅读
  • 0回复

又是全网首创/纯Qt实现28181设备模拟器/rtp视频点播/桌面转28181/任意文件转28181/跨平台 [复制链接]

上一主题 下一主题
离线liudianwu
 

图酷模式  只看楼主 倒序阅读 楼主  发表于: 前天 08:36


## 一、前言说明
这个工具前前后后也算是废了不少功夫,最开始是因为28181服务端的组件已经完美实现,对照国标文档看了很多遍,逐个实现需要的交互协议,整体上比onvif协议要难不少,主要是涉及到的东西比较多,有sip协议,又有xml数据封装,云台控制用的又是模拟设备时代的16进制数据来控制,音视频传输用的又是单独的rtp,而播放控制用的又是rtsp中的控制指令,哎呀我去全部杂交啊,一般人没个几个月搞不定的,发量越来越少是肯定的。

能够把28181的服务端搞定,那设备端的指令就简单多了,底层其实就是udp和tcp通信,根据收到的数据进行解析和交互即可,按照国标文档来就行,肯定错不了,如果错了那肯定是对应平台或者设备厂家有问题没写好。设备端最大难点困在如何发送视频rtp数据这里,一直在想要不要用第三方的轮子比如jrtp,好在之前就对ffmpeg推流很熟悉了,尝试了直接推流rtp,一开始死活不行,后面发现原来格式不对,国标要求的是rtp携带ts格式的数据包,对应不应该是rtp格式而应该是rtp_mpegts,相当于rtp over mpegts,其实udp推流这种就是mpegts格式,这个细节网上很少人提到,搞得这里困了很多天,以为ffmpeg实现不了,原来用纯ffmpeg就可以直接实现的。


## 二、效果图
window.open('http://www.qtcn.org/bbs/attachment/Mon_2509/44_110085_ac249cd4c2e570c.jpg?267');" style="max-width:700px;max-height:700px;" onload="if(is_ie6&&this.offsetWidth>700)this.width=700;" >



## 三、相关地址
1. 国内站点:[https://gitee.com/feiyangqingyun](https://gitee.com/feiyangqingyun)
2. 国际站点:[https://github.com/feiyangqingyun](https://github.com/feiyangqingyun)
3. 个人作品:[https://blog.csdn.net/feiyangqingyun/article/details/97565652](https://blog.csdn.net/feiyangqingyun/article/details/97565652)
4. 文件地址:[https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g](https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g) 提取码:01jf 文件名:bin_video_simulate。

## 四、功能特点
1. 标准onvif协议,支持设备搜索、获取参数、快照抓图等。
2. 支持264/265/aac等标准视音频协议传输。
3. 支持多路批量onvif设备模拟,每一路都独立的端口。
4. 支持本地摄像头采集转成onvif,可选择不同的设备、分辨率、帧率等参数。
5. 支持本地桌面采集转成onvif,可选择不同的屏幕、分辨率、帧率等参数。
6. 支持各种视频文件和视频流转成onvif,可重新设置编码转换以及分辨率转换。
7. 支持4K、8K等高清分辨率,不限制分辨率,非264/265会自动转码推流。
8. 每一路都可以设置统一或者独立的用户验证信息,为空则表示不验证。
9. 可以把任意内容接入到NVR以及视频监控系统,方便保存录像文件,以便回放可查。
10. 也可作为压力测试工具,比如模拟几千路onvif设备,让集成平台软件做接入压力测试。
11. 推出去的流不仅有rtsp格式,还支持rtmp、http、flv、ws-flv、webrtc等方式访问,可以直接网页查看。
12. 在管理工具上可以看到每一路的推流状况以及分辨率信息,非常直观。
13. 支持自动重连拉流,重连推流,保证7乘以24小时稳定运行。
14. 可设置开机自启动运行和后台运行,不显示在任务栏,作为后台服务运行。
15. 可批量添加文件、添加目录,自动将目录下的所有文件添加到模拟器。
16. 多功能添加地址面板,可以选择本地设备和监控设备,本地设备会自动识别摄像头设备和桌面设备,监控设备可以选择不同厂家,自动填充对应rtsp格式,填入用户信息即可,可以批量递增添加监控设备。
17. 可无缝上传到市面上所有的onvif协议设备,包括海康、大华、宇视、华为、天地伟业等,也支持ONVIF Device Manager国际onvif工具。
18. 支持gb28181设备模拟,具备设备注册、设备注销、设备心跳、设备信息、设备配置、设备状态应答等。
19. 支持模拟报警和位置上报等,方便平台侧显示对应设备的实时位置。
20. 支持一键添加批量模拟28181设备,实时显示已注册和已注销状态。
21. 支持将本地桌面、本地摄像头、任意视频文件、视频流文件、手机摄像头等转换成28181设备,添加到NVR或者国标软件平台。
22. sip协议同时支持udp和tcp两种通信方式,视频点播同时支持udp/tcp主动/tcp被动三种方式,涵盖所有可能的场景需求。
23. 无论是onvif设备模拟组件还是28181设备模拟组件,全部原创底层协议解析,纯Qt实现,跨任意平台。
24. 代码结构框架非常清晰,注释详细,代码精简不繁琐,非常易于学习和移植,可以很容易拓展其他接口需求。
25. 支持Qt4/Qt5/Qt6以及后续所有版本、所有编译器、所有开发环境。
26. 支持windows、linux、mac、国产OS、嵌入式linux、RK3588、树莓派、香橙派等系统。

## 五、相关代码
```cpp
#include "gb28181devicepush.h"
#include "ffmpegthread.h"
#include "ffmpegsave.h"
#include "videohelper.h"
#include "osdgraph.h"

bool GB28181DevicePush::disableDecode = true;
GB28181DevicePush::GB28181DevicePush(QObject *parent) : QObject(parent)
{
    ffmpegThread = NULL;
}

GB28181DevicePush::~GB28181DevicePush()
{
    this->stop();
}

void GB28181DevicePush::setPara(const QString &flag, const QString &mediaUrl, const QString &pushUrl)
{
    this->flag = flag;
    this->mediaUrl = mediaUrl;
    this->pushUrl = pushUrl;
}

bool GB28181DevicePush::isOk()
{
    return (ffmpegThread != NULL);
}

void GB28181DevicePush::start()
{
    if (ffmpegThread || mediaUrl.isEmpty() || pushUrl.isEmpty()) {
        return;
    }

    //实例化视频采集线程
    ffmpegThread = new FFmpegThread;
    //关联播放开始信号/用来启动推流
    connect(ffmpegThread, SIGNAL(receivePlayStart(int)), this, SLOT(receivePlayStart(int)));
    //关联录制信号变化/用来判断是否推流成功
    connect(ffmpegThread, SIGNAL(recorderStateChanged(RecorderState, QString)), this, SLOT(recorderStateChanged(RecorderState, QString)));

    //设置保存视频类将数据包信号发出来用于保存文件
    FFmpegSave *saveFile = ffmpegThread->getSaveFile();
    saveFile->setProperty("ssrc", flag);
    connect(saveFile, SIGNAL(receiveSaveStart()), this, SLOT(receiveSaveStart()));
    connect(saveFile, SIGNAL(receiveSaveFinsh()), this, SLOT(receiveSaveFinsh()));
    connect(saveFile, SIGNAL(receiveSaveError(int)), this, SLOT(receiveSaveError(int)));    

    //设置播放地址
    ffmpegThread->setMediaUrl(mediaUrl);
    //设置视频模式
    ffmpegThread->setVideoMode(VideoMode_Painter);
    //设置读取超时时间超时后会自动重连
    ffmpegThread->setReadTimeout(10 * 1000);
    //设置连接超时时间
    ffmpegThread->setConnectTimeout(0);
    //设置重复播放相当于循环推流
    ffmpegThread->setPlayRepeat(true);
    //设置不解码音频
    ffmpegThread->setDecodeAudio(false);
    //设置不解码数据
    ffmpegThread->setDisableDecode(disableDecode);

    //如果是本地设备或者桌面录屏要取出其他参数
    VideoHelper::initVideoPara(ffmpegThread, mediaUrl);

    //启动播放
    ffmpegThread->play();
}

void GB28181DevicePush::stop()
{
    //停止推流和采集并彻底释放对象
    if (ffmpegThread) {
        ffmpegThread->recordStop();
        ffmpegThread->stop();
        ffmpegThread->deleteLater();
        ffmpegThread = NULL;
    }
}

void GB28181DevicePush::receivePlayStart(int time)
{
    //演示添加OSD后推流
#ifdef betaversion
    int height = ffmpegThread->getVideoHeight();
    QList<OsdInfo> osds = OsdGraph::getTestOsd(height);
    ffmpegThread->setOsdInfo(osds);
#endif

    //打开后才能启动录像
    ffmpegThread->recordStart(pushUrl);
}

void GB28181DevicePush::recorderStateChanged(const RecorderState &state, const QString &)
{
    int width = 0;
    int height = 0;
    if (ffmpegThread) {
        width = ffmpegThread->getVideoWidth();
        height = ffmpegThread->getVideoHeight();
    }

    bool start = (state == RecorderState_Recording);
    emit pushStart(flag, width, height, start);
}

void GB28181DevicePush::receiveSaveStart()
{
    emit pushChanged(flag, 0);
}

void GB28181DevicePush::receiveSaveFinsh()
{
    emit pushChanged(flag, 1);
}

void GB28181DevicePush::receiveSaveError(int)
{
    emit pushChanged(flag, 2);
}
```
欢迎关注微信公众号:Qt实战/Qt入门和进阶(各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发) QQ:517216493  WX:feiyangqingyun  QQ群:751439350
快速回复
限100 字节
 
上一个 下一个