]> git.vomp.tv Git - vompclient.git/blob - dssourcepin.cc
Fix for possible crash when removing bar
[vompclient.git] / dssourcepin.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
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 "dssourcepin.h"
21 #include "dssourcefilter.h"
22 #include <Dvdmedia.h>
23 #include <mmreg.h>
24 #include "draintarget.h"
25
26 class DsSFEnumMediaTypes: public IEnumMediaTypes {
27 public:
28   DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos=0);
29   virtual ~DsSFEnumMediaTypes();
30   virtual HRESULT STDMETHODCALLTYPE Next(ULONG nummedia,  AM_MEDIA_TYPE **pins,ULONG *fetched);
31   virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin);
32   virtual HRESULT STDMETHODCALLTYPE Reset();
33   virtual HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **enuma);
34   virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object);
35   virtual ULONG STDMETHODCALLTYPE AddRef();
36     virtual ULONG STDMETHODCALLTYPE Release();
37 protected:
38   DsSourcePin* parent;
39   ULONG curpos;
40   volatile long refs;
41 };
42
43 DsSFEnumMediaTypes::DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos){
44   parent=papa;
45   curpos=pos;
46   parent->AddRef();
47   refs=0;
48 }
49
50 DsSFEnumMediaTypes::~DsSFEnumMediaTypes(){
51   parent->Release();
52 }
53
54 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Next(ULONG numpin, AM_MEDIA_TYPE **pins,ULONG *fetched) {
55   int i;
56
57   if (pins==NULL) return E_POINTER;
58   if (numpin!=1 && fetched==NULL) return E_INVALIDARG;
59   *fetched=0;
60
61   for (i=0;(i<numpin);i++) {
62     pins[i]=(AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
63         if (parent->GetMediaType(curpos+i,pins[i])!=S_OK) {
64                 CoTaskMemFree(pins[i]);
65                 pins[i]=NULL;
66                 return S_FALSE;
67         }    curpos++;
68     if (fetched!=NULL)  (*fetched)++;
69   }
70   return S_OK;
71 }
72
73 HRESULT STDMETHODCALLTYPE   DsSFEnumMediaTypes::Skip(ULONG numpin){
74   curpos+=numpin;
75   if (curpos>1) return S_FALSE;
76   return S_OK;
77 }
78 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Reset(){
79   curpos=0;
80   return S_OK;
81 }
82 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Clone(IEnumMediaTypes **enuma){
83   if (enuma==NULL) return E_POINTER;
84   *enuma=new DsSFEnumMediaTypes(parent,curpos);
85   (*enuma)->AddRef();
86   return S_OK;
87 }
88
89 HRESULT STDMETHODCALLTYPE  DsSFEnumMediaTypes::QueryInterface(REFIID id,void ** object){
90   if (object==NULL) return E_POINTER;
91   if (id==IID_IUnknown ||id == IID_IEnumMediaTypes) {
92     *object=(IUnknown*)this;
93     ((IUnknown*)object)->AddRef();
94     return NOERROR;
95   } else {
96     *object=NULL;
97     return E_NOINTERFACE;
98   }
99 }
100
101
102
103 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::AddRef(){
104   InterlockedIncrement(&refs);
105   long tempref=refs;
106   if (tempref>1) return tempref;
107   else return 1;
108 }
109
110 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::Release(){
111   long tempref=InterlockedDecrement(&refs);
112
113   if (tempref==0) {
114     refs++;
115     delete this;
116     return NULL;
117   } else {
118     if (tempref>1) return tempref;
119     else return 1;
120   }
121 }
122
123
124 void CopyMType(AM_MEDIA_TYPE* dest,const AM_MEDIA_TYPE*source) {
125   memcpy(dest,source,sizeof(AM_MEDIA_TYPE));
126   if (source->pbFormat!=NULL) {
127     dest->pbFormat=(BYTE*)CoTaskMemAlloc(dest->cbFormat);
128     memcpy(dest->pbFormat,source->pbFormat,dest->cbFormat);
129   }
130 }
131 void ReleaseMType(AM_MEDIA_TYPE* free) {
132   if (free->cbFormat!=NULL) CoTaskMemFree(free->pbFormat);
133   free->pbFormat=NULL;
134 }
135
136 DsSourcePin::DsSourcePin(DsSourceFilter *pFilter,
137              HRESULT *phr,LPCWSTR pName,bool audio)
138 {
139   isaudiopin=audio;
140   m_pFilter=pFilter;
141   connected=NULL;
142   connectedinput=NULL;
143   allocator=NULL;
144   if (isaudiopin)
145   {
146       pinmode=MPTYPE_MPEG_AUDIO;
147       //pinmode=MPTYPE_AC3;
148   }
149   else
150   {
151       pinmode=MPTYPE_VIDEO;
152   }
153
154 }
155
156 DsSourcePin::~DsSourcePin()
157 {
158
159
160
161 }
162
163 HRESULT STDMETHODCALLTYPE DsSourcePin::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_IPin) {
170     *object=(IPin*)this;
171     ((IPin*)object)->AddRef();
172     return NOERROR;
173   } else {
174     *object=NULL;
175     return E_NOINTERFACE;
176   }
177 }
178
179 ULONG STDMETHODCALLTYPE DsSourcePin::AddRef(){
180   return m_pFilter->AddRef();
181
182 }
183 ULONG STDMETHODCALLTYPE DsSourcePin::Release(){
184   return m_pFilter->Release();
185 }
186
187
188 /*IPin*/
189 HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype) {
190   if (pinempf==NULL) return E_POINTER;
191   EnterCriticalSection(&m_pFilter->filterlock);
192
193   if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;}
194   if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
195
196   bool gotmt=false;
197
198   if (mtype!=NULL) {
199     if (CheckMediaType(mtype)==S_OK){
200       pinempf->AddRef();
201       if (pinempf->ReceiveConnection((IPin*)this,mtype)==S_OK) {
202         CopyMType(&medtype,mtype);
203         LeaveCriticalSection(&m_pFilter->filterlock);
204       } else {
205         LeaveCriticalSection(&m_pFilter->filterlock);
206   if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat);
207         pinempf->Release();
208         return VFW_E_TYPE_NOT_ACCEPTED;
209       }
210
211     } else {
212       LeaveCriticalSection(&m_pFilter->filterlock);
213  if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat);
214       return VFW_E_TYPE_NOT_ACCEPTED;
215     }
216     CoTaskMemFree(mtype->pbFormat);
217   }else {
218     IEnumMediaTypes * emt;
219     EnumMediaTypes(&emt);
220     AM_MEDIA_TYPE  * emtype;
221     ULONG fetched=0;
222     pinempf->AddRef();
223         
224
225     while (emt->Next(1,&emtype,&fetched)==S_OK) {
226       if (CheckMediaType(emtype)==S_OK){
227         /*      PIN_INFO pini;
228                 pinempf->QueryPinInfo(&pini);
229                 if (pini.pFilter!=NULL) {
230                         FILTER_INFO filti;
231                         pini.pFilter->QueryFilterInfo(&filti);
232
233                         if (filti.pGraph!=NULL) filti.pGraph->Release();
234                         char buffer[MAX_FILTER_NAME*2];
235                         wcstombs(buffer,filti.achName,MAX_FILTER_NAME*2);
236                         MessageBox(0,buffer,"Filter",0);
237                         pini.pFilter->Release();
238                 }*/
239
240         if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
241           connected=pinempf;
242           CopyMType(&medtype,emtype);
243                   if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
244                  
245                   CoTaskMemFree(emtype);
246           gotmt=true;
247           break;
248         }
249
250       }
251  if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
252           CoTaskMemFree(emtype);
253     }
254     emt->Release();
255     if (gotmt==false) {
256       pinempf->EnumMediaTypes(&emt);
257       while (emt->Next(1,&emtype,&fetched)==S_OK) {
258         if (CheckMediaType(emtype)==S_OK){
259           if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
260             connected=pinempf;
261             CopyMType(&medtype,emtype);
262             if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
263                                                 CoTaskMemFree(emtype);
264             gotmt=true;
265             break;
266           }
267
268         }
269         if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
270                 CoTaskMemFree(emtype);
271       }
272       emt->Release();
273       if (gotmt==false) {
274         pinempf->Release();
275         LeaveCriticalSection(&m_pFilter->filterlock);
276         return VFW_E_NO_ACCEPTABLE_TYPES;
277       }
278     }
279   }
280
281   if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) {
282     LeaveCriticalSection(&m_pFilter->filterlock);
283     connected->Release();
284     connected=NULL;
285   /*  connectedinput->Release();
286     connectedinput=NULL;*/
287     return VFW_E_NO_TRANSPORT;
288   }
289   ALLOCATOR_PROPERTIES eigenall;
290   ZeroMemory(&eigenall,sizeof(eigenall));
291   connectedinput->GetAllocatorRequirements(&eigenall);
292   if (eigenall.cbAlign==0) eigenall.cbAlign=1;
293   connectedinput->GetAllocator(&allocator);
294   if (DecideBufferSize(allocator,&eigenall)==S_OK) {
295     if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
296       connected=pinempf;
297       LeaveCriticalSection(&m_pFilter->filterlock);
298       return S_OK;
299     }
300   }
301   if (allocator!=NULL) allocator->Release();
302   allocator=NULL;
303
304   if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER,
305     IID_IMemAllocator,(void **)allocator)==S_OK) {
306       if (DecideBufferSize(allocator,&eigenall)==S_OK) {
307         if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
308           connected=pinempf;
309           LeaveCriticalSection(&m_pFilter->filterlock);
310         return S_OK;
311       }
312     }
313   }
314   if (allocator!=NULL) allocator->Release();
315   allocator=NULL;
316   connected->Release();
317   connected=NULL;
318   connectedinput->Release();
319   connectedinput=NULL;
320   LeaveCriticalSection(&m_pFilter->filterlock);
321   return VFW_E_NO_TRANSPORT;
322
323
324
325
326 }
327 HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect,
328                              const AM_MEDIA_TYPE *mtype){
329      return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins
330 }
331  HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() {
332    EnterCriticalSection(&m_pFilter->filterlock);
333    if (connected!=NULL) {
334      if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
335      /*TODO: Decommit allocator*/
336      allocator->Decommit();
337      allocator->Release();
338      allocator=NULL;
339      ReleaseMType(&medtype);
340      connectedinput->Release();
341      connectedinput=NULL;
342      connected->Release();
343      connected=NULL;
344      LeaveCriticalSection(&m_pFilter->filterlock);
345      return S_OK;
346    }
347    LeaveCriticalSection(&m_pFilter->filterlock);
348    return S_FALSE;
349  }
350
351  HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){
352    if (pin==NULL) return E_POINTER;
353    IPin* pinn=connected;
354    *pin=pinn;
355    if (pinn!=NULL) {
356      pinn->AddRef();
357      return S_OK;
358    } else {
359      return VFW_E_NOT_CONNECTED;
360    }
361  }
362  HRESULT STDMETHODCALLTYPE  DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){
363    if (mtype==NULL) return E_POINTER;
364    if (connected!=NULL){
365     CopyMType(mtype,&medtype);
366     return S_OK;
367    } else {
368      ZeroMemory(mtype,sizeof(*mtype));
369      return VFW_E_NOT_CONNECTED;
370    }
371  }
372  HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){
373    if (info==NULL) return E_POINTER;
374    info->dir=PINDIR_OUTPUT;
375    info->pFilter=(IBaseFilter*)m_pFilter;
376    if (m_pFilter) m_pFilter->AddRef();
377    if (isaudiopin) wcscpy(info->achName,L"Audio");
378    else wcscpy(info->achName,L"Video");
379    return S_OK;
380  }
381
382  HRESULT STDMETHODCALLTYPE  DsSourcePin::QueryDirection(PIN_DIRECTION *dir){
383    if (dir==NULL) return E_POINTER;
384    *dir=PINDIR_OUTPUT;
385    return S_OK;
386  }
387  HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){
388    if (id==NULL) return E_POINTER;
389    *id=(LPWSTR)CoTaskMemAlloc(12);
390    if (*id==NULL) return E_OUTOFMEMORY;
391
392
393    if (isaudiopin) wcscpy(*id,L"Audio");
394     else  wcscpy(*id, L"Video");
395     return S_OK;
396  }
397  HRESULT STDMETHODCALLTYPE  DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) {
398    if (mtype==NULL) return S_FALSE;
399    if (CheckMediaType(mtype)==S_OK) return S_OK;
400    else return S_FALSE;
401  }
402  HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){
403 if (enuma==NULL) return E_POINTER;
404   *enuma=new DsSFEnumMediaTypes( this);
405   (*enuma)->AddRef();
406   return S_OK;
407 }
408
409 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){
410   return E_NOTIMPL;
411 }
412 HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){
413   return E_UNEXPECTED; //we are a output pin!
414 }
415
416 HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){
417   return E_UNEXPECTED;//we are a output pin!
418 }
419
420 HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){
421   if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0);
422   else return E_NOINTERFACE;
423 }
424
425 HRESULT DsSourcePin::deliver(IMediaSample * ms){
426   //EnterCriticalSection(&m_pFilter->filterlock);
427   HRESULT hres;
428
429
430   if (connectedinput!=NULL)hres= connectedinput->Receive(ms);
431   else hres= VFW_E_NOT_CONNECTED;
432   //LeaveCriticalSection(&m_pFilter->filterlock);
433   return hres;
434
435 }
436
437 void DsSourcePin::SetMsToMt(IMediaSample *ms) {
438     ms->SetMediaType(&medtype);
439 }
440
441 bool DsSourcePin::supportsAc3() {
442     if (!isaudiopin)
443     {
444         return false; //Haha a video pin that supports ac3
445     }
446     if (!IsConnected())
447     {
448         return false; //Graph is not build, please wait
449     }
450     if (connected==NULL) 
451     {
452         return false; //Graph is not build, please wait
453     }
454     IPinConnection *pinconn=NULL; //according to docs, this is the prefered method
455     if (connected->QueryInterface(IID_IPinConnection,(void**)&pinconn)==S_OK) {
456         AM_MEDIA_TYPE test;
457         GetMediaType(10,&test);
458         if (pinconn->DynamicQueryAccept(&test)==S_OK)
459         {
460             pinconn->Release();
461             CoTaskMemFree(test.pbFormat);
462             return true;
463         } else {
464             pinconn->Release();
465             CoTaskMemFree(test.pbFormat);
466             return false;
467         }
468     }
469     AM_MEDIA_TYPE test;
470     GetMediaTypeAc3(0,&test);
471     if (connected->QueryAccept(&test)==S_OK)
472     {
473         CoTaskMemFree(test.pbFormat);
474         return true;
475     } 
476     CoTaskMemFree(test.pbFormat);
477     return false;
478
479 }
480
481
482 HRESULT DsSourcePin::GetMediaTypeMpegAudio(int iPosition, AM_MEDIA_TYPE *pmt)
483 {
484   HRESULT hr;
485   switch (iPosition) 
486   {
487       /*  case 0: {
488                 ZeroMemory(pmt,sizeof(*pmt));
489                 pmt->lSampleSize = 1;
490                 pmt->bFixedSizeSamples = TRUE;
491                 pmt->majortype=MEDIATYPE_Audio;
492                 MPEG1WAVEFORMAT wfe;
493                 ZeroMemory(&wfe,sizeof(wfe));
494                 wfe.wfx.cbSize=22;
495                 wfe.wfx.nSamplesPerSec=48000;
496                 wfe.wfx.nChannels=2;
497                 wfe.wfx.nAvgBytesPerSec=32000;
498                 wfe.wfx.nBlockAlign=768;
499                 wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG;
500                 wfe.wfx.wBitsPerSample=0;
501                 wfe.fwHeadLayer=2;
502                 wfe.dwHeadBitrate=256000;
503                 wfe.fwHeadMode=ACM_MPEG_STEREO;
504                 wfe.fwHeadModeExt=1;
505                 wfe.wHeadEmphasis=1;
506                 wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;
507                 pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO;
508                 pmt->formattype=FORMAT_WaveFormatEx;
509                 pmt->cbFormat=sizeof(wfe);
510                 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe));
511                 memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
512                 pmt->lSampleSize=0;
513                 hr=S_OK;
514                           } break;*/
515    case 0: 
516        {
517            ZeroMemory(pmt,sizeof(*pmt));
518            pmt->lSampleSize = 1;
519            pmt->bFixedSizeSamples = TRUE;
520            pmt->majortype = MEDIATYPE_Audio;
521            WAVEFORMATEX wfe;
522            ZeroMemory(&wfe,sizeof(wfe));
523            wfe.cbSize = 22;
524            wfe.nSamplesPerSec = 48000;
525            wfe.nChannels = 2;
526            wfe.nAvgBytesPerSec = 32000;
527            wfe.nBlockAlign = 768;
528            wfe.wFormatTag = WAVE_FORMAT_UNKNOWN;
529            wfe.wBitsPerSample = 0;
530            pmt->subtype = MEDIASUBTYPE_MPEG2_AUDIO;
531                    pmt->formattype = FORMAT_WaveFormatEx;
532                    pmt->cbFormat = sizeof(wfe);
533                    pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe));
534                    memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
535                    pmt->lSampleSize=0;
536                    hr=S_OK;
537        } break;
538    case 1: {
539        ZeroMemory(pmt,sizeof(*pmt));
540            pmt->lSampleSize = 1;
541            pmt->bFixedSizeSamples = TRUE;
542            pmt->majortype = MEDIATYPE_Audio;
543            MPEG1WAVEFORMAT wfe;
544            ZeroMemory(&wfe,sizeof(wfe));
545            wfe.wfx.cbSize = 22;
546            wfe.wfx.nSamplesPerSec = 48000;
547            wfe.wfx.nChannels = 2;
548            wfe.wfx.nAvgBytesPerSec = 32000;
549            wfe.wfx.nBlockAlign = 768;
550            wfe.wfx.wFormatTag = WAVE_FORMAT_UNKNOWN;
551        wfe.wfx.wBitsPerSample = 0;
552         /* wfe.fwHeadLayer=2;
553            wfe.dwHeadBitrate=256000;
554            wfe.fwHeadMode=ACM_MPEG_STEREO;
555            wfe.fwHeadModeExt=1;
556            wfe.wHeadEmphasis=1;
557        wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;*/
558            pmt->subtype=MEDIASUBTYPE_MPEG1Payload;
559            pmt->formattype=FORMAT_WaveFormatEx;
560            pmt->cbFormat=sizeof(wfe);
561            pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe));
562            memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
563            pmt->lSampleSize=0;
564            hr=S_OK;
565            } break;    
566           default: {
567                   hr=VFW_S_NO_MORE_ITEMS;
568           }break;
569   };
570   return hr ;
571 }
572
573 HRESULT DsSourcePin::GetMediaTypeAc3(int iPosition, AM_MEDIA_TYPE *pmt)
574 {
575   HRESULT hr;
576   switch (iPosition)
577   {
578    case 0:
579       { //AC3 for future use
580           ZeroMemory(pmt,sizeof(*pmt));
581           pmt->lSampleSize = 1;
582           pmt->bFixedSizeSamples = TRUE;
583           pmt->majortype = MEDIATYPE_Audio;
584           WAVEFORMATEX wfe;
585           ZeroMemory(&wfe,sizeof(wfe));
586           wfe.cbSize = 22;
587           wfe.nSamplesPerSec = 48000;
588                   wfe.nChannels = 2;
589                   wfe.nAvgBytesPerSec = 32000;
590                   wfe.nBlockAlign = 768;
591                   wfe.wFormatTag = WAVE_FORMAT_UNKNOWN;
592                   wfe.wBitsPerSample = 0;
593                   pmt->subtype = MEDIASUBTYPE_DOLBY_AC3;
594          // pmt->subtype = MEDIASUBTYPE_DOLBY_AC3_SPDIF;
595                   pmt->formattype = FORMAT_WaveFormatEx;
596                   pmt->cbFormat = sizeof(wfe);
597                   pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe));
598                   memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
599                   pmt->lSampleSize = 0;
600                   hr = S_OK;
601       } break;
602   default: {
603       hr=VFW_S_NO_MORE_ITEMS;
604            }break;
605   };
606   return hr ;
607 }
608
609 HRESULT DsSourcePin::GetMediaTypeMpegVideo(int iPosition, AM_MEDIA_TYPE *pmt)
610 {
611   HRESULT hr;
612   if (iPosition == 0)
613   {
614       ZeroMemory(pmt,sizeof(*pmt));
615       pmt->lSampleSize = 1;
616       pmt->bFixedSizeSamples = TRUE;
617       pmt->majortype = MEDIATYPE_Video;
618       hr = S_OK;
619       pmt->subtype = MEDIASUBTYPE_MPEG2_VIDEO;
620       pmt->formattype = FORMAT_MPEG2Video;
621       MPEG2VIDEOINFO hdr;
622       ZeroMemory(&hdr,sizeof(hdr));
623       hdr.dwProfile = AM_MPEG2Profile_Main;
624       hdr.dwLevel = AM_MPEG2Level_Main;
625       hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader);
626       hdr.hdr.bmiHeader.biWidth = 720;
627       hdr.hdr.bmiHeader.biHeight = 568;
628       pmt->cbFormat = sizeof(hdr);
629       pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(hdr));
630       memcpy(pmt->pbFormat,&hdr,sizeof(hdr));
631   } else {
632       hr=VFW_S_NO_MORE_ITEMS;
633   }
634
635   return hr;
636 }
637
638 HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt)
639 {
640
641   switch (pinmode){
642   case MPTYPE_MPEG_AUDIO:
643           return GetMediaTypeMpegAudio(iPosition,pmt);
644   break;
645   case MPTYPE_VIDEO:
646       return GetMediaTypeMpegVideo(iPosition,pmt);
647   break;
648   case MPTYPE_AC3_PRE13:
649   case MPTYPE_AC3:
650       return GetMediaTypeAc3(iPosition,pmt);
651   };
652 }
653
654 void DsSourcePin::SetPinMode(int mode) {
655     pinmode=mode;
656     AM_MEDIA_TYPE amtype;
657     ReleaseMType(&medtype);
658     GetMediaType(0,&medtype);
659 }
660
661 HRESULT DsSourcePin::Inactive() {
662   if (allocator!=NULL) return allocator->Decommit();
663   return VFW_E_NO_ALLOCATOR;
664 }
665
666 HRESULT DsSourcePin::Active() {
667   if (allocator!=NULL) return allocator->Commit();
668   return VFW_E_NO_ALLOCATOR;
669 }
670
671
672 HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){
673   return NOERROR;
674 }
675
676 // No description
677 HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt)
678 {
679     HRESULT res=S_FALSE;
680     bool subtype=false;
681     switch (pinmode) {
682     case MPTYPE_MPEG_AUDIO:
683           subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO));
684       subtype=(pmt->subtype==MEDIASUBTYPE_MPEG1Payload) || subtype;
685       if (pmt->majortype==MEDIATYPE_Audio && subtype) 
686       {
687           res = S_OK ;
688       } 
689       else 
690       {
691           res = S_FALSE ;
692       }
693       break;
694   case MPTYPE_VIDEO:
695        if (pmt->majortype==MEDIATYPE_Video &&
696            pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) 
697        {
698                res = S_OK ;
699         } 
700        else 
701        {
702             res = S_FALSE ;
703         }
704         break;
705   case MPTYPE_AC3_PRE13:
706   case MPTYPE_AC3:
707       subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3);
708       subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3_SPDIF) || subtype;
709       if (pmt->majortype==MEDIATYPE_Audio && subtype) 
710       {
711           res = S_OK ;
712       }
713       else 
714       {
715           res = S_FALSE ;
716       }
717       break;
718     };
719     return res;
720 }
721
722 HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){
723   HRESULT hr;
724
725     if (pa==NULL)return E_POINTER;
726     if (all_pp==NULL) return E_POINTER;
727   if (isaudiopin) {
728     if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
729     {
730       //all_pp->cBuffers = 300;//old
731       all_pp->cBuffers = 50;
732       all_pp->cbBuffer = 64*1024;
733     }
734   } else {
735     if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
736     {
737       //all_pp->cBuffers = 300;//old
738       all_pp->cBuffers = 300;
739       all_pp->cbBuffer = 64*1024;
740     }
741   }
742
743     ALLOCATOR_PROPERTIES all_pp_cur;
744     hr =pa->SetProperties(all_pp,&all_pp_cur);
745     if (FAILED(hr))
746     {
747         return hr;
748     }
749     if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer)
750     {
751         return E_FAIL;
752     }
753
754     return S_OK;
755 }
756
757