Date

Windows Mobile で導入されているフィルタは(残念ながら)かなり少ない。MSDN の Encoded Media のページから辿って Supported Video Codecs をみると Windows Mobile 6 では MS RLE, WMV Encoder DMO だけである。 Audio も MPEG-1 Audio Layer 1,2…。

今回は導入されているフィルタを列挙するアプリを作ってみる。Windows の DirectShow であれば IFilterMapper2 が使えるが、Windows Mobile では前バージョンの IFilterMapper を使う。

UI

画面内に列挙したフィルタ名を表示するためのリストボックスを追加する。180行付近にある WM_CREATE で次のコードを追加する。

1
2
3
4
g_hList = CreateWindow(L"LISTBOX", L"", WS_CHILD|WS_VISIBLE|
    (LBS_NOTIFY | WS_VSCROLL | WS_BORDER)|LBS_HASSTRINGS,
    8, 8, 450, 550, hWnd, NULL
    ,g_hInst, NULL);

g_hList は HWND 型のグローバル変数として宣言しておくこと。

リソースエディタで IDR_MENU に「フィルタ取得」のメニュー項目を作成する。プロパティウインドウを開いて ID を ID_ENUMFILTER と指定する。170行目付近の WM_COMMMAND 処理にコードを追加する。

1
2
case ID_ENUMFILTER:
DoEnumFilter();

DoEnumFilter

FilterMapper を CoCreateInstance で作成する。IFilterMapper::EnumMatchingFilters を使って IEnumRegFilters を取得する。このインターフェイスで 1 つずつフィルタを列挙できる。せっかくなのでカメラデバイスのフィルタも挙げてみた。(参考)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int DoEnumFilter() {
    HRESULT hr;
    IFilterMapper   *pMapper = NULL;
    IEnumRegFilters *pEnum   = NULL;
    IBaseFilter * pFilter = NULL;
    hr = CoCreateInstance(CLSID_FilterMapper, NULL, CLSCTX_INPROC, IID_IFilterMapper, (void **)&pMapper);
    if(FAILED(hr)){
        return 0;
    }
    hr = pMapper->EnumMatchingFilters(&pEnum,0,FALSE,GUID_NULL,GUID_NULL,FALSE,FALSE,GUID_NULL,GUID_NULL);
    REGFILTER *pRF = NULL;
    ULONG cFetched;
    while (pEnum->Next(1, &pRF, &cFetched) == S_OK) {
        SendMessage(g_hList,LB_ADDSTRING,0,(LPARAM)pRF->Name);
        CoTaskMemFree(pRF);

        hr = CoCreateInstance(pRF->Clsid, NULL, CLSCTX_INPROC
            , IID_IBaseFilter, (void **)&pFilter);
        SendMessage(g_hList,LB_ADDSTRING,0,(LPARAM)TEXT(" [IN]"));
        EnumPins(pFilter,PINDIR_INPUT);
        SendMessage(g_hList,LB_ADDSTRING,0,(LPARAM)TEXT(" [OUT]"));
        EnumPins(pFilter,PINDIR_OUTPUT);
        SAFE_RELEASE(pFilter);
    }
    // capture device
    HANDLE handle = NULL;
    DEVMGR_DEVICE_INFORMATION di={sizeof(di)};
    GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A,0x93, 0x3E, 0x4D, 0x7E, 0x3C, 0x86 };
    handle = FindFirstDevice( DeviceSearchByGuid, &guidCamera, &di );
    if(( handle == NULL ) || ( di.hDevice == NULL )) {
    }else{
        SendMessage(g_hList,LB_ADDSTRING,0,(LPARAM)di.szLegacyName );
    }
    FindClose( handle );
    return 1;
}

EnumPins の実装

フィルタに備わっているピンも表示させてみよう。ピンを列挙する EnumPins 関数を実装する。

フィルタの IBaseFilter::EnumPins を呼び出してピンを列挙する。引数 dir で指定した入力ピン、出力ピンと一致していればピン名の文字列をリストボックスに追加する。ただし、このやり方では動的にピンの数が変化するようなフィルタの場合は有効に働かない。既定で備わってるピンのみ列挙される。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
HRESULT EnumPins(IBaseFilter *pFilter,PIN_DIRECTION dir) {
    HRESULT retCode=E_FAIL;
    HRESULT hr=NOERROR;
    IEnumPins *e=NULL;
    IPin *pPin=NULL;
    hr=pFilter->EnumPins(&e);
    if(FAILED(hr)){
        return hr;
    }
    while (e->Next(1, &pPin, NULL) == S_OK){
        PIN_DIRECTION PinDirThis;
        hr=pPin->QueryDirection(&PinDirThis);
        if (FAILED(hr)){
            SAFE_RELEASE(pPin);
            continue;
        }
        if (PinDirThis != dir){
            SAFE_RELEASE(pPin);
            continue;
        }
        PIN_INFO info;
        hr=pPin->QueryPinInfo(&info);
        if (FAILED(hr)){
            SAFE_RELEASE(pPin);
            continue;
        }
        WCHAR name[256];
        _snwprintf(name,256,TEXT("  - %s"),info.achName);
        SendMessage(g_hList,LB_ADDSTRING,0,(LPARAM)name);
        SAFE_RELEASE(info.pFilter);
        SAFE_RELEASE(pPin);
    }
    SAFE_RELEASE(e);
    return retCode;
}

サンプルコード

https://github.com/mahorigahama/WM6Filters


Comments

comments powered by Disqus