2023年全國碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩23頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、<p>  基于局域網(wǎng)的視頻聊天室系統(tǒng)的設(shè)計與實現(xiàn)</p><p><b>  摘 要</b></p><p>  視頻聊天系統(tǒng)作為一種新型的通信和交流工具,突破了地域的限制,可以提供更為便捷、靈活、全面的音、視頻信息的傳遞和服務(wù),具有極其廣泛的發(fā)展前景。</p><p>  本文介紹了采用Microsoft Visual C++

2、6.0編程開發(fā)視頻聊天系統(tǒng)的一套比較常用的解決方案。文字聊天采用TCP模式;語音視頻聊天采用UDP模式,在客戶端之間點對點的進行。在該方案中,通過函數(shù)庫VFW來實現(xiàn)視頻捕獲、影像壓縮以及影像播放。微軟公司提供的專門用于視頻捕獲開發(fā)的工具包VFW,為在Windows操作系統(tǒng)中實現(xiàn)視頻捕獲提供了標準的接口,從而大大降低了程序的開發(fā)難度。在視頻傳輸方面,則通過組建視頻幀,將位圖形式的視頻幀壓縮成幀格式的Mpeg4流,傳輸?shù)娇蛻舳撕?,解壓并顯示

3、影像。同時,在本方案中,采用了線程來實現(xiàn)語音錄制和語音回放,最終實現(xiàn)了通過服務(wù)器中轉(zhuǎn)的文字聊天、點對點的語音視頻聊天。</p><p>  關(guān)鍵詞:文字聊天;VFW;視頻捕獲;視頻傳輸;語音錄制;語音回放</p><p>  The Design and Realization of LAN-Based Video Chat Room System</p><p>

4、<b>  Abstract</b></p><p>  As a new tool about communication, video chatting system has broken through geographical restrictions, has provides more convenient, flexible and complete transmission

5、and service. Furthermore, it has a very bright future.</p><p>  The common solution about how to develop a video chatting system is introduced by the Microsoft Visual C + + 6.0 programming. TCP model is used

6、 in the text chatting and UDP for the point-to-point video chats between the Clients. In this plan, Video Capture, Video Compression Manager and DrawDib are realized by the functions of VFW Library. The special kit VFW (

7、Video for Windows) in video capture offered by Microsoft Corporation, has provided a standard interface for video capture in Windows Oper</p><p>  Key words: text chatting; VFW; Video Capture; video transmis

8、sion; audio recording; audio playing</p><p><b>  目 錄</b></p><p><b>  論文總頁數(shù):24頁</b></p><p><b>  1引言1</b></p><p>  1.1課題背景1</p

9、><p>  1.2國內(nèi)外研究現(xiàn)狀1</p><p>  2理論知識介紹1</p><p>  2.1VFW簡介1</p><p>  2.2線程的實現(xiàn)方法4</p><p><b>  3需求分析5</b></p><p>  3.1軟硬件環(huán)境5<

10、;/p><p>  3.2需求分析5</p><p><b>  4系統(tǒng)結(jié)構(gòu)7</b></p><p>  4.1硬件結(jié)構(gòu)7</p><p>  4.2軟件結(jié)構(gòu)7</p><p>  4.2.1功能需求7</p><p>  4.2.2系統(tǒng)功能模塊圖8&

11、lt;/p><p>  4.3系統(tǒng)各模塊流程圖8</p><p>  5系統(tǒng)的詳細設(shè)計10</p><p>  5.1文字聊天10</p><p>  5.1.1TCP套接字的運用10</p><p>  5.1.2文字聊天實現(xiàn)11</p><p>  5.2語音視頻聊天13

12、</p><p>  5.2.1UDP套接字的運用13</p><p>  5.2.2視頻的捕獲14</p><p>  5.2.3捕獲窗口16</p><p>  5.2.4視頻捕獲驅(qū)動18</p><p>  5.2.5語音錄制18</p><p>  5.2.6語音回

13、放19</p><p>  5.2.7視音頻的傳輸20</p><p><b>  結(jié) 論21</b></p><p><b>  參考文獻22</b></p><p><b>  致 謝23</b></p><p><b&

14、gt;  聲 明24</b></p><p><b>  引言</b></p><p><b>  課題背景</b></p><p>  隨著Internet的不斷發(fā)展普及,網(wǎng)絡(luò)通訊越來越被千家萬戶所接受,成為人們生活中的一部分。網(wǎng)絡(luò)聊天已和手機等一樣,成為人們運用最為廣泛的通信工具之一。本畢業(yè)設(shè)計的目

15、的主要是為了滿足人們通訊交流的便捷,實現(xiàn)靈活、全面的音、視頻信息的傳遞和服務(wù)。模擬騰訊公司的QQ聊天軟件,開發(fā)一個多功能的聊天系統(tǒng)軟件,本畢業(yè)設(shè)計主要實現(xiàn)視頻語音聊天、文字聊天等功能。</p><p><b>  國內(nèi)外研究現(xiàn)狀</b></p><p>  隨著網(wǎng)絡(luò)寬帶業(yè)務(wù)的推廣與普及,加之視頻產(chǎn)品設(shè)備(如攝像頭、耳機、麥克風等)的成熟,普通用戶可以輕松地借助網(wǎng)絡(luò)視頻

16、通訊軟件,實現(xiàn)“面對面”的網(wǎng)絡(luò)交流。信息的無限量擴大,交通工具的便捷,視頻技術(shù)的充分應用等導致了行業(yè)間競爭的全球化,這就要求現(xiàn)代部門、企業(yè)要具備更加靈敏的神經(jīng),更扁平化的管理,更快速的反應和決策,更貼切的市場宣傳和服務(wù)。所有這一切是由信息技術(shù)的發(fā)展所帶來的,同樣也要求有先進的信息技術(shù)來提高部門、企業(yè)的競爭力?,F(xiàn)代通訊已經(jīng)是越來越普及了,必須有效合理的運用視頻產(chǎn)品類設(shè)備來提高信息的傳遞和交流。在同一個局域網(wǎng)中,充分、合理的運用攝像頭、耳機

