1545
|
1 #include "DS_Filter.h"
|
3056
|
2 #include "driver.h"
|
|
3 #include "com.h"
|
168
|
4 #include <stdio.h>
|
|
5 #include <string.h>
|
1545
|
6
|
168
|
7 typedef long STDCALL (*GETCLASS) (const GUID*, const GUID*, void**);
|
|
8
|
1545
|
9 //extern "C" STDCALL void* GetProcAddress(int, const char*); // STDCALL has to be first NetBSD
|
244
|
10
|
3056
|
11 static void DS_Filter_Start(DS_Filter* This)
|
168
|
12 {
|
3056
|
13 HRESULT hr;
|
|
14
|
3467
|
15 if (This->m_pAll)
|
3056
|
16 return;
|
|
17
|
|
18 //Debug printf("DS_Filter_Start(%p)\n", This);
|
|
19 hr = This->m_pFilter->vt->Run(This->m_pFilter, 0);
|
|
20 if (hr != 0)
|
|
21 {
|
|
22 Debug printf("WARNING: m_Filter->Run() failed, error code %x\n", (int)hr);
|
|
23 }
|
|
24 hr = This->m_pImp->vt->GetAllocator(This->m_pImp, &This->m_pAll);
|
|
25
|
|
26 if (hr || !This->m_pAll)
|
|
27 {
|
|
28 Debug printf("WARNING: error getting IMemAllocator interface %x\n", (int)hr);
|
|
29 This->m_pImp->vt->Release((IUnknown*)This->m_pImp);
|
|
30 return;
|
|
31 }
|
|
32 This->m_pImp->vt->NotifyAllocator(This->m_pImp, This->m_pAll, 0);
|
168
|
33 }
|
|
34
|
3056
|
35 static void DS_Filter_Stop(DS_Filter* This)
|
713
|
36 {
|
3467
|
37 if (This->m_pAll)
|
3056
|
38 {
|
|
39 //Debug printf("DS_Filter_Stop(%p)\n", This);
|
3467
|
40 This->m_pFilter->vt->Stop(This->m_pFilter); // causes weird crash ??? FIXME
|
3056
|
41 This->m_pAll->vt->Release((IUnknown*)This->m_pAll);
|
|
42 This->m_pAll = 0;
|
|
43 }
|
1545
|
44 }
|
|
45
|
3056
|
46 void DS_Filter_Destroy(DS_Filter* This)
|
1545
|
47 {
|
3056
|
48 This->Stop(This);
|
|
49
|
|
50 if (This->m_pOurInput)
|
|
51 This->m_pOurInput->vt->Release((IUnknown*)This->m_pOurInput);
|
|
52 if (This->m_pInputPin)
|
|
53 This->m_pInputPin->vt->Disconnect(This->m_pInputPin);
|
|
54 if (This->m_pOutputPin)
|
|
55 This->m_pOutputPin->vt->Disconnect(This->m_pOutputPin);
|
|
56 if (This->m_pFilter)
|
|
57 This->m_pFilter->vt->Release((IUnknown*)This->m_pFilter);
|
|
58 if (This->m_pOutputPin)
|
|
59 This->m_pOutputPin->vt->Release((IUnknown*)This->m_pOutputPin);
|
|
60 if (This->m_pInputPin)
|
|
61 This->m_pInputPin->vt->Release((IUnknown*)This->m_pInputPin);
|
|
62 if (This->m_pImp)
|
|
63 This->m_pImp->vt->Release((IUnknown*)This->m_pImp);
|
713
|
64
|
3056
|
65 if (This->m_pOurOutput)
|
|
66 This->m_pOurOutput->vt->Release((IUnknown*)This->m_pOurOutput);
|
|
67 if (This->m_pParentFilter)
|
3130
|
68 This->m_pParentFilter->vt->Release((IUnknown*)This->m_pParentFilter);
|
3056
|
69 if (This->m_pSrcFilter)
|
|
70 This->m_pSrcFilter->vt->Release((IUnknown*)This->m_pSrcFilter);
|
713
|
71
|
|
72 // FIXME - we are still leaving few things allocated!
|
3056
|
73 if (This->m_iHandle)
|
|
74 FreeLibrary(This->m_iHandle);
|
|
75
|
|
76 free(This);
|
|
77
|
|
78 CodecRelease();
|
713
|
79 }
|
|
80
|
3056
|
81 DS_Filter* DS_FilterCreate(const char* dllname, const GUID* id,
|
|
82 AM_MEDIA_TYPE* in_fmt,
|
|
83 AM_MEDIA_TYPE* out_fmt)
|
168
|
84 {
|
3467
|
85 int init = 0;
|
|
86 char eb[250];
|
|
87 const char* em = NULL;
|
3056
|
88 DS_Filter* This = (DS_Filter*) malloc(sizeof(DS_Filter));
|
|
89 if (!This)
|
|
90 return NULL;
|
|
91
|
|
92 CodecAlloc();
|
|
93
|
|
94 This->m_pFilter = NULL;
|
|
95 This->m_pInputPin = NULL;
|
|
96 This->m_pOutputPin = NULL;
|
|
97 This->m_pSrcFilter = NULL;
|
|
98 This->m_pParentFilter = NULL;
|
|
99 This->m_pOurInput = NULL;
|
|
100 This->m_pOurOutput = NULL;
|
|
101 This->m_pAll = NULL;
|
|
102 This->m_pImp = NULL;
|
|
103
|
|
104 This->Start = DS_Filter_Start;
|
|
105 This->Stop = DS_Filter_Stop;
|
|
106
|
|
107 for (;;)
|
168
|
108 {
|
3056
|
109 HRESULT result;
|
|
110 GETCLASS func;
|
|
111 struct IClassFactory* factory = NULL;
|
|
112 struct IUnknown* object = NULL;
|
|
113 IEnumPins* enum_pins = 0;
|
|
114 IPin* array[256];
|
|
115 ULONG fetched;
|
|
116 unsigned int i;
|
|
117
|
|
118 This->m_iHandle = LoadLibraryA(dllname);
|
|
119 if (!This->m_iHandle)
|
713
|
120 {
|
3467
|
121 em = "could not open DirectShow DLL";
|
3056
|
122 break;
|
713
|
123 }
|
3056
|
124 func = (GETCLASS)GetProcAddress(This->m_iHandle, "DllGetClassObject");
|
713
|
125 if (!func)
|
|
126 {
|
3467
|
127 em = "illegal or corrupt DirectShow DLL";
|
3056
|
128 break;
|
713
|
129 }
|
1545
|
130 result = func(id, &IID_IClassFactory, (void**)&factory);
|
|
131 if (result || !factory)
|
3056
|
132 {
|
3467
|
133 em = "no such class object";
|
3056
|
134 break;
|
|
135 }
|
1545
|
136 result = factory->vt->CreateInstance(factory, 0, &IID_IUnknown, (void**)&object);
|
168
|
137 factory->vt->Release((IUnknown*)factory);
|
1545
|
138 if (result || !object)
|
3056
|
139 {
|
3467
|
140 em = "class factory failure";
|
3056
|
141 break;
|
|
142 }
|
|
143 result = object->vt->QueryInterface(object, &IID_IBaseFilter, (void**)&This->m_pFilter);
|
168
|
144 object->vt->Release((IUnknown*)object);
|
3056
|
145 if (result || !This->m_pFilter)
|
|
146 {
|
3467
|
147 em = "object does not have IBaseFilter interface";
|
3056
|
148 break;
|
|
149 }
|
|
150 // enumerate pins
|
|
151 result = This->m_pFilter->vt->EnumPins(This->m_pFilter, &enum_pins);
|
|
152 if (result || !enum_pins)
|
|
153 {
|
3467
|
154 em = "could not enumerate pins";
|
3056
|
155 break;
|
|
156 }
|
713
|
157
|
168
|
158 enum_pins->vt->Reset(enum_pins);
|
1545
|
159 result = enum_pins->vt->Next(enum_pins, (ULONG)256, (IPin**)array, &fetched);
|
713
|
160 Debug printf("Pins enumeration returned %ld pins, error is %x\n", fetched, (int)result);
|
|
161
|
3056
|
162 for (i = 0; i < fetched; i++)
|
168
|
163 {
|
713
|
164 int direction = -1;
|
168
|
165 array[i]->vt->QueryDirection(array[i], (PIN_DIRECTION*)&direction);
|
3056
|
166 if (!This->m_pInputPin && direction == 0)
|
168
|
167 {
|
3056
|
168 This->m_pInputPin = array[i];
|
|
169 This->m_pInputPin->vt->AddRef((IUnknown*)This->m_pInputPin);
|
168
|
170 }
|
3056
|
171 if (!This->m_pOutputPin && direction == 1)
|
168
|
172 {
|
3056
|
173 This->m_pOutputPin = array[i];
|
|
174 This->m_pOutputPin->vt->AddRef((IUnknown*)This->m_pOutputPin);
|
168
|
175 }
|
|
176 array[i]->vt->Release((IUnknown*)(array[i]));
|
|
177 }
|
3056
|
178 if (!This->m_pInputPin)
|
|
179 {
|
3467
|
180 em = "could not find input pin";
|
3056
|
181 break;
|
|
182 }
|
|
183 if (!This->m_pOutputPin)
|
|
184 {
|
3467
|
185 em = "could not find output pin";
|
3056
|
186 break;
|
|
187 }
|
|
188 result = This->m_pInputPin->vt->QueryInterface((IUnknown*)This->m_pInputPin,
|
|
189 &IID_IMemInputPin,
|
|
190 (void**)&This->m_pImp);
|
713
|
191 if (result)
|
3056
|
192 {
|
3467
|
193 em = "could not get IMemInputPin interface";
|
3056
|
194 break;
|
|
195 }
|
168
|
196
|
3056
|
197 This->m_pOurType = in_fmt;
|
|
198 This->m_pDestType = out_fmt;
|
|
199 result = This->m_pInputPin->vt->QueryAccept(This->m_pInputPin, This->m_pOurType);
|
713
|
200 if (result)
|
3056
|
201 {
|
3467
|
202 em = "source format is not accepted";
|
3056
|
203 break;
|
|
204 }
|
|
205 This->m_pParentFilter = CBaseFilter2Create();
|
|
206 This->m_pSrcFilter = CBaseFilterCreate(This->m_pOurType, This->m_pParentFilter);
|
|
207 This->m_pOurInput = This->m_pSrcFilter->GetPin(This->m_pSrcFilter);
|
|
208 This->m_pOurInput->vt->AddRef((IUnknown*)This->m_pOurInput);
|
713
|
209
|
3056
|
210 result = This->m_pInputPin->vt->ReceiveConnection(This->m_pInputPin,
|
|
211 This->m_pOurInput,
|
|
212 This->m_pOurType);
|
|
213 if (result)
|
|
214 {
|
3467
|
215 em = "could not connect to input pin";
|
3056
|
216 break;
|
|
217 }
|
|
218
|
|
219 This->m_pOurOutput = COutputPinCreate(This->m_pDestType);
|
|
220
|
|
221 result = This->m_pOutputPin->vt->ReceiveConnection(This->m_pOutputPin,
|
|
222 (IPin*) This->m_pOurOutput,
|
|
223 This->m_pDestType);
|
713
|
224 if (result)
|
1545
|
225 {
|
3467
|
226 em = "could not connect to output pin";
|
3056
|
227 break;
|
1545
|
228 }
|
|
229
|
|
230 printf("Using DirectShow codec: %s\n", dllname);
|
3467
|
231 init++;
|
3056
|
232 break;
|
168
|
233 }
|
3056
|
234
|
3467
|
235 if (!init)
|
168
|
236 {
|
3056
|
237 DS_Filter_Destroy(This);
|
3467
|
238 printf("Warning: DS_Filter() %s. (DLL=%.200s)\n", em, dllname);
|
3056
|
239 This = 0;
|
168
|
240 }
|
3056
|
241 return This;
|
168
|
242 }
|