Directorshow Filter的注冊

Windows COM使用注冊表來注冊COM組件豪墅, director fitler遵從COM開發(fā)規(guī)范只恨,所以也需要注冊到注冊表里卖子。
Directorshow filter在注冊表里有兩種注冊布局:

  1. 大多數(shù)的Fitler不需要進(jìn)行filter類型的注冊,按如下布局注冊:
KEY_CLASSES_ROOT
    CLSID
        Filter CLSID 
            REG_SZ: (Default) = Friendly name

            InprocServer32
                REG_SZ: (Default) = File name of the DLL
                REG_SZ: ThreadingModel = Both
  1. 為了讓 System Device Enumerator可以發(fā)現(xiàn)自己,virture camera filter需要將自己注冊到Category下刑峡, 布局如下:
HKEY_CLASSES_ROOT
    CLSID
        Category
            Instance
                Filter CLSID
                    REG_SZ: CLSID = Filter CLSID
                    REG_BINARY: FilterData = Filter information
                    REG_SZ: FriendlyName = Friendly name

帶有Category的值注冊在下面的路徑下:
HKEY_CLASSES_ROOT\CLSID{DA4E3DA0-D07D-11d0-BD50-00A0C911CE86}\Instance
OBS-vcam 的注冊:


image.png

Vivek‘s VCam的注冊:


image.png

注冊信息的聲明
directorshow使用三個(gè)結(jié)構(gòu)類來幫助組織filter, pin, meida type 需要注冊的信息玄柠。

  1. AMOVIESETUP_MEDIATYPE 被用來注冊媒體類型诫舅。
    以下是分別是OBS-VCAM和Vivek項(xiàng)目的媒體類型聲明:
const AMOVIESETUP_MEDIATYPE AMSMediaTypesVCam = 
{ 
    &MEDIATYPE_Video,          //視頻媒體
    &MEDIASUBTYPE_NULL   //null 表示支持任意類型
};
const AMOVIESETUP_MEDIATYPE AMSMediaTypesV =
{
    &MEDIATYPE_Video,
    &MEDIASUBTYPE_YUY2   //obs-vcam只是YUY2格式
};
  1. AMOVIESETUP_PIN用來注冊Pin的相關(guān)信息:
const AMOVIESETUP_PIN AMSPinVCam=
{
    L"Output",             // Pin string name
    FALSE,                 // Is it rendered
    TRUE,                  // Is it an output
    FALSE,                 // Can we have none
    FALSE,                 // Can we have many
    &CLSID_NULL,           // Connects to filter  Obsolete
    NULL,                  // Connects to pin
    1,                     // Number of types
    &AMSMediaTypesVCam      // Pin Media types
};

要注意的是羽利, AMOVIESETUP_PIN有對mediatype的引用。

  1. AMOVIESETUP_FILTER 用來注冊filter相關(guān)信息:
    const AMOVIESETUP_FILTER AMSFilterVCam =
    {
    &CLSID_VirtualCam, // Filter CLSID
    L"Virtual Cam", // String name
    MERIT_DO_NOT_USE, // Filter merit
    1, // Number pins
    &AMSPinVCam // Pin details
    };
    AMOVIESETUP_FILTER包含了對outPin的引用刊懈,參考o(jì)bs-vcam可以看到这弧,當(dāng)需要多個(gè)虛擬攝像頭時(shí)虚汛,需要為每一個(gè)注冊一個(gè)獨(dú)立的fitler, 如果有音頻,音頻要獨(dú)立聲明filter.

將注冊聲明加入factory Template
為了方便com開發(fā)卷哩,Directoryshow引入的fatory Temple 幫助實(shí)現(xiàn)COM要求:


image.png

如上圖 , directshow實(shí)現(xiàn)的COM接口調(diào)用邏輯如下:
a. client 程序調(diào)用coGetclassObject 獲取ClassFacotory.
b. coGetclassObject 調(diào)用DllgetClassObject函數(shù)冷溶,DllgetClassObject在factory template數(shù)組里搜尋滿足CLSID條件的模板尊浓。
C. factory template 創(chuàng)建classfatory并讓其擁有一個(gè)執(zhí)行匹配模板的指針逞频,將他返回給client.
D. Client 調(diào)用IClassFatcory的createInstance方法
D. createInstance通過執(zhí)行模板的指針調(diào)用模板中的初始化函數(shù)眠砾,創(chuàng)建真實(shí)的實(shí)例托酸。