17、、麥克風等設(shè)備來實現(xiàn)文字聊天和語音視頻聊天更是我們生活、學習、工作的便利所在。</p><p><b>  理論知識介紹</b></p><p><b>  VFW簡介</b></p><p>  VFW是Microsoft 1992年推出的關(guān)于數(shù)字視頻的一個軟件包,它能使應用程序數(shù)字化并播放從傳統(tǒng)模擬視頻源得到的視頻剪輯

18、。VFW的一個關(guān)鍵思想是播放時不需要專用硬件,為了解決數(shù)字視頻數(shù)據(jù)量大的問題,需要對數(shù)據(jù)進行壓縮。它引進了一種叫AVI的文件標準,該標準未規(guī)定如何對視頻進行捕獲、壓縮及播放,僅規(guī)定視頻和音頻該如何存儲在硬盤上,以及在AVI文件中交替存儲視頻幀和與之相匹配的音頻數(shù)據(jù)。VFW給程序員提供VBX和AVICap窗口類的高級編程工具,使程序員能通過發(fā)送消息或設(shè)置屬性來捕獲、播放和編輯視頻剪輯。用戶不必專門安裝VFW,在安裝Windows時,安裝程

19、序會自動地安裝配置視頻所需的組件,如設(shè)備驅(qū)動程序、視頻壓縮程序等。</p><p>  VFW主要由以下六個模塊組成:</p><p>  AVICAP.DLL:包含了執(zhí)行視頻捕獲的函數(shù),它給AVI文件、I/O和視頻音頻設(shè)備驅(qū)動程序提供一個高級接口;</p><p>  MSVIDEO.DLL:用一套特殊的DrawDib函數(shù)來處理屏幕上的視頻操作;</p>

20、;<p>  MCIAVI.DRV:此驅(qū)動程序包括對VFW的MCI命令的解釋器;</p><p>  AVIFILE.DLL:支持由標準多媒體I/O(mmio)函數(shù)提供的更高的命令來訪問AVI文件;</p><p>  壓縮管理器(ICM):管理用于視頻壓縮/解壓縮的編解碼器(CODEC);</p><p>  音頻壓縮管理器ACM:提供與ICM相似的

21、服務(wù),不同的是它適于波形音頻。</p><p>  Visual C++在支持VFW方面提供有vfw32.lib、msacm32.lib、winmm.lib等庫。特別是它提供了功能強大、簡單易行、類似于MCIWnd的窗口類AVICap。AVICap為應用程序提供了一個簡單的、基于消息的接口,使之能訪問視頻和波形音頻硬件,并能在將視頻流捕獲到硬盤上的過程中進行控制。</p><p>  AV

22、ICap支持實時的視頻流捕獲和單幀捕獲,并提供對視頻源的控制。雖然MCI也提供數(shù)字視頻服務(wù),比如,它為顯示AVI文件的視頻提供了AVIVideo命令集,為視頻疊加提供了overlay命令集,但這些命令主要是基于文件的操作,不能滿足實時地直接從視頻緩存中獲取數(shù)據(jù)的要求。對于使用沒有視頻疊加能力的捕獲卡的PC機來說,用MCI提供的命令集是無法捕獲視頻流的。而AVICap在捕獲視頻方面具有一定的優(yōu)勢,它能直接訪問視頻緩沖區(qū),不需要生成中間文件

23、,實時性很強,效率很高。同時,它也可將數(shù)字視頻捕獲到文件。</p><p>  在視頻捕獲之前需要創(chuàng)建一個捕獲窗,所有的捕獲操作及其設(shè)置都以它為基礎(chǔ)。用AVICap窗口類創(chuàng)建的窗口(通過capCreateCaptureWindow函數(shù)創(chuàng)建)被稱為“捕獲窗”,其窗口風格一般為WS_CHILD和WS_VISIBLE。實際上,捕獲窗類似于標準控制(如按鈕、列表框等)。捕獲窗具有下列功能:</p><

24、p>  將視頻流和音頻流捕獲到一個AVI文件中;</p><p>  動態(tài)地同視頻和音頻輸入器件連接或斷開;</p><p>  以O(shè)verlay或Preview模式對輸入的視頻流進行實時顯示;</p><p>  在捕獲時可指定所用的文件名并能將捕獲文件的內(nèi)容拷貝到另一個文件;</p><p><b>  設(shè)置捕獲速率;&l

25、t;/b></p><p>  顯示控制視頻源、視頻格式、視頻壓縮的對話框;</p><p>  創(chuàng)建、保存或載入調(diào)色板;</p><p>  將圖像和相關(guān)的調(diào)色板拷貝到剪貼板;</p><p>  將捕獲的一個單幀圖像保存為DIB格式的文件。</p><p>  AVICap在顯示視頻時提供的兩種模式:<

26、/p><p> ?。ˋ)預覽(Preview)模式:該模式使用CPU資源,視頻幀先從捕獲硬件傳到系統(tǒng)內(nèi)存,接著采用GDI函數(shù)在捕獲窗中顯示。在物理上,這種模式需要通過VGA卡在監(jiān)視器上顯示。</p><p> ?。˙)疊加(Overlay)模式:該模式使用硬件疊加進行視頻顯示,疊加視頻的顯示不經(jīng)過VGA卡,疊加視頻的硬件將VGA的輸出信號與其自身的輸出信號合并,形成組合信號顯示在計算機的監(jiān)視器

