《電子技術應用》
您所在的位置:首頁 > 其他 > 業界動態 > DirectShow過濾器組件開發技術及其應用實例

DirectShow過濾器組件開發技術及其應用實例

2009-08-14
作者:盛 健 季曉勇

  摘? 要: 討論了DirectShow過濾器組件的開發技術,給出了網絡視頻應用中的一個過濾器組件開發實例。

  關鍵詞: DirectShow? 過濾器? COM? 視頻應用

?

1? DirectShow概述

  DirectShow是Windows平臺下流行的流媒體開發體系,可以實現高質量的音視頻采集、編輯、編碼、解碼、格式轉換、播放。它解決了網絡音頻及視頻信息傳輸中數據量大、數據源種類多、客戶端軟硬件環境不確定、視頻音頻需要同步等問題,因此有著廣泛的應用。

  DirectShow使用模塊化的體系結構,最主要的組件是過濾器(Filter)。DirectShow把一系列過濾器組合起來形成DirectShow應用程序。每個過濾器提供一種功能,如獲取數據源、編碼、解碼、播放等。DirectShow提供了很多標準過濾器,用戶可以直接使用。但由于媒體格式、壓縮方式、硬件屬性等方面的特殊要求,用戶經常需要自行開發過濾器來滿足具體需求。

DirectShow應用程序中主要包含以下3種過濾器:源過濾器(Source Filter)、轉換過濾器(Transform Filter)、呈現過濾器(Render Filter),分別負責獲取數據流、處理數據流和播放數據流。有時還需要分解過濾器(Splitter Filter)和合并過濾器(Mux Filter)來分解和合并數據流。

  DirectShow是基于COM(組件對象模型)規范的。過濾器是一種COM組件。應用程序把多個過濾器組件組合起來,形成對媒體流的處理流程。這一整套過濾器集合被稱為過濾器圖(Filter Graph)。DirectShow提供FGM(Filter Graph Manager)組件來控制整個過濾器圖。過濾器前后相連,連接點也是COM對象,被稱為針腳(Pin)。

  DirectShow應用程序的原理圖如圖1所示。來自文件系統或外設的數據先由過濾器處理,再存儲到文件系統或由外設播放。過濾器負責與文件系統和外設的交互。應用程序只需控制過濾器,不用關心其他軟件和硬件的具體情況。

?

2?過濾器組件開發技術

  DirectShow為過濾器組件開發提供了一套基類庫(Base Class Library),包括過濾器基類、針腳基類和一些輔助類。基類庫為過濾器組件的開發提供了一個框架,省去了復雜的底層編碼工作。用戶可將開發工作集中到如下二個方面:(1)傳輸和處理媒體流。(2)將過濾器封裝為COM組件。

2.1 媒體流的傳輸和處理

  為了傳輸數據,用戶過濾器先要與過濾器圖中其他過濾器連接起來。連接時要進行媒體格式和內存分配器的協調。過濾器之間通過針腳相連。過濾器之間媒體格式和內存分配器的協調實際上是通過針腳之間的通信來完成的。 

  主動連接方的過濾器的針腳首先獲取自身支持的所有媒體格式,然后把其中一種格式送交給被動連接的一方。被動方的針腳進行判斷:如果支持該格式,媒體格式協調成功;如果被動方不支持該格式,就通知主動方,主動方再提供1種不同的格式送交被動方,直到被動方支持被提供的格式,協調成功,否則,當主動方用完所有支持的格式,協調失敗。

  DirectShow過濾器使用一種稱作內存分配器(Allocator)的COM對象管理媒體流數據。當2個過濾器連接前,其中1個過濾器上的針腳提供1個內存分配器。另外1個過濾器上的針腳對這個內存分配器進行檢測。當2個針腳都支持該內存分配器時,協調成功。

  媒體流傳輸開始之前,內存分配器負責創建一系列內存緩沖區。媒體流傳輸時,上游(Upstream)過濾器填充這些緩沖區,并把它們傳送給下游(Downstream)過濾器。DirectShow使用一種稱作媒體采樣包(Media Sample)的COM對象管理單個緩沖區。通過控制媒體采樣包對象,可以修改當前緩沖區中的媒體類型、時間戳等信息,也可以利用算法處理媒體數據,從而實現對媒體流的處理。

