《DirectShow開發指南》學習筆記 5

2021-08-25 10:56:12 字數 3870 閱讀 7697

filter通過pin這樣的連線,就能「串聯」起來,從而構建乙個完整的filter graph。

filter graph的構建方法大概有以下幾種:

後4種構建方法都有「自動」的功能。在directshow中,這種「自動」機制也稱為智慧型連線(intelligent connect)。

在介紹智慧型連線的具體實現過程之前,先要來看一下filter的merit值。這個merit值可以理解成為filter被智慧型連線所使用的優先順序。directshow定義了6種標準的merit值,filter的merit值只有在大於merit_do_not_use的時候,才有可能被智慧型連線所使用,而在同等條件下(幾個filter完成的功能相同),merit的值越大,這個filter被使用的機會也就越大。在開發自己的filter的過程中,可以取任何dword型別的值來設定自己的filter的merit值,但推薦的一種做法是,在標準值上加乙個偏移量,如merit_do_not_use+1:

enum

;

問:如何修改系統中已經註冊的filter的merit值?

開啟登錄檔,在filter資訊的註冊部分都會發現乙個稱為filterdata的二進位制串型別的鍵值,這個鍵值記錄的內容就包含merit資訊,可以如下定義乙個資料結構來操作filterdata值開始部分的一塊資料:

typedef struct

filter_header;

修改filter的merit值的**如下:

bool setfiltermerit(const char* inclsid, dword inmerit)

\\instance\\";

const long cmaxlength = 1024 * 16;

byte filterdata[cmaxlength];

dword actuallength = 0;

//生成filter資訊註冊部分的註冊入口

char szentry[1000];

strcpy(szentry, cregistryentry);

strcat(szentry, inclsid);

hkey hkey = null;

long result = ::regopenkeyex(hkey_classes_root, szentry, 0, key_all_access, &hkey);

bool pass = (result == error_success);

if (pass)

if (pass)

if (hkey)

return pass;

}

igraphbuilder::addsourcefilter

該方法給出乙個原始檔路徑,filter graph manager能夠為這個原始檔載入乙個相應的source filter。這是乙個分析檔案路徑以及查詢登錄檔的過程。

首先分析檔案路徑中是否有協議名(如http、htp等,filter graph manager認為冒號前的字串為協議名,如myprotocol:中,myprotocol就是協議名)。為了區別協議名和驅動器碟符(如c:\myfile.ext),filter graph manager不承認單字元的協議名,而且字串file:或file://也不認為是協議名。

如果有,則在登錄檔的如下位置尋找這個協議名:

hkey_classes_root

source filter =

extensions

<.ext1> =

<.ext2> =

找到後(是自己的myprotocol),先在extensions子鍵下匹配副檔名。如果副檔名匹配不成功,則使用source filter鍵值指定的clsid。預設情況下(登錄檔中找不到檔案路徑中的協議名),filter graph manager建立乙個稱為file source(url)的filter。

如果檔案路徑中不包含協議名,filter graph manager就分析這個檔案的副檔名,然後倒登錄檔的hkey_classes_root\media type\extension子鍵下去匹配副檔名,如果找到了,就根據source filter鍵值指定的clsid建立filter;找不到,filter graph manager還有最後一招,就是進行檔案的校驗位元組判斷。一些特殊格式的檔案校驗位元組在如下位置註冊:

hkey_classes_root\mediatype\\。(major type和subtype是字串形式)。

登錄檔中各個鍵值結構如下:

0                "0,4,,52494646,8,4,,524d4944"

1                "0,4,,4d546864"

source filter    ""

mediatype下有乙個子鍵(它是mediatype_stream的字串形式),其後面又定義了一系列的subtype(也是字串形式),在subtype子鍵下,還可以看到一些子鍵,其中編號為0、1、2...的即是定義的校驗位元組,source filter即為定義的相應的clsid。

校驗位元組定義塊(block)一般的格式為:offset,cb,mask,val,意思為在檔案頭偏移offset位元組處讀取cb個位元組的資料,將其與mask做位與操作,結果等於val即表示匹配;如果定義的mask為空,可以不做位與操作;如果offset為負數,表示從檔案尾開始計算偏移;如果乙個子鍵有多個定義塊,則所有的定義塊都匹配才能算這個子鍵匹配;如果有多個子鍵用於校驗位元組的定義,那麼任何乙個匹配就表示source filter的匹配。如果登錄檔中定義的所有校驗位元組都不匹配,filter graph manager最後只能預設建立乙個稱為file source(async.)的filter,media type使用。

igraphbuilder::renderfile

該方法給出乙個檔名,首先根據與igraphbuilder::addsourcefilter類似的演算法找到並建立正確的source filter。然後,就從該source filter的各個輸出pin開始,進行剩下的智慧型連線過程。這是乙個「遞迴」過程,直到所有的分支都連到乙個rendering filter上為止。步驟大致為:

如果輸出pin支援istreambuilder介面,則把剩下的工作交給istreambuilder::render;

使用在filter graph manager內部緩衝(cache)中的filter進行試連線;

使用在當前filter graph中還沒有完全連線的filter進行試連線;

igraphbuilder::render

這個方法從當前filter graph的某個filter的指定輸出pin開始,進行從這個pin往下的一條支路的智慧型連線。智慧型連線的演算法與renderfile的類似。

igraphbuilder::connect

這個方法以欲連線的一對輸出pin和輸入pin作為引數,首先進行這兩個pin只見的直接連線,如果不成功,則要插入「中介」filter,這個「中介」filter的選擇以及試連線過程就是乙個智慧型連線過程,演算法與上述renderfile類似。

問:如何讓只能連線過程優先使用我們指定的某個filter?

答:在執行智慧型連線函式之前,可以首先將我們的filter加入到filter graph中。或者再提高乙個優先順序:將filter加入到filter graph manager的內部緩衝中。後一種方法 可以從filter graph manager上獲得igraphconfig介面,然後呼叫其介面方法addfiltertocache來實現。值得注意的是,如果要加入到緩衝中的filter已經在filter graph中了,則這個filter的所有pin必須都處於斷開狀態。

Django Web開發指南

國內第一本django圖書 django web開發指南 歡迎使用django 歡迎來到django的世界,很高興能和你一起進行這趟旅程。你會發現有了這個強大的web框架,做每件事情都變得便捷起來 從設計開發新應用到不用大刀闊斧地修改 就能為現有 提供新的特性和功能。關於本書 市面上已經有了一些講解...

SQL Server 開發指南

sql server 資料庫設計 一 資料庫設計的必要性 二 什麼是資料庫設計 三 資料庫設計的重要 四 資料模型 實體 關係 e r 資料模型 實體 entity 屬性 attribute 關係 relationship 五 資料庫設計步驟 1 需求分析階段 2 概要設計階段 3 詳細設計階段 六...

shell 開發指南

語法 釋義使用示例 bash source 0 取得當前執行的shell檔案所在的路徑 context dirname 上一條指令執行完的退出狀態.0為成功,非0為失敗.if eq 0 then 基本結構 if 條件語句 then 執行語句1 else 執行語句2 fi注意條件語句外有 兩種形式 常...