一、前言
之前用onvif已經完美實現了設備的云臺控制和預置位的功能,這個基礎功能在監控系統中是使用頻率很高的,所有gb28181肯定也提供了這樣的功能,很多人以為是通過包含xml數據,對應節點指定對應的動作來實現,其實不是的,是類似于早期模擬設備的云臺的串口協議中的控制指令,16進制格式的數據,一個個字節表示對應的含義,這個在國標文檔中寫的非常的詳細,按照那個規則來肯定錯不了,上下左右移動有個字節位是固定的數據,所以程序這邊只需要根據要操作的動作填充對應位的數據即可。
和云臺控制一起的還有鏡頭放大縮小、光圈放大縮小、鏡頭聚焦和放焦,這些也都是一樣的規則,奇怪的是,預置位的添加刪除修改調用也都是這個規則,之前還以為是單獨的xml格式的數據或者指令。不過遺憾的是預置位的信息并不支持名稱的修改,而onvif那邊是可以的,有時候希望給預置位改成一個中文的名字方便調用查閱等,不知道后續的國標協議會不會增加進去,個人覺得還是要支持比較好。
//云臺控制:服務端-》設備端
MESSAGE sip:34020000001320000002@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK801c1bb8b2234e2e94be74f0087e28f5
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1022
To: <sip:34020000001320000002@192.168.0.64:5060>
Call-ID: 6822f48163704effb5b58d7031eba9f4
CSeq: 23 MESSAGE
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 251
Content-Type: application/MANSCDP+xml
Contact: <sip:34020000002000000001@192.168.0.110:15060><?xml version="1.0" encoding="GB2312"?>
<Control><CmdType>DeviceControl</CmdType><SN>10022</SN><DeviceID>34020000001310000001</DeviceID><PTZCmd>A50F01029600004D</PTZCmd><Info><ControlPriority>5</ControlPriority></Info>
</Control>//控制應答:設備端-》服務端
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK801c1bb8b2234e2e94be74f0087e28f5
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1022
To: <sip:34020000001320000002@192.168.0.64:5060>;tag=1060605518
Call-ID: 6822f48163704effb5b58d7031eba9f4
CSeq: 23 MESSAGE
User-Agent: IP Camera
Content-Length: 0//停止云臺:服務端-》設備端
MESSAGE sip:34020000001320000002@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK3cb5f960d94549888269c12f4ed29c9e
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1023
To: <sip:34020000001320000002@192.168.0.64:5060>
Call-ID: f3124084767d48909decda7579e3f96b
CSeq: 24 MESSAGE
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 251
Content-Type: application/MANSCDP+xml
Contact: <sip:34020000002000000001@192.168.0.110:15060><?xml version="1.0" encoding="GB2312"?>
<Control><CmdType>DeviceControl</CmdType><SN>10023</SN><DeviceID>34020000001310000001</DeviceID><PTZCmd>A50F0100000000B5</PTZCmd><Info><ControlPriority>5</ControlPriority></Info>
</Control>//停止應答:設備端-》服務端
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK3cb5f960d94549888269c12f4ed29c9e
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1023
To: <sip:34020000001320000002@192.168.0.64:5060>;tag=1071996623
Call-ID: f3124084767d48909decda7579e3f96b
CSeq: 24 MESSAGE
User-Agent: IP Camera
Content-Length: 0//查詢預置位:服務端-》設備端
MESSAGE sip:34020000001320000002@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK5f11d64dadd7466cb06011e8971b788d
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1024
To: <sip:34020000001320000002@192.168.0.64:5060>
Call-ID: aac3afc576894717a72ed58030479bcb
CSeq: 25 MESSAGE
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 155
Content-Type: application/MANSCDP+xml
Contact: <sip:34020000002000000001@192.168.0.110:15060><?xml version="1.0" encoding="GB2312"?>
<Query><CmdType>PresetQuery</CmdType><SN>10024</SN><DeviceID>34020000001310000001</DeviceID>
</Query>//返回預置位:設備端-》服務端
MESSAGE sip:34020000002000000001@3402000000 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.64:5060;rport;branch=z9hG4bK1149716366
From: <sip:34020000001320000002@3402000000>;tag=2001348774
To: <sip:34020000002000000001@3402000000>
Call-ID: 360379917
CSeq: 20 MESSAGE
Content-Type: Application/MANSCDP+xml
Max-Forwards: 70
User-Agent: IP Camera
Content-Length: 258<?xml version="1.0" encoding="GB2312"?>
<Response>
<CmdType>PresetQuery</CmdType>
<SN>10024</SN>
<DeviceID>34020000001310000001</DeviceID>
<PresetList Num="1">
<Item>
<PresetID>1</PresetID>
<PresetName>預置點 1</PresetName>
</Item>
</PresetList>
</Response>//添加預置位:服務端-》設備端
MESSAGE sip:34020000001320000002@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK76caaff468eb43ca9818e6fb38cfd057
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1025
To: <sip:34020000001320000002@192.168.0.64:5060>
Call-ID: a01a7be3ba6b4214ac0755d92d0096c5
CSeq: 26 MESSAGE
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 251
Content-Type: application/MANSCDP+xml
Contact: <sip:34020000002000000001@192.168.0.110:15060><?xml version="1.0" encoding="GB2312"?>
<Control><CmdType>DeviceControl</CmdType><SN>10025</SN><DeviceID>34020000001310000001</DeviceID><PTZCmd>A50F018100020038</PTZCmd><Info><ControlPriority>5</ControlPriority></Info>
</Control>//刪除預置位:服務端-》設備端
MESSAGE sip:34020000001320000002@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK9259fa44edce4797a69c4c58aa408d2c
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1027
To: <sip:34020000001320000002@192.168.0.64:5060>
Call-ID: 1bc5c4f7629b436ca66865c112ba2d47
CSeq: 28 MESSAGE
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 251
Content-Type: application/MANSCDP+xml
Contact: <sip:34020000002000000001@192.168.0.110:15060><?xml version="1.0" encoding="GB2312"?>
<Control><CmdType>DeviceControl</CmdType><SN>10027</SN><DeviceID>34020000001310000001</DeviceID><PTZCmd>A50F01830002003A</PTZCmd><Info><ControlPriority>5</ControlPriority></Info>
</Control>//修改預置位:服務端-》設備端
MESSAGE sip:34020000001320000002@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bKb968612c929f488bb3f105b907a61eba
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1031
To: <sip:34020000001320000002@192.168.0.64:5060>
Call-ID: 37bfa9cea6564707af579159d662db4a
CSeq: 32 MESSAGE
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 251
Content-Type: application/MANSCDP+xml
Contact: <sip:34020000002000000001@192.168.0.110:15060><?xml version="1.0" encoding="GB2312"?>
<Control><CmdType>DeviceControl</CmdType><SN>10031</SN><DeviceID>34020000001310000001</DeviceID><PTZCmd>A50F018100020038</PTZCmd><Info><ControlPriority>5</ControlPriority></Info>
</Control>//調用預置位:服務端-》設備端
MESSAGE sip:34020000001320000002@192.168.0.64:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.110:15060;branch=z3hG9bK3a2b16dffa134a25ad7158ef07ad8b07
From: <sip:34020000002000000001@192.168.0.110:15060>;tag=1032
To: <sip:34020000001320000002@192.168.0.64:5060>
Call-ID: 22431fe05dec47cbb789617b38caef58
CSeq: 33 MESSAGE
User-Agent: wx_feiyangqingyun
Max-Forwards: 70
Content-Length: 251
Content-Type: application/MANSCDP+xml
Contact: <sip:34020000002000000001@192.168.0.110:15060><?xml version="1.0" encoding="GB2312"?>
<Control><CmdType>DeviceControl</CmdType><SN>10032</SN><DeviceID>34020000001310000001</DeviceID><PTZCmd>A50F018200020039</PTZCmd><Info><ControlPriority>5</ControlPriority></Info>
</Control>
二、效果圖
三、相關地址
- 國內站點:https://gitee.com/feiyangqingyun
- 國際站點:https://github.com/feiyangqingyun
- 個人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
- 文件地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取碼:01jf 文件名:bin_video_gb28181。
四、功能特點
- 支持設備注冊、注銷、心跳、校時、注冊認證、注銷認證等。
- 設備上線后可以手動獲取設備狀態、設備信息、配置信息、預置位信息等。
- 設備上線后自動獲取設備通道信息,包括中文通道名稱。識別到通道上線離線變化,會重新獲取該設備的所有通道信息。
- 支持視頻點播,可以分別點播主碼流和子碼流,內置rtp解包線程,解包后發給視頻播放組件解碼播放。
- 每個設備每個通道支持點播多個視頻,通過ssrc區分,支持共用端口和不同端口收流。
- 支持對某個設備下面所有通道、某個通道、某個通道對應的某個流分別關閉。
- 支持錄像文件查詢和回放,回放控制支持暫停播放、繼續播放、倍速播放、切換播放進度。
- 支持錄像文件下載,支持倍速比如8倍速下載,可同時多線程批量下載。
- 回放和下載同時支持IPC和NVR,比如攝像頭自帶的SD存儲卡錄像文件回放,NVR上的硬盤錄像文件回放。
- 支持云臺控制,向上、向下、向左、向右、左上、右上、左下、右下方位移動,鏡頭放大縮小,光圈放大縮小,鏡頭聚焦放焦。
- 支持預置位信息的查詢、調用、添加、修改、刪除等操作。
- 自動目錄訂閱功能,通道上線下線都有對應的信號通知。
- 內置定時讀取通道信息機制,以保證通道信息是最新的,比如有些NVR是不斷更新的通道信息。
- 支持警情訂閱,各種警情事件比如運動目標檢測報警、入侵檢測報警、徘徊檢測報警等自動上報。
- 國標服務同時支持udp和tcp方式,可選只監聽一種或者兩種都監聽,tcp方式自動處理粘包問題。
- 國標拉流同時支持udp、tcp被動、tcp主動三種方式,每個通道都可以自由選擇何種拉流方式。
- 內置拉流端口池,每次拉流從中取出一個,關閉流自動回收端口號,重復利用。
- 收流端口自動糾錯,自動跳過被占用的端口,不會出現端口占用導致收流失敗的情況。
- 視頻播放自適應硬解碼,極低資源占用,實時性極好,帶懸浮條顯示視頻流信息,可以直接在懸浮條單擊按鈕保存錄像文件到本地。
- 支持幾千路國標消息交互并發,實時視頻流支持64路同時顯示,可以拓展更多路數。
- 支持阿里云等云服務器,可以分別設置內網監聽地址和外網訪問地址,一般云服務器上是監聽地址用內網,對外訪問用外網地址。
- 支持視頻分發,也就是推流,視頻通道打開后可以自動推流到流媒體服務器,其他需要的地方拉流即可,支持rtsp、rtmp、hls、webrtc等方式拉流。
- 同時支持gb28181-2011、gb28181-2016、gb28181-2022以及后續可能的所有協議版本。
- SIP解析和交互采用純Qt底層代碼實現,udp/tcp通信交互,祖傳原創代碼解析,不依賴任何第三方。
- 代碼量少,gb28181交互部分共幾千行代碼,注釋詳細,接口友好,使用極其簡單,提供非常詳細的使用示例。
- 支持海康、大華、宇視、華為、天地偉業等所有國標設備。
- 支持所有Qt版本和編譯器以及操作系統,包括但不限于win、linux、mac、android、嵌入式linux、樹莓派香橙派、國產os等。
五、相關代碼
//具體格式規范在gb28181-2016文檔的第79頁
//預置位和巡航等操作也是屬于云臺部分/速度參數就對應的預置位編號
QString GB28181Body::getPtzCmd(PtzType ptzType, quint8 ptzSpeed)
{//協議固定數據格式QByteArray data;data.append(0xA5);data.append(0x0F);data.append(0x01);data.append((char)0x00);data.append((char)0x00);data.append((char)0x00);data.append((char)0x00);data.append((char)0x00);//不同動作填充對應數據/下面的與運算是為了防止數據越界if (ptzType == PtzType_Right) {data[3] = 0x01;data[4] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_RightUp) {data[3] = 0x09;data[4] = ptzSpeed & 0xFF;data[5] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_Up) {data[3] = 0x08;data[5] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_LeftUp) {data[3] = 0x0A;data[4] = ptzSpeed & 0xFF;data[5] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_Left) {data[3] = 0x02;data[4] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_LeftDown) {data[3] = 0x06;data[4] = ptzSpeed & 0xFF;data[5] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_Down) {data[3] = 0x04;data[5] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_RightDown) {data[3] = 0x05;data[4] = ptzSpeed & 0xFF;data[5] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_ZoomIn) {data[3] = 0x10;data[6] = (ptzSpeed & 0x0F) << 4;} else if (ptzType == PtzType_ZoomOut) {data[3] = 0x20;data[6] = (ptzSpeed & 0x0F) << 4;} else if (ptzType == PtzType_IrisIn) {data[3] = 0x44;data[5] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_IrisOut) {data[3] = 0x48;data[5] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_FocusIn) {data[3] = 0x41;data[4] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_FocusOut) {data[3] = 0x42;data[4] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_AddPreset) {data[3] = 0x81;data[5] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_SetPreset) {data[3] = 0x82;data[5] = ptzSpeed & 0xFF;} else if (ptzType == PtzType_DelPreset) {data[3] = 0x83;data[5] = ptzSpeed & 0xFF;}//末尾字節是前面字節加起來int end = 0;int count = data.size();for (int i = 0; i < count - 1; ++i) {end += data.at(i);}data[7] = end;return QString(data.toHex()).toUpper();
}