Qt/C++ プログラミング ビデオ監視システム 81-Onvif アラーム キャプチャ、ビデオ録画および再生

I.はじめに

ビデオ監視システムのグラフィックおよびテキスト アラーム モジュールは、Onvif プロトコルのイベント サブスクリプションを通じて取得され、イベント サブスクリプション後、侵入アラーム/遮断アラーム/越境アラーム/スイッチ アラームなどのデバイスのさまざまなアラーム イベントが取得されます。彼らは率先して加入者に送信し、通常はアラームの開始と終了の 2 回送信し、各イベントはテキスト文字プロトコルの合意に対応するため、辞書テーブルを作成できます。アラームの単語は、メーカーによっては独自にプロトコルを定義している場合があるため、区別しやすいです プログラム内にハードコーディングされていると、後で追加、削除、修正するのに不便なので、メモ帳を作成してくださいファイルまたは json ファイルを使用して、このディクショナリ テーブルを特別に保存します。ユーザーは、開いて変更できます。

監視システムにはログ記録テーブルがあり、これまで保存されていたユーザーの各種操作ログや受信アラームログを記録するための特別なコメントフィールドがあり、このフィールドはアラーム画像またはアラームビデオファイルのパスを保存するために使用され、ユーザーはいつ確認できるようになりますこれらのログが記録されると、現在選択されているレコードをダブルクリックできます。写真の場合は、アラーム画像のプレビューがポップアップ表示されます。アラーム ビデオ ファイルの場合は、ビデオ再生がポップアップ表示されます。これは次と同等です。ログを確認すると、現在のアラーム状態を 1 つずつ対応することもできます。写真またはビデオ ファイルの場合、ビデオ ファイルの優先順位がアラーム画像よりも高くなります。アラーム後、スナップショットが最初にトリガーされます。アラーム録画をトリガーする必要がある合意されたアラーム イベントである場合、ビデオが録画されます。

デモビデオhttps://www.bilibili.com/video/BV1Gp4y1N7bm

2. レンダリング

ここに画像の説明を挿入
ここに画像の説明を挿入

3. 体験アドレス

  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_system。

4. 関連コード

void DeviceOnvif::receiveEvent(const QString &url, const OnvifEventInfo &event)
{
    
    
    //可能临时关闭了事件订阅
    if (!AppConfig::OnvifEvent) {
    
    
        return;
    }

    //事件内容存放在结构体数据中
    //qDebug() << TIMEMS << event;
    QString name = event.dataName;
    QVariant value = event.dataValue;

    //有多种关键字可以自行过滤需要的
    if (!eventName.contains(name)) {
    
    
        //对应收到的未知的报警可以自行根据厂家规则约定加到 config/event.txt 事件字典表中
        qDebug() << TIMEMS << "未知报警事件" << QtHelper::getIP(url) << name << value;
        return;
    } else {
    
    
        qDebug() << TIMEMS << "收到报警事件" << QtHelper::getIP(url) << name << value;
    }

    //过滤不在本系统中的设备发过来的报警
    int index = DbData::IpcInfo_OnvifAddr.indexOf(url);
    if (index < 0) {
    
    
        return;
    }

    //true/1 false/0 字符转成bool类型方便统一判断
    bool alarm = value.toBool();
    QString ipcName = DbData::IpcInfo_IpcName.at(index);
    int i = eventName.indexOf(name);
    QString info = (alarm ? eventAlarm.at(i) : eventNormal.at(i));

    //添加到信息栏
    QString msg = QString("%1%2").arg(ipcName).arg(info);
    DeviceHelper::addMsg(msg, alarm ? 2 : 0);

    //抓拍对应通道图像
    QString flag, fileName;
    if (alarm) {
    
    
        QString rtspMain = DbData::IpcInfo_RtspMain.at(index);
        QString rtspSub = DbData::IpcInfo_RtspSub.at(index);
        VideoWidget *videoWidget = VideoManage::Instance()->getVideoWidget(rtspMain, rtspSub);
        if (videoWidget) {
    
    
            flag = videoWidget->objectName();
            fileName = QString("%1/image_alarm/%2/%3_%4.jpg").arg(QtHelper::appPath()).arg(QDATE).arg(flag).arg(STRDATETIMEMS);
            videoWidget->snap(fileName);

            //放入队列线程处理(保证抓图完成)
            mutex.lock();
            listMsg << info;
            listFile << fileName;
            mutex.unlock();
        }
    }

    //右下角弹出提示
    if (AppConfig::TipInterval != 10000) {
    
    
        QtHelper::showTipBox("提示", msg, AppConfig::FullScreen, true, AppConfig::TipInterval);
    }

    //暂定开关量报警弹出报警视频并录像
    if (alarm && info == "开关量报警") {
    
    
        QString url = DbData::getRtspAddr(index);
        //弹出了报警视频则日志记录中优先存储报警录像文件的名称(直接用报警图片的路径以便统一)
        fileName.replace(".jpg", ".mp4");
        fileName.replace("image_alarm", "video_alarm");
        DeviceHelper::showVideo(url, flag, AppConfig::AlarmSaveTime, fileName);
    }

    //播放报警声音并插入到日志记录数据库(报警带上报警图片路径)
    if (alarm) {
    
    
        DeviceHelper::playAlarm("8.wav");
        DbQuery::addUserLog(flag.right(2), "报警日志", msg, fileName);
    } else {
    
    
        DeviceHelper::stopSound();
        DbQuery::addUserLog("报警日志", msg);
    }
}

