2011-02-11 7 views
2

TransInPlaceFilter baseclass에서 파생 된 작은 변환 필터를 작성하고 C++로 완전히 코딩 된 DirectShow 그래프에서 제대로 작동하도록 관리했습니다. 기본적으로 MSDN에 설명 된 5 단계와 6 단계 마지막 단계를 따랐습니다 (응용 프로그램 내에서 직접 필터를 사용하기 위해).사용자 지정 DirectShow 필터 사용 (DLL, 등록)

많은 이유로 (GraphEdit에서 필터를 사용할 수있는 것을 포함하여), 필터를 DLL로 내보내고 등록해야합니다. 은 "때 CreateInstance"방법의 CFactoryTemplate 클래스, 필터/핀 설명 (AMOVIESETUP_FILTER, AMOVIESETUP_PIN, AMOVIESETUP_MEDIA), 등록/등록 해제 기능, 그리고 마지막으로 DLLmain/엔트리 포인트를 설정 :

나는 these steps을 따르려고 노력했습니다.

코드가 성공적으로 컴파일되고 Regsvr32를 사용하여 아무 문제없이 등록하는 것처럼 보이는 DLL을 제공합니다.

하지만 그때 필터를 사용할 수 없습니다 해요 :

  • 그것은 GraphEdit로의 목록에 나타납니다,하지만 난 그것을 삽입하려고하면 실패 : 0x800401f9 ("오류를 DLL에서"). 나는 (올바른 GUID를 정의한 후, pCustomFilter.CoCreateInstance(CLSID_Custom)를 사용하여) C++에서 그것을 만들려고 할 때
  • , 나는 오류 0x80040154 (REGDB_E_CLASSNOTREG) 내가 여기에 꽤 혼란 스러워요

를 얻을. DLL/등록 코드에서 뭔가 빠졌습니까? 어떤 코드를 사용하고 있다면 대부분의 코드를 게시하고 있습니다.

도움을 주시면 감사하겠습니다. AMOVIESETUP_FILTER, CFactoryTemplate 및 CTransInPlaceFilter 생성자에 전달 : 확인

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; 
} 
+1

아무것도 손에 웃기지 않습니까? CreateInstance에 중단 점을 넣은 다음 VS에서 디버그 exe로 GraphEdit을 설정 했습니까? 그런 다음 브레이크 포인트가 전혀 맞지 않는지 확인하십시오. 또한 GraphEdit에서 필터를 살펴보십시오. 필터 ​​세부 정보를 확장하면 "Filename"경로가 올바른 것입니까? – Ralf

+0

GraphEdit에서 "Filename"이 정확하고 내 DLL을 가리 킵니다. 장점, 핀 및 미디어 정보도 정확합니다. 나중에 GE의 디버깅을 직접 시도해 보겠습니다. – BlueCookie

+0

모든 것이 이제 괜찮습니다! 직접 DLL을 디버깅하면 문제를 해결하는 데 도움이되었습니다. 게시물을 만들고 원래 필터를 편집 할 것입니다 ... – BlueCookie

답변

1

한 것은 GUID가 동일한 어디에나 있다는 것이다.

또한 CCustomFilter :: CreateInstance의 pUnk 및 pHr 매개 변수를 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) 
{;} 
+1

pUnk와 pHr을 필터의 생성자에 전달해야한다는 것에 동의합니다. 그렇게하지 않으면 pHr은 CreateInstance에서 S_OK로 설정되지 않습니다. 그게 문제가 아닌지 확실하지 않습니다. – wimh

+0

방금 ​​생성자에 pUnk 및 pHr 매개 변수를 추가했지만 새로운 오류가 발생했습니다 (정확한 지점과 관련 없음). 자세한 내용은 원본 게시물을 확인하십시오. GUID의 경우 코드에서 전달 된 값은 항상 동일합니다. 런타임에 확인하지 않았지만 수정해야 할 이유가 없습니다. (고맙습니다. 지금까지 많은 도움을주었습니다) – BlueCookie

0

올바른 레지스트리 항목이 작성되었는지 확인 했습니까?

CoCreateInstance의 레지스트리 항목이 필터 열거 항목과 같지 않아서 필터가 GraphEdit의 필터 목록에 나타날 수는 있지만 CoCreateInstance는 실패 할 수 있습니다.

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

+0

방금 ​​regsvr32를 사용한 후 DLL 정보가 HKEY_CLASSES_ROOT \ Wow6432Node \ CLSID \ {76E46C23-7C56-4B6E-B10D-39D6E} (및 \ InprocServer32)에 있으며 필터 정보는 HKEY_CLASSES_ROOT \ Wow6432Node \ CLSID \ {083863F1-70DE-11D0-BD40-00A0C911CE86} \ Instance \ {76E46C23-7C56-4B6E-B10D-39D6E}에 있습니다. "Wow6432Node"를 제외하고 모두 괜찮아 보입니다. 64 비트 컴퓨터에서 컴파일하면 문제가 발생할 수 있습니까? – BlueCookie

+0

거대한, 못생긴 unformated 의견 - 죄송합니다. – BlueCookie

3

문제가 해결되었습니다. 보다 구체적으로 CoCreateInstance 함수 직접 DLL (내가 생각하지 않은 뭔가를해야만 ...) 디버깅

  1. , 나 문자열 매크로 문제를 통지 도움이 : 사실은 두 가지였다. TransInPlaceFilter의 생성자가 잘못된 인수로 호출되었으므로 충돌이 발생했습니다.

  2. 누구나 내가 필요한 모든 기능을 내보낼 수 없다는 사실을 알게되었습니다 (MSDN에서 here으로 설명). 나의 .def 파일에는 DllMain, DllGetClassObject 및 DllCanUnloadNow가 없습니다. 이 2 개의 마지막 함수는 이미 기본 라이브러리에 정의되어 있으므로 def에 표시해야합니다.

`

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

도와 주셔서 감사합니다 많이!

관련 문제