2

小さな変換フィルター (TransInPlaceFilter 基本クラスから派生) を作成し、完全に C++ でコード化された Directshow グラフで適切に機能するように管理しました。基本的に、MSDNで説明されている最初の 5 つの手順と、6 番目の手順の最後の部分 (アプリケーション内でフィルターを直接使用するため) に従いました。

多くの理由 (GraphEdit でフィルターを使用できるなど) により、そのフィルターを DLL にエクスポートして登録する必要があります。

「CreateInstance」メソッドの設定、CFactoryTemplate クラス、フィルター/ピンの説明 (AMOVIESETUP_FILTER、AMOVIESETUP_PIN、AMOVIESETUP_MEDIA)、関数の登録/登録解除、最後に DLLmain/entrypointの手順を実行しようとしています。

コードは正常にコンパイルされ、Regsvr32 を使用して問題なく登録されているように見える DLL を提供します。

しかし、その後、フィルターを使用できません:

  • GraphEdit のリストに表示されますが、挿入しようとすると失敗します: 0x800401f9 ("Error in DLL")。
  • C++ で作成しようとすると (pCustomFilter.CoCreateInstance(CLSID_Custom)正しい GUID を定義した後に を使用)、エラー 0x80040154 (REGDB_E_CLASSNOTREG) が発生します。

私はここでかなり混乱しています。DLL/登録コードで何かを見逃していませんか? 使用しているコードのほとんどを投稿しています。

どんな助けでも大歓迎です。

static const WCHAR g_wszName[] = L"Custom Filter";

AMOVIESETUP_MEDIATYPE sudMediaTypes[] = {
    { &MEDIATYPE_Video, &MEDIASUBTYPE_NULL },
    { &MEDIATYPE_Audio, &MEDIASUBTYPE_NULL },
};

AMOVIESETUP_PIN sudPins[2] = {
    {
        L"Input",            // Name
        FALSE,          // Is this pin rendered?
        FALSE,          // Is it an output pin?
        FALSE,          // Can the filter create zero instances?
        FALSE,          // Does the filter create multiple instances?
        &GUID_NULL,     // Obsolete.
        NULL,           // Obsolete.
        2,              // Number of media types.
        sudMediaTypes   // Pointer to media types.
    },
    {
        L"Output",            // Name
        FALSE,          // Is this pin rendered?
        TRUE,           // Is it an output pin?
        FALSE,          // Can the filter create zero instances?
        FALSE,          // Does the filter create multiple instances?
        &GUID_NULL,     // Obsolete.
        NULL,           // Obsolete.
        2,              // Number of media types.
        sudMediaTypes   // Pointer to media types.
    }
};

AMOVIESETUP_FILTER sudFilterReg = {
    &CLSID_Custom,          // Filter CLSID.
    g_wszName,              // Filter name.
    MERIT_DO_NOT_USE,       // Merit.
    2,                      // Number of pin types.
    sudPins             // Pointer to pin information.
};


CFactoryTemplate g_Templates[] = 
{
  { 
    g_wszName,
    &CLSID_Custom,
    CCustomFilter::CreateInstance,
    NULL,
    &sudFilterReg
  }
};

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

STDAPI DllRegisterServer()
{
    return AMovieDllRegisterServer2( TRUE );
}
STDAPI DllUnregisterServer()
{
    return AMovieDllRegisterServer2( FALSE );
}


extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
{
    return DllEntryPoint(reinterpret_cast<HINSTANCE>(hDllHandle), dwReason, lpReserved);
}

// ---
// Meanwhile, in my filter class...
// ---
CUnknown * WINAPI CCustomFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
{
    CCustomFilter *pFilter = new CCustomFilter();
    if (pFilter== NULL) 
    {
        *pHr = E_OUTOFMEMORY;
    }
    return pFilter;
}
4

3 に答える 3

3

問題が解決しました。それは実際には2つのことでした:

  1. DLL(私が考えていなかったもの...)、より具体的にはCoCreateInstance関数を直接デバッグすることで、文字列マクロの問題に気付くことができました。TransInPlaceFilterのコンストラクターが不正な引数で呼び出されたため、クラッシュが発生しました。

  2. 誰かが私に必要なすべての関数をエクスポートしていないことに気づきました(MSDNでここに説明されています)。私の.defファイルにはDllMain、DllGetClassObject、DllCanUnloadNowがありませんでした。これらの最後の2つの関数は、baseclassesライブラリですでに定義されているため、defに表示する必要があります。

`

LIBRARY "custom_filter"
EXPORTS
    DllMain                 PRIVATE /* missing */
    DllGetClassObject       PRIVATE /* missing */
    DllCanUnloadNow         PRIVATE /* missing */
    DllRegisterServer       PRIVATE
    DllUnregisterServer     PRIVATE

あなたの助けをどうもありがとう!

于 2011-02-14T10:17:02.233 に答える
0

正しいレジストリエントリが書き込まれたことを確認しましたか?

CoCreateInstanceのレジストリエントリは、フィルタ列挙のエントリと同じではないため、GraphEditのフィルタリストにフィルタが表示される可能性がありますが、CoCreateInstanceは失敗します。

http://msdn.microsoft.com/en-us/library/dd390639(v=VS.85).aspx

于 2011-02-13T05:04:10.537 に答える