Использование специального фильтра DirectShow (DLL, зарегистрирован) - PullRequest
2 голосов
/ 11 февраля 2011

Я написал небольшой фильтр преобразования (полученный из базового класса TransInPlaceFilter) и сумел заставить его работать должным образом в графе Directshow, целиком написанном на C ++.Я в основном выполнил 5 первых шагов, описанных в MSDN , и последнюю часть 6-го шага (чтобы использовать фильтр непосредственно в приложении).

По многим причинам (включая возможность использования фильтра в GraphEdit), мне нужно экспортировать этот фильтр в DLL и зарегистрировать его.

Я пытался выполнить эти шаги : настройка "CreateInstance ", класс CFactoryTemplate, описание фильтра / выводов (AMOVIESETUP_FILTER, AMOVIESETUP_PIN, AMOVIESETUP_MEDIA), регистрация / отмена регистрации функций и, наконец, DLLmain / точка входа.

Код успешно компилируется и предоставляет DLL, которая, кажется, регистрируетсябез проблем с помощью Regsvr32.

Но тогда я не могу использовать фильтр:

  • Он появляется в списке в GraphEdit, но не удается, когда я пытаюсь его вставить: 0x800401f9(«Ошибка в 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;
}

Ответы [ 3 ]

3 голосов
/ 14 февраля 2011

Проблема решена. На самом деле это были две вещи:

  1. Непосредственная отладка DLL (что-то, о чем я не думал ...), в частности функция CoCreateInstance, помогла мне заметить проблему со строковыми макросами. Конструктор для TransInPlaceFilter был вызван с неверным аргументом, который вызвал сбой.

  2. Кто-то заставил меня заметить, что я не экспортировал все необходимые функции (как описано здесь в MSDN). В моем файле .def отсутствовали DllMain, DllGetClassObject и DllCanUnloadNow. Эти две последние функции просто должны появиться в def, поскольку они уже определены в библиотеке базовых классов.

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

Большое спасибо за вашу помощь!

1 голос
/ 12 февраля 2011

Необходимо проверить, что GUID везде одинаков: AMOVIESETUP_FILTER, CFactoryTemplate и передается в конструктор CTransInPlaceFilter.

Кроме того, рекомендуется передавать параметры pUnk и pHr в CCustomFilter :: CreateInstance в ваш конструктор CCustomFilter и оттуда в конструктор CTransInPlaceFilter, чтобы любые ошибки могли быть переданы вызывающей стороне. В вашем случае любые такие ошибки будут проглочены вашим конструктором. Пример:

CUnknown* WINAPI FramerateDisplayFilter::CreateInstance(LPUNKNOWN pUnk, 
                                                        HRESULT *pHr )
{
  FramerateDisplayFilter *pFilter = new FramerateDisplayFilter(pUnk, pHr);
  if (pFilter== NULL) 
  {
    *pHr = E_OUTOFMEMORY;
  }
  return pFilter;
}


FramerateDisplayFilter::FramerateDisplayFilter(LPUNKNOWN pUnk, HRESULT *pHr)
: CTransInPlaceFilter(NAME("CSIR RTVC Framerate Estimator Filter"), pUnk,   
                      CLSID_RTVCFramerateEstimatorFilter, pHr, false),
  m_uiEstimatedFramerate(0),
  m_bSeenFirstFrame(false),
  m_previousTimestamp(0)
{;}
0 голосов
/ 13 февраля 2011

Вы убедились, что были записаны правильные записи реестра?

Запись реестра для CoCreateInstance отличается от записи для перечисления фильтров, поэтому фильтр может появиться в списке фильтров GraphEdit, но при этом произойдет сбой CoCreateInstance.

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

...