Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
Windos
win32.3rdparty
win32.directx.audio
win32.directx.ddk
win32.directx.graphics
win32.directx.input
win32.directx.managed
win32.directx.misc
win32.directx.networking
win32.directx.sdk
win32.directx.video
win32.dirx.grap.shaders
win32.gdi
win32.international
win32.kernel
win32.messaging
win32.mmedia
win32.networks
win32.ole
win32.rtc
win32.tapi
win32.tapi.beta
win32.tools
win32.ui
win32.wince
win32.wmi
windows.mediacenter
winfx.aero
winfx.announcements
winfx.avalon
winfx.collaboration
winfx.fundamentals
winfx.general
winfx.indigo
winfx.sdk
winfx.winfs
  
 
date: Sun, 16 Oct 2005 02:52:01 -0700,    group: microsoft.public.win32.programmer.directx.misc        back       


Creating a custom DirectShow renderer filter.   
Hi,

I need to create a filter which is an alternative to the "File Writer" 
DirectShow Filter, specifically one which sends whatever it receives straight 
over the network. I am familiar with DirectShow, but not filter writing, and 
relatively familiar with C++. I have tried various tutorials and wizards and 
templates, but haven't really had much success at all in understanding the 
process. Could somebody please enlighten me as to how the filter-writing 
process works?

-- 

Andrew Garrett
Epstone Networks
date: Sun, 16 Oct 2005 02:52:01 -0700   author:   Andrew Garrett

Re: Creating a custom DirectShow renderer filter.   
On Sun, 16 Oct 2005 02:52:01 -0700, "Andrew Garrett"
 wrote:

>Hi,
>
>I need to create a filter which is an alternative to the "File Writer" 
>DirectShow Filter, specifically one which sends whatever it receives straight 
>over the network. I am familiar with DirectShow, but not filter writing, and 
>relatively familiar with C++. I have tried various tutorials and wizards and 
>templates, but haven't really had much success at all in understanding the 
>process. Could somebody please enlighten me as to how the filter-writing 
>process works?

The documentation does a fairly good job of explaining what needs to be
done. Look at the documentation for CBaseRenderer, for instance. What,
specifically, are you having problems with?

-- 
Be seeing you.
date: Sun, 16 Oct 2005 10:56:36 -0500   author:   Thore Karlsen [MVP DX]

Re: Creating a custom DirectShow renderer filter.   
On Sun, 16 Oct 2005 10:56:36 -0500, Thore Karlsen [MVP DX] wrote:

> The documentation does a fairly good job of explaining what needs to be
> done. Look at the documentation for CBaseRenderer, for instance. What,
> specifically, are you having problems with?

Also, the Dump sample is a good place to start.

Unfortunately, the filter wizard on my site does not support renderers.

-- 
Please read this before replying:
1. Dshow & posting help:  http://tmhare.mvps.org/help.htm
2. Trim & respond inline (please don't top post or snip everything)
3. Benefit others:  follow up if you are helped or you found a solution
date: Sun, 16 Oct 2005 12:48:05 -0600   author:   The March Hare [MVP]

Re: Creating a custom DirectShow renderer filter.   
"Thore Karlsen [MVP DX]" wrote:

> On Sun, 16 Oct 2005 02:52:01 -0700, "Andrew Garrett"
>  wrote:
> 
> >Hi,
> >
> >I need to create a filter which is an alternative to the "File Writer" 
> >DirectShow Filter, specifically one which sends whatever it receives straight 
> >over the network. I am familiar with DirectShow, but not filter writing, and 
> >relatively familiar with C++. I have tried various tutorials and wizards and 
> >templates, but haven't really had much success at all in understanding the 
> >process. Could somebody please enlighten me as to how the filter-writing 
> >process works?
> 
> The documentation does a fairly good job of explaining what needs to be
> done. Look at the documentation for CBaseRenderer, for instance. What,
> specifically, are you having problems with?

I'll take a look at that documentation - I was looking at basing it on the 
CBaseFilter class - in accordance with the MSDN Documentation on writing a 
transform filter (which was the only documentation i could find on writing a 
filter. In any case, I'll have a look and get back to you. Thanks for your 
help.
> 
> -- 
> Be seeing you.
>
date: Sun, 16 Oct 2005 16:30:02 -0700   author:   Andrew Garrett

Re: Creating a custom DirectShow renderer filter.   
I've created the filter for myself, but I need to load it into GraphEdit to 
test it. I've implemented all the stuff it says I should implement on the 
MSDN website, and got it to appear in GraphEdit. My problem is that when I 
try to create it in GraphEdit, it gives me the message:

"The filter could not be created. Resources used by this filter may already 
be in use.

Error in the DLL (Return code 0x800401f9)".

The source code relevant to my implementation of registration follows:

//----------BEGIN-SOURCE-CODE--------//
//COM-DLL-Stuff.cpp

#include "stdafx.h"
#include "DirectShow Network Sender.h"
;
static WCHAR g_wszName[] = L"Epstone Network Sender Filter";

CUnknown * WINAPI CreateSenderInstance(LPUNKNOWN pUnk, HRESULT *pHr);

CFactoryTemplate g_Templates[] = 
{
  { 
    g_wszName,
    &CLSID_NETWORKSENDERFILTER,
    CreateSenderInstance,
    NULL,
    NULL
  }
};

REGPINTYPES rptTypes[] = {{ &MEDIATYPE_Stream, &MEDIASUBTYPE_None }};

REGFILTERPINS sudPins = {
	NULL,
	true,
	false,
	false,
	false,
	NULL,
	NULL,
	1,
	&rptTypes[0]
};

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


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

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

STDAPI DllRegisterServer()
{

    HRESULT hr;
    IFilterMapper2 *pFM2 = NULL;

    hr = AMovieDllRegisterServer2(TRUE);
    if (FAILED(hr))
        return hr;

    hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
            IID_IFilterMapper2, (void **)&pFM2);

    if (FAILED(hr))
        return hr;

    hr = pFM2->RegisterFilter(
        CLSID_NETWORKSENDERFILTER,			// Filter CLSID. 
        g_wszName,							// Filter name.
        NULL,								// Device moniker. 
        &CLSID_LegacyAmFilterCategory,		// Video compressor category.
        g_wszName,							// Instance data.
        &rf2FilterReg						// Pointer to filter information.
    );
    pFM2->Release();
    return hr;

}
STDAPI DllUnregisterServer()
{
    HRESULT hr;
    IFilterMapper2 *pFM2 = NULL;

    hr = AMovieDllRegisterServer2(FALSE);
    if (FAILED(hr))
        return hr;
 
    hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
            IID_IFilterMapper2, (void **)&pFM2);

    if (FAILED(hr))
        return hr;

    hr = pFM2->UnregisterFilter(&CLSID_LegacyAmFilterCategory, 
            g_wszName, CLSID_NETWORKSENDERFILTER);

    pFM2->Release();
    return hr;
}

//DLLExport.def

LIBARY			DirectShow Network Sender Filter.ax
EXPORTS
                DllGetClassObject PRIVATE
                DllCanUnloadNow PRIVATE
                DllRegisterServer PRIVATE
                DllUnregisterServer PRIVATE
//----------END-SOURCE-CODE-----------//
-- 
Andrew Garrett
Epstone Networks
date: Mon, 17 Oct 2005 19:51:03 -0700   author:   Andrew Garrett

Re: Creating a custom DirectShow renderer filter.   
Okay, I resolved my previous issue (issue was not renaming .dll to .ax). I 
now have a bigger problem. When I create an instance of the filter, I end up 
with an exception trying to execute code at 0x0000. I believe the problem is 
that the pUnk pointer is NULL when it is passed to my CreateInstance 
function, and therefore is so when it is passed to the CBaseRenderer 
Constructor.
-- 

Andrew Garrett
Epstone Networks
date: Tue, 18 Oct 2005 16:10:02 -0700   author:   Andrew Garrett

Re: Creating a custom DirectShow renderer filter.   
On Tue, 18 Oct 2005 16:10:02 -0700, "Andrew Garrett"
 wrote:

>Okay, I resolved my previous issue (issue was not renaming .dll to .ax). I 
>now have a bigger problem. When I create an instance of the filter, I end up 
>with an exception trying to execute code at 0x0000. I believe the problem is 
>that the pUnk pointer is NULL when it is passed to my CreateInstance 
>function, and therefore is so when it is passed to the CBaseRenderer 
>Constructor.

The best way to find out is to check the call stack in the debugger when
you get the crash. pUnk is normally NULL, though, and CBaseRenderer can
deal with that just fine, so that shouldn't be a problem.

-- 
Be seeing you.
date: Wed, 19 Oct 2005 10:49:28 -0500   author:   Thore Karlsen [MVP DX]

Re: Creating a custom DirectShow renderer filter.   
"Thore Karlsen [MVP DX]" wrote:

> On Tue, 18 Oct 2005 16:10:02 -0700, "Andrew Garrett"
>  wrote:
> 
> >Okay, I resolved my previous issue (issue was not renaming .dll to .ax). I 
> >now have a bigger problem. When I create an instance of the filter, I end up 
> >with an exception trying to execute code at 0x0000. I believe the problem is 
> >that the pUnk pointer is NULL when it is passed to my CreateInstance 
> >function, and therefore is so when it is passed to the CBaseRenderer 
> >Constructor.
> 
> The best way to find out is to check the call stack in the debugger when
> you get the crash. pUnk is normally NULL, though, and CBaseRenderer can
> deal with that just fine, so that shouldn't be a problem.

The call stack isn't helping at all. All it gives is 0x000000() - doesn't 
tell me where the problem came from. The only thing i can see is: "Unhandled 
exception at 0x00000000 in Webcam Capture Test.exe: 0xC0000005: Access 
violation reading location 0x00000000.". I had a look at 0xC0000005 and it 
seems blank. The size of my created renderer is 16 bytes. Is this normal. I 
can give you further output from my debugging output.

Thanks

> 
> -- 
> Be seeing you.
>
date: Wed, 19 Oct 2005 19:36:05 -0700   author:   Andrew Garrett

Re: Creating a custom DirectShow renderer filter.   
On Wed, 19 Oct 2005 19:36:05 -0700, "Andrew Garrett"
 wrote:

>> >Okay, I resolved my previous issue (issue was not renaming .dll to .ax). I 
>> >now have a bigger problem. When I create an instance of the filter, I end up 
>> >with an exception trying to execute code at 0x0000. I believe the problem is 
>> >that the pUnk pointer is NULL when it is passed to my CreateInstance 
>> >function, and therefore is so when it is passed to the CBaseRenderer 
>> >Constructor.

>> The best way to find out is to check the call stack in the debugger when
>> you get the crash. pUnk is normally NULL, though, and CBaseRenderer can
>> deal with that just fine, so that shouldn't be a problem.

>The call stack isn't helping at all. All it gives is 0x000000() - doesn't 
>tell me where the problem came from. The only thing i can see is: "Unhandled 
>exception at 0x00000000 in Webcam Capture Test.exe: 0xC0000005: Access 
>violation reading location 0x00000000.". I had a look at 0xC0000005 and it 
>seems blank. The size of my created renderer is 16 bytes. Is this normal. I 
>can give you further output from my debugging output.

OK, how about stepping through your code until you get to the line that
causes the crash, and then posting the code around that point? From the
sound of it, your application is a relatively simple test application,
so it shouldn't be too hard to pinpoint the location that causes the
crash. I'll need to see some code to determine what the problem is.

-- 
Be seeing you.
date: Thu, 20 Oct 2005 10:00:32 -0500   author:   Thore Karlsen [MVP DX]