factory Template被聲明為全局?jǐn)?shù)組,它的結(jié)構(gòu)如下:
CFactoryTemplate g_Templates[1] =
{
{
L"My Component", // Name
&CLSID_MyComponent, // CLSID
CMyComponent::CreateInstance, // Method to create an instance of MyComponent
NULL, // Initialization function
NULL // Set-up information (for filters)
}
};
每個(gè)模板包含5個(gè)字段励堡,對應(yīng)注冊的com組件名稱,CLSID, 創(chuàng)建方法刨疼, 額外的初始化方法,以及用于注冊表的注冊信息揩慕。
將注冊表需要的注冊變量填入最后一個(gè)字段,就可以用directshow提供的方法進(jìn)行注冊迎卤。
除了要生命一個(gè)全局模板數(shù)組外玷坠,同時(shí)還需要聲明一個(gè)全局變量指明模板數(shù)量劲藐。
下面時(shí)obs-vcam的類工廠模板和全局變量:

CFactoryTemplate g_Templates[NUM_VIDEO_FILTERS + 1] =
{
    {
        L"OBS-Camera",
        &CLSID_OBS_VirtualV,
        CreateInstance,
        NULL,
        &AMSFilterV
    },
    {
        L"OBS-Camera2",
        &CLSID_OBS_VirtualV2,
        CreateInstance2,
        NULL,
        &AMSFilterV2
    },
    {
        L"OBS-Camera3",
        &CLSID_OBS_VirtualV3,
        CreateInstance3,
        NULL,
        &AMSFilterV3
    },
    {
        L"OBS-Camera4",
        &CLSID_OBS_VirtualV4,
        CreateInstance4,
        NULL,
        &AMSFilterV4
    },
    {
        L"OBS-Audio",
        &CLSID_OBS_VirtualA,
        CVAudio::CreateInstance,
        NULL,
        &AMSFilterA
    }
};

int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);

OBS-VCAM注冊了4個(gè)虛擬攝像頭組件樟凄,每個(gè)組件都有不同的CLSID,但是它們引用的是相同的組件聘芜,也就是每個(gè)cliid下的InprocServer32的內(nèi)容相同缝龄,這樣雖然有不同的CLIID但是會(huì)指向同一個(gè)組件。

實(shí)現(xiàn)注冊方法
DLL 規(guī)定了5個(gè)需要實(shí)現(xiàn)的函數(shù):
DllMain Dll的入口函數(shù)二拐,在Directshow中使用DllEntryPoint作為入口聲明。
DllGetClassObject: 創(chuàng)建COM對象工廠百新。
DllUnloadNow(): 查詢是否可以被卸載了。
DllRegisterServer: 為dll注冊注冊表信息仗哨。
DllUnregisterServer: 移除注冊的信息。
Directshow lib已經(jīng)實(shí)現(xiàn)了前三個(gè)铅辞,創(chuàng)建對象只需要根據(jù)模板定義好實(shí)例化方法就可以。 但是后兩個(gè)需要開發(fā)者來實(shí)現(xiàn)斟珊。
Directshow提供了 AMovieDllRegisterServer2 來幫助注冊信息。
Vivek 項(xiàng)目注冊方法的實(shí)現(xiàn):