2.2 COM組件的實現

  COM組件的實現包括如下內容:用接口規定過濾器組件對外提供的功能;提供類廠,用以創建COM對象的實例;提供COM對象所在dll文件的各個輔助函數,以完成COM組件在應用程序中的載入和釋放,在注冊表中的注冊和注銷。

  DirectShow中的過濾器、針腳等COM對象通過接口對外提供各種功能。除了提供標準的接口之外,DirectShow還提供了DECLARE_INTERFACE宏讓用戶自定義接口,從而滿足用戶對過濾器組件的指定要求。

  COM實現機制中用類廠創建COM對象實例。DirectShow提供了類廠類CClassFactory和類廠模板類CFactoryTemplate。通過將不同的類廠模板的內容填入類廠,實現不同的類廠對象,從而創建不同COM對象實例。

  過濾器是dll文件格式的COM組件,需要以下函數:DllMain(載入時的入口)、DllGetClassObject(創建類廠對象)、DllCanUnloadNow(判斷是否釋放dll)、DllRegisterServer(在注冊表中注冊dll)、DllUnregisterServer(在注冊表中反注冊dll)。DirectShow已經實現了前3個函數。后面的2個函數通常調用DirectShow中的函數AMovieDllRegisterServer2()來實現,即:

  STDAPI DllRegisterServer()

???? ?? ?????? {?? return AMovieDllRegisterServer2(TRUE );}

????STDAPI DllUnregisterServer()

????????????? ? {?? return AMovieDllRegisterServer2(FALSE);}

3? 過濾器組件開發技術應用實例

???下面介紹過濾器組件開發技術在網絡視頻服務中的一個應用實例。“網絡數字攝像機”系統使用攝像機采集視頻,經過編碼壓縮后發送到網絡上。客戶端程序接收數據并解碼。用戶過濾器利用這些數據生成視頻流,進行播放或者錄像。“網絡數字攝像機”客戶端程序的基本流程如圖2所示。

?

  客戶端程序采用多線程的方式,網絡數據接收線程、解碼線程與視頻流生成線程同時運行。在線程之間使用隊列存放數據。前一個線程將數據寫入隊列,后一個線程從隊列中取出數據。要實現的過濾器組件例程位于視頻流生成線程內,與解碼線程共享一個數據隊列。此隊列放在一個自定義的類CDataAdmin中。解碼線程把數據放到隊列中。用戶過濾器從隊列中取出數據,生成視頻流。

3.1 用戶過濾器的實現

  (1)選擇合適的基類

  用戶過濾器使用整個過濾器圖外部的數據生成視頻流,屬于源過濾器。基類庫中的CSource類是源過濾器的基類,CSource使用CSourceStream基類作為它的針腳。本例中從這2個類派生出CCustomFilter和CCustomPin,作為實際使用的過濾器類和針腳類。

  (2)通過自定義接口獲得隊列數據

  為了獲得過濾器外部的隊列數據,需要為CCustomFilter提供一個自定義的接口。下面的代碼定義了一個IDataSource接口:DECLARE_INTERFACE_(IDataSource,IUnknown){STDMETHOD(SetData)(THIS_CDataAdmin*pData)PURE;}。CCustomFilter繼承該接口,對外提供了一個SetData()操作。SetData()將外部傳入的CDataAdmin*類型的指針賦值給CCustomFilter的成員變量,過濾器即獲取到外部隊列數據。

  (3)協調媒體類型

  CSourceStream基類完成了媒體類型協調中大部分的工作,用戶只需要指定過濾器針腳支持的媒體格式。CSourceStream的成員函數GetMediaType()負責完成這個任務,用戶必須在該函數中為過濾器指定媒體格式。媒體流的信息存放在一個VIDEOINFOHEADER的結構中,指針pvi指向該結構。函數GetMediaType()中指定媒體格式的代碼如下:

  pMediaType->SetType(&MEDIATYPE_Video);

    //設置媒體主類型

  pMediaType->SetSubtype(&GetBitmapSubtype(&pvi->bmiHeader));  //設置媒體次類型

  pMediaType->SetFormatType(&FORMAT_VideoInfo);

                                  //設置媒體格式

  pMediaType->SetTemporalCompression(FALSE);

                                  //不壓縮媒體流

  pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);     //設置媒體采樣包大小

  (4)協調內存分配器

  CSourceStream基類完成了大多數內存分配器的協調工作。用戶還需要指定每個媒體采樣包的大小。CSourceStream基類的成員函數DecideBufferSize()負責完成此任務。下面是該函數中的主要代碼。

  pRequest->cbBuffer=pvi->bmiHeader.biSizeImage;

                                  //獲取采樣包大小需求信息

  ALLOCATOR_PROPERTIES Actual;

  hr=pAlloc->SetProperties(pRequest,&Actual);

                                  //指定采樣包大小,并返回實際的設置結果

  (5)生成視頻流

  CSourceStream基類的FillBuffer()成員函數負責把外部隊列數據加入到視頻流中。用戶可以在此函數內部先處理數據,再把處理過的數據加入視頻流中。本例中經用戶過濾器解碼后的數據,不需要進行處理。函數FillBuffer()中的主要代碼如下。

                                 //獲取當前媒體采樣包對應的緩沖區的地址和大小

  BYTE*pData;

  DWORD cbData;

  pSample->GetPointer(&pData);

  cbData=pSample->GetSize();

                                  //獲取媒體信息

  VIDEOINFOHEADER*pVih=(VIDEOINFOHEADER*)

  m_mt.pbFormat;

                                 //從數據隊列中取出數據填充到當前緩沖區中

  m_pFilePack=m_pPinData->GetDataBuffer();

  memcpy(pData,m_pFilePack,min(pVih->

  bmiHeader.biSizeImage,cbData));

                                 //給媒體采樣包加上時間戳

  REFERENCE_TIME rtStart=m_iFrameNumber

  *m_rtFrameLength;

  REFERENCE_TIME rtStop=rtStart+m_rtFrameLength;

  pSample->SetTime(&rtStart,&rtStop);

                                 ?//幀計數器加1

  m_iFrameNumber++;

  (6)生成COM組件

  過濾器開發工作的最后一步是將過濾器封裝成COM組件。此外,需要提供類廠模板。代碼如下:

  CFactoryTemplate g_Templates[]={g_wszCustomFilter,

  &CLSID_CustomFilter,CCustomFilter∷CreateInstance,

  NULL,NULL };                          //將過濾器信息填入類廠模板

  int g_cTemplates=sizeof(g_Templates)/sizeof(g_Templates[0]);  //類廠模板個數

