DirectShow組件原理分析及應用

1 DirectX簡介

  DirectX是Microsoft公司為游戲和其他高性能多媒體應用所提供的一套底層應用程序編程接口。這些接口包括對二維和三維圖形,聲效和音樂,輸入設備以及多玩家網絡游戲等的支持。目前DirectX的最高版本是DirectX 9.0。

  1.1 DirectX的組成

  DirectX 9.0由下列組件構成:

  (1)DirectX Graphics:該組件組合DirectX舊版本中的DirectDraw和Direct3D兩個組件,使其成為一個適用于所有圖形程序的單獨的應用程序接口。其中的Direct3D擴展(D3DX)應用程序庫簡化了多數圖形程序的工作。

  (2)DirectInput:支持各種輸入設備,完全支持力反饋技術。

  (3)DirectPlay:支持多玩家網絡游戲。

  (4)DirectSound:支持用于播放和捕獲音頻波形的高性能音頻應用軟件的開發。

  (5)DirectMusic:為音樂音軌以及基于波表、MIDI(Musical Instrument Devices Interface)或其他由DirectMusic Producer創作的非音樂音軌,提供了一套完整的解決方案。

  (6)DirectShow:提供對多媒體數據流的高質量捕獲和回放。

  (7)DirectSetup:一個簡單的應用程序接口,提供DirectX組件的自動安裝。

  (8)DirectX Media Objects:提供對數據流對象的讀寫支持,包括視頻和音頻的編解碼器及其效果。

  1.2 COM簡介

  DirectX的功能都是以COM組件的形式提供的。COM是組件對象模型(Component Object Model)的簡寫,它是一種協議,是對象連接和嵌入(Object Linking and Embedding)的基礎。COM通常以動態鏈接庫(DLL)的形式存在,它是建立在二進制規范上的對象。COM定義并實現了軟部件(如應用程序、數據對象、控件及服務)機制,并把他們統稱為"對象"。每個軟部件對象由數據以及訪問數據的函數組成,訪問軟部件對象數據的函數集合稱為"接口"。在應用程序看來COM是一個黑箱,可調用COM提供的方法但不知道它的具體實現。在使用DirectShow編程時,用戶創建的自定義組件必須以COM形式實現,所以必須知道如何實現COM,而一般的應用程序只需要了解COM的接口和用法就可以了。
2 DirectShow的系統組成

  DirectShow技術是建立在DirectDraw和DirectSound組件基礎之上的,它通過DirectDraw對顯卡進行控制以顯示視頻,通過DirectSound對聲卡進行控制以播放聲音。 DirectShow可提供高質量的多媒體流的捕獲和回放功能;支持多種媒體格式,包括ASF(Advanced Systems Format),MPEG(Motion Picture Experts Group),AVI(Audio-Video Interleaved),MP3(MPEG Audio Layer-3)和WAV聲音文件;可以從硬件上捕獲媒體數據流;可以自動檢測并使用視頻和音頻加速硬件。因此,DirectShow可以充分發揮媒體的性能,提高運行速度,可以簡化媒體播放、媒體間的格式轉換和媒體捕獲等工作。同時,它還具有極大的可擴展性和靈活性,可以由用戶自己創建組件,并將這個組件加入DirectShow結構中以支持新的格式或特殊的效果。
應用程序與DirectShow組件以及DirectShow所支持的軟硬件之間的關系如圖1所示。


圖1 DirectShow系統框圖

  2.1 過濾器(filter)

  由圖1可以看到,過濾器是DirectShow最基本的組成元件。過濾器是一個COM組件,是完成DirectShow處理過程的基本單元。 DirectShow提供了一組標準的過濾器供應用程序使用,程序開發者也可以創建自定義的過濾器來擴充DirectShow的功能,但必須是以COM形式建立的。DirectX為用戶提供了DirectShow基類庫(DirectShow Base Class Library),用戶自定義的過濾器都可以從基類庫提供的基類和接口派生出來。
