168
|
1 #include <stdio.h>
|
|
2 #include <string.h>
|
|
3 #include "DS_Filter.h"
|
|
4 #include <except.h>
|
|
5 //#include "../loader/loader.h"
|
|
6 #include <string>
|
713
|
7 #include <iostream>
|
168
|
8 #define __MODULE__ "DirectShow generic filter"
|
|
9
|
|
10 using namespace std;
|
|
11
|
|
12 typedef long STDCALL (*GETCLASS) (const GUID*, const GUID*, void**);
|
|
13 extern "C" char* def_path;
|
|
14
|
342
|
15 extern "C" int STDCALL expLoadLibraryA(const char*);
|
168
|
16 extern "C" STDCALL void* GetProcAddress(int, const char*);
|
|
17 extern "C" int STDCALL FreeLibrary(int);
|
|
18
|
244
|
19 extern "C" void Setup_LDT_Keeper();
|
|
20 extern "C" void setup_FS_Segment();
|
|
21
|
168
|
22 DS_Filter::DS_Filter()
|
|
23 :m_iHandle(0), m_pFilter(0), m_pInputPin(0),
|
713
|
24 m_pOutputPin(0), m_pSrcFilter(0), m_pParentFilter(0),
|
|
25 m_pOurInput(0), m_pOurOutput(0), m_pAll(0), m_pImp(0),
|
|
26 m_iState(0)
|
168
|
27 {
|
|
28 }
|
|
29
|
713
|
30 void DS_Filter::clean()
|
|
31 {
|
|
32 m_iState = 0;
|
|
33
|
|
34 if (m_pOurInput)
|
|
35 m_pOurInput->vt->Release((IUnknown*)m_pOurInput);
|
|
36 if (m_pInputPin)
|
|
37 m_pInputPin->vt->Disconnect(m_pInputPin);
|
|
38 if (m_pOutputPin)
|
|
39 m_pOutputPin->vt->Disconnect(m_pOutputPin);
|
|
40 if (m_pFilter)
|
|
41 m_pFilter->vt->Release((IUnknown*)m_pFilter);
|
|
42 if (m_pOutputPin)
|
|
43 m_pOutputPin->vt->Release((IUnknown*)m_pOutputPin);
|
|
44 if (m_pInputPin)
|
|
45 m_pInputPin->vt->Release((IUnknown*)m_pInputPin);
|
|
46 if (m_pImp)
|
|
47 m_pImp->vt->Release((IUnknown*)m_pImp);
|
|
48
|
|
49 delete m_pOurOutput;
|
|
50 delete m_pParentFilter;
|
|
51 delete m_pSrcFilter;
|
|
52
|
|
53 // FIXME - we are still leaving few things allocated!
|
|
54 if (m_iHandle)
|
|
55 FreeLibrary(m_iHandle);
|
|
56
|
|
57 }
|
|
58
|
|
59 DS_Filter::~DS_Filter()
|
|
60 {
|
|
61 //cout << "Destruction of DS_FILTER" << endl;
|
|
62 Stop();
|
|
63 if (m_iState == 1)
|
|
64 clean();
|
|
65 //cout << "Destruction of DS_FILTER done" << endl;
|
|
66 }
|
|
67
|
|
68 void DS_Filter::Create(char* dllname, const GUID* id, AM_MEDIA_TYPE* in_fmt, AM_MEDIA_TYPE* out_fmt)
|
168
|
69 {
|
244
|
70
|
|
71 Setup_LDT_Keeper();
|
|
72
|
168
|
73 try
|
|
74 {
|
342
|
75 // string _fullname=def_path;
|
|
76 // _fullname+="/";
|
|
77 // _fullname+=dllname;
|
|
78 m_iHandle= expLoadLibraryA(dllname);
|
713
|
79 if (!m_iHandle)
|
|
80 {
|
|
81 char e[1024];
|
1096
|
82 snprintf(e, 1024, "Could not open DirectShow DLL: %s", dllname);
|
713
|
83 throw FATAL(e);
|
|
84 }
|
168
|
85 GETCLASS func=(GETCLASS)GetProcAddress(m_iHandle, "DllGetClassObject");
|
713
|
86 if (!func)
|
|
87 {
|
|
88 char e[1024];
|
1096
|
89 snprintf(e, 1024, "Illegal or corrupt DirectShow DLL: %s", dllname);
|
713
|
90 throw FATAL(e);
|
|
91 }
|
168
|
92
|
|
93 HRESULT result;
|
|
94 IClassFactory* factory=0;
|
|
95 result=func(id, &IID_IClassFactory, (void**)&factory);
|
|
96 if(result || (!factory)) throw FATAL("No such class object");;
|
244
|
97
|
713
|
98 setup_FS_Segment();
|
168
|
99
|
713
|
100 IUnknown* object=0;
|
|
101 result=factory->vt->CreateInstance(factory, 0, &IID_IUnknown, (void**)&object);
|
168
|
102 factory->vt->Release((IUnknown*)factory);
|
|
103 if(result || (!object)) throw FATAL("Class factory failure");
|
713
|
104
|
168
|
105 result=object->vt->QueryInterface(object, &IID_IBaseFilter, (void**)&m_pFilter);
|
|
106 object->vt->Release((IUnknown*)object);
|
|
107 if(result || (!m_pFilter)) throw FATAL("Object does not have IBaseFilter interface");
|
713
|
108
|
168
|
109 IEnumPins* enum_pins=0;
|
|
110 // enumerate pins
|
|
111 result=m_pFilter->vt->EnumPins(m_pFilter, &enum_pins);
|
|
112 if(result || (!enum_pins)) throw FATAL("Could not enumerate pins");
|
|
113 IPin* array[256];
|
|
114 ULONG fetched;
|
|
115 enum_pins->vt->Reset(enum_pins);
|
|
116 result=enum_pins->vt->Next(enum_pins, (ULONG)256, (IPin**)array, &fetched);
|
713
|
117 Debug printf("Pins enumeration returned %ld pins, error is %x\n", fetched, (int)result);
|
|
118
|
|
119 for (unsigned i = 0; i < fetched; i++)
|
168
|
120 {
|
713
|
121 int direction = -1;
|
168
|
122 array[i]->vt->QueryDirection(array[i], (PIN_DIRECTION*)&direction);
|
713
|
123 if (!m_pInputPin && direction == 0)
|
168
|
124 {
|
713
|
125 m_pInputPin = array[i];
|
168
|
126 m_pInputPin->vt->AddRef((IUnknown*)m_pInputPin);
|
|
127 }
|
713
|
128 if (!m_pOutputPin && direction == 1)
|
168
|
129 {
|
713
|
130 m_pOutputPin = array[i];
|
168
|
131 m_pOutputPin->vt->AddRef((IUnknown*)m_pOutputPin);
|
|
132 }
|
|
133 array[i]->vt->Release((IUnknown*)(array[i]));
|
|
134 }
|
713
|
135 if (!m_pInputPin)
|
|
136 throw FATAL("Input pin not found");
|
|
137 if (!m_pOutputPin)
|
|
138 throw FATAL("Output pin not found");
|
168
|
139
|
713
|
140 result = m_pInputPin->vt->QueryInterface((IUnknown*)m_pInputPin,
|
|
141 &IID_IMemInputPin,
|
|
142 (void**)&m_pImp);
|
168
|
143 if(result)
|
|
144 throw FATAL("Error getting IMemInputPin interface");
|
|
145 m_pOurType=in_fmt;
|
|
146 m_pDestType=out_fmt;
|
|
147 result=m_pInputPin->vt->QueryAccept(m_pInputPin, m_pOurType);
|
713
|
148 if (result)
|
|
149 throw FATAL("Source format is not accepted");
|
168
|
150
|
|
151 m_pParentFilter=new CBaseFilter2;
|
|
152 m_pSrcFilter=new CBaseFilter(*m_pOurType, m_pParentFilter);
|
|
153 m_pOurInput=m_pSrcFilter->GetPin();
|
|
154 m_pOurInput->vt->AddRef((IUnknown*)m_pOurInput);
|
713
|
155
|
|
156 result=m_pInputPin->vt->ReceiveConnection(m_pInputPin, m_pOurInput,
|
|
157 m_pOurType);
|
|
158 if (result)
|
|
159 throw FATAL("Error connecting to input pin");
|
|
160
|
|
161 m_pOurOutput = new COutputPin(*m_pDestType);
|
|
162
|
|
163 result = m_pOutputPin->vt->ReceiveConnection(m_pOutputPin,
|
|
164 m_pOurOutput,
|
|
165 m_pDestType);
|
|
166 if (result)
|
|
167 throw FATAL("Error connecting to output pin");
|
|
168 cout << "Using DirectShow codec: " << dllname << endl;
|
|
169 m_iState = 1;
|
168
|
170 }
|
|
171 catch(FatalError e)
|
|
172 {
|
|
173 e.PrintAll();
|
713
|
174 clean();
|
168
|
175 throw;
|
|
176 }
|
|
177 }
|
713
|
178
|
168
|
179 void DS_Filter::Start()
|
|
180 {
|
713
|
181 if (m_iState != 1)
|
168
|
182 return;
|
713
|
183
|
168
|
184 HRESULT hr=m_pFilter->vt->Run(m_pFilter, 0);
|
713
|
185 if (hr != 0)
|
168
|
186 {
|
713
|
187 Debug cerr<<"WARNING: m_Filter->Run() failed, error code "<<hex<<hr<<dec<<endl;
|
168
|
188 }
|
|
189 hr=m_pImp->vt->GetAllocator(m_pImp, &m_pAll);
|
713
|
190 if (hr)
|
168
|
191 {
|
713
|
192 Debug cerr<<"Error getting IMemAllocator interface "<<hex<<hr<<dec<<endl;
|
168
|
193 m_pImp->vt->Release((IUnknown*)m_pImp);
|
|
194 return;
|
|
195 }
|
|
196 m_pImp->vt->NotifyAllocator(m_pImp, m_pAll, 0);
|
713
|
197 m_iState = 2;
|
168
|
198 }
|
713
|
199
|
168
|
200 void DS_Filter::Stop()
|
|
201 {
|
713
|
202 if (m_iState == 2)
|
|
203 {
|
|
204 m_pAll->vt->Release((IUnknown*)m_pAll);
|
|
205 m_pAll=0;
|
|
206 m_pFilter->vt->Stop(m_pFilter);
|
|
207 m_iState=1;
|
|
208 }
|
168
|
209 }
|