视频技术
轉自http://www.cnblogs.com/light169/archive/2007/03/24/686406.html
?
點對點視頻會議程序VideoNet開發例解
Easy Digital Camera Connection
VideoNet
利用VC++實現局域網實時視頻傳輸
VC++6.0平臺下利用DirectShow技術實現DV設備的視頻處理
CAviCap and CFrameGrabber - wrappers for AVICap Window
Tracking an object from a live video input
http://tag.csdn.net/tag/directshow/2.html? CSDN上很多例子
http://search.csdn.net/search/DirectShow/4/dev/
在VC中調用DirectShow全屏播放視頻
Directshow(SDK)學習筆記九_視頻捕捉
用DirectShow實現QQ的音視頻聊天功能
用.NET 2.0壓縮/解壓功能處理大型數據
DirectShowNet Library
http://directshownet.sourceforge.net/
室外5公里的802.11B無線遠程連接
用Delphi開發視頻聊天軟件
基于VFW的視頻應用程序開發?
Visual C++視頻會議開發技術與實例(附光盤)
我去年做了一段時間局域網上的實時視頻傳輸,如果是服務器對多用戶進行實時的視頻傳輸,以我的經驗: ?
? ? ? ? 1.服務器軟件用多線程: ?
? ? ? ? ? ? (1)主線程:讀出(看你的圖象具體怎么上PC機了)一幀視頻數據,送給拆分線程。 ?
? ? ? ? ? ? (2)拆分線程:接到一幀視頻,開始拆包、做幀標記、打序列號,送給發送線程。 ?
? ? ? ? ? ? (3)發送線程:用RTP ? socket把封裝好的數據包發給客戶端。此socket是點對多點、單向 ?
? ? ? ? ? ? ? ? ? ? 有根方式的組播套接字,實際上是基于UDP派生的,但他用到了RTP和RTCP(實時傳輸 ?
? ? ? ? ? ? ? ? ? ? 協議和實時傳輸控制協議),如果你傳輸的不是實時數據,直接用UDP就行了。 ?
? ?
? ? ? ? 2.客戶端軟件結構一般用多線程,線程間用事件對象進行同步,而共享數據區用臨界區對象進 ?
? 行同步。 ?
? ? ? ? ? (1)主線程:接收網絡數據包的線程,優先級最高,可以盡量保證不丟數據,也采用RTP協 ?
? ? ? ? ? ? ? ? ? ? 議,用網絡事件來觸發。主線程接收到視頻數據包后,將數據放入一個鏈表中,然后 ?
? ? ? ? ? ? ? ? ? ? 用事件對象觸發組裝線程。 ?
? ? ? ? ? (2)組裝線程:從鏈表中讀出數據包,要進行幀確認、排序等工作,當把一幀圖象的所有 ?
? ? ? ? ? ? ? ? ? 包都取到時,再調用組裝模塊(可以是一個函數),將這些數據包組裝成完整的一個 ?
? ? ? ? ? ? ? ? ? 幀,然后送到解壓線程。 ?
? ? ? ? ? (3)若干解壓播放線程。主要考慮到如果你客戶端軟件想同時播放多畫面,比如說4畫面圖 ?
? ? ? ? ? ? ? ? ? ? 象,就要用4個解壓播放線程。 ?
? ? ? ? ? (4)至于圖象存儲,要看你的客戶需要怎么存了,如果是手工存當然不需要單開線程,如果 ?
? ? ? ? ? ? ? ? ? 是規定定時存或在某個事件發生時自動存盤,就需要單開一個線程,由定時器到時消息 ?
? ? ? ? ? ? ? ? ? 或此事件發生來觸發。??
將每幀視頻數據按某種編碼格式編碼(如mpg4, ? h263等)壓縮通過rtp傳輸到另一機子上,用rtcp控制調整傳輸速率。 ?
? 你可以先用udp傳一下看看。 ?
? ?
? http://www.dlc.sjtu.edu.cn/newspost/newsdetail.asp?newsno=1546 ?
? ?
? 目前,互聯網上用于多媒體數據流的技術協議有實時傳輸協議RTP、實時傳輸控制協議RTCP、實時流協議RTSP、資源預訂協議RSVP等。RTP主要處理一對一、一對多的多媒體數據流傳輸任務,可以按照UDP、TCP及ATM等協議傳輸數據,負責提供時間信息和控制流同步。RTCP的作用則在于與RTP一起解決非常關鍵的流量控制和擁塞控制問題,兩種協議配合使用可以大大提高傳輸效率,所以是在線實時數據傳送的主要方式。RTSP協議定義一對多程序有效地通過IP網絡傳送多媒體數據的方式,在體系結構中位于RTP和RTCP之上。與HTTP協議相比,RTSP的特點在于客戶端和服務器端都可以發出請求,是一種雙向的傳輸協議。另外,由于多媒體數據的流式傳輸對網絡延時非常敏感,所以需要預先為流媒體的傳輸預留一部分網絡帶寬,這項功能可以通過資源預訂協議RSVP獲得實現。 ? ?
? ?
? 文件格式 ? ?
? 與傳輸協議的相對統一不同,流媒體文件的格式現在相當繁雜,如視頻文件就有MPEG、AVI、RM、DVI、QuickTime等多種格式,其它還有ASF、應用于Flash動畫的SWF等格式。不過總的來說,在互聯網上得到廣泛應用的還是微軟的ASF、RealNetworks的Real ? system和蘋果公司的QuickTime。ASF在微軟深厚的市場應用和技術實力支持下,不僅可以以任何編碼方式進行壓縮和解壓縮,還適應于所有的底層網絡傳輸協議,所以推出后迅速成為主要的流媒體文件格式。RealSystem則包括了RealAudio、RealVideo、RealFlash和RealPresentation四種文件格式,分別用于制作不同類型的流媒體文件。RealSystem是幾乎每個網絡用戶都曾經接觸過的流媒體技術,性能表現非常穩定,大量的流媒體服務網站都采用了這項技術,中國網絡用戶看到的多數在線影視節目也都是RealSystem格式的。QuickTime和RealSystem一樣,也是出現較早的流媒體文件格式之一,目前已經發展到支持實時和快速啟動兩種類型的數據流,應用方式相當靈活。這三種流媒體技術都有廠商提供的成熟的支持系統,系統中一般包括流媒體文件的制作、發布、客戶端播放等多種工具,便于技術的推廣應用。 ? ?
? 不過互聯網上的主流技術不一定能充分滿足廣電行業的需求,一些專家在談及廣電領域的流媒體應用時,就更為看好MPEG-4。MPEG-4的突出優點是具有交互功能,可以使影視節目具有類似網站和視頻游戲的交互性,而這正是新一代廣電系統的發展方向之一。再加上無線視頻傳輸通常采用MPEG-4格式,所以MPEG-4的發展潛力是相當可觀的。??
include ? <dshow.h> ?
? #include ? <streams.h> ?
? #include ? <windows.h> ?
? #include ? <mmsystem.h> ?
? #include ? <stdio.h> ?
? ?
? class ? CMemStream ? : ? public ? CAsyncStream ?
? { ?
? public: ?
? ? ? ? ? CMemStream(LPBYTE ? pbData, ? LONGLONG ? llLength, ? DWORD ? dwKBPerSec ? = ? INFINITE) ? : ?
? ? ? ? ? ? ? ? ? m_pbData(pbData), ?
? ? ? ? ? ? ? ? ? m_llLength(llLength), ?
? ? ? ? ? ? ? ? ? m_rllPosition(0), ?
? ? ? ? ? ? ? ? ? m_dwKBPerSec(dwKBPerSec) ?
? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? m_dwTimeStart ? ? = ? timeGetTime(); ?
? ?
? clearPlayBuf(); ?
? ?
? m_packetsize ? = ? 1024*32; ?
? ?
? m_packetnum ? = ? 32; //1M ?
? ?
? m_playbufsize ? ? = ? m_packetsize ? * ? m_packetnum; ?
? ?
? m_playbuf ? ? ? ? ? ? = ? new ? BYTE[m_playbufsize]; ?
? ?
? m_llLength ? = ? 4000000000000; ?
? ?
? m_fileheadsize ? = ? m_packetsize ? * ? 10; ?
? ?
? hMutex ? = ? CreateMutex(NULL,FALSE,"protect ? buf"); ?
? ?
? m_bheadover ? = ? FALSE; ?
? ?
? m_breadnum ? ? ? ? ? = ? 0; ?
? ?
? hLogFile ? = ? fopen("log.txt","w+"); ?
? ?
? ? ? ? ? } ?
? ? ? ?
? ~CMemStream() ?
? ? ? { ?
? clearPlayBuf(); ?
? ?
? delete ? m_playbuf; ?
? ?
? fclose(hLogFile); ?
? ? ? } ?
? ?
? ? ? ? ? HRESULT ? Read(PBYTE ? pbBuffer, ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DWORD ? dwBytesToRead, ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? BOOL ? bAlign, ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LPDWORD ? pdwBytesRead) ?
? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? CAutoLock ? lck(&m_csLock); ?
? ? ? ? ? ? ? ? ? DWORD ? dwReadLength; ?
? ?
? ?
? dwReadLength ? = ? dwBytesToRead; ?
? ? ? ? ? ? ? ? ? ?
? //當沒有處理完播放頭的時候處于等待狀態 ?
? if(!m_bheadover) ?
? { ?
? while(m_a_fw < m_fileheadsize) ?
? { ?
? fprintf(hLogFile,"Wait ? Head/n"); ?
? Sleep(100); ?
? } ?
? } ?
? ?
? m_bheadover = ? TRUE; ?
? ?
? ?
? while(CanR()==false) ?
? { ?
? fprintf(hLogFile,"CanR=false"); ?
? Sleep(100); ?
? } ?
? fprintf(hLogFile,"/n"); ?
? ?
? m_rllPosition = m_a_fr ? % ? m_playbufsize; ?
? ?
? //fprintf(hLogFile,"Read:m_rllPosition=%d/n",m_rllPosition); ?
? //fprintf(hLogFile,"Read:m_wllPosition=%d/n/n",m_wllPosition); ?
? ?
? //讀取緩沖區數據并播放 ?
? WaitForSingleObject(hMutex,INFINITE); ? ?
? ?
? CopyMemory((PVOID)pbBuffer, ?
? ? (PVOID)(m_playbuf+m_rllPosition), ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dwReadLength); ?
? ?
? ReleaseMutex(hMutex); ?
? ?
? m_a_fr ? += ? dwReadLength; ?
? ?
? *pdwBytesRead ? ? ? = ? dwReadLength; ?
? ? ? ? ? ? ? ? ? ?
? return ? S_OK; ?
? ? ? ? ? } ?
? ?
? bool ? Write(PBYTE ? buf) ?
? ? ? { ?
? if(CanW()==false) ?
? { ?
? fprintf(hLogFile,"CanW=false"); ?
? return ? false; ?
? } ?
? fprintf(hLogFile,"/n"); ?
? ?
? m_wllPosition = m_a_fw ? % ? m_playbufsize; ?
? ?
? //fprintf(hLogFile,"Write:m_rllPosition=%d/n",m_rllPosition); ?
? //fprintf(hLogFile,"Write:m_wllPosition=%d/n/n",m_wllPosition); ?
? ?
? //添加新的數據進緩沖區 ?
? WaitForSingleObject(hMutex,INFINITE); ? ?
? ? ? ?
? CopyMemory((PVOID)(m_playbuf+m_wllPosition), ?
? ? (PVOID)buf, ?
? ? m_packetsize); ? ?
? ?
? ReleaseMutex(hMutex); ?
? ?
? m_a_fw ? += ? m_packetsize; ?
? ?
? return ? true; ?
? ? ? } ?
? ? ? ?
? ULONG getPacketSize() ?
? { ?
? return ? m_packetsize; ?
? } ?
? ?
? HRESULT ? SetPointer(LONGLONG ? llPos) ?
? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? if ? (llPos ? < ? 0 ? || ? llPos ? > ? m_llLength) ? { ?
? ? ? ? ? ? ? ? ? ? ? ? ? return ? S_FALSE; ?
? ? ? ? ? ? ? ? ? } ? else ? { ?
? //關鍵,過濾器要對流預讀,會有一次跳回0. ?
? //害的我調試了兩天,發發牢騷,哈哈~ ?
? ? ? ? ? ? ? ? ? ? ? ? ? m_a_fr ? = ? llPos; ?
? ? ? ? ? ? ? ? ? ? ? ? ? return ? S_OK; ?
? ? ? ? ? ? ? ? ? } ?
? ? ? ? ? } ?
? ?
? void ? setFileHeadSize(ULONG ? fileheadsize) ?
? { ?
? if(fileheadsize > m_packetsize ? *10) ?
? { ?
? m_fileheadsize = fileheadsize; ?
? }else{ ?
? m_fileheadsize ? = ? m_packetsize*10; ?
? } ?
? } ?
? ?
? ?
? ? ? ? ? LONGLONG ? Size(LONGLONG ? *pSizeAvailable) ?
? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? LONGLONG ? llCurrentAvailable ? = ?
? ? ? ? ? ? ? ? ? ? ? ? ? Int32x32To64((timeGetTime() ? - ? m_dwTimeStart),m_dwKBPerSec); ?
? ? ? ? ? ? ? ? ? *pSizeAvailable ? = ? min(m_llLength, ? llCurrentAvailable); ?
? ? ? ? ? ? ? ? ? return ? m_llLength; ?
? ? ? ? ? } ?
? ?
? void ? clearPlayBuf() ?
? { ?
? m_rllPosition ? ? = ? 0; ?
? ?
? m_wllPosition ? ? = ? 0; ?
? ?
? m_a_fr ? = ? 0; ?
? ?
? m_a_fw ? = ? 0; ?
? ?
? } ?
? ?
? bool ? CanR() ?
? { ?
? ? ? if ? ((m_a_fw - m_a_fr) >= ? m_packetsize) ?
? { ?
? return ? true; ?
? }else{ ?
? return ? false; ?
? } ?
? } ?
? ?
? bool ? CanW() ?
? { ?
? if ? ((m_a_fw - m_a_fr) <= ? (m_playbufsize - m_packetsize)) ?
? { ?
? return ? true; ?
? }else{ ?
? return ? false; ?
? } ?
? } ?
? ?
? ?
? ?
? ? ? ? ? DWORD ? Alignment() ?
? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? return ? 1; ?
? ? ? ? ? } ?
? ? ? ? ? void ? Lock() ?
? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? m_csLock.Lock(); ?
? ? ? ? ? } ?
? ? ? ? ? void ? Unlock() ?
? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? m_csLock.Unlock(); ?
? ? ? ? ? } ?
? ?
? private: ?
? ? ? ? ? CCritSec m_csLock; ?
? ? ? ? ? const ? PBYTE m_pbData; ?
? ? ? ? ? LONGLONG m_llLength; ?
? ? ? ? ? DWORD m_dwKBPerSec; ?
? ? ? ? ? DWORD m_dwTimeStart; ?
? ?
? PBYTE m_playbuf; //自定義緩沖區 ?
? ULONG m_playbufsize; ? ? ? ? //自定義緩沖區大小 ?
? ULONG m_packetsize; //一幀的大小 ?
? ULONG m_packetnum; //緩沖區中幀的數量 ?
? ?
? ULONG m_wllPosition; ? ? ? ? //相對寫地址 ?
? ? ? ULONG m_rllPosition; ? ? ? ? //相對讀地址 ?
? ?
? ? ? ? ? LONGLONG m_a_fr; //絕對讀地址 ?
? LONGLONG m_a_fw; //絕對寫地址 ?
? ?
? HANDLE hMutex; //關鍵段保護 ?
? ?
? ULONG m_fileheadsize; //要預讀的文件頭大小 ?
? BOOL m_bheadover; //時候讀完頭 ?
? ?
? ULONG m_breadnum; //流指針跳回0的次數 ?
? ?
? FILE *hLogFile; ?
? }; ?
? ?
? class ? CMemReader ? : ? public ? CAsyncReader ?
? { ?
? public: ?
? STDMETHODIMP ? Register() ?
? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? return ? S_OK; ?
? ? ? ? ? } ?
? ? ? ? ? STDMETHODIMP ? Unregister() ?
? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? return ? S_OK; ?
? ? ? ? ? } ?
? ? ? ? ? CMemReader(CMemStream ? *pStream, ? CMediaType ? *pmt, ? HRESULT ? *phr) ? : ?
? ? ? ? ? ? ? ? ? CAsyncReader(NAME("Mem ? Reader"), ? NULL, ? pStream, ? phr) ?
? ? ? ? ? { ?
? ? ? ? ? ? ? ? ? m_mt ? = ? *pmt; ?
? ? ? ? ? } ?
? };??
當前,在Windows 平臺下開發視頻應用程序一般采用兩種方式:一種是基于視頻采集卡所附帶的二次軟件開發包SDK(Software development kit)進行。這種方式的優點是應用方便,容易上手,缺點是對硬件的依賴性較強,靈活性差,且功能參差不齊,不能充分滿足各種視頻應用程序的開發需要;
另一種方式是基于VFW(Video for Windows)進行的。VFW 是Microsoft公司為開發Windows平臺下的視頻應用程序提供的軟件工具包,提供了一系列應用程序編程接口(API),用戶可以通過它們很方便地實現視頻捕獲[1]、視頻編輯及視頻播放等通用功能,還可利用回調函數開發更復雜的視頻應用程序。它的特點是播放視頻時不需要專用的硬件設備,而且應用靈活,可以滿足視頻應用程序開發的需要。Windows操作系統自身就攜帶了VFW,系統安裝時,會自動安裝VFW的相關組件。VC++自4.0以來就支持VFW,大大簡化了視頻應用程序的開發。目前,PC機上多媒體應用程序的視頻部分,大都是利用VFW API開發的。
1?VFW 的體系結構
VFW以消息驅動方式對視頻設備進行存取,可以很方便地控制設備數據流的工作過程。目前,大多數的視頻采集卡驅動程序都支持VFW接口,它主要包括多個動態連接庫,通過這些組件間的協調合作,來完成視頻的捕獲、視頻壓縮及播放功能。VFW體系結構如圖1所示。
1)VICAP.DLL:主要實現視頻捕獲功能,包含了用于視頻捕獲的函數,為音像交錯AVI (Audio video interleaved)格式文件和視頻、音頻設備程序提供一個高級接口。
2)MSVIDEO.DLL:能夠將視頻捕獲窗口與獲驅動設備連接起來,支持ICM視頻編碼服務。
3)MCIAVI.DRV:包含MCI(Media control interface)命令解釋器,實現回放功能。
4)AVIFILE.DLL:提供對AVI文件的讀寫操作等文件管理功能。
5)ICM ( Installable compression manager ):即壓縮管理器,提供對存儲在AVI文件中視頻圖像數據的壓縮、解壓縮服務。
???????6)ACM ( Audio Compression Manager ):即音頻壓縮管理器,提供實時音頻壓縮及解壓縮功能。
| Capture Application |
| Playback Application |
| Edit Application |
| AVICAP.DLL ?AVICAP |
| MSVIDEO.DLL MCIWnd |
| ACM |
| MCIAVI.DRV MCI Command Interpreter |
| MSVIDEO.DLL Video in???? ICM Channel |
| AVIFILE.DLL File / Stream Handler |
| MSVIDEO.DLL Drawdib?ICM? |
| Capture Application |
| Playback Application |
| Edit Application |
| AVICAP.DLL ?AVICAP |
| MSVIDEO.DLL MCIWnd |
| ACM |
| MCIAVI.DRV MCI Command Interpreter |
| MSVIDEO.DLL Video in???? ICM Channel |
| AVIFILE.DLL File / Stream Handler |
| MSVIDEO.DLL Drawdib?ICM? |
| Capture Application |
| Playback Application |
| Edit Application |
| AVICAP.DLL ? ? AVICAP |
| MSVIDEO.DLL ? ? MCIWnd |
| ACM |
| MCIAVI.DRV ? ? MCI Command Interpreter |
| MSVIDEO.DLL ? ? Video in???? ICM Channel |
| ? AVIFILE.DLL ? File / Stream Handler |
| ? MSVIDEO.DLL ? Drawdib?ICM? |
?2?視頻捕獲
視頻數據的實時采集,主要通過AVICAP模塊中的消息、宏函數、結構以及回調函數來完成。視頻捕獲的一般過程如下:
2.1 建立捕獲窗口
利用AVICAP 組件函數 capCreateCaptureWindow() 建立視頻捕獲窗口,它是所有捕獲工作及設置的基礎,其主要功能包括:① 動態地同視頻和音頻輸入器連接或斷開;② 設置視頻捕獲速率;③ 提供視頻源、視頻格式以及是否采用視頻壓縮的對話框;④ 設置視頻采集的顯示模式為Overlay或為Preview; ⑤ 實時獲取每一幀視頻數據;⑥ 將一視頻流和音頻流捕獲并保存到一個AVI文件中; ⑦ 捕獲某一幀數字視頻數據,并將單幀圖像以DIB格式保存;⑧ 指定捕獲數據的文件名,并能將捕獲的內容拷貝到另一文件。
2.2 登記回調函數[2]
登記回調函數用來實現用戶的一些特殊需要。在以一些實時監控系統或視頻會議系統中,需要將數據流在寫入磁盤以前就必須加以處理,達到實時功效。應用程序可用捕獲窗來登記回調函數,以便及時處理以下情況:捕獲窗狀態改變、出錯、使用視頻或音頻緩存、放棄控制權等,相應的回調函數分別為 capStatusCallback(), capErrorCallback(), capVideoStreamCallback(), capWaveStreamCallback(),capYieldCallback()。
2.3 獲取捕獲窗口的缺省設置
通過宏capCaptureGetSetup(hWndCap,&m_Parms,sizeof(m_Parms))來完成。
2.4 設置捕獲窗口的相關參數
通過宏capCaptureSetSetup(hWndCap,&m_Parms,sizeof(m_Parms))來完成。
2.5 連接捕獲窗口與視頻捕獲卡
通過宏capDriveConnect(hWndCap,0)來完成。
2.6 獲取采集設備的功能和狀態
通過宏capDriverGetCaps(hWndCap,&m_CapDrvCap,sizeof(CAPDRIVERCAPS))來獲取
視頻設備的能力,通過宏capGetStatus(hWndCap,&m_CapStatus,sizeof(m_CapStatus))
來獲取視頻設備的狀態。
2.7 設置捕獲窗口顯示模式
視頻顯示有Overlay(疊加)和Preview(預覽)兩種模式。在疊加模式下,捕獲視頻數據布展系統資源,顯示速度快,視頻采集格式為YUV格式,可通過capOverlay(hWndCap,TRUE)來設置;預覽模式下要占用系統資源,視頻由系統調用GDI函數在捕獲窗顯示,顯示速度慢,它支持RGB視頻格式。
2.8 捕獲圖像到緩存或文件并作相應處理
若要對采集數據進行實時處理,則應利用回調機制,由capSetCallbackOnFrame(hWndCap, FrameCall-
backProc)完成單幀視頻采集;由capSetCallbackOnVideoStream(hWndCap, VideoCallbackProc)完成視頻流采集。如果要保存采集數據,則可調用capCaptureSequence(hWnd);要指定文件名,可調用capFileSetCap-
ture(hwnd, Filename)。
2.9 終止視頻捕獲 斷開與視頻采集設備的連接
調用capCatureStop(hWndCap)停止采集,調用capDriverDisconnect(hWndCap), 斷開視頻窗口與捕獲驅動程序的連接。
3?視頻編輯和播放
利用VFW,不僅可以實現視頻流的實時采集,還提供了編輯和播放功能,主要通過AVIFILE、ICM、ACM、MCIWnd 等組件之間的協作來完成。
?????? 1) AVIFileInit();//初始化;
2) AVIFileOpen(); //打開一個AVI文件并獲文件的句柄;
3) AVIFileInfo(); //獲取文件的相關信息,如圖像的Width和Height等;
4) AVIFileGetStream(); //建立一個指向需要訪問的數據流的指針;
5) AVIStreamInfo(); //獲取存儲數據流信息的AVISTREAMINFO結構;
6) AVIStreamRead(); //讀取數據流中的原始數據, 對AVI文件進行所需的編輯處理;
7) AVIStreamRelease(); //釋放指向視頻流的指針;
8) AVIFileRelease();AVIFileExit(); //釋放AVI文件。
若數據是壓縮過的,則用AVIStreamGetFrameOpen(),AVIStreamGetFrame()和AVIStreamGetFrameClose()來操作,可以完成對視頻流的逐幀分解。
3.2?視頻播放
對于實現視頻流的播放,VFW提供了MCIWnd窗口類[4],主要用于創建視頻播放區,控制并修改MCI窗口當前加載媒體的屬性。一個由函數、消息和宏組成的庫與MCIWnd相關聯,通過它們可以進行AVI文件操作,很方便地使應用程序完成視頻播放功能。
1)MCIWndCreate(); //注冊MCIWnd窗口類,創建MCIWnd窗口,并指定窗口風格;
2)AVIFileInit(); //初始化;
3) AVIFileOpen(); //打開AVI文件;
4) AVIFileGetStream(); //獲得視頻流;
5)運用相關函數進行各種播放任務:MCIWndPlay()正向播放AVI文件內容,MCIWndPlayReverse()反向播放,MCIWndResume() 恢復播放,MCIWndPlayPause()暫停播放,MCIWndStop()停止播放等等。
6) AVIStreamRelease(); //釋放視頻流;
7)AVIFileRease();AVIFileExit(); //斷開與AVI文件的連接,釋放視頻源。
由以上步驟可以看出,視頻播放是視頻編輯其中的一種操作。
總結
- 上一篇: C++运用类函数创造对象,求自定义边长的
- 下一篇: RouterOS v7 策略路由配置实例