過濾器主要分為以下幾種類型:

  (1)源過濾器(source filter):源過濾器引入數據到過濾器圖表中,數據來源可以是文件、網絡、照相機等。不同的源過濾器處理不同類型的數據源。

  (2)變換過濾器(transform filter):變換過濾器的工作是獲取輸入流,處理數據,并生成輸出流。變換過濾器對數據的處理包括編解碼、格式轉換、壓縮解壓縮等。

  (3)提交過濾器(renderer filter):提交過濾器在過濾器圖表里處于最后一級,它們接收數據并把數據提交給外設。

  (4)分割過濾器(splitter filter):分割過濾器把輸入流分割成多個輸出。例如,AVI分割過濾器把一個AVI格式的字節流分割成視頻流和音頻流。

  (5)混合過濾器(mux filter):混合過濾器把多個輸入組合成一個單獨的數據流。例如,AVI混合過濾器把視頻流和音頻流合成一個AVI格式的字節流。

  過濾器的這些分類并不是絕對的,例如一個ASF讀過濾器(ASF Reader filter)既是一個源過濾器又是一個分割過濾器。

   在DirectShow里,一組過濾器稱為一個過濾器圖表(filter graph)。過濾器圖表用來連接過濾器以控制媒體流,它也可以將數據返回給應用程序,并搜索所支持的過濾器。過濾器有三種可能的狀態:運行、停止和暫停。暫停是一種中間狀態,停止狀態到運行狀態必定經過暫停狀態。暫停可以理解為數據就緒狀態,是為了快速切換到運行狀態而設計的。在暫停狀態下,數據線程是啟動的,但被提交過濾器阻塞了。通常情況下,過濾器圖表中所有過濾器的狀態是一致的。

  2.2 引腳(pin)

  過濾器可以和一個或多個過濾器相連,連接的接口也是COM形式的,稱為引腳。過濾器利用引腳在各個過濾器間傳輸數據。每個引腳都是從Ipin這個COM對象派生出來的。每個引腳都是過濾器的私有對象,過濾器可以動態的創建引腳,銷毀引腳,自由控制引腳的生存時間。引腳可以分為輸入引腳(Input pin)和輸出引腳(Output pin)兩種類型,兩個相連的引腳必須是不同種類的,即輸入引腳只能和輸出引腳相連,且連接的方向總是從輸出引腳指向輸入引腳。

  過濾 器之間的連接(也就是引腳之間的連接),實際上是連接雙方媒體類型(Media Type)協商的過程。連接的大致過程為:如果調用連接函數時已經指定了完整的媒體類型,則用這個媒體類型進行連接,成功與否都結束連接過程;如果沒有指定或不完全指定了媒體類型,則進入下面的枚舉過程--枚舉欲連接的輸入引腳上所有的媒體類型,逐一用這些媒體類型與輸出引腳進行連接(如果連接函數提供了不完全媒體類型,則要先將每個枚舉出來的媒體類型與它進行匹配檢查),如果輸出引腳也接受這種媒體類型,則引腳之間的連接宣告成功;如果所有輸入引腳上枚舉的媒體類型,輸出引腳都不支持,則枚舉輸出引腳上的所有媒體類型,并逐一用這些媒體類型與輸入引腳進行連接,如果輸入引腳接受其中的一種媒體類型,則引腳之間的連接宣告成功;如果輸出引腳上的所有媒體類型,輸入引腳都不支持,則這兩個引腳之間的連接過程宣告失敗。過濾器與引腳連接如圖2所示。


圖2 過濾器和引腳連接示意圖

  2.3 媒體類型(Media Type)

  媒體類型是描述數字媒體格式的一種通用的可擴展方式。兩個過濾器相連時,必須使用一致的媒體類型,否則這兩個過濾器就不能相連。媒體類型能識別上一級過濾器傳送給下一級過濾器的數據類型,并對數據進行分類。
