日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

利用VC++实现局域网实时传输

發布時間:2023/12/10 c/c++ 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用VC++实现局域网实时传输 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文針對不同的局域網,提出一種通用的實時視頻傳輸的解決方案。在使用Divx編解碼的基礎上,提出了從壓縮、組幀、發送到接收、解壓整個流程的思想,具體實施方案和VC++實現核心源代碼以及傳輸控制策略,有效地保證了高質量的實時視頻傳輸。

關鍵詞客戶/服務器;實時視頻傳輸;Divx

引言

在局域網內部實時傳輸視頻已經得到廣泛應用。現在用以傳輸視頻的局域網大多數是有線局域網,因為有線局域網技術成熟,傳輸速度快,穩定性好。但是視頻數據量大,有線網絡也會出現工作不穩定,引起數據堵塞,時間久了會導致嚴重的延遲現象;如果工作的環境不固定,要求移動性,那么就要采用無線網絡,如今無線網卡的工作隨環境的變化而變得不穩定,這樣會導致視頻傳輸的質量大幅度下降,容易引起畫面的重影、抖動、花屏等現象。本文針對不同的局域網,提出一種通用的實時視頻傳輸的解決方案,使用VC++自封裝的WindowsVFWSDK軟件開發包進行二次開發,通過Divx編解碼,按照制定的傳輸策略,能夠有效地解決由于網絡的局部不穩定導致的視頻圖像重影、抖動、花屏等的問題。

局域網中實時視頻傳輸存在的問題

為了在局域網上有效的、高質量的傳輸視頻流,需要多種技術的支持,包括視頻的壓縮、編碼技術,應用層質量控制技術等等。

網絡的帶寬是有限的,所以需要壓縮傳輸視頻圖像,MPEG-4被廣泛的應用于網絡環境下的實時視頻傳輸,因為MPEG-4具有:可以達到很高的壓縮比;具有靈活的編碼和解碼復雜性;基于對象的編碼方式,允許視頻、音頻對象的交互;具有很強的容錯能力等優點。本文采用Divx編解碼器對視頻進行編碼、壓縮,實際上Divx=(視頻)MPEG-4+(音頻)MP3。

應用層質量控制技術現在采用的是RTP/RTCP協議,以確保視頻流在網絡中低時延、高質量地傳輸。RTP數據傳輸協議負責音視頻數據的流化和負載,RTCP負責RTP數據報文的傳輸控制。此協議是通過客戶端(接收方)反饋網絡的狀況,服務器端(發送方)來調整信息采集、發送的速度和壓縮率。但是,對于圖像采集速度固定,需要軟件進行壓縮、解壓,調整采集的速度會引起采集的數據來不及壓縮而直接丟棄,調整編碼器的壓縮率需要重新設置編碼器的參數,重啟編碼器,相應的解碼器也要調整,這個過程中需要很長的時間,達不到實時的要求。所以本文沒有采用RTP/RTCP協議,而是從發送端出發,實時判斷網絡狀況,采用“停等”策略進行實時傳輸。

網絡通信有兩種協議TCP和UDP,UDP更適合于網絡環境下的視頻傳輸,但是它不提供檢錯和糾錯功能,一旦網絡出現堵塞時,大量的數據報文會丟失。對于Divx編解碼技術,是以幀為單位進行編解碼的,分為關鍵幀和非關鍵幀。在傳輸過程中,由于壓縮率比較高,只要一幀中錯一比特位,將影響其它幾百甚至幾千的比特位,直接造成圖像的模糊、花屏等現象。只有等到下一次關鍵幀的到來才有可能恢復圖像的清晰。為了保證傳輸的正確性,自己需要在應用層制定協議。如此一來,UDP的優勢蕩然無存。所以本文選擇使用TCP來進行網絡通信。綜合使用VFW技術、流媒體技術,輔助以“停等”控制策略,較好的解決局域網中實時視頻傳輸容易引起的重影、抖動、花屏的問題。

實時視頻傳輸實現

為了達到視頻傳輸的實時性,總的思想是最少的發送冗余信息,最大程度上發送最新的視頻。

