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