實際在很多應用程序中,用戶根本不需要擔心媒體類型的問題,DirectShow會處理好所有的細節。但有些應用程序需要對媒體類型進行操作。媒體類型一般可以有兩種表示:AM_MEDIA_TYPE和CMediaType。前者是一個結構,后者是從這個結構繼承過來的類。


  每個AM_MEDIA_TYPE由三部分組成:Major type、Subtype和Format type。這三個部分都使用GUID(全局唯一標識符)來唯一標示。Major type主要定性描述一種媒體類型,這種媒體類型可以是視頻、音頻、比特數據流或MIDI數據等等;Subtype進一步細化媒體類型,如果是視頻的話可以進一步指定是RGB-24,還是RGB-32,或是UYVY等等;Format type則用一個結構更進一步細化媒體類型。

  如果媒體類型的三個部分都指定了某個具體的GUID值,則稱這個媒體類型是完全指定的;如果媒體類型的三個部分中有任何一個值是GUID_NULL,則稱這個媒體類型是不完全指定的。GUID_NULL具有通配符的作用。


  2.4 過濾器圖表管理器(Filter Graph Manager)

  DirectShow通過過濾器圖表管理器來控制過濾器圖表中的過濾器。過濾器圖表管理器是COM 形式的,它的功能有:協調過濾器間的狀態轉變;建立參考時鐘;把事件(event)傳送給應用程序;為應用程序提供建立過濾器圖表的方法。

  一些常用的過濾器圖表管理器接口如下:

   IGraphBuilder:為應用程序提供創建過濾器圖表的方法。

   IMediaControl:提供控制過濾器圖表中多媒體數據流的方法,包括運行、暫停和停止。IMediaEventEx:繼承自IMediaEvent接口,處理過濾器圖表的事件。

   IVideoWindow:用于設置多媒體播放器窗口的屬性,應用程序可以用它來設置窗口的所有者、位置和尺寸等屬性。

   IBasicAudio:用于控制音頻流的音量和平衡。

   IBasicVideo:用于設置視頻特性,如視頻顯示的目的區域和源區域。

   IMediaSeeking:提供搜索數據流位置和設置播放速率的方法。

   IMediaPosition:用于尋找數據流的位置。

   IVideoFrameStep:用于步進播放視頻流,可使DirectShow應用程序,包括DVD播放器一次只播放一幀視頻。

  2.5 過濾器圖表中的數據流動

  當用戶要創建自定義的過濾器時,就需要了解媒體數據是如何在過濾器圖表中傳輸的。為了在過濾器圖表中傳送媒體數據,DirectShow過濾器需要支持一些協議,稱之為傳輸協議(transport)。相連的過濾器必須支持同樣的傳輸協議,否則不能交換媒體數據。

  大多數的DirectShow過濾器把媒體數據保存在主存儲器中,并通過引腳把數據提交給其它的過濾器,這種傳輸稱為局部存儲器傳輸(local memory transport)。雖然局部存儲器傳輸在DirectShow中最常用,但并不是所有的過濾器都使用它。例如,有些過濾器通過硬件傳送媒體數據,引腳只是用來提交控制信息,如IOverlay接口。

  DirectShow為局部存儲器傳輸定義了兩種機制:推模式(push model)和拉模式(pull model)。在推模式中,源過濾器生成數據并提交給下一級過濾器。下一級過濾器被動的接收數據,完成處理后再傳送給再下一級過濾器。在拉模式中,源過濾器與一個分析過濾器相連。分析過濾器向源過濾器請求數據后,源過濾器才傳送數據以響應請求。推模式使用的是IMemInputPin接口,拉模式使用 IAsyncReader接口,推模式比拉模式要更常用。
3 利用DirectShow開發簡單媒體播放器

  本節介紹基于DirectShow開發簡單媒體播放器的關鍵步驟。

  3.1 初始化DirectShow

  由于DirectShow的組件都是以COM形式存在的,因此首先要調用CoInitializeEx函數來初始化COM庫,嵌入所有的動態鏈接庫和資源。否則,所有對QueryInterface的調用都會失敗。

  3.2 創建過濾器圖表管理器接口

  首先申明并初始化所需的接口:
// DirectShow interfaces
IGraphBuilder *pGB = NULL;
IMediaControl *pMC = NULL;
IMediaEventEx *pME = NULL;
IVideoWindow *pVW = NULL;
IBasicAudio *pBA = NULL;
IBasicVideo *pBV = NULL;
IMediaSeeking *pMS = NULL;
IMediaPosition *pMP = NULL;
IVideoFrameStep *pFS = NULL;
  然后實例化一個過濾器圖表管理器,并查詢各接口:

// Get the interface for DirectShow's GraphBuilder
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGB);
// QueryInterface for DirectShow interfaces
pGB->QueryInterface(IID_IMediaControl, (void **)&pMC);
pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME);
pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS);
pGB->QueryInterface(IID_IMediaPosition, (void **)&pMP);
// Query for video interfaces, which may not be relevant for audio files
pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW);
pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV);
// Query for audio interfaces, which may not be relevant for video-only files
pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA);


  3.3 創建過濾器圖表

  應用DirectShow創建過濾器圖表時,用戶完全不需要操心系統使用了哪一類過濾器以及過濾器是怎樣連接的。只要調用IGraphBuilder::RenderFile函數,就可以建成一個完整的過濾器圖表。