局域網實時視頻傳輸采用服務器/客戶機模式,利用VC++實現。其工作流程如圖1所示。

視頻采集采用AVICap從視頻采集卡捕獲視頻圖像,得到的是位圖型式的視頻幀,然后用Divx編碼器進行壓縮,通過Winsock實現壓縮后的視頻數據在局域網中的實時傳輸,接收完的數據交給Divx解碼器解壓,最后實現視頻顯示。

在VC++中,采用VFW技術,客戶端通過capSetCallbackOnFrame()注冊回調函數,當采集卡采集到一幅圖像后,系統就會自動調用回調函數,然后再回調函數中使用ICSeqCompressFrame()函數進行壓縮。然后再通過Winsock將壓縮后的數據發送到服務器端。服務器端接收完一幀以后,交給ICDecompress()解壓,最后用SetDIBitsToDevice()將圖像顯示出來。

1、視頻幀的組建

視頻采集的數據是位圖型式的視頻幀,Divx編碼器壓縮以后形成以幀為格式的Mpeg4流。Divx解碼器也是以幀的格式解壓。所以提出以幀為單位發送視頻數據流。為了在接收端能夠方便地提取出一幀,提出如所示的格式組建幀。

幀開始標志

幀大小

幀編號

幀類型

幀數據

視頻幀格式

完整的一幀由5個字段組成,各個字段的意義幀開始標志,標志著一幀地開始,占用4個字節的空間。不妨設為0xffffffff。幀大小,表示整個幀的大小,包括5個字段的大小,占用4個字節的空間。幀編號,表示幀的順序編號,占用4個字節的空間。幀類型,標志此幀是否是關鍵幀,占用1個字節的空間。幀數據,存放壓縮后一幀的完整數據。

2、視頻幀的發送

實時視頻傳輸為了實時,要不斷地將壓縮好的數據發送到接受端。所以在發送端創建一個線程,專門用來發送數據。同時主線程仍然不停的采集數據并進行壓縮。發送線程的工作流程如圖3所示。

不妨假設創建的線程名為sendThread,核心代碼實現

while(1)

{

isOK=true;//準備就緒

SuspendThread(sendThread);//掛起線程

isOK=false;//線程正在發送數據

intlength=frameLength;//待發數據長度

if(length<50000){//判斷數據是否正常

intn=0;

intsendCount=0;

while(length>0){

n=send(sock,(char*)imageBuf+sendCount,length,0);//發送數據,

//imageBuf是指針,指向待發數據幀

if(n==SOCKET_ERROR)//網絡出現異常,則退出線程

break;

length-=n;

sendCount+=n;

}

}

}

線程中發送的數據幀是按照上一節中的方法組建好的數據幀。這種方法能夠保證正在發送的當前幀能夠完整地到達接收端。

注意此線程中剛開始或者每當發送完一幀以后,線程就轉到掛起狀態,等待外界喚醒。這個任務由回調函數完成,在回調函數中,判定如果發送線程準備就緒(處于掛起狀態),則進行圖像壓縮,然后喚醒線程發送壓縮完的數據,否則直接跳出,等待下一次調用回調函數,這種策略稱之為“停等”策略,在后面有詳細介紹。

3、視頻幀的接收

接收端最重要的是從接受的數據流中提取出完整的一幀。方法的思想是:首先從數據流中尋找幀開始標志,再從緊挨后面的數據中提取出幀的大小,然后再從接收緩沖區中讀入該幀剩余的數據。再尋找下一幀的開始標志,如此往復。圖4是接收端的工作流程。

同樣接收端創建一個線程專門用來執行數據接收。不妨假設線程名為recThread,核心代碼實現

while(temp!=SOCKET_ERROR)

