]> git.vomp.tv Git - vompclient.git/blob - dssourcefilter.cc
Windows updates
[vompclient.git] / dssourcefilter.cc
1 /*\r
2     Copyright 2004-2006 Marten Richter\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 */\r
20 #include "dssourcefilter.h"\r
21 \r
22 #define AUDIOPIN_NAME L"Audio"\r
23 #define VIDEOPIN_NAME L"Video"\r
24 \r
25 class DsSFEnumPins: public IEnumPins {\r
26 public:\r
27         DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos=0);\r
28         virtual ~DsSFEnumPins();\r
29         virtual HRESULT STDMETHODCALLTYPE Next(ULONG numpin,IPin **pins,ULONG *fetched);\r
30         virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin);\r
31         virtual HRESULT STDMETHODCALLTYPE Reset();\r
32         virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPins **enuma);\r
33         virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object);\r
34         virtual ULONG STDMETHODCALLTYPE AddRef();\r
35     virtual ULONG STDMETHODCALLTYPE Release();\r
36 protected:\r
37         DsSourcePin* audiopin;\r
38         DsSourcePin* videopin;\r
39         DsSourceFilter *filter;\r
40         ULONG curpos;\r
41         volatile long refs;\r
42 };\r
43 \r
44 DsSFEnumPins::DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos){\r
45         audiopin=audio;\r
46         videopin=video;\r
47         curpos=pos;\r
48         filter=filt;\r
49         filt->AddRef();\r
50         refs=0;\r
51         \r
52 }\r
53 \r
54 DsSFEnumPins::~DsSFEnumPins(){\r
55         filter->Release();\r
56         \r
57 }\r
58 \r
59 HRESULT STDMETHODCALLTYPE DsSFEnumPins::Next(ULONG numpin,IPin **pins,ULONG *fetched) {\r
60         int i;\r
61         if (fetched==NULL) return E_POINTER;\r
62         if (pins==NULL) return E_POINTER;\r
63         *fetched=0;\r
64 \r
65         for (i=0;(i<numpin)&& (curpos<2);i++) {\r
66                 switch (curpos) {\r
67                 case 0: audiopin->AddRef();  pins[i]=(IPin*)audiopin;break;\r
68                 case 1: videopin->AddRef(); pins[i]=(IPin*)videopin;break;\r
69                 };\r
70                 (*fetched)++;\r
71                 curpos++;\r
72         }\r
73         if ((*fetched)!=numpin) return S_FALSE;\r
74         return S_OK;\r
75 }\r
76 \r
77 HRESULT STDMETHODCALLTYPE DsSFEnumPins::Skip(ULONG numpin){\r
78         curpos+=numpin;\r
79         if (curpos>2) return S_FALSE;\r
80         return S_OK;\r
81 }\r
82 HRESULT STDMETHODCALLTYPE DsSFEnumPins::Reset(){\r
83         curpos=0;\r
84         return S_OK;\r
85 }\r
86 HRESULT STDMETHODCALLTYPE DsSFEnumPins::Clone(IEnumPins **enuma){\r
87         if (enuma==NULL) return E_POINTER;\r
88         *enuma=new DsSFEnumPins(audiopin,videopin,filter,curpos);\r
89         (*enuma)->AddRef();\r
90         return S_OK;\r
91 }\r
92 \r
93 HRESULT STDMETHODCALLTYPE  DsSFEnumPins::QueryInterface(REFIID id,void ** object){\r
94         if (object==NULL) return E_POINTER;\r
95         if (id==IID_IUnknown ||id == IID_IEnumPins) {\r
96                 *object=(IUnknown*)this;\r
97                 ((IUnknown*)object)->AddRef();\r
98                 return NOERROR;\r
99         } else {\r
100                 *object=NULL;\r
101                 return E_NOINTERFACE;\r
102         }\r
103 }\r
104 \r
105 \r
106 \r
107 ULONG STDMETHODCALLTYPE DsSFEnumPins::AddRef(){\r
108         InterlockedIncrement(&refs);\r
109         long tempref=refs;\r
110         if (tempref>1) return tempref;\r
111         else return 1;\r
112 }\r
113 \r
114 ULONG STDMETHODCALLTYPE DsSFEnumPins::Release(){\r
115         long tempref=InterlockedDecrement(&refs);\r
116         \r
117         if (tempref==0) {\r
118                 refs++;\r
119                 delete this;\r
120                 return NULL;\r
121         } else {\r
122                 if (tempref>1) return tempref;\r
123                 else return 1;\r
124         }\r
125 }\r
126 \r
127 \r
128 \r
129 \r
130 \r
131 \r
132 \r
133 DsSourceFilter::DsSourceFilter()\r
134 {\r
135         //add audio pin\r
136         HRESULT res;\r
137         audiopin=new DsSourcePin(this,&res,L"Vomp Audio Out",true);\r
138         videopin=new DsSourcePin(this,&res,L"Vomp Video Out",false);\r
139         filtergraph=NULL;\r
140         clock=NULL;\r
141         mystate=State_Stopped;\r
142         laststart=0;\r
143         refs=0;\r
144         InitializeCriticalSection(&filterlock);\r
145 \r
146 }\r
147 \r
148 DsSourceFilter::~DsSourceFilter()\r
149 {\r
150         if (audiopin) delete audiopin;\r
151         if (videopin) delete videopin;\r
152         if (clock) {\r
153                 clock->Release();\r
154                 clock=NULL;\r
155         }\r
156         DeleteCriticalSection(&filterlock);\r
157         \r
158 }\r
159 \r
160 HRESULT STDMETHODCALLTYPE  DsSourceFilter::GetClassID(CLSID *clsid){\r
161         if (clsid==NULL) return E_POINTER;\r
162         *clsid=_uuidof(this);\r
163         return S_OK;\r
164 }\r
165 \r
166 HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryInterface(REFIID id,void ** object){\r
167         if (object==NULL) return E_POINTER;\r
168         if (id==IID_IUnknown) {\r
169                 *object=(IUnknown*)this;\r
170                 AddRef();\r
171                 return NOERROR;\r
172         } else if (id==IID_IBaseFilter) {\r
173                 *object=(IBaseFilter*)this;\r
174                 AddRef();\r
175                 return NOERROR;\r
176         } else if (id==IID_IMediaFilter) {\r
177                 *object=(IMediaFilter*)this;\r
178                 AddRef();\r
179                 return NOERROR;\r
180         }else {\r
181                 *object=NULL;\r
182                 return E_NOINTERFACE;\r
183         }\r
184 }\r
185 \r
186 ULONG STDMETHODCALLTYPE DsSourceFilter::AddRef(){\r
187         InterlockedIncrement(&refs);\r
188         long tempref=refs;\r
189         if (tempref>1) return tempref;\r
190         else return 1;\r
191 }\r
192 ULONG STDMETHODCALLTYPE DsSourceFilter::Release(){\r
193         long tempref=InterlockedDecrement(&refs);\r
194         \r
195         if (tempref==0) {\r
196                 refs++;\r
197                 delete this;\r
198                 return NULL;\r
199         } else {\r
200                 if (tempref>1) return tempref;\r
201                 else return 1;\r
202         }\r
203 }\r
204 \r
205 /*IBaseFilter*/\r
206 HRESULT STDMETHODCALLTYPE DsSourceFilter::EnumPins(IEnumPins **enumar){\r
207         if (enumar==NULL) return E_POINTER;\r
208         *enumar=new DsSFEnumPins(audiopin,videopin, this);\r
209         (*enumar)->AddRef();\r
210         return S_OK;\r
211 }\r
212 \r
213 HRESULT STDMETHODCALLTYPE DsSourceFilter::FindPin(LPCWSTR iden,IPin **pin){\r
214         if (pin==NULL) return E_POINTER;\r
215         EnterCriticalSection(&filterlock);\r
216 \r
217         if (wcscmp(AUDIOPIN_NAME,iden)==NULL) {\r
218                 *pin=(IPin*)audiopin;\r
219                 (*pin)->AddRef();\r
220                 LeaveCriticalSection(&filterlock);\r
221                 return S_OK;\r
222         }\r
223         if (wcscmp(VIDEOPIN_NAME,iden)==NULL) {\r
224                 *pin=(IPin*)videopin;\r
225                 (*pin)->AddRef();\r
226                 LeaveCriticalSection(&filterlock);\r
227                 return S_OK;\r
228         }\r
229 \r
230         *pin=NULL;\r
231         LeaveCriticalSection(&filterlock);\r
232     return VFW_E_NOT_FOUND;\r
233 }\r
234 HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryFilterInfo(FILTER_INFO *info){\r
235         if (info==NULL) return E_POINTER;\r
236         wcsncpy(info->achName,L"VompWinFilter", sizeof(info->achName)/sizeof(WCHAR));\r
237         info->pGraph=filtergraph;\r
238         if (info->pGraph!=NULL) info->pGraph->AddRef();\r
239         return NOERROR;\r
240 }\r
241 \r
242 HRESULT STDMETHODCALLTYPE DsSourceFilter::JoinFilterGraph(IFilterGraph *graph,LPCWSTR name){\r
243         //Should we lock\r
244         EnterCriticalSection(&filterlock);\r
245         filtergraph=graph;\r
246         //filtergraph->AddRef();\r
247         //We ignore the name\r
248         LeaveCriticalSection(&filterlock);\r
249         \r
250         return S_OK;\r
251 }\r
252 HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryVendorInfo(LPWSTR *vendinf) {\r
253         return E_NOTIMPL;\r
254 }\r
255 \r
256 \r
257 /*IMediaFilter*/\r
258 HRESULT STDMETHODCALLTYPE DsSourceFilter::GetState(DWORD timeout,FILTER_STATE *state){\r
259         if (state==NULL) return E_POINTER;\r
260         EnterCriticalSection(&filterlock);\r
261         *state=mystate;\r
262         LeaveCriticalSection(&filterlock);\r
263         return S_OK;\r
264 }\r
265 \r
266 HRESULT STDMETHODCALLTYPE DsSourceFilter::SetSyncSource(IReferenceClock *uhr){\r
267         EnterCriticalSection(&filterlock);\r
268         //MessageBox(0,"Sets ync","",0);\r
269         if (clock!=NULL) {\r
270                 clock->Release();\r
271         }\r
272         if (uhr!=NULL) {\r
273                 uhr->AddRef();\r
274         }\r
275         clock=uhr;\r
276         LeaveCriticalSection(&filterlock);\r
277         \r
278         return S_OK;\r
279 }\r
280 HRESULT STDMETHODCALLTYPE DsSourceFilter::GetSyncSource(IReferenceClock **uhr){\r
281         if (uhr==NULL) return E_POINTER;\r
282         EnterCriticalSection(&filterlock);\r
283         if (clock!=NULL) clock->AddRef();\r
284         *uhr=clock;\r
285         LeaveCriticalSection(&filterlock);\r
286         \r
287         return S_OK;\r
288 }\r
289 \r
290 HRESULT STDMETHODCALLTYPE DsSourceFilter::Stop(){\r
291         EnterCriticalSection(&filterlock);\r
292         HRESULT aphres=S_OK;\r
293         HRESULT vphres=S_OK;\r
294         \r
295         if (audiopin->IsConnected()){\r
296                 aphres=audiopin->Inactive();\r
297         }\r
298         if (videopin->IsConnected()){\r
299                 vphres=videopin->Inactive();\r
300         }\r
301                 \r
302         mystate=State_Stopped;\r
303         LeaveCriticalSection(&filterlock);\r
304         if (aphres!=S_OK) return aphres;\r
305         if (vphres!=S_OK) return vphres;\r
306         return S_OK;\r
307 }\r
308 \r
309 HRESULT STDMETHODCALLTYPE DsSourceFilter::Pause(){\r
310         EnterCriticalSection(&filterlock);\r
311         HRESULT aphres;\r
312         HRESULT vphres;\r
313         \r
314         if (audiopin->IsConnected()){\r
315                 aphres=audiopin->Active();\r
316                 if (aphres!=S_OK) {\r
317                         LeaveCriticalSection(&filterlock);\r
318                         return aphres;\r
319                 }\r
320         }\r
321         if (videopin->IsConnected()){\r
322                 vphres=videopin->Active();\r
323                 if (vphres!=S_OK) {\r
324                         LeaveCriticalSection(&filterlock);\r
325                         return vphres;\r
326                 }\r
327         }\r
328                 \r
329         mystate=State_Paused;\r
330         LeaveCriticalSection(&filterlock);\r
331         \r
332 \r
333         return S_OK;\r
334 }\r
335 HRESULT STDMETHODCALLTYPE DsSourceFilter::Run(REFERENCE_TIME start){\r
336         \r
337         HRESULT aphres;\r
338         HRESULT vphres;\r
339         EnterCriticalSection(&filterlock);\r
340 \r
341         if (mystate==State_Stopped) {\r
342                 HRESULT phres=Pause();\r
343                 if (phres!=S_OK){\r
344                         LeaveCriticalSection(&filterlock);\r
345                         return phres;\r
346                 }\r
347         }\r
348         \r
349         laststart=start;\r
350         \r
351 \r
352         if (audiopin->IsConnected()){\r
353                 aphres=audiopin->Run(start);\r
354                 if (aphres!=S_OK) {\r
355                         LeaveCriticalSection(&filterlock);\r
356                         return aphres;\r
357                 }\r
358         }\r
359         \r
360         if (videopin->IsConnected()){\r
361                 vphres=videopin->Run(start);\r
362                 if (vphres!=S_OK) {\r
363                         LeaveCriticalSection(&filterlock);\r
364                         return vphres;\r
365                 }\r
366         }\r
367                 \r
368         mystate=State_Running;\r
369         LeaveCriticalSection(&filterlock);\r
370         \r
371 \r
372         return S_OK;\r
373 }\r
374 \r
375 \r
376 \r
377 int DsSourceFilter::GetPinCount()\r
378 {\r
379         return 2; //audio and video\r
380 }\r
381 \r
382 \r
383 \r
384 int DsSourceFilter::getCurrentAudioMediaSample(IMediaSample** ms)\r
385 {\r
386         if (!audiopin  || !IsActive()) {\r
387                 return 0;\r
388         }\r
389         if (audiopin->getCurrentMediaSample(ms)!=S_OK) {\r
390                 return 0;\r
391         }\r
392         return 1;\r
393 }\r
394 \r
395 int DsSourceFilter::getCurrentVideoMediaSample(IMediaSample** ms)\r
396 {\r
397         if (!videopin || !IsActive()) {\r
398                 return 0;\r
399         }\r
400         if (videopin->getCurrentMediaSample(ms)!=S_OK) {\r
401                 return 0;\r
402         }\r
403         return 1;\r
404 }\r
405 \r
406 int DsSourceFilter::DeliverAudioMediaSample(IMediaSample* ms)\r
407 {\r
408         if (!audiopin || !IsActive()) {\r
409                 ms->Release();\r
410                 return 0;\r
411         }\r
412         if (audiopin->deliver(ms)!=S_OK) {\r
413                 ms->Release();\r
414                 return 0;\r
415         }\r
416         ms->Release();\r
417         return 1;\r
418 \r
419 }\r
420 \r
421 int DsSourceFilter::DeliverVideoMediaSample(IMediaSample* ms)\r
422 {\r
423         if (!videopin || !IsActive()) {\r
424                 ms->Release();\r
425                 return 0;\r
426         }\r
427         if (videopin->deliver(ms)!=S_OK) {\r
428                 ms->Release();\r
429                 return 0;\r
430         }\r
431         ms->Release();\r
432         return 1;\r
433 \r
434 }\r
435 \r
436 \r