27、上。只有部分視頻捕獲卡才具有視頻疊加能力。</p><p>  靈活編寫AVICap提供的回調(diào)函數(shù)還可滿足一些特殊需求。比如,將宏capCaptureSequenceNoFile同用capSetCallbackOnVideoStream登記的回調(diào)函數(shù)一起使用,可使應用程序直接使用視頻和音頻數(shù)據(jù)。在視頻聊天的應用程序中可利用這一點來獲得視頻幀,回調(diào)函數(shù)將捕獲的圖像傳到遠端的計算機。應用程序可用捕獲窗來登記回調(diào)函數(shù)(

28、由用戶編寫,而由系統(tǒng)調(diào)用),以便在發(fā)生下列情況時,它能通知應用程序,作出相應的反應:捕獲窗狀態(tài)改變;出錯;視頻幀和音頻緩存可以使用;在捕獲過程中,其它應用程序處于讓步(Yield)地位。</p><p>  視頻捕獲編程也要用到涉及視頻捕獲的結(jié)構(gòu)、宏、消息和函數(shù)。令人高興的是,發(fā)送AVICap窗口消息所能完成的功能都能調(diào)用相應的宏來完成。例如,SendMessage(hWndCap,WM_CAP_DRIVER_C

29、ONNECT,0,0L)與capDriverConnect(hWndCap,0)的作用相同,都是將創(chuàng)建的捕獲窗同視頻輸入器件連接起來。</p><p>  視頻部分主要是利用Video Capture函數(shù)庫來獲取影像的。Video Capture主要提供下列功能:連接驅(qū)動程序;獲取影像、聲音資料,并顯示在屏幕上或者是存成AVI文件;獲取單張影像顯示在屏幕上,拷貝至剪貼簿,或者是存成DIB(Device-Indep

30、endent Bitmap)文件。</p><p>  Video Capture的主要結(jié)構(gòu):</p><p>  結(jié)構(gòu)體CAPTUREPARAMS主要包含一些獲取圖像的參數(shù):DWORD dwRequestMicroSecPerFrame代表相鄰兩個frame的獲取時間間隔;BOOL fYield值為TRUE,則表示W(wǎng)indows會以另一個thread來捕獲影像,值為FALSE,程序會在捕

31、捉影像后顯示忙碌狀態(tài);BOOL fCaptureAudio其值表示是否需要同時獲取聲音資料。</p><p>  結(jié)構(gòu)體BITMAPINFO和點陣圖有關(guān),主要定義了影像獲取之后顯示在屏幕上、存儲在文件中的格式,它包含兩個成員:BITMAPINFOHEADER bmiHeader描述影像性質(zhì)的結(jié)構(gòu),其成員記載了影像的大小、顏色深度和壓縮的方式,該成員在Video Capture、Video Compression

32、Manager和DrawDib函數(shù)庫中,以及有關(guān)于點陣圖的應用中;RGBQUAD bmiColors指向color table第一個元素的位置。</p><p>  結(jié)構(gòu)體COMPVARS主要是記錄所有和壓縮相關(guān)的信息,重要的成員:DWORD fccHandler為compressor句柄;LPBITMAPINFO lpbiIn指向待壓縮影像BITMAPINFO的指標;LPBITMAPINFO lpbitOut:

33、指向壓縮完影像BITMAPINFO的指標;LONG lKey代表key-frame rate,而所謂key frame是指此frame在解壓縮時不需要依賴前面的frame;LONG lQ代表影像壓縮后的品質(zhì),取值為1~10000的整數(shù)。</p><p>  Video Compression Functions主要記錄壓縮功能相關(guān)的信息,其包含的比較重要的成員:ICLocate輸入指向壓縮前后BITMAPINFO

34、的指標,以及欲使用的codecs;ICCompressorChoose呼叫一個系統(tǒng)內(nèi)建的對話,其中包含所有可能使用的codes以及其相關(guān)參數(shù);ICCompressQuery詢問compressor是否支持某種壓縮方式,輸入?yún)?shù)為compressor handle及指向壓縮前后BITMAPINFO的指標,此函數(shù)會傳回詢問結(jié)果;ICCompressBegin要求系統(tǒng)準備相關(guān)資源以供壓縮之用;ICCompress壓縮某個frame;ICCom

35、pressEnd歸還相關(guān)資源給系統(tǒng);ICDompressQuery詢問decompressor是否支持某種解壓縮方式;ICDompressBegin要求系統(tǒng)準備相關(guān)資源以供解壓縮之用;ICDompress解壓縮某一個frame;ICDompressEnd歸還相關(guān)資源給系統(tǒng);ICDompressFree歸還COMPVARS所占用的資源。</p><p><b>  線程的實現(xiàn)方法</b><

36、;/p><p>  線程是一個獨立的執(zhí)行流,是進程內(nèi)部的一個獨立的執(zhí)行單元,相當于一個子程序,它對應于Visual C++中的CWinThread類對象。單獨一個執(zhí)行程序運行時,缺省地包含了一個主線程,主線程以函數(shù)地址的形式出現(xiàn),提供程序的啟動點,當主線程終止時,進程也隨之終止。根據(jù)實際需要,應用程序可以分解成許多獨立執(zhí)行的線程,每個線程并行的運行在同一進程中。</p><p>  一個進程中

37、的所有線程都在該進程的虛擬地址空間中,使用該進程的全局變量和系統(tǒng)資源。操作系統(tǒng)給每個線程分配不同的CPU時間片,在某一個時刻,CPU只執(zhí)行一個時間片內(nèi)的線程,多個時間片中的相應線程在CPU內(nèi)輪流執(zhí)行,由于每個時間片時間很短,所以對用戶來說,仿佛各個線程在計算機中是并行處理的。操作系統(tǒng)是根據(jù)線程的優(yōu)先級來安排CPU的時間,優(yōu)先級高的線程優(yōu)先運行,優(yōu)先級低的線程則繼續(xù)等待。</p><p>  Windows提供了兩

38、種線程:用戶界面線程和工作線程(又稱為后臺線程)。用戶界面線程通常用來處理用戶的輸入并響應各種事件和消息,其實,應用程序的主執(zhí)行線程CWinApp對象就是一個用戶界面線程,當應用程序啟動時自動創(chuàng)建和啟動,同樣它的終止也意味著該程序的結(jié)束,進程終止。工作線程用來執(zhí)行程序的后臺處理任務(wù),比如計算、調(diào)度、對串口的讀寫操作等,它和用戶界面線程的區(qū)別是它不用從CWinThread類派生來創(chuàng)建,對它來說最重要的是如何實現(xiàn)工作線程任務(wù)的運行控制函數(shù)。

39、工作線程和用戶界面線程啟動時要調(diào)用同一個函數(shù)的不同版本;一個進程中的所有線程共享它們父進程的變量,但同時每個線程可以擁有自己的變量。</p><p>  這里主要介紹用戶界面線程的運用:</p><p><b>  線程的啟動</b></p><p>  創(chuàng)建一個用戶界面線程,首先要從類CwinThread產(chǎn)生一個派生類,同時必須使DECLAR

