DirectShow Filter (COM Issues)
- From: Andrew Garrett <AndrewGarrett@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Wed, 15 Mar 2006 00:01:27 -0800
Hi,
I am trying to write a DirectShow filter to allow a programmer to send data
being sent in a stream over the network. I have run into problems creating an
interface to allow the programmer to set a socket to send the data over.
Unfortunately, when I try to query for this interface, I get a NULL pointer,
but functions involving the interface still seem to work. Additionally, when
they do work, setting the socket does not work, and the socket always seems
to be a certain random number. Excerpts of code follow.
DS Network Sender.CPP:
#include "stdafx.h"
#include "DirectShow Network Sender.h"
;
bool Compare_IID(const IID firstguid, const IID secondguid); //Forward
define Compare_GUID utility function
CNetworkSenderFilter::CNetworkSenderFilter(TCHAR *tszName, LPUNKNOWN pUnk,
HRESULT *phr)
:CBaseRenderer( CLSID_NETWORKSENDERFILTER, tszName, pUnk, phr ),
IDSNetSender()
{
m_sock = NULL;
//MessageBoxA(NULL, "Creating new instance of CNetworkSenderFilter",
"HELLO", MB_ICONINFORMATION);
}
HRESULT CNetworkSenderFilter::CheckMediaType( const CMediaType *pmt ) {
return S_OK;
}
HRESULT CNetworkSenderFilter::DoRenderSample( IMediaSample *pMediaSample ) {
BYTE* data = NULL;
long length = 0;
CheckPointer(pMediaSample, E_POINTER);
pMediaSample->GetPointer( &data );
length = pMediaSample->GetSize();
send( m_sock, (char*) data, length, 0 );
return S_OK;
}
HRESULT CNetworkSenderFilter::SetSocket( SOCKET thesock ) {
CAutoLock cal(&m_Lock);
m_sock = thesock;
return S_OK;
}
STDMETHODIMP CNetworkSenderFilter::NonDelegatingQueryInterface(REFIID riid,
void **ppv)
{
CheckPointer(ppv,E_POINTER);
if (riid == IID_IDSNetSender) {
return GetInterface((IDSNetSender *) this, ppv);
} else {
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;
}
DS NETWORK SENDER.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 );
DEFINE_GUID( IID_IDSNetSender, 0x333cb892, 0x7dd3, 0x4fb5, 0xac, 0x9d, 0x73,
0x30, 0xbc, 0xa4, 0x3b, 0x37);
class CNetworkSenderFilter: public CBaseRenderer, public IDSNetSender {
public:
DECLARE_IUNKNOWN;
char *pName;
IUnknown *r_pUnknown;
HRESULT NoHRESULT;
~CNetworkSenderFilter( ) /*~CBaseRenderer()*/ {}
HRESULT CheckMediaType( const CMediaType *pmt );
HRESULT DoRenderSample( IMediaSample *pMediaSample );
STDMETHODIMP SetSocket( SOCKET sock );
STDMETHODIMP NonDelegatingQueryInterface(const IID &riid, void**ppv);
static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr);
//CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr);
private:
SOCKET m_sock;
CNetworkSenderFilter(IN TCHAR *tszName, IN LPUNKNOWN pUnk, OUT HRESULT *phr);
CCritSec m_Lock;
}
COM 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_NULL, // 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 //Filter Name
, &CLSID_NETWORKSENDERFILTER //Filter CLSID
, CNetworkSenderFilter::CreateInstance //Filter creation sub
, NULL //Initialisation function
, &sudSender //Pin information
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
CUnknown * WINAPI CNetworkSenderFilter::CreateInstance(LPUNKNOWN pUnk,
HRESULT *pHr)
{
*pHr = S_OK;
CNetworkSenderFilter *filter = new
CNetworkSenderFilter(NAME("CNetworkSenderFilter"), pUnk, pHr);
if (!filter)
*pHr = E_OUTOFMEMORY;
return filter;
}
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);
}
TEST.CPP:
// Webcam Capture Test.cpp : Defines the entry point for the console
application.
//
#include "stdafx.h"
#include "DSNetSender_h.h"
DEFINE_GUID( IID_IDSNetSender, 0x333cb892, 0x7dd3, 0x4fb5, 0xac, 0x9d, 0x73,
0x30, 0xbc, 0xa4, 0x3b, 0x37);
int _tmain(int argc, _TCHAR* argv[])
{
//Local variables
IGraphBuilder *pGraph;
ICaptureGraphBuilder2 *pBuilder;
HRESULT hr;
IBaseFilter *pCap = NULL;
ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pCapEnum = NULL;
IMoniker *pEncodeMoniker = NULL;
IMoniker *pCaptureMoniker = NULL;
IMediaControl *pMediaControl = NULL;
IEnumMoniker *pCompressEnum = NULL;
IBaseFilter *pEncoder = NULL;
IPropertyBag *pPropBag = NULL;
VARIANT varName;
BSTR sName;
_bstr_t codecname("MJPEG Compressor");
char* lastcodec;
REFERENCE_TIME rtStart = 0, rtStop = 600000000; //Run for 60 seconds
CoInitialize( NULL );
hr = S_OK;
//Set up the graph
hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,
(void **) &pGraph );
hr = CoCreateInstance( CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2, (void **) &pBuilder );
pBuilder->SetFiltergraph( pGraph );
//Set up Network Sender
UUID CLSID_NETWORKSENDERFILTER;
UuidFromString( (unsigned char*)"6DBA0953-4108-4263-93D3-0C9241BD563E",
&CLSID_NETWORKSENDERFILTER );
//Initialise the capture device
hr = CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **) &pDevEnum );
hr = pDevEnum->CreateClassEnumerator( CLSID_VideoCompressorCategory,
&pCompressEnum, 0 );
int i = 0;
hr = pCompressEnum->Next( 1, &pEncodeMoniker, NULL );
hr = pEncodeMoniker->BindToStorage( 0, 0, IID_IPropertyBag, (void **)
&pPropBag);
VariantInit( &varName );
hr = pPropBag->Read( L"FriendlyName", &varName, 0 );
sName = varName.bstrVal;
lastcodec = new char[255];
strcpy(lastcodec, "blank");
do {
hr = pCompressEnum->Next( 1, &pEncodeMoniker, NULL );
hr = pEncodeMoniker->BindToStorage( 0, 0, IID_IPropertyBag, (void **)
&pPropBag);
VariantInit( &varName );
hr = pPropBag->Read( L"FriendlyName", &varName, 0 );
sName = varName.bstrVal;
bstr_t sName_t(sName);
strcpy(lastcodec, (char*) sName_t);
Sleep(500);
} while ( strncmp(lastcodec, "MJPEG Compressor", 5) != 0 );
printf("Got correct filter: %s\r\n", lastcodec);
//Comment this part out for testing without a webcam
hr = pDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory,
&pCapEnum, 0 );
hr = pCapEnum->Next( 1, &pCaptureMoniker, NULL );
hr = pCaptureMoniker->BindToObject( 0, 0, IID_IBaseFilter, (void**) &pCap);
hr = pGraph->AddFilter( pCap, L"Capture Filter" );
pCaptureMoniker->Release();
pCapEnum->Release();
//Got our capture device
//Get a Compressor Filter
hr = pEncodeMoniker->BindToObject( 0, 0, IID_IBaseFilter, (void**)
&pEncoder );
hr = pGraph->AddFilter( pEncoder, L"Compressor" );
pEncodeMoniker->Release();
pDevEnum->Release();
pCompressEnum->Release();
//Create our controller
hr = pGraph->QueryInterface( IID_IMediaControl, (void**) &pMediaControl );
//Set up the rendering
//Set up Network Sender
// UUID CLSID_NETWORKSENDERFILTER;
// UuidFromString( (unsigned char*)"6DBA0953-4108-4263-93D3-0C9241BD563E",
&CLSID_NETWORKSENDERFILTER );
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 pNSender interface: %li\r\n", hr);
WSADATA wsa;
WSAStartup(MAKEWORD(2,2), &wsa);
WSASetLastError(0);
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
hr = pNSender->SetSocket(sock);
hr = pGraph->AddFilter( pSender, L"Sender" ) ;
//hr = pBuilder->RenderStream( &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
pCap, NULL, NULL );
hr = pBuilder->RenderStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap,
NULL, pSender );
//And hit the go button
hr = pMediaControl->Run( );
Sleep( 10000 );
pMediaControl->Stop( );
pMediaControl->Release();
pGraph->Release();
pBuilder->Release();
return 0;
}
Any help would be appreciated.
Andrew Garrett,
Epstone Networks
--
Andrew Garrett
Epstone Networks
.
- Prev by Date: Re: Registering type library
- Next by Date: Getting IDispatch from IUnknown
- Previous by thread: Re: Registering type library
- Next by thread: Getting IDispatch from IUnknown
- Index(es):
Relevant Pages
|