2001-03-20 00:05:27 +00:00
|
|
|
#include "DS_Filter.h"
|
2001-11-21 19:12:39 +00:00
|
|
|
#include "driver.h"
|
|
|
|
#include "com.h"
|
2001-08-16 00:50:02 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2002-09-13 19:43:17 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include "win32.h" // printf macro
|
2001-08-16 00:50:02 +00:00
|
|
|
|
|
|
|
typedef long STDCALL (*GETCLASS) (const GUID*, const GUID*, void**);
|
|
|
|
|
2002-11-26 21:00:20 +00:00
|
|
|
//void trapbug();
|
2001-03-29 12:38:51 +00:00
|
|
|
|
2001-11-21 19:12:39 +00:00
|
|
|
static void DS_Filter_Start(DS_Filter* This)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
2001-11-21 19:12:39 +00:00
|
|
|
HRESULT hr;
|
|
|
|
|
2001-12-11 23:29:24 +00:00
|
|
|
if (This->m_pAll)
|
2001-11-21 19:12:39 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
//Debug printf("DS_Filter_Start(%p)\n", This);
|
2002-11-26 21:00:20 +00:00
|
|
|
hr = This->m_pFilter->vt->Run(This->m_pFilter, (REFERENCE_TIME)0);
|
2001-11-21 19:12:39 +00:00
|
|
|
if (hr != 0)
|
|
|
|
{
|
|
|
|
Debug printf("WARNING: m_Filter->Run() failed, error code %x\n", (int)hr);
|
|
|
|
}
|
|
|
|
hr = This->m_pImp->vt->GetAllocator(This->m_pImp, &This->m_pAll);
|
|
|
|
|
|
|
|
if (hr || !This->m_pAll)
|
|
|
|
{
|
|
|
|
Debug printf("WARNING: error getting IMemAllocator interface %x\n", (int)hr);
|
|
|
|
This->m_pImp->vt->Release((IUnknown*)This->m_pImp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
This->m_pImp->vt->NotifyAllocator(This->m_pImp, This->m_pAll, 0);
|
2001-03-20 00:05:27 +00:00
|
|
|
}
|
|
|
|
|
2001-11-21 19:12:39 +00:00
|
|
|
static void DS_Filter_Stop(DS_Filter* This)
|
2001-05-06 21:43:45 +00:00
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
if (This->m_pAll)
|
2001-11-21 19:12:39 +00:00
|
|
|
{
|
|
|
|
//Debug printf("DS_Filter_Stop(%p)\n", This);
|
2001-12-11 23:29:24 +00:00
|
|
|
This->m_pFilter->vt->Stop(This->m_pFilter); // causes weird crash ??? FIXME
|
2001-11-21 19:12:39 +00:00
|
|
|
This->m_pAll->vt->Release((IUnknown*)This->m_pAll);
|
|
|
|
This->m_pAll = 0;
|
|
|
|
}
|
2001-08-16 00:50:02 +00:00
|
|
|
}
|
|
|
|
|
2001-11-21 19:12:39 +00:00
|
|
|
void DS_Filter_Destroy(DS_Filter* This)
|
2001-08-16 00:50:02 +00:00
|
|
|
{
|
2001-11-21 19:12:39 +00:00
|
|
|
This->Stop(This);
|
|
|
|
|
|
|
|
if (This->m_pOurInput)
|
|
|
|
This->m_pOurInput->vt->Release((IUnknown*)This->m_pOurInput);
|
|
|
|
if (This->m_pInputPin)
|
|
|
|
This->m_pInputPin->vt->Disconnect(This->m_pInputPin);
|
|
|
|
if (This->m_pOutputPin)
|
|
|
|
This->m_pOutputPin->vt->Disconnect(This->m_pOutputPin);
|
|
|
|
if (This->m_pFilter)
|
|
|
|
This->m_pFilter->vt->Release((IUnknown*)This->m_pFilter);
|
|
|
|
if (This->m_pOutputPin)
|
|
|
|
This->m_pOutputPin->vt->Release((IUnknown*)This->m_pOutputPin);
|
|
|
|
if (This->m_pInputPin)
|
|
|
|
This->m_pInputPin->vt->Release((IUnknown*)This->m_pInputPin);
|
|
|
|
if (This->m_pImp)
|
|
|
|
This->m_pImp->vt->Release((IUnknown*)This->m_pImp);
|
|
|
|
|
|
|
|
if (This->m_pOurOutput)
|
|
|
|
This->m_pOurOutput->vt->Release((IUnknown*)This->m_pOurOutput);
|
|
|
|
if (This->m_pParentFilter)
|
2001-11-26 00:56:11 +00:00
|
|
|
This->m_pParentFilter->vt->Release((IUnknown*)This->m_pParentFilter);
|
2001-11-21 19:12:39 +00:00
|
|
|
if (This->m_pSrcFilter)
|
|
|
|
This->m_pSrcFilter->vt->Release((IUnknown*)This->m_pSrcFilter);
|
2001-05-06 21:43:45 +00:00
|
|
|
|
|
|
|
// FIXME - we are still leaving few things allocated!
|
2001-11-21 19:12:39 +00:00
|
|
|
if (This->m_iHandle)
|
2002-11-26 21:00:20 +00:00
|
|
|
FreeLibrary((unsigned)This->m_iHandle);
|
2001-11-21 19:12:39 +00:00
|
|
|
|
|
|
|
free(This);
|
|
|
|
|
|
|
|
CodecRelease();
|
2001-05-06 21:43:45 +00:00
|
|
|
}
|
|
|
|
|
2001-11-21 19:12:39 +00:00
|
|
|
DS_Filter* DS_FilterCreate(const char* dllname, const GUID* id,
|
|
|
|
AM_MEDIA_TYPE* in_fmt,
|
|
|
|
AM_MEDIA_TYPE* out_fmt)
|
2001-05-06 21:43:45 +00:00
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
int init = 0;
|
2002-09-22 02:33:28 +00:00
|
|
|
// char eb[250];
|
2001-12-11 23:29:24 +00:00
|
|
|
const char* em = NULL;
|
2002-11-26 21:00:20 +00:00
|
|
|
HRESULT result;
|
2001-11-21 19:12:39 +00:00
|
|
|
DS_Filter* This = (DS_Filter*) malloc(sizeof(DS_Filter));
|
|
|
|
if (!This)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
CodecAlloc();
|
|
|
|
|
|
|
|
This->m_pFilter = NULL;
|
|
|
|
This->m_pInputPin = NULL;
|
|
|
|
This->m_pOutputPin = NULL;
|
|
|
|
This->m_pSrcFilter = NULL;
|
|
|
|
This->m_pParentFilter = NULL;
|
|
|
|
This->m_pOurInput = NULL;
|
|
|
|
This->m_pOurOutput = NULL;
|
|
|
|
This->m_pAll = NULL;
|
|
|
|
This->m_pImp = NULL;
|
|
|
|
|
|
|
|
This->Start = DS_Filter_Start;
|
|
|
|
This->Stop = DS_Filter_Stop;
|
|
|
|
|
|
|
|
for (;;)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
2001-11-21 19:12:39 +00:00
|
|
|
GETCLASS func;
|
|
|
|
struct IClassFactory* factory = NULL;
|
|
|
|
struct IUnknown* object = NULL;
|
|
|
|
IEnumPins* enum_pins = 0;
|
|
|
|
IPin* array[256];
|
|
|
|
ULONG fetched;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
This->m_iHandle = LoadLibraryA(dllname);
|
|
|
|
if (!This->m_iHandle)
|
2001-05-06 21:43:45 +00:00
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "could not open DirectShow DLL";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
2001-05-06 21:43:45 +00:00
|
|
|
}
|
2002-11-26 21:00:20 +00:00
|
|
|
func = (GETCLASS)GetProcAddress((unsigned)This->m_iHandle, "DllGetClassObject");
|
2001-05-06 21:43:45 +00:00
|
|
|
if (!func)
|
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "illegal or corrupt DirectShow DLL";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
2001-05-06 21:43:45 +00:00
|
|
|
}
|
2001-08-16 00:50:02 +00:00
|
|
|
result = func(id, &IID_IClassFactory, (void**)&factory);
|
|
|
|
if (result || !factory)
|
2001-11-21 19:12:39 +00:00
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "no such class object";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-08-16 00:50:02 +00:00
|
|
|
result = factory->vt->CreateInstance(factory, 0, &IID_IUnknown, (void**)&object);
|
2001-03-20 00:05:27 +00:00
|
|
|
factory->vt->Release((IUnknown*)factory);
|
2001-08-16 00:50:02 +00:00
|
|
|
if (result || !object)
|
2001-11-21 19:12:39 +00:00
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "class factory failure";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
result = object->vt->QueryInterface(object, &IID_IBaseFilter, (void**)&This->m_pFilter);
|
2001-03-20 00:05:27 +00:00
|
|
|
object->vt->Release((IUnknown*)object);
|
2001-11-21 19:12:39 +00:00
|
|
|
if (result || !This->m_pFilter)
|
|
|
|
{
|
2002-09-13 19:43:17 +00:00
|
|
|
em = "object does not provide IBaseFilter interface";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-08-16 00:50:02 +00:00
|
|
|
// enumerate pins
|
2001-11-21 19:12:39 +00:00
|
|
|
result = This->m_pFilter->vt->EnumPins(This->m_pFilter, &enum_pins);
|
2001-08-16 00:50:02 +00:00
|
|
|
if (result || !enum_pins)
|
2001-11-21 19:12:39 +00:00
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "could not enumerate pins";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-03-20 00:05:27 +00:00
|
|
|
enum_pins->vt->Reset(enum_pins);
|
2001-08-16 00:50:02 +00:00
|
|
|
result = enum_pins->vt->Next(enum_pins, (ULONG)256, (IPin**)array, &fetched);
|
2002-11-26 21:00:20 +00:00
|
|
|
Debug printf("Pins enumeration returned %ld pins, error is %x\n", fetched, (int)result);
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-11-21 19:12:39 +00:00
|
|
|
for (i = 0; i < fetched; i++)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
2001-05-06 21:43:45 +00:00
|
|
|
int direction = -1;
|
2001-03-20 00:05:27 +00:00
|
|
|
array[i]->vt->QueryDirection(array[i], (PIN_DIRECTION*)&direction);
|
2001-11-21 19:12:39 +00:00
|
|
|
if (!This->m_pInputPin && direction == 0)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
2001-11-21 19:12:39 +00:00
|
|
|
This->m_pInputPin = array[i];
|
|
|
|
This->m_pInputPin->vt->AddRef((IUnknown*)This->m_pInputPin);
|
2001-03-20 00:05:27 +00:00
|
|
|
}
|
2001-11-21 19:12:39 +00:00
|
|
|
if (!This->m_pOutputPin && direction == 1)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
2001-11-21 19:12:39 +00:00
|
|
|
This->m_pOutputPin = array[i];
|
|
|
|
This->m_pOutputPin->vt->AddRef((IUnknown*)This->m_pOutputPin);
|
2001-03-20 00:05:27 +00:00
|
|
|
}
|
|
|
|
array[i]->vt->Release((IUnknown*)(array[i]));
|
|
|
|
}
|
2001-11-21 19:12:39 +00:00
|
|
|
if (!This->m_pInputPin)
|
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "could not find input pin";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!This->m_pOutputPin)
|
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "could not find output pin";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
result = This->m_pInputPin->vt->QueryInterface((IUnknown*)This->m_pInputPin,
|
|
|
|
&IID_IMemInputPin,
|
|
|
|
(void**)&This->m_pImp);
|
2001-05-06 21:43:45 +00:00
|
|
|
if (result)
|
2001-11-21 19:12:39 +00:00
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "could not get IMemInputPin interface";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-11-21 19:12:39 +00:00
|
|
|
This->m_pOurType = in_fmt;
|
|
|
|
This->m_pDestType = out_fmt;
|
|
|
|
result = This->m_pInputPin->vt->QueryAccept(This->m_pInputPin, This->m_pOurType);
|
2001-05-06 21:43:45 +00:00
|
|
|
if (result)
|
2001-11-21 19:12:39 +00:00
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "source format is not accepted";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
This->m_pParentFilter = CBaseFilter2Create();
|
|
|
|
This->m_pSrcFilter = CBaseFilterCreate(This->m_pOurType, This->m_pParentFilter);
|
|
|
|
This->m_pOurInput = This->m_pSrcFilter->GetPin(This->m_pSrcFilter);
|
|
|
|
This->m_pOurInput->vt->AddRef((IUnknown*)This->m_pOurInput);
|
|
|
|
|
|
|
|
result = This->m_pInputPin->vt->ReceiveConnection(This->m_pInputPin,
|
|
|
|
This->m_pOurInput,
|
|
|
|
This->m_pOurType);
|
|
|
|
if (result)
|
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "could not connect to input pin";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-11-21 19:12:39 +00:00
|
|
|
This->m_pOurOutput = COutputPinCreate(This->m_pDestType);
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-11-21 19:12:39 +00:00
|
|
|
result = This->m_pOutputPin->vt->ReceiveConnection(This->m_pOutputPin,
|
|
|
|
(IPin*) This->m_pOurOutput,
|
|
|
|
This->m_pDestType);
|
2001-05-06 21:43:45 +00:00
|
|
|
if (result)
|
2001-08-16 00:50:02 +00:00
|
|
|
{
|
2001-12-11 23:29:24 +00:00
|
|
|
em = "could not connect to output pin";
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
2001-08-16 00:50:02 +00:00
|
|
|
}
|
|
|
|
|
2001-12-11 23:29:24 +00:00
|
|
|
init++;
|
2001-11-21 19:12:39 +00:00
|
|
|
break;
|
2001-03-20 00:05:27 +00:00
|
|
|
}
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-12-11 23:29:24 +00:00
|
|
|
if (!init)
|
2001-05-06 21:43:45 +00:00
|
|
|
{
|
2001-11-21 19:12:39 +00:00
|
|
|
DS_Filter_Destroy(This);
|
2002-11-26 21:00:20 +00:00
|
|
|
printf("Warning: DS_Filter() %s. (DLL=%.200s, r=0x%x)\n", em, dllname, result);
|
2001-11-21 19:12:39 +00:00
|
|
|
This = 0;
|
2001-05-06 21:43:45 +00:00
|
|
|
}
|
2001-11-21 19:12:39 +00:00
|
|
|
return This;
|
2001-03-20 00:05:27 +00:00
|
|
|
}
|