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