40、E_DYNCREATE和IMPLEMENT_DYNCREATE來聲明和實現(xiàn)這個CwinThread派生類。第二步是根據(jù)需要重載該派生類的一些成員函數(shù)如:ExitInstance()、InitInstance()、OnIdle()、PreTranslateMessage()等函數(shù)。最后調(diào)用AfxBeginThread()函數(shù)的一個版本:CWinThread* AfxBeginThread (CRuntimeClass* pThreadCl

41、ass,int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL)啟動該用戶界面線程,其中第一個參數(shù)為指向定義的用戶界面線程類指針變量,第二個參數(shù)為線程的優(yōu)先級,第三個參數(shù)為線程所對應的堆棧大小,第四個參數(shù)為線程創(chuàng)建時的附加標志,缺省為

42、正常狀態(tài),如為CREATE_S</p><p><b>  線程的優(yōu)先級</b></p><p>  CwinThread類的成員函數(shù)用于線程優(yōu)先級的操作:</p><p>  int GetThreadPriority();</p><p>  BOOL SetThradPriority()(int nPriority

43、);</p><p><b>  線程的掛起和恢復</b></p><p>  CWinThread類中包含了應用程序掛起和恢復它所創(chuàng)建的線程的函數(shù),其中SuspendThread()用來掛起線程,暫停線程的執(zhí)行;ResumeThread()用來恢復線程的執(zhí)行。如果你對一個線程連續(xù)若干次執(zhí)行SuspendThread(),則需要連續(xù)執(zhí)行相應次的ResumeThread

44、()來恢復線程的運行。</p><p><b>  結(jié)束線程</b></p><p>  終止線程有三種途徑,線程可以在自身內(nèi)部調(diào)用AfxEndThread()來終止自身的運行;可以在線程的外部調(diào)用BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode)來強行終止一個線程的運行,然后調(diào)用CloseHandle()函數(shù)

45、釋放線程所占用的堆棧;第三種方法是改變?nèi)肿兞?,使線程的執(zhí)行函數(shù)返回,則該線程終止。</p><p><b>  需求分析</b></p><p><b>  軟硬件環(huán)境</b></p><p>  電腦兩臺以上,分別配有攝像頭、麥克風、音箱或耳機等外部設(shè)備;Windows XP系統(tǒng),Microsoft Visual St

46、udio 6.0編程開發(fā)系統(tǒng)等。</p><p><b>  需求分析</b></p><p>  在同一個局域網(wǎng)中,如何根據(jù)自身業(yè)務(wù)的要求,量身定制,對視頻設(shè)備進行合理搭配,選擇一套合理的視頻聊天室系統(tǒng)。如何來滿足局域網(wǎng)內(nèi)部用戶的通訊要求,在考慮到網(wǎng)絡(luò)帶寬的同時,提高視頻清晰度,動態(tài)畫面的流暢,語音的實時傳輸?shù)龋乾F(xiàn)代社會通訊所必需的。設(shè)計本系統(tǒng)時,分析網(wǎng)絡(luò)承載、

47、整個系統(tǒng)結(jié)構(gòu)的組建等是實現(xiàn)局域網(wǎng)文字聊天和語音視頻聊天所必需的。</p><p>  文字、語音視頻聊天作為一種廣泛的網(wǎng)絡(luò)應用對其基礎(chǔ)的承載網(wǎng)絡(luò)環(huán)境有著較高的網(wǎng)絡(luò)要求。其中應重點考慮的是網(wǎng)絡(luò)的帶寬情況、端到端的時延、時延抖動、丟包率等問題。</p><p>  網(wǎng)絡(luò)帶寬需求,視頻聊天對網(wǎng)絡(luò)的帶寬需求為“視頻帶寬+IP包頭開銷”,計算方法為:網(wǎng)絡(luò)帶寬 = 視頻帶寬 × 1.2。&l

48、t;/p><p>  端到端的時延,網(wǎng)絡(luò)傳輸不可避免的會發(fā)生傳輸時延,通常建議視頻聊天的通用時延小于150ms。</p><p>  時延抖動,由于音頻/視頻的傳輸為實時的交互,因此網(wǎng)絡(luò)的時延抖動更為重要,一般,視頻聊天的時延抖動控制在50ms內(nèi)。</p><p>  丟包率,網(wǎng)絡(luò)數(shù)據(jù)傳輸經(jīng)常會出現(xiàn)丟包現(xiàn)象,視頻傳輸過程中數(shù)據(jù)丟包嚴重的話會影響在線視頻聊天質(zhì)量。因此,在

49、設(shè)計上應將網(wǎng)絡(luò)上的丟包率控制在1%以內(nèi)。</p><p>  視頻聊天對實時性要求較高的網(wǎng)絡(luò)應用,作為其基礎(chǔ)的承載網(wǎng)絡(luò)有較高的寬帶和對網(wǎng)絡(luò)中的業(yè)務(wù)流量有較高的控制能力。而視頻聊天系統(tǒng)本身對帶寬的要求為62kbit/s~2Mbit/s,但是為了滿足流暢的視音頻效果,要求帶寬不低于384kbit/s。</p><p>  文字、視頻聊天的功能和應用效果體現(xiàn)在客戶端,而服務(wù)器端則是必不可少的,對

50、于系統(tǒng)的需求分析在系統(tǒng)設(shè)計的過程中應該明確、細致:</p><p>  文字聊天:首先啟動服務(wù)器端,當用戶啟動客戶端時,用服務(wù)器保存的用戶名和密碼來驗證客戶是否已經(jīng)登錄到服務(wù)器。只有當有兩個以上的用戶啟動客戶端時,才可以進行文字聊天,聊天內(nèi)容要經(jīng)過服務(wù)器中轉(zhuǎn),分別在服務(wù)器端和兩個聊天的客戶端顯示聊天。</p><p>  語音視頻聊天:在有兩個客戶在線的情況下,才能進行語音視頻聊天。兩個用