3.2 實際應用效果

??? 在“網絡數字攝像機”系統的客戶端應用程序中使用上例的過濾器組件,若連接到視頻播放過濾器(Video Renderer)則可播放視頻,播放效果如圖3所示;若連接到寫文件過濾器(File Writer),可將視頻直接寫成硬盤文件,實現視頻錄像。過濾器采用COM組件的形式,可方便地移植到其他機器和應用程序中。

4? 結束語

  過濾器組件在目前多種多樣的音頻視頻流媒體應用中發揮著重要作用。過濾器組件的開發具有較大的實用價值,但有一定的難度和復雜性。本文討論了用戶過濾器開發中的原理和技術。文中過濾器組件例子的開發過程具有較大的通用性,可供其他開發者參考。

?

參考文獻

1? Kruglinski D J.VC++技術內幕(第4版).北京:清華大學出版社,1999

2? 潘愛民.COM原理和應用.北京:清華大學出版社,1999

本站內容除特別聲明的原創文章之外,轉載內容只為傳遞更多信息,并不代表本網站贊同其觀點。轉載的所有的文章、圖片、音/視頻文件等資料的版權歸版權所有權人所有。本站采用的非本站原創文章及圖片等內容無法一一聯系確認版權者。如涉及作品內容、版權和其它問題,請及時通過電子郵件或電話通知我們,以便迅速采取適當措施,避免給雙方造成不必要的經濟損失。聯系電話:010-82306118;郵箱:aet@chinaaet.com。
主站蜘蛛池模板: 国产成人精品一区二区app | 门事件精品视频在线观看 | 日韩99| 99热免费在线| 九九九精品视频 | 中文字幕天天躁日日躁狠狠躁免费 | 久久久久久青草大香综合精品 | 九九国产精品 | 青草视频.com | 黄色一级短视频 | 国产成人综合网在线播放 | 欧美男女交性过程视频 | 99视频国产精品免费观看app | 永久在线毛片免费观看 | 视频一区视频二区在线观看 | 久久综合视频网 | 国产第一亚洲 | 五月婷婷丁香综合网 | 午夜.dj高清在线观看免费4 | 国产门事件在线观看 | 国产羞羞的视频在线观看免费 | 国产亚洲美女精品久久久久狼 | 欧美日韩在线精品成人综合网 | 免费人成年短视频在线观看免费网站 | 免费国产成人 | 国产热视频 | 久草视频国产 | 99这里 | 精品乱码一区二区三区四区 | 福利在线一区二区 | 国内a级毛片 | 国产com | 日韩第一视频 | 成人h网站在线观看 | 免费色视频网站 | 色视频在线观看免费 | 极品公子之杨凝冰 | 欧美影院网站视频观看 | 国内自拍偷拍视频 | 欧美无遮挡一区二区三区 | 国产免费一区二区三区 |