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