// Have the graph builder construct its the appropriate graph automatically
pGB->RenderFile(wFile, NULL);


  創建成功后,過濾器圖表就可以用來播放多媒體文件了。DirectShow調用IMediaControl::Run函數來播放媒體文件。

// Run the graph to play the media file
pMC->Run();


  3.4 使用DirectShow的事件響應機制

  DirectShow的事件響應機制是過濾器圖表管理器與用戶進行交互的接口,DirectShow處理的可以是一些事先可以預期的事件,比如數據流的結束;也可以是一些無法預期的錯誤。有的事件可以由過濾器圖表管理器自己處理,但如果過濾器圖表管理器自己無法處理這些事件,它就把事件的通知放在事件隊列里。用戶程序就可以通過IMediaEventEx接口得到事件,并對它做出相應的處理。

  3.5 清除DirectShow

  在程序結束時必須調用Release函數釋放DirectShow的接口指針,并調用CoUninitialize函數來卸載COM庫,釋放所有的動態鏈接庫和資源。

  4 結束語

  應用DirectX的組件DirectShow進行多媒體應用程序的開發需了解多方面的知識,但在很多應用中利用DirectShow的特性可以減少工作量并能獲得非常高的運行效率。在Visual C++ 6.0的開發環境中利用DirectShow開發的簡單媒體播放器,具有隨機播放、暫停和調整播放速率等功能,且可以播放多種媒體文件,播放效果非常流暢。因此,基于DirectShow開發多媒體應用程序的方法簡單高效,是一種值得推薦的方法。??

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455410.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455410.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455410.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

接口安全

老大發了篇文章,讓看如何寫出安全的接口。 如何寫出安全的API接口?接口參數加密簽名設計思路轉載于:https://www.cnblogs.com/Tpf386/p/7053795.html

python中xml模塊_python學習第十五天-2(XML模塊)

也是一種文本轉換形式。importxxxxxxxxxxxxxxxxxxx asxx,可以用xx代替xxxxxxxxxxxxxxxxxxx模塊xml文件的新增,修改,刪除,查詢。新增:?import xml.etree.ElementTreeas ET?new_xmlET.Element(nameList)#創建xml的根節點相當于na…

ubuntu系統下Java環境JDK的安裝

Debian Linux下安裝jdk 下載壓縮包 官網下載對應的.gz包 點擊下載 解壓文件 創建一個目錄用于存放解壓后的文件,并解壓縮到該目錄下 sudo mkdir /opt/java8 sudo tar -zxvf jdk-8u221-linux-x64.tar.gz -C /opt/java8修改環境變量 sudo vim ~/.bashrc 進入…

棧溢出筆記1.3 準備Shellcode

經過1.1和1.2節的講述,我們已經知道了怎樣更改EIP的值。程序運行函數之后將跳轉到我們設定的位置開始運行,因此,我們須要準備一個自己的程序,接手后面的工作。這是一個什么樣的程序?是一個C語言編寫的代碼?…

DirectShow開發快速入門之慨述

文章來源:http://tech.163.com/school 2005-08-18 10:21:32 來源: 天極網摘要:本篇文檔概括性的介紹了DirectShow的主要組成部分,以及一些Directshow的基本概念。熟悉這些基本的知識對于Directshow的應用開發或者過濾器的開發者都會有所幫助…

Android selector中的item的順序

在selector中,要將默認狀態的item放在最后面,因為一旦前面的item滿足匹配條件,后面的item就不會去匹配。因此,把默認狀態的item放在前面的話,后面的item沒有執行的機會轉載于:https://www.cnblogs.com/xiaoyuersdch/p/…

權限表使用聯合主鍵嗎_天天寫 order by,你知道Mysql底層執行流程嗎?

前言 在實際的開發中一定會碰到根據某個字段進行排序后來顯示結果的需求,但是你真的理解order by在 Mysql 底層是如何執行的嗎?假設你要查詢城市是蘇州的所有人名字,并且按照姓名進行排序返回前 1000 個人的姓名、年齡,這條 sql 語…

nodejs簡介

nodejs是啥? Node.js是運行在服務端的JavaScript。 Node.js是一個基于Chrome JavaScript運行時建立的一個平臺。 Node.js是一個事件驅動I/O服務端JavaScript環境,基于Google的V8引擎,V8引擎執行Javascript的速度非常快,性能非常…