#include "onvifevent.h"

OnvifEvent::OnvifEvent(QObject *parent) : QObject(parent)
{
    
    
    device = (OnvifDevice *)parent;

    //事件定时器请求事件地址
    timerEvent = new QTimer(this);
    connect(timerEvent, SIGNAL(timeout()), this, SLOT(getEvent()));
    timerEvent->setInterval(10 * 60 * 1000);

    //消息定时器请求事件内容
    timerMessage = new QTimer(this);
    connect(timerMessage, SIGNAL(timeout()), this, SLOT(pullMessage()));
    timerMessage->setInterval(1 * 60 * 1000);
}

void OnvifEvent::receiveEvent(const OnvifEventInfo &event)
{
    
    
    if (!event.dataName.isEmpty()) {
    
    
        emit receiveEvent(device->onvifAddr, event);
        //正确格式 2020-10-10T08:40:14Z|LogicalState>|1
        //过滤格式 2020-10-10T08:23:11.000000Z|State|true>
        if (event.time.length() != 20) {
    
    
            return;
        }
    }

    pullMessage();
}

QString OnvifEvent::getEvent(const QString &timeout)
{
    
    
    //读取文件传入带用户认证的通用头部数据和其他参数构建要发送的数据
    QString file = OnvifHelper::getFile(":/onvifsend/CreatePullPointSubscription.xml");
    file = file.arg(device->getHeadData()).arg(timeout);

    //发送网络请求
    QByteArray dataSend = file.toUtf8();
    QNetworkReply *reply = device->request->post(device->eventUrl, dataSend, OnvifRequest::timeout + 500);

    //拿到请求结果并处理数据
    QByteArray dataReceive;
    bool ok = device->checkData(reply, dataReceive, "订阅事件服务");
    if (ok) {
    
    
        //解析事件请求地址
        OnvifQuery query;
        if (query.setData(dataReceive)) {
    
    
            eventAddr = query.getEventAddr(device->addrPort);
            QTimer::singleShot(100, this, SLOT(pullMessage()));
        }
    }

    //启动事件定时器
    if (!timerEvent->isActive()) {
    
    
        timerEvent->start();
    }

    //启动消息定时器
    if (!timerMessage->isActive()) {
    
    
        //timerMessage->start();
    }

    return eventAddr;
}

void OnvifEvent::pullMessage(const QString &timeout)
{
    
    
    QMutexLocker locker(&mutex);
    if (eventAddr.isEmpty()) {
    
    
        return;
    }

    emit receiveInfo(QString("请求事件 -> %1").arg(eventAddr));

    //读取文件传入带用户认证的通用头部数据和其他参数构建要发送的数据
    QString uuid = OnvifHelper::getUuid();
    QString file = OnvifHelper::getFile(":/onvifsend/PullMessages.xml");
    file = file.arg(device->getUserToken()).arg(uuid).arg(eventAddr).arg(timeout);

    //发送网络请求
    QByteArray dataSend = file.toUtf8();
    device->request->post2(eventAddr, dataSend);
}

5. 特徴

5.1 ソフトウェアモジュール

  1. ビデオ監視モジュール、デバイス リスト、グラフィック アラーム情報、ウィンドウ情報、PTZ 制御、プリセット位置、クルーズ設定、デバイス制御、フローティング マップ、Web ブラウジングなどを含む、さまざまなドッキング小さなウィンドウ サブモジュール。
  2. ローカル再生、リモート再生、デバイス再生、画像再生、ビデオアップロードなどのビデオ再生モジュール。
  3. 写真地図、オンライン地図、オフライン地図、経路計画などを含む電子地図モジュール
  4. ローカル ログ、デバイス ログなどを含むログ クエリ モジュール。
  5. システム設定モジュール。システム設定 (基本設定、ビデオ パラメータ、データベース設定、マップ構成、シリアル ポート構成など)、ビデオ レコーダー管理、カメラ管理、ポーリング構成、録画計画、ユーザー管理などが含まれます。

