谷歌無插件實時預覽海康攝像頭


之前使用的海康的前端開發包,利用插件進行視頻預覽,但是谷歌下面目前不支持插件,所以只能另尋他路。

技術方案

平台為Ubuntu+nginx,利用nginx的代理將web通訊轉發給webserver,通訊利用websocket通訊。server端以libevent為基礎,構建reactor模式服務器,這樣可以大量接入連接。前端采用streamedian,這是開源的,他采用init,join兩個數據通道。

nginx配置如下

nginx配置轉發如下

location / {
        proxy_pass http://127.0.0.1:9004;
		#proxy_pass http://172.16.10.4:49240/ws;
		proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
		
		
        #proxy_redirect              off;
        #proxy_set_header            Host $host;
        #proxy_set_header            X-Real-IP $remote_addr;
        #proxy_read_timeout          3600s;
        #proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
       
    }

  

reactor模型

reactor模型主要是針對libevent的單線程單進程模式,所有的連接都設置成非租塞模式,通過不停地監聽數據的寫入,然后進行分類處理,監聽結構配置如下:

 

 

flags = fcntl(rfd->fd, F_GETFL);
flags |= O_NONBLOCK;
 fcntl(rfd->fd, F_SETFL, flags);

 

配置成非阻塞是因為libevent全部是輪詢,效率高,阻塞會影響到整體效率,但會有個問題,導致connect的時候會出現連接不上,需要采用以下方式:

if(ret == -1 && (REACTOR_InProgress || REACTOR_WOULDBLOCK))
    {
        debug("ACT:need check\r\n");
        rfd = setfd(base,fd,type_CONNECT,app,arg);;
        if(rfd != NULL)
        {
            return rfd;
        }
    }
if(    type != type_LISTEN){
        evWrite = event_new(rfd->base, rfd->fd, EV_WRITE,_canWrite,rfd);
        timeout.tv_sec = 5;
        timeout.tv_usec = 0;
        flags = event_add(evWrite,&timeout );//&timeout//只要是可寫的,write觸發了的,就是正常連接
        rfd->evWrite = evWrite;
    }    

觸發一個寫的動作,並加上時間限制為5秒,這樣寫成功了,就連接成功了,如果返回超時信號,就沒有連接成功。

 

websocket協議的解析

1.發送GET數據包,由client發起連接,其中會包含contrl命令,和sharekey(Sec-WebSocket-Protocol: control),建立INIT通道。
2.接收到包后添加control控制口令,和sharekey發送回client,
以上是websocket的套路,按規矩來就行了,接下來的就是streamedian的套路了
3.client發送cam的ip和port,由於用了掩碼加密,需要解密
4.攝像頭可以連接后,服務端發送wsp OK的數據包給服務端,同時還需要隨機生成一個channel,此處我是用的SHA1加密的客戶端和端口。
5.此時client會再次發起連接,此時建立數據JOIN通道。(Sec-WebSocket-Protocol: data),完成連接后發送wspOK。
6.建立連接完成后,client發送RTSP 指令,server收到后透明轉發給攝像頭,充當中間件的角色,這些交互都在INIT通道完成,最終攝像頭發送rtp數據包給server,server通過join通道將rtp包發送給web頁面。

rtp包的轉發

rtp包的包頭為“$”,接着為0x00,然后是兩位數據的包的長度,可以根據包的長度來尋找下一個包的幀頭,由於數據包可能會出現粘包,所以接收采用窗口接收的方式的來進行,保證每次接收的數據粘連在窗口的tail上,解析完了之后從head進行數據的釋放。

 

源代碼地址:

https://github.com/hpwang666/liveRtsp.git

測試效果

搜狗瀏覽器,谷歌瀏覽器(版本 75.0.3770.142(正式版本) (64 位))均可流暢查看。測試時間1個小時。

測試方式:首先運行./wsServer  ,他會監聽9004端口,之前的nginx配置已經將視頻請求信息轉發給了9004端口

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM