]> git.vomp.tv Git - vompclient.git/blob - dssourcefilter.cc
Ac3 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);
30   virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin);
31   virtual HRESULT STDMETHODCALLTYPE Reset();
32   virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPins **enuma);
33   virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object);
34   virtual ULONG STDMETHODCALLTYPE AddRef();
35     virtual ULONG STDMETHODCALLTYPE Release();
36 protected:
37   DsSourcePin* audiopin;
38   DsSourcePin* videopin;
39   DsSourceFilter *filter;
40   ULONG curpos;
41   volatile long refs;
42 };
43
44 DsSFEnumPins::DsSFEnumPins(DsSourcePin* audio,DsSourcePin* video,DsSourceFilter *filt,ULONG pos){
45   audiopin=audio;
46   videopin=video;
47   curpos=pos;
48   filter=filt;
49   filt->AddRef();
50   refs=0;
51
52 }
53
54 DsSFEnumPins::~DsSFEnumPins(){
55   filter->Release();
56
57 }
58
59 HRESULT STDMETHODCALLTYPE DsSFEnumPins::Next(ULONG numpin,IPin **pins,ULONG *fetched) {
60   int i;
61   if (fetched==NULL) return E_POINTER;
62   if (pins==NULL) return E_POINTER;
63   *fetched=0;
64
65   for (i=0;(i<numpin)&& (curpos<2);i++) {
66     switch (curpos) {
67     case 0: audiopin->AddRef();  pins[i]=(IPin*)audiopin;break;
68     case 1: videopin->AddRef(); pins[i]=(IPin*)videopin;break;
69     };
70     (*fetched)++;
71     curpos++;
72   }
73   if ((*fetched)!=numpin) return S_FALSE;
74   return S_OK;
75 }
76
77 HRESULT STDMETHODCALLTYPE DsSFEnumPins::Skip(ULONG numpin){
78   curpos+=numpin;
79   if (curpos>2) return S_FALSE;
80   return S_OK;
81 }
82 HRESULT STDMETHODCALLTYPE DsSFEnumPins::Reset(){
83   curpos=0;
84   return S_OK;
85 }
86 HRESULT STDMETHODCALLTYPE DsSFEnumPins::Clone(IEnumPins **enuma){
87   if (enuma==NULL) return E_POINTER;
88   *enuma=new DsSFEnumPins(audiopin,videopin,filter,curpos);
89   (*enuma)->AddRef();
90   return S_OK;
91 }
92
93 HRESULT STDMETHODCALLTYPE  DsSFEnumPins::QueryInterface(REFIID id,void ** object){
94   if (object==NULL) return E_POINTER;
95
96   if (id==IID_IUnknown ||id == IID_IEnumPins) {
97     *object=(IUnknown*)this;
98     ((IUnknown*)object)->AddRef();
99     return NOERROR;
100   } else {
101     *object=NULL;
102     return E_NOINTERFACE;
103   }
104 }
105
106
107
108 ULONG STDMETHODCALLTYPE DsSFEnumPins::AddRef(){
109   InterlockedIncrement(&refs);
110   long tempref=refs;
111   if (tempref>1) return tempref;
112   else return 1;
113 }
114
115 ULONG STDMETHODCALLTYPE DsSFEnumPins::Release(){
116   long tempref=InterlockedDecrement(&refs);
117
118   if (tempref==0) {
119     refs++;
120     delete this;
121     return NULL;
122   } else {
123     if (tempref>1) return tempref;
124     else return 1;
125   }
126 }
127
128
129
130
131
132
133
134 DsSourceFilter::DsSourceFilter()
135 {
136   //add audio pin
137   HRESULT res;
138   audiopin=new DsSourcePin(this,&res,L"Vomp Audio Out",true);
139   videopin=new DsSourcePin(this,&res,L"Vomp Video Out",false);
140   filtergraph=NULL;
141   clock=NULL;
142   mystate=State_Stopped;
143   laststart=0;
144   refs=0;
145   InitializeCriticalSection(&filterlock);
146
147 }
148
149 DsSourceFilter::~DsSourceFilter()
150 {
151   if (audiopin) delete audiopin;
152   if (videopin) delete videopin;
153   if (clock) {
154     clock->Release();
155     clock=NULL;
156   }
157   DeleteCriticalSection(&filterlock);
158
159 }
160
161 HRESULT STDMETHODCALLTYPE  DsSourceFilter::GetClassID(CLSID *clsid){
162   if (clsid==NULL) return E_POINTER;
163   *clsid=_uuidof(this);
164   return S_OK;
165 }
166
167 HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryInterface(REFIID id,void ** object){
168   if (object==NULL) return E_POINTER;
169   if (id==IID_IUnknown) {
170     *object=(IUnknown*)this;
171     AddRef();
172     return NOERROR;
173   } else if (id==IID_IBaseFilter) {
174     *object=(IBaseFilter*)this;
175     AddRef();
176     return NOERROR;
177   } else if (id==IID_IMediaFilter) {
178     *object=(IMediaFilter*)this;
179     AddRef();
180     return NOERROR;
181   }else {
182     *object=NULL;
183     return E_NOINTERFACE;
184   }
185 }
186
187 ULONG STDMETHODCALLTYPE DsSourceFilter::AddRef(){
188   InterlockedIncrement(&refs);
189   long tempref=refs;
190   if (tempref>1) return tempref;
191   else return 1;
192 }
193 ULONG STDMETHODCALLTYPE DsSourceFilter::Release(){
194   long tempref=InterlockedDecrement(&refs);
195
196   if (tempref==0) {
197     refs++;
198     delete this;
199     return NULL;
200   } else {
201     if (tempref>1) return tempref;
202     else return 1;
203   }
204 }
205
206 /*IBaseFilter*/
207 HRESULT STDMETHODCALLTYPE DsSourceFilter::EnumPins(IEnumPins **enumar){
208   if (enumar==NULL) return E_POINTER;
209   *enumar=new DsSFEnumPins(audiopin,videopin, this);
210   (*enumar)->AddRef();
211   return S_OK;
212 }
213
214 HRESULT STDMETHODCALLTYPE DsSourceFilter::FindPin(LPCWSTR iden,IPin **pin){
215   if (pin==NULL) return E_POINTER;
216   EnterCriticalSection(&filterlock);
217
218   if (wcscmp(AUDIOPIN_NAME,iden)==NULL) {
219     *pin=(IPin*)audiopin;
220     (*pin)->AddRef();
221     LeaveCriticalSection(&filterlock);
222     return S_OK;
223   }
224   if (wcscmp(VIDEOPIN_NAME,iden)==NULL) {
225     *pin=(IPin*)videopin;
226     (*pin)->AddRef();
227     LeaveCriticalSection(&filterlock);
228     return S_OK;
229   }
230
231   *pin=NULL;
232   LeaveCriticalSection(&filterlock);
233     return VFW_E_NOT_FOUND;
234 }
235 HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryFilterInfo(FILTER_INFO *info){
236   if (info==NULL) return E_POINTER;
237   wcsncpy(info->achName,L"VompWinFilter", sizeof(info->achName)/sizeof(WCHAR));
238   info->pGraph=filtergraph;
239   if (info->pGraph!=NULL) info->pGraph->AddRef();
240   return NOERROR;
241 }
242
243 HRESULT STDMETHODCALLTYPE DsSourceFilter::JoinFilterGraph(IFilterGraph *graph,LPCWSTR name){
244   //Should we lock
245   EnterCriticalSection(&filterlock);
246   filtergraph=graph;
247   //filtergraph->AddRef();
248   //We ignore the name
249   LeaveCriticalSection(&filterlock);
250
251   return S_OK;
252 }
253 HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryVendorInfo(LPWSTR *vendinf) {
254   return E_NOTIMPL;
255 }
256
257
258 /*IMediaFilter*/
259 HRESULT STDMETHODCALLTYPE DsSourceFilter::GetState(DWORD timeout,FILTER_STATE *state){
260   if (state==NULL) return E_POINTER;
261   EnterCriticalSection(&filterlock);
262   *state=mystate;
263   LeaveCriticalSection(&filterlock);
264   return S_OK;
265 }
266
267 HRESULT STDMETHODCALLTYPE DsSourceFilter::SetSyncSource(IReferenceClock *uhr){
268   EnterCriticalSection(&filterlock);
269   if (clock!=NULL) {
270     clock->Release();
271   }
272   if (uhr!=NULL) {
273     uhr->AddRef();
274   }
275   clock=uhr;
276   LeaveCriticalSection(&filterlock);
277
278   return S_OK;
279 }
280 HRESULT STDMETHODCALLTYPE DsSourceFilter::GetSyncSource(IReferenceClock **uhr){
281   if (uhr==NULL) return E_POINTER;
282   EnterCriticalSection(&filterlock);
283   if (clock!=NULL) clock->AddRef();
284   *uhr=clock;
285   LeaveCriticalSection(&filterlock);
286
287   return S_OK;
288 }
289
290 HRESULT STDMETHODCALLTYPE DsSourceFilter::Stop(){
291   EnterCriticalSection(&filterlock);
292   HRESULT aphres=S_OK;
293   HRESULT vphres=S_OK;
294
295   if (audiopin->IsConnected()){
296     aphres=audiopin->Inactive();
297   }
298   if (videopin->IsConnected()){
299     vphres=videopin->Inactive();
300   }
301
302   mystate=State_Stopped;
303   LeaveCriticalSection(&filterlock);
304   if (aphres!=S_OK) return aphres;
305   if (vphres!=S_OK) return vphres;
306   return S_OK;
307 }
308
309 HRESULT STDMETHODCALLTYPE DsSourceFilter::Pause(){
310   EnterCriticalSection(&filterlock);
311   HRESULT aphres;
312   HRESULT vphres;
313
314   if (audiopin->IsConnected()){
315     aphres=audiopin->Active();
316     if (aphres!=S_OK) {
317       LeaveCriticalSection(&filterlock);
318       return aphres;
319     }
320   }
321   if (videopin->IsConnected()){
322     vphres=videopin->Active();
323     if (vphres!=S_OK) {
324       LeaveCriticalSection(&filterlock);
325       return vphres;
326     }
327   }
328
329   mystate=State_Paused;
330   LeaveCriticalSection(&filterlock);
331
332
333   return S_OK;
334 }
335 HRESULT STDMETHODCALLTYPE DsSourceFilter::Run(REFERENCE_TIME start){
336
337   HRESULT aphres;
338   HRESULT vphres;
339   EnterCriticalSection(&filterlock);
340
341   if (mystate==State_Stopped) {
342     HRESULT phres=Pause();
343     if (phres!=S_OK){
344       LeaveCriticalSection(&filterlock);
345       return phres;
346     }
347   }
348
349   laststart=start;
350
351
352   if (audiopin->IsConnected()){
353     aphres=audiopin->Run(start);
354     if (aphres!=S_OK) {
355       LeaveCriticalSection(&filterlock);
356       return aphres;
357     }
358   }
359
360   if (videopin->IsConnected()){
361     vphres=videopin->Run(start);
362     if (vphres!=S_OK) {
363       LeaveCriticalSection(&filterlock);
364       return vphres;
365     }
366   }
367
368   mystate=State_Running;
369   LeaveCriticalSection(&filterlock);
370
371
372   return S_OK;
373 }
374
375
376
377 int DsSourceFilter::GetPinCount()
378 {
379   return 2; //audio and video
380 }
381
382
383
384 int DsSourceFilter::getCurrentAudioMediaSample(IMediaSample** ms)
385 {
386   if (!audiopin  || !IsActive()) {
387     return 0;
388   }
389   if (audiopin->getCurrentMediaSample(ms)!=S_OK) {
390     return 0;
391   }
392   return 1;
393 }
394
395 int DsSourceFilter::getCurrentVideoMediaSample(IMediaSample** ms)
396 {
397   if (!videopin || !IsActive()) {
398     return 0;
399   }
400   if (videopin->getCurrentMediaSample(ms)!=S_OK) {
401     return 0;
402   }
403   return 1;
404 }
405
406 int DsSourceFilter::DeliverAudioMediaSample(IMediaSample* ms)
407 {
408   if (!audiopin || !IsActive()) {
409     ms->Release();
410     return 0;
411   }
412   if (audiopin->deliver(ms)!=S_OK) {
413     ms->Release();
414     return 0;
415   }
416   ms->Release();
417   return 1;
418
419 }
420
421 bool DsSourceFilter::supportsAc3()
422 {
423     if (!audiopin || !IsActive()) {
424         return false;
425     }
426     return audiopin->supportsAc3();
427 }
428
429 int DsSourceFilter::DeliverVideoMediaSample(IMediaSample* ms)
430 {
431   if (!videopin || !IsActive()) {
432     ms->Release();
433     return 0;
434   }
435   if (videopin->deliver(ms)!=S_OK) {
436     ms->Release();
437     return 0;
438   }
439   ms->Release();
440   return 1;
441
442 }
443
444 bool DsSourceFilter::changeAType(int type,IMediaSample* ms)
445 {
446     if (!audiopin ) {
447         return false;
448     }
449     audiopin->SetPinMode(type);
450     audiopin->SetMsToMt(ms);
451
452
453     return true;
454 }