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