51、戶要進行語音視頻聊天時,一個用戶選中另一個用戶的用戶名,根據(jù)該用戶名在后臺鏈表中的對應IP地址查找用戶并請求視頻連接。當雙方確認視頻連接后就進行視頻傳輸,并顯示在客戶端,同時用線程實現(xiàn)語音錄制和回放。這樣,兩個用戶就實現(xiàn)了點對點的語音視頻聊天。在進行語音視頻聊天的過程中,不能再與其它用戶進行語音視頻聊天,但能夠與其它用戶進行文字聊天。</p><p><b>  系統(tǒng)結(jié)構(gòu)</b></p

52、><p><b>  硬件結(jié)構(gòu)</b></p><p>  該系統(tǒng)采用的是Server/Client結(jié)構(gòu),服務(wù)器端是一臺PC機,而客戶端是PC機和一個數(shù)字攝像頭、耳機和麥克風。它們進行文字聊天時,要經(jīng)過服務(wù)器進行中轉(zhuǎn),而當進行語音視頻聊天時是客戶端與客戶端之間直接進行的點對點的連接,它們之間的網(wǎng)絡(luò)拓撲結(jié)構(gòu)如圖1。在圖中,為了簡便,沒有畫出麥克風、音箱或耳機等外部設(shè)備。&l

53、t;/p><p>  圖1 網(wǎng)絡(luò)拓撲結(jié)構(gòu)圖</p><p><b>  軟件結(jié)構(gòu)</b></p><p><b>  功能需求</b></p><p>  通過需求調(diào)研并分析,確定系統(tǒng)具備的基本功能,包括:文字聊天、語音視頻聊天。</p><p><b>  文字聊天:

54、</b></p><p>  文字聊天采用的是TCP模式,包括服務(wù)器端和客戶端。首先啟動服務(wù)器端,客戶端通過用戶名和密碼登錄服務(wù)器,服務(wù)器響應客戶端登錄并提示有用戶登錄,此時兩個用戶就可以進行文字聊天,在文字聊天時通過服務(wù)器中轉(zhuǎn),而每個用戶可以同時與多個用戶進行文字聊天。當有用戶退出時,服務(wù)器做出響應,提示在線用戶,××用戶下線。</p><p><b

55、>  語音視頻聊天:</b></p><p>  語音視頻聊天時采用的是UCP模式,客戶端與客戶端點對點的進行,不需要經(jīng)過服務(wù)器端中轉(zhuǎn)。在文字聊天的基礎(chǔ)上,客戶端之間自行處理的語音視頻聊天,運用VFW函數(shù)庫中的函數(shù)對USB口輸入的數(shù)字視頻信息進行相關(guān)處理,比如:視頻捕獲、影像壓縮以及影像播放等,同時利用線程來處理聲音部分的錄制、回放等。A客戶端向B客戶端請求語音視頻聊天是通過B客戶端的用戶名來獲

56、得B客戶端的IP地址,并向B客戶端發(fā)送語音視頻聊天請求,當B客戶端接受后捕獲視頻,并進行壓縮傳輸?shù)紸客戶端解壓并進行顯示,在B客戶端接受視頻的同時,A客戶端也捕獲視頻,壓縮傳輸?shù)紹客戶端解壓并進行顯示。</p><p><b>  系統(tǒng)功能模塊圖</b></p><p>  該系統(tǒng)分為服務(wù)器端和客戶端,完成了文字聊天和語音視頻聊天,使用上只有文字聊天時才會通過服務(wù)器端

57、,而對于語音視頻聊天就只需要對整個在線客戶端兩兩之間進行點對點的視頻聊天。而在語音視頻時包括了視頻捕獲、視頻壓縮、解壓縮、語音錄制、語音回放以及視頻傳輸?shù)?。整個系統(tǒng)的功能模塊圖如圖2。</p><p>  圖2 系統(tǒng)功能模塊圖</p><p><b>  系統(tǒng)各模塊流程圖</b></p><p>  在整個系統(tǒng)中主要運行兩個功能:圖3 文字聊天

58、流程圖和圖4 語音視頻聊天流程圖。</p><p>  圖3 文字聊天流程圖</p><p>  圖4 語音視頻聊天流程圖</p><p><b>  系統(tǒng)的詳細設(shè)計</b></p><p><b>  文字聊天</b></p><p><b>  TCP套接字的運

59、用</b></p><p>  在文字聊天時,服務(wù)器端與客戶端的連接是采用的TCP套接節(jié)進行連接。TCP套接字的使用如圖5。創(chuàng)建CSocket對象CSocketServer來處理服務(wù)器端與客戶端的連接,CSocket繼承于CasyncSocket,是Windows Socket API的高層抽象。CSocket通常和CsocketFile以及Carchive類混合使用,這兩個類負責數(shù)據(jù)的發(fā)送和接收。要

60、使用CSocket對象,首先要調(diào)用構(gòu)造函數(shù),然后調(diào)用Create函數(shù)創(chuàng)建一個Socket句柄。CSocket函數(shù)缺省是創(chuàng)建一個流Socket;如果沒有使用CArchive類,那么還可以創(chuàng)建一個數(shù)據(jù)報Socket。服務(wù)器端調(diào)用Accept,客戶端調(diào)用Connect,然后創(chuàng)建一個CsocketFile去關(guān)聯(lián)CSocket。接下來的操作可以創(chuàng)建CArchive對象關(guān)聯(lián)CsocketFile,以用來發(fā)送和接收數(shù)據(jù)。</p><

61、;p>  圖5 TCP套接字的使用</p><p><b>  文字聊天實現(xiàn)</b></p><p>  ChatServer服務(wù)器運行時,利用一個CSocket對象CSocketServer啟動服務(wù)器,用函數(shù)gethostname來獲得服務(wù)器端主機名和IP,同時在服務(wù)器對話框中顯示服務(wù)器IP,并將分配的固定端口號8123顯示在對話框中。用一個list列表顯示在