5.2 基本機能

  1. さまざまなビデオ ストリーム (rtsp、rtmp、http など)、ビデオ ファイル (mp4、rmvb、avi など)、ローカル USB カメラ再生をサポートします。
  2. 1、4、6、8、9、13、16、25、36、64 画面切り替えを含むマルチ画面切り替えをサポートします。
  3. 全画面切り替え、マウスの右ボタン メニュー、ツールバー ボタン、ショートカット キー (Alt+Enter 全画面表示、ESC で全画面終了) などのさまざまな切り替え方法をサポートします。
  4. 1、4、9、16 画面ポーリングを含むビデオ ポーリングをサポートし、ポーリング グループ (ポーリング プラン)、ポーリング間隔、コード ストリーム タイプなどを設定できます。
  5. デバイス検索、PTZ 制御、プリセット位置、デバイス制御 (画像パラメータ、校正時間、システム再起動、スナップショット画像など) を含む onvif プロトコルをサポートします。
  6. 権限管理をサポートし、ログの削除、システムのシャットダウンなど、異なるユーザーが異なるモジュール権限に対応できます。
  7. sqlite、mysql、sqlserver、postgresql、oracle、Renda Jincang など、さまざまなデータベースがサポートされています。
  8. ローカル USB カメラは、解像度やフレーム レートなどのパラメータの設定をサポートしています。
  9. すべてのドッキング モジュールは、表示と非表示を制御するための対応するメニューを自動的に生成します。このメニューは、タイトル バーを右クリックするとポップアップ表示されます。
  10. すべてのモジュールの表示、すべてのモジュールの非表示、通常のレイアウトのリセット、全画面レイアウトのリセットをサポートします。
  11. デバイスをダブルクリックすると、イメージ マップ、オンライン マップ、オフライン マップなどをサポートするリアルタイム プレビュー ビデオがポップアップ表示されます。
  12. カメラ ノードを対応するウィンドウにドラッグしてビデオを再生し、ローカル ファイルのドラッグによる直接再生をサポートします。
  13. ビデオの削除は、マウスの右ボタンでの削除、サスペンションバーを閉じて削除、ビデオ監視パネルの外側にドラッグして削除など、複数の方法をサポートしています。
  14. 絵地図上のデバイスボタンは自由にドラッグでき、位置情報は自動保存されます。Baidu マップ上でマウスをクリックすると、デバイスの位置を更新するために使用される緯度と経度の情報を取得できます。
  15. ビデオ監視パネル ウィンドウ内のどのチャンネルもドラッグと切り替えをサポートしており、即座に応答します。
  16. Baidu マップ、ビューの切り替え、移動軌跡、装備ポイント、緯度と経度を取得するためのマウス押下などがカプセル化されています。
  17. ノードをダブルクリックしたり、ノードをドラッグしたり、ウィンドウをドラッグして位置を入れ替えたりするなどの操作を行うと、最後の再生アドレスが自動的に更新されて保存され、次回ソフトウェアを開いたときに自動的に適用されます。
  18. 右下隅にある音量バー コントロールはフォーカスを失い、自動的に非表示になり、音量バーにはミュート アイコンが表示されます。
  19. ビデオのスクリーンショットをサポートし、単一またはすべてのチャンネルのスクリーンショットを指定できます。また、下部の小さなツールバーにはスクリーンショット ボタンもあります。
  20. 時間外にマウスポインターを自動的に非表示にする、自動全画面メカニズムをサポートします。
  21. onvif PTZ コントロールをサポートし、リセットやフォーカス調整を含め、PTZ カメラを上下左右に移動できます。
  22. onvif プリセット位置をサポートし、プリセット位置を追加、削除、変更でき、開始位置を呼び出すことができます。
  23. 明るさ、コントラスト、彩度、シャープネスなどを含む onvif 画像パラメータ設定をサポートします。
  24. 画像キャプチャ、ネットワーク設定、時刻調整、再起動、イベントサブスクリプションなど、onvif のその他の操作をサポートします。
  25. Hikvision、Dahua、Uniview、Tiandiweiye、Huawei などを含むがこれらに限定されない、あらゆる onvif カメラをサポートします。
  26. ビデオは、オプションのタイミング ストレージまたは単一ファイル ストレージ、およびオプションのストレージ間隔で保存できます。
  27. ビデオストリームの通信モードtcp+udpを設定でき、ビデオのデコード速度優先、品質優先、バランスなどを設定できます。
  28. ソフトウェアの中国語名、英語名、ロゴアイコンなどを設定できます。
  29. 保存されたビデオ ファイルは、指定したディレクトリにエクスポートし、バッチでサーバーにアップロードできます。
  30. 完璧な録画プラン設定、各チャンネルをサポート 7 * 24 時間、30 分ごとに録画を保存するかどうかを設定します。

