國标GB28181對接視訊流
今天抽空寫下以GB28181的方式擷取錄影機視訊流以備後用,同時也希望能幫助到正着手開發GB28181對接視訊的同學,這塊的資料實在不多。
今天講的内容不涉及到平台對接,平台對接下次有時間再講,平台對接相對更麻煩點。通過GB28181擷取錄影機視訊流,首先需要錄影機支援GB28181
,如何知道錄影機是否支援GB28181協定呢?請看下圖:
圖1.錄影機28181協定配置圖
圖1 展示了海康錄影機配置GB28181頁面,其他廠家錄影機GB28181配置頁面(我遇到的)基本跟海康配置的頁面相同。
下面介紹下各配置項基本意義:
本地端口:預設為5060,SIP服務發送指令給錄影機時需要知道錄影機GB28181端口号,要不向哪發?
SIP伺服器ID:說簡單就是 伺服器的辨別,隻不過這個辨別有一定的要求,具體請參見28181-2001标準安全防範視訊監控聯網系統資訊傳輸交換控制技術要求.pdf
當然也可以參考新點的文檔,新舊文檔這部分差異不大。文檔在從群裡下載下傳。
SIP服務域:實際就是SIP伺服器ID前10位。
SIP伺服器位址:SIP服務所在機器的IP位址(如果存在多網卡建議将不用的網卡禁用掉)。
SIP伺服器端口:SIP服務Port,其他SIP服務發送指令到此端口與之通信。
其他的配置預設即可。
GB28181配置好以後,需要啟動錄影機GB28181服務。
啟動錄影機GB28181的方法是勾選“啟用”選項,啟動成功後,錄影機會向SIP Server發送注冊消息,通過抓包可以看到具體的注冊消息内容:
圖2 錄影機發送注冊消息圖
看下注冊消息的具體内容:
圖3 具體注冊消息圖
重要是Cantact資訊,包含了錄影機GB28181 SIP ID 以及IP位址和端口号,這樣與錄影機通信的SIP服務就知道往哪裡回應答消息。
錄影機端基本介紹了完了(錄影機端相當于SIP Client),下面 介紹CG28181 服務端也即 SIP Server,這正是我們要實作的。
實作CG28181服務端可以借助于現有的開源庫 PJSIP,自己實作開發量還是很大的,具體的實作步驟如下:
一. 将PJSIP運作起來,畢竟人家是一個服務。隻有運作以後才能接收用戶端發來的消息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
以上是PJSip初始化的代碼,需要将服務将要監聽的端口傳給PJSIP,這樣服務就在監聽的端口接收SIP 消息了。
二. 應答注冊消息
錄影機端發送來Register消息後,如果服務端不應答,錄影機端會一直發送直到收到服務端應答為止。如果伺服器端重新運作,需要手動再次
開啟錄影機,如果等錄影機自己再次發送注冊消息可能是一個小時以後,我們當然不希望那麼久。
服務端應答注冊消息代碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
1 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | |
OnReceive方法内Resonse方法實作了發送響應資料到用戶端(錄影機):
void Response(pjsip_rx_data* rdata, int st_code,int headType)
{
std::lock_guard<mutex> lk(lock);
pjsip_tx_data* tdata;
pjsip_endpt_create_response(endPoint, rdata, st_code, nullptr, &tdata);
auto date = DateTimeFormatter::format(LocalDateTime(), "%Y-%m-%dT%H:%M:%S");
pj_str_t c;
pj_str_t key;
pjsip_hdr *hdr;
switch(headType)
{
case DateHead:
key = pj_str("Date");
hdr = reinterpret_cast<pjsip_hdr*>(pjsip_date_hdr_create(pool, &key, pj_cstr(&c, date.c_str())));
pjsip_msg_add_hdr(tdata->msg, hdr);
break;
case AuthenHead:
pjsip_auth_srv_challenge(&authentication, nullptr, nullptr, nullptr, PJ_FALSE, tdata);
break;
default:
break;
}
pjsip_response_addr addr;
pjsip_get_response_addr(pool, rdata, &addr);
pjsip_endpt_send_response(endPoint, &addr, tdata, nullptr, nullptr);
}
實際也就是利用發PJSIP發送一些字元串給用戶端。具體發送了些什麼,可以抓個包看下。
圖4 SIP服務應答注冊消息
SIP 服務實際回了“200 OK” 給錄影機端。看下具體的消息内容:
圖5 “200 OK” 具體内容
SIP服務端響應注冊指令後,發送Invite請求,請求catalog資訊,也就是裝置基本資訊,具體的方法上面已
給出,具體的内容是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
SIP服務端 發送了請求catalog 消息,錄影機端收到消息發送其自身的catalog消息,SIP 服務端将在OnReceive中收到具體的catalog消息。取catalog消息的方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | |
SIP服務取都錄影機的資訊後就可以發送請求視訊資訊了,請求視訊最為關鍵的是SDP,下面看下SDP資訊如何填寫:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
發送請求視訊指令到錄影機端當然也是通過PJSIP API實作代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
代碼就不解釋了,要想知道到底發了什麼還是抓個包看看,無論你用什麼方法隻要抓包的資料是正确定說明發送成功了。
圖6 服務端發送invite視訊消息
錄影機端收到Invite請求後,會将視訊資料以rtp的方式推送到指定的端口,端口在invite消息指定。
這樣在指定的位址(ip + port)就可以拿到資料了。
最後提供一個測試demo,demo的作用是可以讓大家抓包,看看雙方都發了些什麼。
demo運作界面如下:
圖6 demo運作初始界面
1.運作demo後,首先配置好配置,如果不知道可以預設,但IP位址需要修改,端口不能被占用。
2.完成配置各配置項以後點選擷取視訊源按鈕 等待錄影機端注冊。
3.錄影機端開啟28181功能:具體的方法可以是:平台選擇方式下拉框先選擇一個非28181方式,點選儲存,再選擇28181方式并點選儲存。
4.錄影機端成功開啟28181功能以後,視訊源下拉框中會顯示錄影機的名稱資訊。
5.選中視訊源下拉框中出現的選項并點選播放按鈕,正常情況下會可以播放從錄影機端過來的視訊流。
成功接入視訊源并播放的運作界面如下。
圖7 demo成功運作以後的界面
Demo 可以在群裡下載下傳。
如需交流,可以加QQ群1038388075,766718184,或者QQ:350197870
視訊教程 播放位址: https://space.bilibili.com/241181578/
視訊下載下傳位址:http://www.chungen90.com/?news_33/
Demo下載下傳位址: http://www.chungen90.com/?news_34