62、線用戶,隨時更新用戶登錄情況,用一個edit box顯示客戶端的聊天內(nèi)容以及系統(tǒng)提示消息。每一個ChatClient客戶端啟動時,利用服務(wù)器內(nèi)定的用戶號和密碼來登錄(如圖6)。在整個系統(tǒng)中,利用鏈表來處理所有的用戶信息:當有用戶登錄時,在鏈表尾部加入該用戶信息;當用戶下線時,在該鏈表中刪除用戶,并提示所有用戶,該用戶下線。在對鏈表進行操作的同時,要更新list列表中的信息。</p><p><b>  

63、圖6 用戶登錄界面</b></p><p>  ChatServer服務(wù)器端響應客戶端文字聊天時的中轉(zhuǎn)情況如圖7。</p><p>  圖7 服務(wù)器響應文字聊天信息中轉(zhuǎn)</p><p>  ChatClient客戶端兩兩間進行文字聊天時,發(fā)送信息的處理函數(shù)如下:</p><p>  void CChatClientDlg::OnC

64、hatBtSend() //發(fā)送信息按鍵</p><p><b>  {</b></p><p>  if( !m_bConnect)</p><p><b>  {</b></p><p>  SetMessageBox("請連接服務(wù)器!\r\n");</p>

65、<p><b>  return ;</b></p><p><b>  }</b></p><p>  CString str;</p><p>  CString szUserName;</p><p>  CMesg msg;</p><p>  GetD

66、lgItemText(IDC_MESSAGE,str);</p><p>  GetDlgItemText(IDC_USERNAME,szUserName);</p><p>  if( str.GetLength() <= 0 )</p><p><b>  {</b></p><p>  SetMessageB

67、ox("請輸入想要發(fā)送的信息!\r\n");</p><p><b>  return ;</b></p><p><b>  }</b></p><p>  if ( szUserName.GetLength() <= 0)</p><p><b>  {<

68、;/b></p><p>  SetMessageBox("請選擇說話對象!\r\n");</p><p><b>  return ;</b></p><p><b>  }</b></p><p><b>  //消息封裝</b></p>

69、;<p>  msg.m_szCommand.Format("Message");</p><p>  msg.m_szRecObject.Format(szUserName);</p><p>  msg.m_szText.Format(str);</p><p>  m_csClient->SendM(&msg);

70、</p><p>  AddReceiver(szUserName , true);</p><p>  AddChatMessage(str);</p><p><b>  }</b></p><p>  在聊天兩個客戶端的信息情況如圖8和圖9。</p><p><b>  圖8 接收

71、文字信息</b></p><p><b>  圖9 發(fā)送文字信息</b></p><p><b>  語音視頻聊天</b></p><p><b>  UDP套接字的運用</b></p><p>  在實現(xiàn)語音視頻聊天時,采用的是基于UDP套接字的點對點模式,而UD

72、P面向的是無連接的數(shù)據(jù)服務(wù),其套接字的使用如圖10所示。</p><p>  圖10 UDP套接字的使用</p><p><b>  視頻的捕獲</b></p><p>  利用VFW接口,視頻捕獲可以分為以下幾個步驟:</p><p>  建立視頻采集窗口:該窗口用來接收視頻捕捉驅(qū)動程序傳來的數(shù)據(jù)和消息。</p&

73、gt;<p>  連接視頻驅(qū)動程序:將建立的視頻捕捉窗口與視頻設(shè)備驅(qū)動程序相連。</p><p><b>  視頻捕獲初始化。</b></p><p>  視頻捕捉設(shè)置:VFW下視頻捕捉參數(shù)的設(shè)置可以通過調(diào)用函數(shù)或彈出對話框的形式來實現(xiàn)。一般視頻驅(qū)動程序允許設(shè)置的參數(shù)包括視頻源選擇、視頻格式、視頻顯示格式等。</p><p>  

74、設(shè)置回調(diào)函數(shù):通過回調(diào)函數(shù)來通知程序視頻事件的發(fā)生,比如捕捉一幀圖像成功的消息,捕捉出錯的消息等。</p><p>  結(jié)束捕捉:結(jié)束捕捉是應該有一些清除工作。如釋放分配的內(nèi)存,斷開捕捉窗口與視頻捕捉驅(qū)動程序的連接,清除視頻捕捉窗口等。</p><p>  窗口類為捕獲數(shù)字視頻流及其相關(guān)操作提供了很大的方便,靈活編寫其中的回調(diào)函數(shù)可滿足實時視頻傳輸?shù)男枰?,例如應用程序可直接從緩沖中取得數(shù)字

75、視頻并對其進行壓縮編碼后實時地傳到遠端的客戶端。</p><p>  在VC++中,采用VFW技術(shù),客戶端通過capSetCallbackOnFrame()注冊回調(diào)函數(shù),當采集卡采集到一幅圖像后,系統(tǒng)就會自動調(diào)用回調(diào)函數(shù),然后再回調(diào)函數(shù)中使用ICSeqCompressFrame()函數(shù)進行壓縮。然后再通過Winsock將壓縮后的數(shù)據(jù)發(fā)送到另一客戶端。該客戶端接收完一幀以后,交給ICDecompress()解壓,最

76、后用SetDIBitsToDevice()將圖像顯示出來。</p><p>  基本的捕獲設(shè)置包括設(shè)置捕獲速度(每秒捕獲多少幀)、是否同時捕獲聲頻、捕獲緩沖、允許最大丟失多少幀和是否使用DOS內(nèi)存,以及使用鍵盤的哪個鍵或鼠標的哪個鍵來終止捕獲等內(nèi)容,這些設(shè)置使用CAPTUREPARAMS結(jié)構(gòu)來描述,capCaptureGetSetup宏來得到當前的設(shè)置,然后改變此結(jié)構(gòu)的成員變量,再使用capCaptureSetS

77、etup宏設(shè)置新的設(shè)置。</p><p>  設(shè)置捕獲速度,通過使用capCaptureGetSetup宏來得到當前的捕捉速度,將當前的捕捉速度保存在CAPTUREPARAMS結(jié)構(gòu)的dwRequestMicroSecPerFrame成員變量中,也可以通過設(shè)置此變量來改變當前設(shè)置值。</p><p>  設(shè)置終止捕獲,同樣通過使用capCaptureGetSetup宏來得到當前的設(shè)置,當前按