5.3 特徴

  1. メインインターフェイスはドッキングフォームモードを採用しており、さまざまなコンポーネントが小さなモジュールの形で追加され、任意のモジュールをカスタマイズして追加できます。
  2. ドッキング モジュールはどこにでもドラッグして埋め込んだりフローティングしたりでき、全画面および複数画面の最大化をサポートします。
  3. デュアルレイアウトファイルストレージメカニズム、通常モードと全画面モードは異なるレイアウトスキームに対応し、自動的に切り替えて保存します。たとえば、全画面モードでは複数のモジュールを強調表示し、指定された位置にそれらを透明に表示できます。これはよりSF的です。そして現代的。
  4. オリジナルの onvif プロトコル メカニズムは、基盤となるプロトコル分析 (udp ブロードキャスト検索 + http リクエスト実行コマンド) を採用しており、軽量で理解しやすく、学習と拡張が容易であり、gsoap などのサードパーティ コンポーネントに依存しません。
  5. オリジナルデータのインポート、エクスポート、印刷のメカニズムは、コンポーネントに依存せずにクロスプラットフォームで即座にデータをエクスポートします。
  6. データのインポートおよびエクスポート コンポーネント (XLS、PDF へのエクスポート、印刷)、データベース コンポーネント (データベース管理スレッド、自動クリーニング データ スレッド、ユニバーサル ページング、データ リクエストなど) を含む、複数の組み込みオリジナル コンポーネント。世界最高の価値があります。 、マップ コンポーネント、ビデオ モニタリング コンポーネント、マルチスレッド ファイル送受信コンポーネント、onvif 通信コンポーネント、共通ブラウザ カーネル コンポーネントなど。
  7. カスタム情報ボックス + エラーボックス + お問い合わせボックス + 右下のプロンプトボックス (複数の形式を含む) など。
  8. 絶妙なスキニング、最大17セットのスキンスタイルを自由に変更でき、メニューなども含めすべてのスタイルが統一されています。
  9. ビデオ コントロールのフローティング バーは単独で複数のボタンを追加でき、監視インターフェイスの下部にある小さなツールバーも単独でボタンを追加できます。
  10. カメラ ノードをダブルクリックするとビデオが自動的に再生され、ノードをダブルクリックするとビデオが順番に自動的に追加され、自動的に次のビデオにジャンプします。親ノードをダブルクリックすると、ノードの下にすべてのビデオが自動的に追加されます。オプションのメインストリームとサブストリーム。
  11. ビデオレコーダー管理、カメラ管理では、情報の追加、削除、変更、インポート、エクスポート、印刷が可能で、再起動せずに新しいデバイス情報を即座に適用してツリーリストを生成します。
  12. さまざまなカーネルを選択して自由に切り替えることができ、ffmpeg、vlc、mpv などを pro に設定できます。最もクロスプラットフォームである ffmpeg を使用することをお勧めします。Linux および Mac プラットフォームでコンパイルされたライブラリがデフォルトで提供されます。
  13. ハード デコードをサポートし、ハード デコード タイプ (qsv、dxva2、d3d11va など) を設定できます。
  14. デフォルトでは、opengl がビデオの描画に使用され、CPU リソースの使用量が非常に低く、yuyv と nv12 の 2 つの描画形式をサポートし、パフォーマンスは爆発的です。
  15. ラベルとグラフィック情報は、マスク レイヤへの描画、ピクチャへの描画、ソースからの描画 (対応する情報はファイルに保存可能) の 3 つの描画方法をサポートしています。
  16. 高度にカスタマイズ可能で、ユーザーはこれに基づいて、カスタムモジュールの追加、動作モードの追加、ロボット監視、ドローン監視、掘削機監視などの独自の機能を簡単に派生できます。
  17. xp、win7、win10、win11、linux、mac、各種国内システム(UOS、Winning Kirin、Galaxy Kirinなど)、組み込みLinuxおよびその他のシステムをサポートします。
  18. コメントは完全で、プロジェクト構造は明確で、非常に詳細で完全なユーザー開発マニュアルは各コード ファイルの機能説明に正確であり、バージョンは継続的に反復されています。

Guess you like

Origin blog.csdn.net/feiyangqingyun/article/details/132595639