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