78、鍵設(shè)置保存在CAPTUREPARAMS結(jié)構(gòu)的vKeyAbort成員中,鼠標設(shè)置保存在fAbortLeftMouse和fAbortRightMouse成員中,通過修改可以設(shè)置新的熱健或者鼠標左右鍵,修改完成后,使用capCaptureSetSetup宏來進行更新。</p><p>  捕獲的時間限制,用CAPTUREPARAMS結(jié)構(gòu)中的fLimitEnabled表示捕獲是否有時間的限制,wTimeLimit用來設(shè)置

79、指示捕獲最大的持續(xù)時間,其單位為秒。使用capCaptureGetSetup宏來得到當前的設(shè)置值。</p><p>  下面程序為設(shè)置CAPTUREPARAMS結(jié)構(gòu)的實現(xiàn)代碼:</p><p>  BOOL VideoCapture::SetCapturePara()</p><p><b>  {</b></p><p&g

80、t;  CAPTUREPARMS CapParms={0};</p><p>  capCaptureGetSetup(m_capwnd,&CapParms,sizeof(CapParms));</p><p>  //得到當前的捕獲速度</p><p>  CapParms.fAbortLeftMouse = FALSE;</p><

81、p>  CapParms.fAbortRightMouse = FALSE;</p><p>  CapParms.fYield = TRUE;</p><p>  CapParms.fCaptureAudio = FALSE;</p><p>  CapParms.wPercentDropForError = 80;</p><p>

82、  if(!capCaptureSetSetup(m_capwnd,&CapParms,sizeof(CapParms)))</p><p><b>  {</b></p><p>  //log.WriteString("\n Failed to set the capture parameters ");</p><

83、;p>  return FALSE;</p><p><b>  }</b></p><p>  // Set Video Format </p><p>  capGetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));</p><p>  m_bmpi

84、nfo.bmiHeader.biWidth=IMAGE_WIDTH;</p><p>  m_bmpinfo.bmiHeader.biHeight=IMAGE_HEIGHT;</p><p>  BOOL ret=capSetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));</p><p>  //lo

85、g.WriteString("\n Video parameters set properly");</p><p>  return ret;</p><p><b>  }</b></p><p>  //終止一個捕獲任務(wù)</p><p>  BOOL VideoCapture::StopCapt

86、ure()</p><p><b>  {</b></p><p>  capCaptureStop(m_capwnd);</p><p>  capCaptureAbort(m_capwnd);</p><p>  Sleep(500);</p><p>  return TRUE;</

87、p><p><b>  }</b></p><p><b>  捕獲窗口</b></p><p>  在捕獲前必須創(chuàng)建一個捕獲窗口(Capture Widnow),下面介紹有關(guān)捕獲窗口的情況:創(chuàng)建一個AVICap捕獲窗口,用capCreateCaptureWindow函數(shù)并返回一個句柄。將捕獲窗口連接至捕獲設(shè)備,用capDri

88、verConnect函數(shù)來使一個捕獲窗口與一個捕獲設(shè)備連接或關(guān)聯(lián)連接上后,就可以通過捕獲窗口向捕獲設(shè)備發(fā)送各種消息,可以使用函數(shù)capGetDriverDescription來獲得已安裝的捕獲設(shè)備名稱及版本,將其列舉在實現(xiàn)程序過程中。再利用capDriverGetName函數(shù)來得到捕獲設(shè)備的名稱將獲得的版本發(fā)送到capDriverGetVersion。如果斷開捕獲窗口與捕獲設(shè)備的連接用capDriverDisconnect。</p

89、><p>  捕獲窗口的狀態(tài),用capGetStatus函數(shù)來獲得當前捕獲窗口的狀態(tài),得到一個CAPSTATUS結(jié)構(gòu)的拷貝。該結(jié)構(gòu)的內(nèi)容包含了圖片的尺寸、卷軸的當前位置、overlay和preview是否已設(shè)置。由于其信息是動態(tài)的,每當捕獲的視頻流的尺寸發(fā)生改變,程序應該在獲取捕獲設(shè)備的視頻格式以后及時進行刷新。而捕獲窗口尺寸的改變并不影響實際的捕獲視頻流的尺寸。該尺寸由視頻捕獲設(shè)備的格式和視頻對話框決定。</

90、p><p><b>  //捕獲窗口</b></p><p>  BOOL VideoCapture::Initialize()</p><p><b>  {</b></p><p>  char devname[128]={0},devversion[128]={0};</p><

91、;p>  int index=0;</p><p>  BOOL ret = TRUE, ret1 = TRUE, ret2 = TRUE, ret3 = TRUE;</p><p>  TRACE("VideoCapture::Initialize\n");</p><p>  //創(chuàng)建一個AVICap捕獲窗口</p>&l

92、t;p>  m_capwnd = capCreateCaptureWindow("Capture",WS_POPUP,0,0,1,1,0,0);</p><p>  if(!m_capwnd)</p><p><b>  {</b></p><p>  return FALSE;</p><p>

93、;<b>  }</b></p><p>  //connect callback functions</p><p>  ret = capSetUserData(m_capwnd,this);</p><p>  //Change destroy functions also........</p><p>  re

94、t1 = capSetCallbackOnVideoStream(m_capwnd,OnCaptureVideo);</p><p>  //得到已安裝的捕獲設(shè)備的名稱及版本</p><p>  ret2 = capGetDriverDescription(index,devname,100,devversion,100);</p><p>  // Connect

95、 to webcam driver</p><p>  //使一個捕獲窗口與一個捕獲設(shè)備連接或關(guān)聯(lián)</p><p>  ret3 = capDriverConnect(m_capwnd,index);</p><p>  if(!(ret && ret1 && ret2 && ret3))</p><

96、;p><b>  {</b></p><p>  // Device may be open already or it may not have been</p><p>  // closed properly last time.</p><p>  AfxMessageBox("Unable to open Video

97、Capture Device");</p><p>  //log.WriteString("\n Unable to connect driver to the window");</p><p>  m_capwnd=NULL;</p><p>  return FALSE;</p><p><b&g

98、t;  }</b></p><p>  // Set the capture parameters</p><p>  if(SetCapturePara()==FALSE)</p><p><b>  {</b></p><p>  // log.WriteString("\n Setting