jumpserver v0.4.0 基于 CenOS7 的安裝詳解

標簽(linux): jumpserver 筆者Q:972581034 交流群:605799367。有任何疑問可與筆者或加群交流 首首先使用Jumpserver前要理解清楚這三個用戶關系: 1.用戶: 是指你在web上創建的用戶,會在跳板機上創建這個用戶,作用就是用…

Node.js中事件的循環

Node.js 事件循環 Node.js 是單進程單線程應用程序,但是通過事件和回調支持并發,所以性能非常高。 Node.js 的每一個 API 都是異步的,并作為一個獨立線程運行,使用異步函數調用,并處理并發。 Node.js 基本上所有的事…

python爬boss網站_python之requests爬蟲Boss數據

python之requests爬蟲Boss數據需要用到的庫:reqeusts、lxml沒有的可以用直接下載pip install requestspip install lxm這里以python崗位,地點北京為例爬取的數據就是崗位名稱、薪資、地點 首先導入需要用到的模塊import requestsfrom lxml import etree崗…

live555源代碼簡介

文章出自:http://blog.csdn.net/imliujie/archive/2008/01/30/2072657.aspx live555源代碼簡介liveMedia項目的源代碼包括四個基本的庫,各種測試代碼以及IVE555 Media Server。四個基本的庫分別是UsageEnvironment&TaskScheduler,groups…

并發無鎖隊列學習(單生產者單消費者模型)

1、引言 本文介紹單生產者單消費者模型的隊列。依據寫入隊列的內容是定長還是變長,分為單生產者單消費者定長隊列和單生產者單消費者變長隊列兩種。單生產者單消費者模型的隊列操作過程是不須要進行加鎖的。生產者通過寫索引控制入隊操作,消費者通過讀索…

ecshop 收貨人信息電話必填改為手機必填

首先通過在flow.dwt中,查找flow.php?stepconsignee中的關鍵字 consignee(結算中心)查找所在模板/Library/consignee.lbi 大概57行 把必填去掉,其次 在js/shopping_flow.js里邊注釋掉 if (Utils.isEmpty(frm.elements[‘tel’].v…

流媒體傳輸協議

1.流媒體( Streaming Media) 1.1流媒體概念 流媒體技術是網絡技術和多媒體技術發展到一定階段的產物。術語流媒體既可以指在網上傳輸連續時基媒體的流式技術,也可以指使用流式技術的連續時基媒體本身。在網上傳輸音頻、視頻等多媒體信息目前主要有兩種方式:下載和流…

關閉瀏覽器網頁觸發事件_淺析瀏覽器渲染和 script 加載

前言前端代碼離不開瀏覽器環境,理解 js、css 代碼如何在瀏覽器中工作是非常重要的。如何優化渲染過程中的回流,重繪?script 腳本在頁面中是怎么個加載順序?了解這些對前端性能優化起著非常大的作用。借著這篇文章,讓自…

Open vSwitch實驗常用命令

1. 基本架構 ovs-vsctl: 管理ovsdb-server的配置,提供OVSDB的配置方法,包括創建和刪除網橋、端口等; ovs-ofctl: 提供ovs-vswitchd的流表配置方法; ovs-dpctl: 配置OVS內核模塊,提供緩存流表的操作方法&#xff1b…

記IOS8中碰到的一個JS bug

IOS8的JS版本過低導致 var id "123"; var temp1 {id, "left": "200"}; // error in IOS8 var temp2 {"id":id, "left": "200"};平時還是多寫ES5的代碼,es6的語法總能碰到兼容的坑。 改了好幾天。…

Emmet的html語法

Emmet的html語法 所有操作按下“tab”鍵即可瞬間完成 元素 1.在編輯器中輸入元素名稱,即可自動補全生成 HTML 標簽,即使不是標準的 HTML 標簽。 2.輸入:! 或者 html:5 或者 html:4s 或者 html:4t 將自動補全html基本結構 嵌套操作 1.使用…

RTP Payload Format for H.264 Video

H.264 RTP協議的封裝格式rfc3984 英文原版:http://tools.ietf.org/html/rfc3984 部分中文翻譯: H.264 視頻 RTP 負載格式 1. 網絡抽象層單元類型 (NALU) NAL單元1字節包頭負載 NALU 頭由一個字節組成, 它的語法如下: —————|0|1|2|3|4|5|6|7|------…