2001-03-20 00:05:27 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "DS_Filter.h"
|
|
|
|
#include <except.h>
|
|
|
|
//#include "../loader/loader.h"
|
|
|
|
#include <string>
|
2001-05-06 21:43:45 +00:00
|
|
|
#include <iostream>
|
2001-03-20 00:05:27 +00:00
|
|
|
#define __MODULE__ "DirectShow generic filter"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
typedef long STDCALL (*GETCLASS) (const GUID*, const GUID*, void**);
|
|
|
|
extern "C" char* def_path;
|
|
|
|
|
2001-04-11 02:11:39 +00:00
|
|
|
extern "C" int STDCALL expLoadLibraryA(const char*);
|
2001-03-20 00:05:27 +00:00
|
|
|
extern "C" STDCALL void* GetProcAddress(int, const char*);
|
|
|
|
extern "C" int STDCALL FreeLibrary(int);
|
|
|
|
|
2001-03-29 12:38:51 +00:00
|
|
|
extern "C" void Setup_LDT_Keeper();
|
|
|
|
extern "C" void setup_FS_Segment();
|
|
|
|
|
2001-03-20 00:05:27 +00:00
|
|
|
DS_Filter::DS_Filter()
|
|
|
|
:m_iHandle(0), m_pFilter(0), m_pInputPin(0),
|
2001-05-06 21:43:45 +00:00
|
|
|
m_pOutputPin(0), m_pSrcFilter(0), m_pParentFilter(0),
|
|
|
|
m_pOurInput(0), m_pOurOutput(0), m_pAll(0), m_pImp(0),
|
|
|
|
m_iState(0)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2001-05-06 21:43:45 +00:00
|
|
|
void DS_Filter::clean()
|
|
|
|
{
|
|
|
|
m_iState = 0;
|
|
|
|
|
|
|
|
if (m_pOurInput)
|
|
|
|
m_pOurInput->vt->Release((IUnknown*)m_pOurInput);
|
|
|
|
if (m_pInputPin)
|
|
|
|
m_pInputPin->vt->Disconnect(m_pInputPin);
|
|
|
|
if (m_pOutputPin)
|
|
|
|
m_pOutputPin->vt->Disconnect(m_pOutputPin);
|
|
|
|
if (m_pFilter)
|
|
|
|
m_pFilter->vt->Release((IUnknown*)m_pFilter);
|
|
|
|
if (m_pOutputPin)
|
|
|
|
m_pOutputPin->vt->Release((IUnknown*)m_pOutputPin);
|
|
|
|
if (m_pInputPin)
|
|
|
|
m_pInputPin->vt->Release((IUnknown*)m_pInputPin);
|
|
|
|
if (m_pImp)
|
|
|
|
m_pImp->vt->Release((IUnknown*)m_pImp);
|
|
|
|
|
|
|
|
delete m_pOurOutput;
|
|
|
|
delete m_pParentFilter;
|
|
|
|
delete m_pSrcFilter;
|
|
|
|
|
|
|
|
// FIXME - we are still leaving few things allocated!
|
|
|
|
if (m_iHandle)
|
|
|
|
FreeLibrary(m_iHandle);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
DS_Filter::~DS_Filter()
|
|
|
|
{
|
|
|
|
//cout << "Destruction of DS_FILTER" << endl;
|
|
|
|
Stop();
|
|
|
|
if (m_iState == 1)
|
|
|
|
clean();
|
|
|
|
//cout << "Destruction of DS_FILTER done" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DS_Filter::Create(char* dllname, const GUID* id, AM_MEDIA_TYPE* in_fmt, AM_MEDIA_TYPE* out_fmt)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
2001-03-29 12:38:51 +00:00
|
|
|
|
|
|
|
Setup_LDT_Keeper();
|
|
|
|
|
2001-03-20 00:05:27 +00:00
|
|
|
try
|
|
|
|
{
|
2001-04-11 02:11:39 +00:00
|
|
|
// string _fullname=def_path;
|
|
|
|
// _fullname+="/";
|
|
|
|
// _fullname+=dllname;
|
|
|
|
m_iHandle= expLoadLibraryA(dllname);
|
2001-05-06 21:43:45 +00:00
|
|
|
if (!m_iHandle)
|
|
|
|
{
|
|
|
|
char e[1024];
|
2001-06-11 12:47:48 +00:00
|
|
|
snprintf(e, 1024, "Could not open DirectShow DLL: %s", dllname);
|
2001-05-06 21:43:45 +00:00
|
|
|
throw FATAL(e);
|
|
|
|
}
|
2001-03-20 00:05:27 +00:00
|
|
|
GETCLASS func=(GETCLASS)GetProcAddress(m_iHandle, "DllGetClassObject");
|
2001-05-06 21:43:45 +00:00
|
|
|
if (!func)
|
|
|
|
{
|
|
|
|
char e[1024];
|
2001-06-11 12:47:48 +00:00
|
|
|
snprintf(e, 1024, "Illegal or corrupt DirectShow DLL: %s", dllname);
|
2001-05-06 21:43:45 +00:00
|
|
|
throw FATAL(e);
|
|
|
|
}
|
2001-03-20 00:05:27 +00:00
|
|
|
|
|
|
|
HRESULT result;
|
|
|
|
IClassFactory* factory=0;
|
|
|
|
result=func(id, &IID_IClassFactory, (void**)&factory);
|
|
|
|
if(result || (!factory)) throw FATAL("No such class object");;
|
|
|
|
|
2001-05-06 21:43:45 +00:00
|
|
|
setup_FS_Segment();
|
2001-03-20 00:05:27 +00:00
|
|
|
|
2001-05-06 21:43:45 +00:00
|
|
|
IUnknown* object=0;
|
|
|
|
result=factory->vt->CreateInstance(factory, 0, &IID_IUnknown, (void**)&object);
|
2001-03-20 00:05:27 +00:00
|
|
|
factory->vt->Release((IUnknown*)factory);
|
|
|
|
if(result || (!object)) throw FATAL("Class factory failure");
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-03-20 00:05:27 +00:00
|
|
|
result=object->vt->QueryInterface(object, &IID_IBaseFilter, (void**)&m_pFilter);
|
|
|
|
object->vt->Release((IUnknown*)object);
|
|
|
|
if(result || (!m_pFilter)) throw FATAL("Object does not have IBaseFilter interface");
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-03-20 00:05:27 +00:00
|
|
|
IEnumPins* enum_pins=0;
|
|
|
|
// enumerate pins
|
|
|
|
result=m_pFilter->vt->EnumPins(m_pFilter, &enum_pins);
|
|
|
|
if(result || (!enum_pins)) throw FATAL("Could not enumerate pins");
|
|
|
|
IPin* array[256];
|
|
|
|
ULONG fetched;
|
|
|
|
enum_pins->vt->Reset(enum_pins);
|
|
|
|
result=enum_pins->vt->Next(enum_pins, (ULONG)256, (IPin**)array, &fetched);
|
2001-05-06 21:43:45 +00:00
|
|
|
Debug printf("Pins enumeration returned %ld pins, error is %x\n", fetched, (int)result);
|
|
|
|
|
|
|
|
for (unsigned 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-05-06 21:43:45 +00:00
|
|
|
if (!m_pInputPin && direction == 0)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
2001-05-06 21:43:45 +00:00
|
|
|
m_pInputPin = array[i];
|
2001-03-20 00:05:27 +00:00
|
|
|
m_pInputPin->vt->AddRef((IUnknown*)m_pInputPin);
|
|
|
|
}
|
2001-05-06 21:43:45 +00:00
|
|
|
if (!m_pOutputPin && direction == 1)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
2001-05-06 21:43:45 +00:00
|
|
|
m_pOutputPin = array[i];
|
2001-03-20 00:05:27 +00:00
|
|
|
m_pOutputPin->vt->AddRef((IUnknown*)m_pOutputPin);
|
|
|
|
}
|
|
|
|
array[i]->vt->Release((IUnknown*)(array[i]));
|
|
|
|
}
|
2001-05-06 21:43:45 +00:00
|
|
|
if (!m_pInputPin)
|
|
|
|
throw FATAL("Input pin not found");
|
|
|
|
if (!m_pOutputPin)
|
|
|
|
throw FATAL("Output pin not found");
|
|
|
|
|
|
|
|
result = m_pInputPin->vt->QueryInterface((IUnknown*)m_pInputPin,
|
|
|
|
&IID_IMemInputPin,
|
|
|
|
(void**)&m_pImp);
|
2001-03-20 00:05:27 +00:00
|
|
|
if(result)
|
|
|
|
throw FATAL("Error getting IMemInputPin interface");
|
|
|
|
m_pOurType=in_fmt;
|
|
|
|
m_pDestType=out_fmt;
|
|
|
|
result=m_pInputPin->vt->QueryAccept(m_pInputPin, m_pOurType);
|
2001-05-06 21:43:45 +00:00
|
|
|
if (result)
|
|
|
|
throw FATAL("Source format is not accepted");
|
2001-03-20 00:05:27 +00:00
|
|
|
|
|
|
|
m_pParentFilter=new CBaseFilter2;
|
|
|
|
m_pSrcFilter=new CBaseFilter(*m_pOurType, m_pParentFilter);
|
|
|
|
m_pOurInput=m_pSrcFilter->GetPin();
|
|
|
|
m_pOurInput->vt->AddRef((IUnknown*)m_pOurInput);
|
2001-05-06 21:43:45 +00:00
|
|
|
|
|
|
|
result=m_pInputPin->vt->ReceiveConnection(m_pInputPin, m_pOurInput,
|
|
|
|
m_pOurType);
|
|
|
|
if (result)
|
|
|
|
throw FATAL("Error connecting to input pin");
|
|
|
|
|
|
|
|
m_pOurOutput = new COutputPin(*m_pDestType);
|
|
|
|
|
|
|
|
result = m_pOutputPin->vt->ReceiveConnection(m_pOutputPin,
|
|
|
|
m_pOurOutput,
|
|
|
|
m_pDestType);
|
|
|
|
if (result)
|
|
|
|
throw FATAL("Error connecting to output pin");
|
|
|
|
cout << "Using DirectShow codec: " << dllname << endl;
|
|
|
|
m_iState = 1;
|
2001-03-20 00:05:27 +00:00
|
|
|
}
|
|
|
|
catch(FatalError e)
|
|
|
|
{
|
|
|
|
e.PrintAll();
|
2001-05-06 21:43:45 +00:00
|
|
|
clean();
|
2001-03-20 00:05:27 +00:00
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-03-20 00:05:27 +00:00
|
|
|
void DS_Filter::Start()
|
|
|
|
{
|
2001-05-06 21:43:45 +00:00
|
|
|
if (m_iState != 1)
|
2001-03-20 00:05:27 +00:00
|
|
|
return;
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-03-20 00:05:27 +00:00
|
|
|
HRESULT hr=m_pFilter->vt->Run(m_pFilter, 0);
|
2001-05-06 21:43:45 +00:00
|
|
|
if (hr != 0)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
2001-05-06 21:43:45 +00:00
|
|
|
Debug cerr<<"WARNING: m_Filter->Run() failed, error code "<<hex<<hr<<dec<<endl;
|
2001-03-20 00:05:27 +00:00
|
|
|
}
|
|
|
|
hr=m_pImp->vt->GetAllocator(m_pImp, &m_pAll);
|
2001-05-06 21:43:45 +00:00
|
|
|
if (hr)
|
2001-03-20 00:05:27 +00:00
|
|
|
{
|
2001-05-06 21:43:45 +00:00
|
|
|
Debug cerr<<"Error getting IMemAllocator interface "<<hex<<hr<<dec<<endl;
|
2001-03-20 00:05:27 +00:00
|
|
|
m_pImp->vt->Release((IUnknown*)m_pImp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_pImp->vt->NotifyAllocator(m_pImp, m_pAll, 0);
|
2001-05-06 21:43:45 +00:00
|
|
|
m_iState = 2;
|
2001-03-20 00:05:27 +00:00
|
|
|
}
|
2001-05-06 21:43:45 +00:00
|
|
|
|
2001-03-20 00:05:27 +00:00
|
|
|
void DS_Filter::Stop()
|
|
|
|
{
|
2001-05-06 21:43:45 +00:00
|
|
|
if (m_iState == 2)
|
|
|
|
{
|
|
|
|
m_pAll->vt->Release((IUnknown*)m_pAll);
|
|
|
|
m_pAll=0;
|
|
|
|
m_pFilter->vt->Stop(m_pFilter);
|
|
|
|
m_iState=1;
|
|
|
|
}
|
2001-03-20 00:05:27 +00:00
|
|
|
}
|