99、 capture parameters failed");</p><p>  capDriverDisconnect(m_capwnd); //使捕獲窗口與一個捕獲設(shè)備斷開</p><p>  return FALSE;</p><p><b>  }</b></p><p>  return TRUE;&l

100、t;/p><p><b>  }</b></p><p><b>  視頻捕獲驅(qū)動</b></p><p>  視頻捕獲必須具有視頻捕獲驅(qū)動才能進行,其相關(guān)內(nèi)容如下:</p><p>  視頻捕獲驅(qū)動的性能,capDriverGetCap函數(shù)得到當前連接視頻驅(qū)動的硬件性能,該信息保存在CAPDRIVER

101、CAPS結(jié)構(gòu)中;視頻對話框,每個視頻驅(qū)動能夠提供4個對話框來控制視頻捕獲和數(shù)字化處理視頻對話框定義的視頻壓縮率和圖像品質(zhì)等。視頻對話框都在視頻捕獲驅(qū)動中定義。這個四個對話框分別為:Video Source對話框用于控制選擇視頻來源(capDlgVideoSource);Video Format對話框定義視頻幀的尺寸和精度,以及視頻捕獲卡的壓縮設(shè)置(capDlgVideoFormat);Video Display對話框控制在視頻捕獲期間相

102、關(guān)顯示器上的顯示(capDlgVideoDisplay);Video Compression對話框控制壓縮和圖像品質(zhì)(caoDlgVideoCompression)。</p><p><b>  語音錄制</b></p><p>  在音頻的錄制和播放時,采用的用戶界面線程來處理,是CWinThread對象,根據(jù)前面線程的介紹,一步一步的來實現(xiàn)。錄音用的一個CWinT

103、hread對象CAudioRec來實現(xiàn),部分實現(xiàn)代碼:</p><p>  LRESULT CAudioRec::OnStartRecording(WPARAM wp, LPARAM lp)</p><p><b>  {</b></p><p>  if(recording)return FALSE;</p><p>

104、;<b>  //打開錄音設(shè)備</b></p><p>  MMRESULT mmReturn = ::waveInOpen( &m_hRecord, WAVE_MAPPER,</p><p>  &m_WaveFormatEx, ::GetCurrentThreadId(), 0, CALLBACK_THREAD);</p><p

105、>  if(mmReturn!=MMSYSERR_NOERROR )return FALSE;</p><p>  if(mmReturn==MMSYSERR_NOERROR )</p><p><b>  {</b></p><p>  for(int i=0; i < MAXRECBUFFER ; i++)</p>

106、<p><b>  {</b></p><p>  //為錄音設(shè)備準備緩存</p><p>  mmReturn = ::waveInPrepareHeader(m_hRecord,</p><p>  rechead[i], sizeof(WAVEHDR));</p><p>  //給輸入設(shè)備增加一個緩

107、存</p><p>  mmReturn = ::waveInAddBuffer(m_hRecord,</p><p>  rechead[i], sizeof(WAVEHDR));</p><p><b>  }</b></p><p>  mmReturn = ::waveInStart(m_hRecord);

108、//開始錄音</p><p>  if(mmReturn==MMSYSERR_NOERROR ) recording=TRUE;</p><p><b>  }</b></p><p>  return TRUE;</p><p><b>  }</b></p><p>&

109、lt;b>  語音回放</b></p><p>  相對錄音而言,播放就簡單多了,同樣用的一個CWinThread對象CAudioPlay來實現(xiàn),部分實現(xiàn)代碼:</p><p>  LRESULT CAudioPlay::OnWriteSoundData(WPARAM wParam, LPARAM lParam)</p><p><b>

110、  {</b></p><p>  //TRACE("CAudioPlay::OnWriteSoundData\n");</p><p>  MMRESULT mmResult = FALSE;</p><p>  char *p=NULL;</p><p>  int length=(int) wParam

111、;</p><p>  if(Playing==FALSE)return FALSE;</p><p>  if(length<=0)return FALSE;</p><p>  WAVEHDR *lpHdr=new WAVEHDR;</p><p>  if(!lpHdr)return FALSE;</p>&l

112、t;p>  p=new char [length];</p><p>  if(!p){delete lpHdr;</p><p>  return FALSE;}</p><p>  ZeroMemory(lpHdr,sizeof(WAVEHDR));</p><p>  ZeroMemory(p,length);</p>

113、;<p>  CopyMemory(p,(char*)lParam,length);</p><p>  lpHdr->lpData=p;</p><p>  lpHdr->dwBufferLength = length;</p><p>  mmResult = ::waveOutPrepareHeader(m_hPlay, lpHdr,

114、 sizeof(WAVEHDR)); </p><p>  //為回放設(shè)備準備內(nèi)存塊</p><p>  if(mmResult)</p><p><b>  {</b></p><p>  delete lpHdr;delete p;</p><p>  return mmResult;<

115、/p><p><b>  }</b></p><p>  mmResult = ::waveOutWrite(m_hPlay, lpHdr, sizeof(WAVEHDR));//寫數(shù)據(jù)(放音)</p><p>  if(mmResult){delete lpHdr;delete p;</p><p>  return mm

116、Result; }</p><p>  m_Count++;</p><p>  return MMSYSERR_NOERROR;</p><p><b>  }</b></p><p><b>  視音頻的傳輸</b></p><p>  視頻采集采用AVICap從視頻采集

117、卡捕獲視頻圖像,得到的是位圖形式的視頻幀,然后用Divx編碼器進行壓縮,壓縮以后形成以幀為格式的Mpeg4流。通過Winsock實現(xiàn)壓縮后的視頻數(shù)據(jù)在局域網(wǎng)中的實時傳輸,接收完的數(shù)據(jù)交給Divx解碼器,以幀的格式解壓,最后實現(xiàn)視頻顯示。所以提出以幀為單位發(fā)送視頻數(shù)據(jù)流。為了在接收端能夠方便地提取出一幀,提出如表1所示的格式組建幀。完整的一幀由5個字段組成,各個字段的意義如下:幀開始標志:標志著一幀地開始,占用4個字節(jié)的空間;幀大?。罕硎?/p>

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論