Re: Creating a custom DirectShow renderer filter.   
"Thore Karlsen [MVP DX]" wrote:

> On Wed, 19 Oct 2005 19:36:05 -0700, "Andrew Garrett"
>  wrote:
> 
> >> >Okay, I resolved my previous issue (issue was not renaming .dll to .ax). I 
> >> >now have a bigger problem. When I create an instance of the filter, I end up 
> >> >with an exception trying to execute code at 0x0000. I believe the problem is 
> >> >that the pUnk pointer is NULL when it is passed to my CreateInstance 
> >> >function, and therefore is so when it is passed to the CBaseRenderer 
> >> >Constructor.
> 
> >> The best way to find out is to check the call stack in the debugger when
> >> you get the crash. pUnk is normally NULL, though, and CBaseRenderer can
> >> deal with that just fine, so that shouldn't be a problem.
> 
> >The call stack isn't helping at all. All it gives is 0x000000() - doesn't 
> >tell me where the problem came from. The only thing i can see is: "Unhandled 
> >exception at 0x00000000 in Webcam Capture Test.exe: 0xC0000005: Access 
> >violation reading location 0x00000000.". I had a look at 0xC0000005 and it 
> >seems blank. The size of my created renderer is 16 bytes. Is this normal. I 
> >can give you further output from my debugging output.
> 
> OK, how about stepping through your code until you get to the line that
> causes the crash, and then posting the code around that point? From the
> sound of it, your application is a relatively simple test application,
> so it shouldn't be too hard to pinpoint the location that causes the
> crash. I'll need to see some code to determine what the problem is.
The problem occurs in some ASM code - stepping through in the VS debugger I 
have found a stack trace:
 	DSNetworkSender.ax!CClassFactory::CreateInstance()  + 0xa9	C++
 	ole32.dll!775202e3() 	
 	ole32.dll!77520143() 	
 	ole32.dll!775203f2() 	
 	ole32.dll!77520369() 	
 	ole32.dll!7752112b() 	
 	ole32.dll!775210e2() 	
 	ole32.dll!77520453() 	
 	ole32.dll!77520143() 	
 	ole32.dll!775200de() 	
 	ntdll.dll!7c90fb6c() 	
 	ntdll.dll!7c90fb71() 	
 	kernel32.dll!7c809392() 	
 	ole32.dll!7750055e() 	
 	ole32.dll!7750067b() 	
 	ole32.dll!7750078e() 	
 	ole32.dll!775009b5() 	
 	ole32.dll!775017f3() 	
 	ole32.dll!775008df() 	
 	ole32.dll!775008fa() 	
 	ole32.dll!7751e53b() 	
 	ole32.dll!7751f4a2() 	
 	ole32.dll!77520143() 	
 	ole32.dll!7751f4ed() 	
 	ole32.dll!7751ff88() 	
 	ntdll.dll!7c96d886() 	
 	ntdll.dll!7c96d886() 	
 	ntdll.dll!7c949d18() 	
 	ntdll.dll!7c91b686() 	
 	ntdll.dll!7c91056d() 	
 	advapi32.dll!77dde0ae() 	
 	advapi32.dll!77dde32e() 	
 	advapi32.dll!77dde343() 	
 	advapi32.dll!77dde350()

and some asm code from that particular location:

10001E2A  push        1    
10001E2C  mov         ecx,esi 
10001E2E  call        dword ptr [edx+0Ch] 
10001E31  mov         eax,dword ptr [esp+1Ch] 
10001E35  pop         esi  
10001E36  pop         ebx  
10001E37  pop         ebp  
10001E38  ret         10h  
10001E3B  mov         eax,dword ptr [esi] 
10001E3D  push        esi  
10001E3E  call        dword ptr [eax+4] 
10001E41  mov         ecx,dword ptr [esi] 
10001E43  push        ebp  
10001E44  push        ebx  
10001E45  push        esi  
10001E46  call        dword ptr [ecx] 
10001E48  mov         dword ptr [esp+1Ch],eax 
10001E4C  mov         edx,dword ptr [esi] 
10001E4E  push        esi  
10001E4F  call        dword ptr [edx+8] 
10001E52  mov         eax,dword ptr [esp+1Ch] 
10001E56  pop         esi  
10001E57  pop         ebx  
10001E58  pop         ebp  
10001E59  ret         10h  
10001E5C  int         3    
10001E5D  int         3    
10001E5E  int         3    
10001E5F  int         3

It appears to be having trouble creating an instance of the class factory, 
having a quick squizz over the code. My code from the class factory part of 
my dll follows:

//COM DLL Stuff.cpp

#include "stdafx.h"
#include "DirectShow Network Sender.h"
;
static WCHAR g_wszName[] = L"Epstone Network Sender Filter";

// Setup information
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
    &MEDIATYPE_Video,       // Major type
    &MEDIASUBTYPE_NULL      // Minor type
};

const AMOVIESETUP_PIN sudpPins[] =
{
    { L"Input",             // Pins string name
	  FALSE,					// Is it rendered
      FALSE,                // Is it an output
      FALSE,                // Are we allowed none
      FALSE,                // And allowed many
      &CLSID_NULL,          // Connects to filter
      NULL,                 // Connects to pin
      1,                    // Number of types
      &sudPinTypes          // Pin information
    }
};

const AMOVIESETUP_FILTER sudSender =
{
    &CLSID_NETWORKSENDERFILTER,	// Filter CLSID
    g_wszName,					// String name
    MERIT_DO_NOT_USE,			// Filter merit
    1,							// Number of pins
    sudpPins					// Pin information
};

// List of class IDs and creator functions for the class factory. This
// provides the link between the OLE entry point in the DLL and an object
// being created. The class factory will call the static CreateInstance

CFactoryTemplate g_Templates[] = {
    { g_wszName
    , &CLSID_NETWORKSENDERFILTER
	, (LPFNNewCOMObject) CNetworkSenderFilter::CreateInstance
    , NULL
    , &sudSender }
};

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



