]> git.vomp.tv Git - vompclient-marten.git/blob - dssourcefilter.cc
Fix bug in demuxer widescreen signaling
[vompclient-marten.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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         if (id==IID_IUnknown ||id == IID_IEnumPins) {
96                 *object=(IUnknown*)this;
97                 ((IUnknown*)object)->AddRef();
98                 return NOERROR;
99         } else {
100                 *object=NULL;
101                 return E_NOINTERFACE;
102         }
103 }
104
105
106
107 ULONG STDMETHODCALLTYPE DsSFEnumPins::AddRef(){
108         InterlockedIncrement(&refs);
109         long tempref=refs;
110         if (tempref>1) return tempref;
111         else return 1;
112 }
113
114 ULONG STDMETHODCALLTYPE DsSFEnumPins::Release(){
115         long tempref=InterlockedDecrement(&refs);
116         
117         if (tempref==0) {
118                 refs++;
119                 delete this;
120                 return NULL;
121         } else {
122                 if (tempref>1) return tempref;
123                 else return 1;
124         }
125 }
126
127
128
129
130
131
132
133 DsSourceFilter::DsSourceFilter()
134 {
135         //add audio pin
136         HRESULT res;
137         audiopin=new DsSourcePin(this,&res,L"Vomp Audio Out",true);
138         videopin=new DsSourcePin(this,&res,L"Vomp Video Out",false);
139         filtergraph=NULL;
140         clock=NULL;
141         mystate=State_Stopped;
142         laststart=0;
143         refs=0;
144         InitializeCriticalSection(&filterlock);
145         
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
170         if (id==IID_IUnknown) {
171                 *object=(IUnknown*)this;
172                 AddRef();
173                 return NOERROR;
174         } else if (id==IID_IBaseFilter) {
175                 *object=(IBaseFilter*)this;
176                 AddRef();
177                 return NOERROR;
178         } else if (id==IID_IMediaFilter) {
179                 *object=(IMediaFilter*)this;
180                 AddRef();
181                 return NOERROR;
182         }else {
183                 *object=NULL;
184                 return E_NOINTERFACE;
185         }
186 }
187
188 ULONG STDMETHODCALLTYPE DsSourceFilter::AddRef(){
189         InterlockedIncrement(&refs);
190         long tempref=refs;
191         if (tempref>1) return tempref;
192         else return 1;
193 }
194 ULONG STDMETHODCALLTYPE DsSourceFilter::Release(){
195         long tempref=InterlockedDecrement(&refs);
196         
197         if (tempref==0) {
198                 refs++;
199                 delete this;
200                 return NULL;
201         } else {
202                 if (tempref>1) return tempref;
203                 else return 1;
204         }
205 }
206
207 /*IBaseFilter*/
208 HRESULT STDMETHODCALLTYPE DsSourceFilter::EnumPins(IEnumPins **enumar){
209         if (enumar==NULL) return E_POINTER;
210         *enumar=new DsSFEnumPins(audiopin,videopin, this);
211         (*enumar)->AddRef();
212         return S_OK;
213 }
214
215 HRESULT STDMETHODCALLTYPE DsSourceFilter::FindPin(LPCWSTR iden,IPin **pin){
216         if (pin==NULL) return E_POINTER;
217         EnterCriticalSection(&filterlock);
218
219         if (wcscmp(AUDIOPIN_NAME,iden)==NULL) {
220                 *pin=(IPin*)audiopin;
221                 (*pin)->AddRef();
222                 LeaveCriticalSection(&filterlock);
223                 return S_OK;
224         }
225         if (wcscmp(VIDEOPIN_NAME,iden)==NULL) {
226                 *pin=(IPin*)videopin;
227                 (*pin)->AddRef();
228                 LeaveCriticalSection(&filterlock);
229                 return S_OK;
230         }
231
232         *pin=NULL;
233         LeaveCriticalSection(&filterlock);
234     return VFW_E_NOT_FOUND;
235 }
236 HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryFilterInfo(FILTER_INFO *info){
237         if (info==NULL) return E_POINTER;
238         wcsncpy(info->achName,L"VompWinFilter", sizeof(info->achName)/sizeof(WCHAR));
239         info->pGraph=filtergraph;
240         if (info->pGraph!=NULL) info->pGraph->AddRef();
241         return NOERROR;
242 }
243
244 HRESULT STDMETHODCALLTYPE DsSourceFilter::JoinFilterGraph(IFilterGraph *graph,LPCWSTR name){
245         //Should we lock
246         EnterCriticalSection(&filterlock);
247         filtergraph=graph;
248         //filtergraph->AddRef();
249         //We ignore the name
250         LeaveCriticalSection(&filterlock);
251         
252         return S_OK;
253 }
254 HRESULT STDMETHODCALLTYPE DsSourceFilter::QueryVendorInfo(LPWSTR *vendinf) {
255         return E_NOTIMPL;
256 }
257
258
259 /*IMediaFilter*/
260 HRESULT STDMETHODCALLTYPE DsSourceFilter::GetState(DWORD timeout,FILTER_STATE *state){
261         if (state==NULL) return E_POINTER;
262         EnterCriticalSection(&filterlock);
263         *state=mystate;
264         LeaveCriticalSection(&filterlock);
265         return S_OK;
266 }
267
268 HRESULT STDMETHODCALLTYPE DsSourceFilter::SetSyncSource(IReferenceClock *uhr){
269         EnterCriticalSection(&filterlock);
270         if (clock!=NULL) {
271                 clock->Release();
272         }
273         if (uhr!=NULL) {
274                 uhr->AddRef();
275         }
276         clock=uhr;
277         LeaveCriticalSection(&filterlock);
278         
279         return S_OK;
280 }
281 HRESULT STDMETHODCALLTYPE DsSourceFilter::GetSyncSource(IReferenceClock **uhr){
282         if (uhr==NULL) return E_POINTER;
283         EnterCriticalSection(&filterlock);
284         if (clock!=NULL) clock->AddRef();
285         *uhr=clock;
286         LeaveCriticalSection(&filterlock);
287         
288         return S_OK;
289 }
290
291 HRESULT STDMETHODCALLTYPE DsSourceFilter::Stop(){
292         EnterCriticalSection(&filterlock);
293         HRESULT aphres=S_OK;
294         HRESULT vphres=S_OK;
295         
296         if (audiopin->IsConnected()){
297                 aphres=audiopin->Inactive();
298         }
299         if (videopin->IsConnected()){
300                 vphres=videopin->Inactive();
301         }
302                 
303         mystate=State_Stopped;
304         LeaveCriticalSection(&filterlock);
305         if (aphres!=S_OK) return aphres;
306         if (vphres!=S_OK) return vphres;
307         return S_OK;
308 }
309
310 HRESULT STDMETHODCALLTYPE DsSourceFilter::Pause(){
311         EnterCriticalSection(&filterlock);
312         HRESULT aphres;
313         HRESULT vphres;
314         
315         if (audiopin->IsConnected()){
316                 aphres=audiopin->Active();
317                 if (aphres!=S_OK) {
318                         LeaveCriticalSection(&filterlock);
319                         return aphres;
320                 }
321         }
322         if (videopin->IsConnected()){
323                 vphres=videopin->Active();
324                 if (vphres!=S_OK) {
325                         LeaveCriticalSection(&filterlock);
326                         return vphres;
327                 }
328         }
329                 
330         mystate=State_Paused;
331         LeaveCriticalSection(&filterlock);
332         
333
334         return S_OK;
335 }
336 HRESULT STDMETHODCALLTYPE DsSourceFilter::Run(REFERENCE_TIME start){
337         
338         HRESULT aphres;
339         HRESULT vphres;
340         EnterCriticalSection(&filterlock);
341
342         if (mystate==State_Stopped) {
343                 HRESULT phres=Pause();
344                 if (phres!=S_OK){
345                         LeaveCriticalSection(&filterlock);
346                         return phres;
347                 }
348         }
349         
350         laststart=start;
351         
352
353         if (audiopin->IsConnected()){
354                 aphres=audiopin->Run(start);
355                 if (aphres!=S_OK) {
356                         LeaveCriticalSection(&filterlock);
357                         return aphres;
358                 }
359         }
360         
361         if (videopin->IsConnected()){
362                 vphres=videopin->Run(start);
363                 if (vphres!=S_OK) {
364                         LeaveCriticalSection(&filterlock);
365                         return vphres;
366                 }
367         }
368                 
369         mystate=State_Running;
370         LeaveCriticalSection(&filterlock);
371         
372
373         return S_OK;
374 }
375
376
377
378 int DsSourceFilter::GetPinCount()
379 {
380         return 2; //audio and video
381 }
382
383
384
385 int DsSourceFilter::getCurrentAudioMediaSample(IMediaSample** ms)
386 {
387         if (!audiopin  || !IsActive()) {
388                 return 0;
389         }
390         if (audiopin->getCurrentMediaSample(ms)!=S_OK) {
391                 return 0;
392         }
393         return 1;
394 }
395
396 int DsSourceFilter::getCurrentVideoMediaSample(IMediaSample** ms)
397 {
398         if (!videopin || !IsActive()) {
399                 return 0;
400         }
401         if (videopin->getCurrentMediaSample(ms)!=S_OK) {
402                 return 0;
403         }
404         return 1;
405 }
406
407 int DsSourceFilter::DeliverAudioMediaSample(IMediaSample* ms)
408 {
409         if (!audiopin || !IsActive()) {
410                 ms->Release();
411                 return 0;
412         }
413         if (audiopin->deliver(ms)!=S_OK) {
414                 ms->Release();
415                 return 0;
416         }
417         ms->Release();
418         return 1;
419
420 }
421
422 bool DsSourceFilter::supportsAc3()
423 {
424     if (!audiopin || !IsActive()) {
425         return false;
426     }
427     return audiopin->supportsAc3();
428 }
429
430 int DsSourceFilter::DeliverVideoMediaSample(IMediaSample* ms)
431 {
432         if (!videopin || !IsActive()) {
433                 ms->Release();
434                 return 0;
435         }
436         if (videopin->deliver(ms)!=S_OK) {
437                 ms->Release();
438                 return 0;
439         }
440         ms->Release();
441         return 1;
442
443 }
444
445 bool DsSourceFilter::changeAType(int type,IMediaSample* ms)
446 {
447     if (!audiopin ) {
448         return false;
449     }
450     audiopin->SetPinMode(type);
451     audiopin->SetMsToMt(ms);
452     
453
454     return true;
455 }
456
457 bool DsSourceFilter::changeVType(int type,IMediaSample* ms,void * details)
458 {
459     if (!videopin ) {
460         return false;
461     }
462     videopin->SetPinMode(type,details);
463     videopin->SetMsToMt(ms);
464     
465
466     return true;
467 }
468
469