STDAPI RegisterFilters( BOOL bRegister )
{
    HRESULT hr = NOERROR;
    WCHAR achFileName[MAX_PATH];
    char achTemp[MAX_PATH];
    ASSERT(g_hInst != 0);

    if( 0 == GetModuleFileNameA(g_hInst, achTemp, sizeof(achTemp))) 
        return AmHresultFromWin32(GetLastError());

    MultiByteToWideChar(CP_ACP, 0L, achTemp, lstrlenA(achTemp) + 1, 
                       achFileName, NUMELMS(achFileName));
  
    hr = CoInitialize(0);
    if(bRegister)
    {
        hr = AMovieSetupRegisterServer(CLSID_VirtualCam, L"Virtual Cam", achFileName, L"Both", L"InprocServer32");
    }

    if( SUCCEEDED(hr) )
    {
        IFilterMapper2 *fm = 0;
        hr = CreateComObject( CLSID_FilterMapper2, IID_IFilterMapper2, fm );
        if( SUCCEEDED(hr) )
        {
            if(bRegister)
            {
                IMoniker *pMoniker = 0;
                REGFILTER2 rf2;
                rf2.dwVersion = 1;
                rf2.dwMerit = MERIT_DO_NOT_USE;
                rf2.cPins = 1;
                rf2.rgPins = &AMSPinVCam;
                hr = fm->RegisterFilter(CLSID_VirtualCam, L"Virtual Cam", &pMoniker, &CLSID_VideoInputDeviceCategory, NULL, &rf2);
            }
            else
            {
                hr = fm->UnregisterFilter(&CLSID_VideoInputDeviceCategory, 0, CLSID_VirtualCam);
            }
        }

      // release interface
      //
      if(fm)
          fm->Release();
    }

    if( SUCCEEDED(hr) && !bRegister )
        hr = AMovieSetupUnregisterServer( CLSID_VirtualCam );

    CoFreeUnusedLibraries();  //卸載所有不在需要的dll,例如注冊完后的IID_IFilterMapper2
    CoUninitialize(); //在當(dāng)前線程關(guān)閉com服務(wù)旨椒,下載所有dll和釋放資源等堵漱。
    return hr;
}

參數(shù)bRegister為ture時(shí)表示注冊,為false表示移除勤庐;
根據(jù)directshow文檔,使用 AMovieDllRegisterServer2注冊有很多的限制愉镰,對于vcam場景,由于需要支持硬件設(shè)備录择,需要注冊額外的兩個(gè)信息,medium 和pin category. medium定義了和已經(jīng)建通信的方法糊肠, pin category定義了pin的功能辨宠。
在上文货裹,AMovieSetupRegisterServer被用來注冊通用的filter信息,它被注冊在CLSID下:

image.png

然后使用IFilterMapper2::RegisterFilter方法將fitler注冊到CLSID_VideoInputDeviceCategory下赋兵。這里需要用的REGFILTERPINS2結(jié)構(gòu):

REGFILTER2 rf2FilterReg = {
    1,              // Version 1 (no pin mediums or pin category).
    MERIT_NORMAL,   // Merit.
    1,              // Number of pins.
    &sudPins        // Pointer to pin information.
};

這里dwVersion(第一個(gè)字段)為一搔预,表示使用AMOVIESETUP_PIN格式的的定義霹期。Merit(第二個(gè)字段拯田,表示加入Filter Graph Manager的順序)這里使用MERIT_DO_NOT_USE.
注冊結(jié)果如下:

image.png

在第二個(gè)注冊信息中,它包含了pin的定義船庇,媒體類型等信息,但是沒有包含路徑信息(包含在第一個(gè)中)鸭轮,所以第二條信息看起來只是給system_device_enumerates使用的。 這也是obs-vcam可以用一個(gè)lib模擬多個(gè)攝像頭的原因邑蒋。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末按厘,一起剝皮案震驚了整個(gè)濱河市医吊,隨后出現(xiàn)的幾起案子刻剥,更是在濱河造成了極大的恐慌滩字,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件麦箍,死亡現(xiàn)場離奇詭異,居然都是意外死亡享钞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門栗竖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狐肢,你說我怎么就攤上這事》菝” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵鲤孵,是天一觀的道長辰如。 經(jīng)常有香客問我普监,道長琉兜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任呕童,我火速辦了婚禮,結(jié)果婚禮上奸汇,老公的妹妹穿的比我還像新娘。我一直安慰自己擂找,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布贯涎。 她就那樣靜靜地躺著慢洋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪普筹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天太防,我揣著相機(jī)與錄音,去河邊找鬼。 笑死幔嗦,一個(gè)胖子當(dāng)著我的面吹牛沥潭,可吹牛的內(nèi)容都是我干的崭添。 我是一名探鬼主播叛氨,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼屁置!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起仁连,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤饭冬,失蹤者是張志新(化名)和其女友劉穎使鹅,沒想到半個(gè)月后昌抠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡裁厅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年侨艾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唠梨。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖当叭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情均牢,我是刑警寧澤糠雨,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站琅攘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏坞琴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一剧辐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧溉奕,春花似錦、人聲如沸加勤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽未檩。三九已至,卻和暖如春冤狡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筒溃。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工怜奖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浑测,地道東北人歪玲。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像滥崩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子钙皮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容