CUnknown *CNetworkSenderFilter::CreateInstance(IN LPUNKNOWN pUnk, OUT 
HRESULT *pHr)
{

	char *message = new char[255];
	char *hrstr = new char[20];
	char *ptrstr = new char[20];
	int pfsize;
	char *szpfstr = new char[20];
	char *pHrstr = new char[20];
	char *pUnkstr = new char[20];

	*pHr = S_OK;

    CNetworkSenderFilter * pTheFilter;

	TCHAR *tszName;

	strcpy( (char*) tszName, "CNetworkSenderFilter" );
		
	pTheFilter = new CNetworkSenderFilter( tszName, pUnk, pHr );
    if (pTheFilter== NULL) 
    {
        *pHr = E_OUTOFMEMORY;
    }

//Display debugging message
	strcpy( message, "Creating CNetworkSenderFilter, hr=" );
	itoa( *pHr, hrstr, 16 );
	strcat( message, hrstr );
	ltoa( (long) pTheFilter, ptrstr, 16 );
	strcat( message, ", pFilter=" );
	strcat( message, ptrstr );
	pfsize = sizeof( *pTheFilter );
	itoa( pfsize, szpfstr, 16 );
	strcat( message, ", sizeof(*pTheFilter)=" );
	strcat( message, szpfstr );
	ltoa( (long) pHr, pHrstr, 16 );
	strcat( message, ", *pHr=" );
	strcat( message, pHrstr );
	ltoa( (long) pUnk, pUnkstr, 16 );
	strcat( message, ", *pUnk=" );
	strcat( message, pUnkstr );

	MessageBox( NULL, message, "", MB_OK | MB_ICONINFORMATION );

	delete message;
	delete hrstr;
	delete ptrstr;
	delete szpfstr;
	delete pHrstr;
	delete pUnkstr;

    return pTheFilter;
}

STDAPI DllRegisterServer()
{

    return AMovieDllRegisterServer2(TRUE);

}
STDAPI DllUnregisterServer()
{

    return AMovieDllRegisterServer2(FALSE);

}

// If we declare the correct C runtime entrypoint and then forward it to the 
DShow base
// classes we will be sure that both the C/C++ runtimes and the base classes 
are initialized
// correctly
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);
}

> 
> -- 
> Be seeing you.
>
date: Thu, 20 Oct 2005 15:55:02 -0700   author:   Andrew Garrett

Re: Creating a custom DirectShow renderer filter.   
On Thu, 20 Oct 2005 15:55:02 -0700, "Andrew Garrett"
 wrote:

[...]

>	TCHAR *tszName;
>
>	strcpy( (char*) tszName, "CNetworkSenderFilter" );

Here you have two problems. First, you're copying to an uninitialized
string pointer. Second, if you're compiling for Unicode, the string will
be invalid. If you're never compiling for Unicode, you shouldn't be
using TCHAR.

Also, you really shouldn't be allocating C strings without a very good
reason. This is 2005, and we now have classes like std::string and
CString. :)

-- 
Be seeing you.
date: Thu, 20 Oct 2005 18:53:06 -0500   author:   Thore Karlsen [MVP DX]

Re: Creating a custom DirectShow renderer filter.   
"Thore Karlsen [MVP DX]" wrote:

> On Thu, 20 Oct 2005 15:55:02 -0700, "Andrew Garrett"
>  wrote:
> 
> [...]
> 
> >	TCHAR *tszName;
> >
> >	strcpy( (char*) tszName, "CNetworkSenderFilter" );
> 
> Here you have two problems. First, you're copying to an uninitialized
> string pointer. Second, if you're compiling for Unicode, the string will
> be invalid. If you're never compiling for Unicode, you shouldn't be
> using TCHAR.
I'm never compiling for unicode, but the CBaseRenderer argument expects a 
TCHAR pointer, which I am providing it. Fixing up the NULL pointer issue 
gives me this error instead - "Unhandled exception at 0x0012ffe0 in Webcam 
Capture Test.exe: 0xC000001D: Illegal Instruction."

Stack Trace:
	0012ffe0()	
 	DSNetworkSender.ax!CClassFactory::CreateInstance()  + 0x98	C++

Disassembly:
0012FFBB  add         byte ptr [eax],al 
0012FFBD  add         byte ptr [eax],al 
0012FFBF  add         al,dh 
0012FFC1  call        dword ptr [edx] 
0012FFC3  add         byte ptr [edi+6Dh],cl 
0012FFC6  cmp         dword ptr [edi+ecx*2+5Bh],407C91h 
0012FFCE  add         byte ptr [eax],al 
0012FFD0  add         byte ptr [eax-3],ah 
0012FFD3  jg          0012FFF2 
0012FFD5  add         byte ptr [eax],al 
0012FFD7  ror         al,0FFh 
0012FFDA  adc         al,byte ptr [eax] 
0012FFDC  db          b8h  
0012FFDD  in          eax,dx 
0012FFDE  adc         al,byte ptr [eax] 
0012FFE0  db          ffh  
0012FFE1  db          ffh  
0012FFE2  db          ffh  
0012FFE3  push        ebx  
0012FFE5  cdq              
0012FFE6  cmp         dword ptr [eax+ebx*2+6Dh],0FFFFFF81h 
0012FFEB  jl          0012FFED

> 
> Also, you really shouldn't be allocating C strings without a very good
> reason. This is 2005, and we now have classes like std::string and
> CString. :)
> 
> -- 
> Be seeing you.
>
date: Thu, 20 Oct 2005 17:36:06 -0700   author:   Andrew Garrett

Re: Creating a custom DirectShow renderer filter.   
"Andrew Garrett" wrote:

> "Thore Karlsen [MVP DX]" wrote:
> 
> > On Thu, 20 Oct 2005 15:55:02 -0700, "Andrew Garrett"
> >  wrote:
> > 
> > [...]
> > 
> > >	TCHAR *tszName;
> > >
> > >	strcpy( (char*) tszName, "CNetworkSenderFilter" );
> > 
> > Here you have two problems. First, you're copying to an uninitialized
> > string pointer. Second, if you're compiling for Unicode, the string will
> > be invalid. If you're never compiling for Unicode, you shouldn't be
> > using TCHAR.
> I'm never compiling for unicode, but the CBaseRenderer argument expects a 
> TCHAR pointer, which I am providing it. Fixing up the NULL pointer issue 
> gives me this error instead - "Unhandled exception at 0x0012ffe0 in Webcam 
> Capture Test.exe: 0xC000001D: Illegal Instruction."

Okay, I've fixed this one up - it was some code I'd been testing out in the 
constructor to try and fix my previous problem. I have (yet another) issue , 
"Unhandled exception at 0x10001e54 (DSNetworkSender.ax) in Webcam Capture 
Test.exe: 0xC0000005: Access violation reading location 0xcc00890c.".

Stack Trace:

>	DSNetworkSender.ax!_DllGetClassObject@12()  + 0x14	C++
 	ole32.dll!7750206a() 	
 	ole32.dll!77520a03() 	
 	ole32.dll!7752071d() 	
 	ole32.dll!7752029f() 	
 	ole32.dll!77520143() 	
 	ole32.dll!775203f2() 	
 	ole32.dll!77520369() 	
 	ole32.dll!7752112b() 	
 	ole32.dll!775210e2() 	
 	ole32.dll!77520453() 	
 	ole32.dll!77520143() 	
 	ole32.dll!775200de() 	
 	ntdll.dll!7c90fb6c() 	
 	ntdll.dll!7c90fb71() 	
 	kernel32.dll!7c809392() 	
 	ole32.dll!7750055e() 	
 	ole32.dll!7750067b() 	
 	ole32.dll!7750078e() 	
 	ole32.dll!775009b5() 	
 	ole32.dll!775017f3() 	
 	ole32.dll!775008df() 	
 	ole32.dll!775008fa() 	
 	ole32.dll!7751e53b() 	
 	ole32.dll!7751f4a2() 	
 	ole32.dll!77520143() 	
 	ole32.dll!7751f4ed() 	
 	ole32.dll!7751ff88() 	
 	ntdll.dll!7c96d886() 	
 	ntdll.dll!7c96d886() 	
 	ntdll.dll!7c949d18() 	
 	ntdll.dll!7c91b686() 	
 	ntdll.dll!7c91056d() 	
 	advapi32.dll!77dde0ae() 	
 	advapi32.dll!77dde32e() 	
 	advapi32.dll!77dde343() 	
 	advapi32.dll!77dde350() 	

Code:

//Main.cpp

#include "DirectShow Network Sender.h"
;

CNetworkSenderFilter::CNetworkSenderFilter(TCHAR *tszName, LPUNKNOWN pUnk, 
HRESULT *phr)
	:CBaseRenderer( CLSID_NETWORKSENDERFILTER, tszName, pUnk, phr )
{
}

//Main.h

#pragma once

#include "stdafx.h"

//#define CLSID_NETWORKSENDERFILTER GUID_NULL

// GUID {6DBA0953-4108-4263-93D3-0C9241BD563E}
DEFINE_GUID( CLSID_NETWORKSENDERFILTER, 0x6dba0953, 0x4108, 0x4263, 0x93, 
0xd3, 0xc, 0x92, 0x41, 0xbd, 0x56, 0x3e );

class CNetworkSenderFilter: public CBaseRenderer {
public:
	DECLARE_IUNKNOWN;

	char *pName;
	IUnknown *r_pUnknown;
	HRESULT NoHRESULT;
	__stdcall CNetworkSenderFilter(IN TCHAR *tszName, IN LPUNKNOWN pUnk, OUT 
HRESULT *phr);
	__stdcall ~CNetworkSenderFilter( ) /*~CBaseRenderer()*/ {}
	HRESULT CheckMediaType( const CMediaType *pmt );
	HRESULT DoRenderSample( IMediaSample *pMediaSample );
	SOCKET *sock;
	static CUnknown *CreateInstance(IN LPUNKNOWN pUnk, OUT HRESULT *pHr);
	//CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr);
}

//COM DLL Stuff.cpp

#include "stdafx.h"
#include "DirectShow Network Sender.h"
;
static WCHAR g_wszName[] = L"Epstone Network Sender Filter";

// Setup information
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
    &MEDIATYPE_Video,       // Major type
    &MEDIASUBTYPE_NULL      // Minor type
};

const AMOVIESETUP_PIN sudpPins[] =
{
    { L"Input",             // Pins string name
	  FALSE,					// Is it rendered
      FALSE,                // Is it an output
      FALSE,                // Are we allowed none
      FALSE,                // And allowed many
      &CLSID_NULL,          // Connects to filter
      NULL,                 // Connects to pin
      1,                    // Number of types
      &sudPinTypes          // Pin information
    }
};

const AMOVIESETUP_FILTER sudSender =
{
    &CLSID_NETWORKSENDERFILTER,	// Filter CLSID
    g_wszName,					// String name
    MERIT_DO_NOT_USE,			// Filter merit
    1,							// Number of pins
    sudpPins					// Pin information
};

// List of class IDs and creator functions for the class factory. This
// provides the link between the OLE entry point in the DLL and an object
// being created. The class factory will call the static CreateInstance

CFactoryTemplate g_Templates[] = {
    { g_wszName
    , &CLSID_NETWORKSENDERFILTER
	, (LPFNNewCOMObject) CNetworkSenderFilter::CreateInstance
    , NULL
    , &sudSender }
};

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