{

if(!isStart){//幀數據是否開始,true表示開始

if(endNum>3)//endNum紀錄當前接收未處理的數據

endNum=0;

temp=recv(clisock,(char*)(recBuf+endNum),1000,0);//從緩沖區讀取數據

startPos=serchStr(temp+endNum);//查找幀開始標志

if(startPos!=-1){

isStart=true;

endNum=temp+endNum-startPos-4;

memcpy(imageBuf,recBuf+startPos+4,endNum);//保存幀數據

}

else{

memcpy(recBuf,recBuf+temp+endNum-3,3);//保存最后三個字節的數據

endNum=3;

}

}

else{

if(endNum<4){//判定緊跟開始標志的數據,如果小于4表示不能獲得幀大小

temp=recv(clisock,(char*)(recBuf),1000,0);//讀入數據

memcpy(imageBuf+endNum,recBuf,temp);//保存數據

endNum+=temp;

if(endNum<4)

continue;

frameSize=*((int*)imageBuf);//獲得幀大小

if(frameSize<500frameSize>50000){//異常處理(幀大小非法)

isStart=false;//丟棄數據重新查找幀開始標志

endNum=0;

continue;

}

frameSize-=endNum+4;

}

else{

while(frameSize>0&&temp!=SOCKET_ERROR){//獲得完整幀的剩余數據

temp=recv(clisock,(char*)(imageBuf+endNum),frameSize,0);

endNum+=temp;

frameSize-=temp;

}

if(frameSize<=0){//幀結束置位,解壓

isStart=false;

endNum=0;

deCompress();//判斷數據的有效性,調用ICDecompress進行解壓

}

}

}

}

以上程序執行的結果是將完整的一幀(除幀開始標志)保存在imageBuf中。

4、“停等”控制策略

如果局域網通信速率很高,而且工作穩定,則按照以上說的方法進行實時視頻傳輸,不需要任何控制策略,就可以達到非常好的效果。但是在很多情況下,網絡會出現異常,這樣會導致數據傳輸率明顯下降,造成發送端數據積壓,等待發送的數據不能正常發出去。此時就要采取一定的策略來控制發送端,以達到實時性的要求。

上文發送程序中,變量isOK是用來表示發送端當前幀有沒有發完,如果發完則置為true,同時也表示發送端準備就緒,可以繼續發送數據,否則為false。那么可以用isOK來通知視頻采集和壓縮線程,如果isOK為true,則可以采集視頻并且壓縮,然后喚醒發送線程繼續發送新來的幀數據,否則一直等待,直到網絡可以繼續發送數據(isOK為true)。當然,視頻采集一直不停的進行,那么當網絡發生數據堵塞時,只要不讓編碼器進行壓縮則可解決;當網絡恢復正常時,繼續進行壓縮傳輸,換句話說,當網絡發生堵塞時,直接拋棄等待發送的幀,保證一旦網絡恢復時,發送最新的壓縮幀。當然要保證一旦有一幀開始發送,就要將其完全發出。

按照這樣的“停等”策略進行實時視頻傳輸,只會帶來一個問題:當網絡質量差時,接收端畫面中的移動目標會出現瞬間移動的現象。但是這種策略會保證不會出現重影,抖動,花屏等現象。

結論

提出的實時視頻傳輸方案在100M的局域網、10M局域網和11M無線局域網中進行了測試。測試時讓一個目標在鏡頭前(發送端)移動,觀察接收端視頻的顯示。在不同的局域網中進行了多次測試,每次測試時間從10分鐘到30分鐘不等,并且改變目標的運動速度進行實驗。最后將數據匯總,得出統計結果。測試結果如表1所示。

表1不同局域網下的測試結果

劇烈運動

正常運動

緩慢運動

100M局域網

圖像清晰,很流暢

圖像清晰,很流暢

圖像清晰,很流暢

10M局域網

偶爾出現停頓,丟幀率1%左右

圖像清晰,人眼感覺流暢

圖像清晰,很流暢

11M無線局域網

經常出現停頓,丟幀率5%-6%

經常出現停頓,丟幀率2%-3%

偶爾出現停頓,丟幀率1%左右

其中,

注:11M無線網卡是通過USB1.0接口和PC機連接的,如果采用USB2.0接口效果會更好。

從實際測試的結果看,效果是良好的,除了出現瞬間移動外,圖像能夠保持清晰,消除了由于網絡質量差而導致的重影、抖動等現象,對于不同的局域網都能滿足實時傳輸的要求。

總結

以上是生活随笔為你收集整理的利用VC++实现局域网实时传输的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。