CUnknown *CNetworkSenderFilter::CreateInstance(IN LPUNKNOWN pUnk, OUT 
HRESULT *pHr)
{

	char *message = new char[255];
	char *hrstr = new char[20];
	char *ptrstr = new char[20];
	int pfsize;
	char *szpfstr = new char[20];
	char *pHrstr = new char[20];
	char *pUnkstr = new char[20];

	*pHr = S_OK;

    CNetworkSenderFilter * pTheFilter;

	TCHAR *tszName = new TCHAR[255];

	strcpy( (char*) tszName, "CNetworkSenderFilter" );

	pTheFilter = new CNetworkSenderFilter( tszName, pUnk, pHr );
    if (pTheFilter== NULL) 
    {
        *pHr = E_OUTOFMEMORY;
    }

	strcpy( message, "Creating CNetworkSenderFilter, hr=" );
	itoa( *pHr, hrstr, 16 );
	strcat( message, hrstr );
	ltoa( (long) pTheFilter, ptrstr, 16 );
	strcat( message, ", pFilter=" );
	strcat( message, ptrstr );
	pfsize = sizeof( *pTheFilter );
	itoa( pfsize, szpfstr, 16 );
	strcat( message, ", sizeof(*pTheFilter)=" );
	strcat( message, szpfstr );
	ltoa( (long) pHr, pHrstr, 16 );
	strcat( message, ", *pHr=" );
	strcat( message, pHrstr );
	ltoa( (long) pUnk, pUnkstr, 16 );
	strcat( message, ", *pUnk=" );
	strcat( message, pUnkstr );

	MessageBox( NULL, message, "", MB_OK | MB_ICONINFORMATION );

	delete message;
	delete hrstr;
	delete ptrstr;
	delete szpfstr;
	delete pHrstr;
	delete pUnkstr;

    return pTheFilter;
}

STDAPI DllRegisterServer()
{

    return AMovieDllRegisterServer2(TRUE);

}
STDAPI DllUnregisterServer()
{

    return AMovieDllRegisterServer2(FALSE);

}

// If we declare the correct C runtime entrypoint and then forward it to the 
DShow base
// classes we will be sure that both the C/C++ runtimes and the base classes 
are initialized
// correctly
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);
}
date: Thu, 20 Oct 2005 17:49:07 -0700   author:   Andrew Garrett

Re: Creating a custom DirectShow renderer filter.   
On Thu, 20 Oct 2005 17:36:06 -0700, "Andrew Garrett"
 wrote:

>> >	TCHAR *tszName;
>> >
>> >	strcpy( (char*) tszName, "CNetworkSenderFilter" );

>> Here you have two problems. First, you're copying to an uninitialized
>> string pointer. Second, if you're compiling for Unicode, the string will
>> be invalid. If you're never compiling for Unicode, you shouldn't be
>> using TCHAR.

>I'm never compiling for unicode, but the CBaseRenderer argument expects a 
>TCHAR pointer, which I am providing it.

That's not the way it works. TCHAR is a typedef for either char or
wchar_t, depending on whether you are compiling for Unicode or not.
Those are two completely different types, and you can't use strcpy() to
copy a char string to a wchar_t string. What's more, since you're not
compiling for Unicode anyway, you can just pass the string directly.

You are also not deleting your strings correctly. You have to delete
them with delete [], not plain delete. It's better not to allocate and
deallocate these strings at all.

Try rewriting your function like this:

CUnknown *CNetworkSenderFilter::CreateInstance(IN LPUNKNOWN pUnk, OUT 
HRESULT *pHr)
{
   *pHr = S_OK;

   CNetworkSenderFilter *filter = new 
      CNetworkSenderFilter("CNetworkSenderFilter", pUnk, pHr);

   if (!filter) 
      *pHr = E_OUTOFMEMORY;

   return filter;
}

If you want to construct a temporary string for debug purposes, I
recommend either the CString class, std::string, std::stringstream, or
sprintf()/wsprintf() to a local char array.

-- 
Be seeing you.
date: Thu, 20 Oct 2005 19:59:55 -0500   author:   Thore Karlsen [MVP DX]

Re: Creating a custom DirectShow renderer filter.   
"Thore Karlsen [MVP DX]" wrote:

> On Thu, 20 Oct 2005 17:36:06 -0700, "Andrew Garrett"
>  wrote:
> 
> >> >	TCHAR *tszName;
> >> >
> >> >	strcpy( (char*) tszName, "CNetworkSenderFilter" );
> 
> >> Here you have two problems. First, you're copying to an uninitialized
> >> string pointer. Second, if you're compiling for Unicode, the string will
> >> be invalid. If you're never compiling for Unicode, you shouldn't be
> >> using TCHAR.
> 
> >I'm never compiling for unicode, but the CBaseRenderer argument expects a 
> >TCHAR pointer, which I am providing it.
> 
> That's not the way it works. TCHAR is a typedef for either char or
> wchar_t, depending on whether you are compiling for Unicode or not.
> Those are two completely different types, and you can't use strcpy() to
> copy a char string to a wchar_t string. What's more, since you're not
> compiling for Unicode anyway, you can just pass the string directly.
> 
> You are also not deleting your strings correctly. You have to delete
> them with delete [], not plain delete. It's better not to allocate and
> deallocate these strings at all.
> 
> Try rewriting your function like this:
> 
> CUnknown *CNetworkSenderFilter::CreateInstance(IN LPUNKNOWN pUnk, OUT 
> HRESULT *pHr)
> {
>    *pHr = S_OK;
> 
>    CNetworkSenderFilter *filter = new 
>       CNetworkSenderFilter("CNetworkSenderFilter", pUnk, pHr);
> 
>    if (!filter) 
>       *pHr = E_OUTOFMEMORY;
> 
>    return filter;
> }
Copy-and-pasted this routine into my code, still no luck. The error again: 
"Unhandled exception at 0x00000000 in Webcam Capture Test.exe: 0xC0000005: 
Access violation reading location 0x00000000."

Stack Trace:

>	DSNetworkSender.ax!CClassFactory::CreateInstance()  + 0xa9	C++
 	ole32.dll!775202e3() 	
 	ole32.dll!77520143() 	
 	ole32.dll!775203f2() 	
 	ole32.dll!77520369() 	
 	ole32.dll!7752112b() 	
 	ole32.dll!775210e2() 	
 	ole32.dll!77520453() 	
 	ole32.dll!77520143() 	
 	ole32.dll!775200de() 	
 	ntdll.dll!7c90fb6c() 	
 	ntdll.dll!7c90fb71() 	
 	kernel32.dll!7c809392() 	
 	ole32.dll!7750055e() 	
 	ole32.dll!7750067b() 	
 	ole32.dll!7750078e() 	
 	ole32.dll!775009b5() 	
 	ole32.dll!775017f3() 	
 	ole32.dll!775008df() 	
 	ole32.dll!775008fa() 	
 	ole32.dll!7751e53b() 	
 	ole32.dll!7751f4a2() 	
 	ole32.dll!77520143() 	
 	ole32.dll!7751f4ed() 	
 	ole32.dll!7751ff88() 	
 	ntdll.dll!7c96d886() 	
 	ntdll.dll!7c96d886() 	
 	ntdll.dll!7c949d18() 	
 	ntdll.dll!7c91b686() 	
 	ntdll.dll!7c91056d() 	
 	advapi32.dll!77dde0ae() 	
 	advapi32.dll!77dde32e() 	
 	advapi32.dll!77dde343() 	
 	advapi32.dll!77dde350() 	

> 
> If you want to construct a temporary string for debug purposes, I
> recommend either the CString class, std::string, std::stringstream, or
> sprintf()/wsprintf() to a local char array.
> 
> -- 
> Be seeing you.
>
date: Thu, 20 Oct 2005 18:39:02 -0700   author:   Andrew Garrett

Re: Creating a custom DirectShow renderer filter.   
On Thu, 20 Oct 2005 18:39:02 -0700, "Andrew Garrett"
 wrote:

[...]

>Copy-and-pasted this routine into my code, still no luck. The error again: 
>"Unhandled exception at 0x00000000 in Webcam Capture Test.exe: 0xC0000005: 
>Access violation reading location 0x00000000."

OK, try changing the signature of CNetworkSenderFilter::CreateInstance()
to this:

   static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT 
      *pHr);

And remove the cast to LPFNNewCOMObject in g_Templates:

CFactoryTemplate g_Templates[] =
{
    {
      g_wszName,
      &CLSID_NETWORKSENDERFILTER,
      CNetworkSenderFilter::CreateInstance,
      NULL,
      &sudSender
    }
};

You shouldn't do any casts without a very good reason, and it looks like
you cast here to silence the compiler when it warned you about using the
wrong calling convention.

-- 
Be seeing you.
date: Thu, 20 Oct 2005 21:33:30 -0500   author:   Thore Karlsen [MVP DX]

Re: Creating a custom DirectShow renderer filter.   
"Thore Karlsen [MVP DX]" wrote:

> On Thu, 20 Oct 2005 18:39:02 -0700, "Andrew Garrett"
>  wrote:
> 
> [...]
> 
> >Copy-and-pasted this routine into my code, still no luck. The error again: 
> >"Unhandled exception at 0x00000000 in Webcam Capture Test.exe: 0xC0000005: 
> >Access violation reading location 0x00000000."
> 
> OK, try changing the signature of CNetworkSenderFilter::CreateInstance()
> to this:
> 
>    static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT 
>       *pHr);
> 
> And remove the cast to LPFNNewCOMObject in g_Templates:
> 
> CFactoryTemplate g_Templates[] =
> {
>     {
>       g_wszName,
>       &CLSID_NETWORKSENDERFILTER,
>       CNetworkSenderFilter::CreateInstance,
>       NULL,
>       &sudSender
>     }
> };
> 
> You shouldn't do any casts without a very good reason, and it looks like
> you cast here to silence the compiler when it warned you about using the
> wrong calling convention.
That did the trick - i seemed to have forgotten the WINAPI bit. It tests 
okay in GraphEdit now. Thanks a lot
> 
> -- 
> Be seeing you.
>
date: Thu, 20 Oct 2005 20:53:03 -0700   author:   Andrew Garrett

Continued...   
Hi,

It's been a while since i touched on this issue, but I'm now trying to 
integrate the completed filter into my application. Unfortunately, I can't 
figure out how to send the filter a socket handle over which to send data. I 
believe I need to write a new COM Interface, however I would prefer not to 
have to resort to such measures. Is there a simpler way of going about this? 
If not, could somebody please walk me through the process of creating such an 
interface, as I find the MSDN documentation does not give me a step by step 
overview of how to do so.

Thanks,

Andrew Garrett
Epstone Networks
date: Tue, 21 Feb 2006 22:56:28 -0800   author:   Andrew Garrett

Re: Continued...   
On Tue, 21 Feb 2006 22:56:28 -0800, Andrew Garrett wrote:

> It's been a while since i touched on this issue,...

What issue?

-- 
Please read this before replying:
1. Dshow & posting help:  http://tmhare.mvps.org/help.htm
2. Trim & respond inline (please don't top post or snip everything)
3. Benefit others:  follow up if you are helped or you found a solution
date: Wed, 22 Feb 2006 07:56:27 -0700   author:   The March Hare [MVP]

Re: Continued...   
"The March Hare [MVP]" wrote:

> On Tue, 21 Feb 2006 22:56:28 -0800, Andrew Garrett wrote:
> 
> > It's been a while since i touched on this issue,...
> 
> What issue?
Creating the DirectShow filter. How do you suggest passing this socket 
Handle as a  parameter?
> 

Thanks,

 Andrew Garrett
 Epstone Networks
date: Wed, 22 Feb 2006 13:37:29 -0800   author:   Andrew Garrett

Re: Continued...   
On Wed, 22 Feb 2006 13:37:29 -0800, Andrew Garrett wrote:

> Creating the DirectShow filter. How do you suggest passing this socket 
> Handle as a  parameter?

You create a custom interface on your filter.  The filter wizard on my site
creates a sample custom interface (works with VS2003).

-- 
Please read this before replying:
1. Dshow & posting help:  http://tmhare.mvps.org/help.htm
2. Trim & respond inline (please don't top post or snip everything)
3. Benefit others:  follow up if you are helped or you found a solution
date: Thu, 23 Feb 2006 06:42:48 -0700   author:   The March Hare [MVP]

Re: Continued...   
"The March Hare [MVP]" wrote:

> On Wed, 22 Feb 2006 13:37:29 -0800, Andrew Garrett wrote:
> 
> > Creating the DirectShow filter. How do you suggest passing this socket 
> > Handle as a  parameter?
> 
> You create a custom interface on your filter.  The filter wizard on my site
> creates a sample custom interface (works with VS2003).
> 
That's how I thought it was done. However, I'm using Visual Studio 2005. 
From the looks of MSDN, I need to create an Interface Definition (IDL) file, 
and then compile it using a MIDL compiler and somehow import it into my 
Visual Studio 2005 project. Is this correct?
-- 

Andrew Garrett
Epstone Networks
date: Thu, 23 Feb 2006 13:35:28 -0800   author:   Andrew Garrett

Re: Continued...   
On Thu, 23 Feb 2006 13:35:28 -0800, Andrew Garrett wrote:

> That's how I thought it was done. However, I'm using Visual Studio 2005. 
> From the looks of MSDN, I need to create an Interface Definition (IDL) file, 
> and then compile it using a MIDL compiler and somehow import it into my 
> Visual Studio 2005 project. Is this correct?

You can do it this way but I don't use MIDL so I can't give any expert
advice.  See Geraint's GMFBridge same which, IIRC, does it this way.  Or,
if you have VS2003 lying around, just create a project there and see what
it does.  Or, for an SDK sample that has a custom interface to model from
look at ezrgb.

-- 
Please read this before replying:
1. Dshow & posting help:  http://tmhare.mvps.org/help.htm
2. Trim & respond inline (please don't top post or snip everything)
3. Benefit others:  follow up if you are helped or you found a solution
date: Thu, 23 Feb 2006 15:42:07 -0700   author:   The March Hare [MVP]

Re: Continued...   
"The March Hare [MVP]" wrote:

> On Thu, 23 Feb 2006 13:35:28 -0800, Andrew Garrett wrote:
> 
> > That's how I thought it was done. However, I'm using Visual Studio 2005. 
> > From the looks of MSDN, I need to create an Interface Definition (IDL) file, 
> > and then compile it using a MIDL compiler and somehow import it into my 
> > Visual Studio 2005 project. Is this correct?
> 
> You can do it this way but I don't use MIDL so I can't give any expert
> advice.  See Geraint's GMFBridge same which, IIRC, does it this way.  Or,
> if you have VS2003 lying around, just create a project there and see what
> it does.  Or, for an SDK sample that has a custom interface to model from
> look at ezrgb.

I've created the interface using MIDL, compiled it and imported the 
necessary C files into my original DLL. I've also overridden 
NonDelegatingQueryInterface like so:

STDMETHODIMP CNetworkSenderFilter::NonDelegatingQueryInterface(REFIID riid, 
void **ppv)
{
	
	bool IsIDSNetSender = Compare_IID( riid, IID_IDSNetSender );

	if (IsIDSNetSender == true) {
		printf("Querying for IDSNetSender interface\r\n");
	} else {
		printf("Querying for another interface\r\n");
	}

    if (IsIDSNetSender == true)
    {
        return GetInterface((IDSNetSender*)this, ppv);
    }
    // Default: Call parent class method. 
    // The CUnknown class must be in the inheritance chain.
    return CBaseRenderer::NonDelegatingQueryInterface(riid, ppv);
}

bool Compare_IID(const IID firstguid, const IID secondguid) {
	if ((firstguid.Data1) != (secondguid.Data1)) {return false;}
	if ((firstguid.Data2) != (secondguid.Data2)) {return false;}
	if ((firstguid.Data3) != (secondguid.Data3)) {return false;}
	return true;
}

But when I instantiate the filter and try to get its interface, like so:

	IBaseFilter *pSender = NULL;
	IDSNetSender *pNSender = NULL;

	CoCreateInstance( CLSID_NETWORKSENDERFILTER, NULL, CLSCTX_INPROC_SERVER, 
IID_IBaseFilter, (void**) &pSender );

	//Get the IDSNetSender Interface

	hr = pSender->QueryInterface( IID_IDSNetSender, (void**) &pNSender );
	
	printf("hr from getting IDSNetSender pointer: %li\r\n", hr);

	hr = pNSender->SetSocket(NULL);

	hr = pGraph->AddFilter( pSender, L"Network Sender Filter" );

pNSender is actually a NULL pointer, however I can still call ->SetSocket 
and I get the correct address for the this pointer in my routine. It seems to 
correctly set this->sock perfectly in that routine, however when it runs 
DoRenderSample, this->sock acts as if it's never changed, and the this 
pointer references a completely different location in memory. Well, I'm 
flummoxed. Here are my DoRenderSample and SetSocket routines:

HRESULT CNetworkSenderFilter::DoRenderSample( IMediaSample *pMediaSample ) {
	BYTE* data = NULL;
	long length = 0;

	pMediaSample->GetPointer( &data );
	length = pMediaSample->GetSize();

	send( sock, (char*) data, length, 0 );

	return S_OK;
}

HRESULT CNetworkSenderFilter::SetSocket( SOCKET thesock ) {
	this->sock = thesock;

	return S_OK;
}

Thanks
--
Andrew Garrett
Epstone Networks

--
Andrew Garrett
Epstone Networks
date: Sun, 26 Feb 2006 03:50:26 -0800   author:   Andrew Garrett

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us