2 Copyright 2004-2005 Chris Tallon
4 This file is part of VOMP.
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.
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.
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
20 #include "dssourcepin.h"
21 #include "dssourcefilter.h"
24 #include "draintarget.h"
26 class DsSFEnumMediaTypes: public IEnumMediaTypes {
28 DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos=0);
29 virtual ~DsSFEnumMediaTypes();
30 virtual HRESULT STDMETHODCALLTYPE Next(ULONG nummedia, AM_MEDIA_TYPE **pins,ULONG *fetched);
31 virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin);
32 virtual HRESULT STDMETHODCALLTYPE Reset();
33 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **enuma);
34 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object);
35 virtual ULONG STDMETHODCALLTYPE AddRef();
36 virtual ULONG STDMETHODCALLTYPE Release();
43 DsSFEnumMediaTypes::DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos){
50 DsSFEnumMediaTypes::~DsSFEnumMediaTypes(){
54 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Next(ULONG numpin, AM_MEDIA_TYPE **pins,ULONG *fetched) {
57 if (pins==NULL) return E_POINTER;
58 if (numpin!=1 && fetched==NULL) return E_INVALIDARG;
61 for (i=0;(i<numpin);i++) {
62 pins[i]=(AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
63 if (parent->GetMediaType(curpos+i,pins[i])!=S_OK) {
64 CoTaskMemFree(pins[i]);
68 if (fetched!=NULL) (*fetched)++;
73 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Skip(ULONG numpin){
75 if (curpos>1) return S_FALSE;
78 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Reset(){
82 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Clone(IEnumMediaTypes **enuma){
83 if (enuma==NULL) return E_POINTER;
84 *enuma=new DsSFEnumMediaTypes(parent,curpos);
89 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::QueryInterface(REFIID id,void ** object){
90 if (object==NULL) return E_POINTER;
91 if (id==IID_IUnknown ||id == IID_IEnumMediaTypes) {
92 *object=(IUnknown*)this;
93 ((IUnknown*)object)->AddRef();
103 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::AddRef(){
104 InterlockedIncrement(&refs);
106 if (tempref>1) return tempref;
110 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::Release(){
111 long tempref=InterlockedDecrement(&refs);
118 if (tempref>1) return tempref;
124 void CopyMType(AM_MEDIA_TYPE* dest,const AM_MEDIA_TYPE*source) {
125 memcpy(dest,source,sizeof(AM_MEDIA_TYPE));
126 if (source->pbFormat!=NULL) {
127 dest->pbFormat=(BYTE*)CoTaskMemAlloc(dest->cbFormat);
128 memcpy(dest->pbFormat,source->pbFormat,dest->cbFormat);
131 void ReleaseMType(AM_MEDIA_TYPE* free) {
132 if (free->cbFormat!=NULL) CoTaskMemFree(free->pbFormat);
136 DsSourcePin::DsSourcePin(DsSourceFilter *pFilter,
137 HRESULT *phr,LPCWSTR pName,bool audio)
146 pinmode=MPTYPE_MPEG_AUDIO;
147 //pinmode=MPTYPE_AC3;
151 pinmode=MPTYPE_VIDEO;
156 DsSourcePin::~DsSourcePin()
163 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInterface(REFIID id,void ** object){
164 if (object==NULL) return E_POINTER;
165 if (id==IID_IUnknown) {
166 *object=(IUnknown*)this;
167 ((IUnknown*)object)->AddRef();
169 } else if (id==IID_IPin) {
171 ((IPin*)object)->AddRef();
175 return E_NOINTERFACE;
179 ULONG STDMETHODCALLTYPE DsSourcePin::AddRef(){
180 return m_pFilter->AddRef();
183 ULONG STDMETHODCALLTYPE DsSourcePin::Release(){
184 return m_pFilter->Release();
189 HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype) {
190 if (pinempf==NULL) return E_POINTER;
191 EnterCriticalSection(&m_pFilter->filterlock);
193 if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;}
194 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
199 if (CheckMediaType(mtype)==S_OK){
201 if (pinempf->ReceiveConnection((IPin*)this,mtype)==S_OK) {
202 CopyMType(&medtype,mtype);
203 LeaveCriticalSection(&m_pFilter->filterlock);
205 LeaveCriticalSection(&m_pFilter->filterlock);
206 if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat);
208 return VFW_E_TYPE_NOT_ACCEPTED;
212 LeaveCriticalSection(&m_pFilter->filterlock);
213 if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat);
214 return VFW_E_TYPE_NOT_ACCEPTED;
216 CoTaskMemFree(mtype->pbFormat);
218 IEnumMediaTypes * emt;
219 EnumMediaTypes(&emt);
220 AM_MEDIA_TYPE * emtype;
225 while (emt->Next(1,&emtype,&fetched)==S_OK) {
226 if (CheckMediaType(emtype)==S_OK){
228 pinempf->QueryPinInfo(&pini);
229 if (pini.pFilter!=NULL) {
231 pini.pFilter->QueryFilterInfo(&filti);
233 if (filti.pGraph!=NULL) filti.pGraph->Release();
234 char buffer[MAX_FILTER_NAME*2];
235 wcstombs(buffer,filti.achName,MAX_FILTER_NAME*2);
236 MessageBox(0,buffer,"Filter",0);
237 pini.pFilter->Release();
240 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
242 CopyMType(&medtype,emtype);
243 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
245 CoTaskMemFree(emtype);
251 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
252 CoTaskMemFree(emtype);
256 pinempf->EnumMediaTypes(&emt);
257 while (emt->Next(1,&emtype,&fetched)==S_OK) {
258 if (CheckMediaType(emtype)==S_OK){
259 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
261 CopyMType(&medtype,emtype);
262 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
263 CoTaskMemFree(emtype);
269 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
270 CoTaskMemFree(emtype);
275 LeaveCriticalSection(&m_pFilter->filterlock);
276 return VFW_E_NO_ACCEPTABLE_TYPES;
281 if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) {
282 LeaveCriticalSection(&m_pFilter->filterlock);
283 connected->Release();
285 /* connectedinput->Release();
286 connectedinput=NULL;*/
287 return VFW_E_NO_TRANSPORT;
289 ALLOCATOR_PROPERTIES eigenall;
290 ZeroMemory(&eigenall,sizeof(eigenall));
291 connectedinput->GetAllocatorRequirements(&eigenall);
292 if (eigenall.cbAlign==0) eigenall.cbAlign=1;
293 connectedinput->GetAllocator(&allocator);
294 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
295 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
297 LeaveCriticalSection(&m_pFilter->filterlock);
301 if (allocator!=NULL) allocator->Release();
304 if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER,
305 IID_IMemAllocator,(void **)allocator)==S_OK) {
306 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
307 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
309 LeaveCriticalSection(&m_pFilter->filterlock);
314 if (allocator!=NULL) allocator->Release();
316 connected->Release();
318 connectedinput->Release();
320 LeaveCriticalSection(&m_pFilter->filterlock);
321 return VFW_E_NO_TRANSPORT;
327 HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect,
328 const AM_MEDIA_TYPE *mtype){
329 return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins
331 HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() {
332 EnterCriticalSection(&m_pFilter->filterlock);
333 if (connected!=NULL) {
334 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
335 /*TODO: Decommit allocator*/
336 allocator->Decommit();
337 allocator->Release();
339 ReleaseMType(&medtype);
340 connectedinput->Release();
342 connected->Release();
344 LeaveCriticalSection(&m_pFilter->filterlock);
347 LeaveCriticalSection(&m_pFilter->filterlock);
351 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){
352 if (pin==NULL) return E_POINTER;
353 IPin* pinn=connected;
359 return VFW_E_NOT_CONNECTED;
362 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){
363 if (mtype==NULL) return E_POINTER;
364 if (connected!=NULL){
365 CopyMType(mtype,&medtype);
368 ZeroMemory(mtype,sizeof(*mtype));
369 return VFW_E_NOT_CONNECTED;
372 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){
373 if (info==NULL) return E_POINTER;
374 info->dir=PINDIR_OUTPUT;
375 info->pFilter=(IBaseFilter*)m_pFilter;
376 if (m_pFilter) m_pFilter->AddRef();
377 if (isaudiopin) wcscpy(info->achName,L"Audio");
378 else wcscpy(info->achName,L"Video");
382 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryDirection(PIN_DIRECTION *dir){
383 if (dir==NULL) return E_POINTER;
387 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){
388 if (id==NULL) return E_POINTER;
389 *id=(LPWSTR)CoTaskMemAlloc(12);
390 if (*id==NULL) return E_OUTOFMEMORY;
393 if (isaudiopin) wcscpy(*id,L"Audio");
394 else wcscpy(*id, L"Video");
397 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) {
398 if (mtype==NULL) return S_FALSE;
399 if (CheckMediaType(mtype)==S_OK) return S_OK;
402 HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){
403 if (enuma==NULL) return E_POINTER;
404 *enuma=new DsSFEnumMediaTypes( this);
409 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){
412 HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){
413 return E_UNEXPECTED; //we are a output pin!
416 HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){
417 return E_UNEXPECTED;//we are a output pin!
420 HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){
421 if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0);
422 else return E_NOINTERFACE;
425 HRESULT DsSourcePin::deliver(IMediaSample * ms){
426 //EnterCriticalSection(&m_pFilter->filterlock);
430 if (connectedinput!=NULL)hres= connectedinput->Receive(ms);
431 else hres= VFW_E_NOT_CONNECTED;
432 //LeaveCriticalSection(&m_pFilter->filterlock);
437 void DsSourcePin::SetMsToMt(IMediaSample *ms) {
438 ms->SetMediaType(&medtype);
441 bool DsSourcePin::supportsAc3() {
444 return false; //Haha a video pin that supports ac3
448 return false; //Graph is not build, please wait
452 return false; //Graph is not build, please wait
454 IPinConnection *pinconn=NULL; //according to docs, this is the prefered method
455 if (connected->QueryInterface(IID_IPinConnection,(void**)&pinconn)==S_OK) {
457 GetMediaType(10,&test);
458 if (pinconn->DynamicQueryAccept(&test)==S_OK)
461 CoTaskMemFree(test.pbFormat);
465 CoTaskMemFree(test.pbFormat);
470 GetMediaTypeAc3(0,&test);
471 if (connected->QueryAccept(&test)==S_OK)
473 CoTaskMemFree(test.pbFormat);
476 CoTaskMemFree(test.pbFormat);
482 HRESULT DsSourcePin::GetMediaTypeMpegAudio(int iPosition, AM_MEDIA_TYPE *pmt)
488 ZeroMemory(pmt,sizeof(*pmt));
489 pmt->lSampleSize = 1;
490 pmt->bFixedSizeSamples = TRUE;
491 pmt->majortype=MEDIATYPE_Audio;
493 ZeroMemory(&wfe,sizeof(wfe));
495 wfe.wfx.nSamplesPerSec=48000;
497 wfe.wfx.nAvgBytesPerSec=32000;
498 wfe.wfx.nBlockAlign=768;
499 wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG;
500 wfe.wfx.wBitsPerSample=0;
502 wfe.dwHeadBitrate=256000;
503 wfe.fwHeadMode=ACM_MPEG_STEREO;
506 wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;
507 pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO;
508 pmt->formattype=FORMAT_WaveFormatEx;
509 pmt->cbFormat=sizeof(wfe);
510 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe));
511 memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
517 ZeroMemory(pmt,sizeof(*pmt));
518 pmt->lSampleSize = 1;
519 pmt->bFixedSizeSamples = TRUE;
520 pmt->majortype = MEDIATYPE_Audio;
522 ZeroMemory(&wfe,sizeof(wfe));
524 wfe.nSamplesPerSec = 48000;
526 wfe.nAvgBytesPerSec = 32000;
527 wfe.nBlockAlign = 768;
528 wfe.wFormatTag = WAVE_FORMAT_UNKNOWN;
529 wfe.wBitsPerSample = 0;
530 pmt->subtype = MEDIASUBTYPE_MPEG2_AUDIO;
531 pmt->formattype = FORMAT_WaveFormatEx;
532 pmt->cbFormat = sizeof(wfe);
533 pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe));
534 memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
539 ZeroMemory(pmt,sizeof(*pmt));
540 pmt->lSampleSize = 1;
541 pmt->bFixedSizeSamples = TRUE;
542 pmt->majortype = MEDIATYPE_Audio;
544 ZeroMemory(&wfe,sizeof(wfe));
546 wfe.wfx.nSamplesPerSec = 48000;
547 wfe.wfx.nChannels = 2;
548 wfe.wfx.nAvgBytesPerSec = 32000;
549 wfe.wfx.nBlockAlign = 768;
550 wfe.wfx.wFormatTag = WAVE_FORMAT_UNKNOWN;
551 wfe.wfx.wBitsPerSample = 0;
552 /* wfe.fwHeadLayer=2;
553 wfe.dwHeadBitrate=256000;
554 wfe.fwHeadMode=ACM_MPEG_STEREO;
557 wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;*/
558 pmt->subtype=MEDIASUBTYPE_MPEG1Payload;
559 pmt->formattype=FORMAT_WaveFormatEx;
560 pmt->cbFormat=sizeof(wfe);
561 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe));
562 memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
567 hr=VFW_S_NO_MORE_ITEMS;
573 HRESULT DsSourcePin::GetMediaTypeAc3(int iPosition, AM_MEDIA_TYPE *pmt)
579 { //AC3 for future use
580 ZeroMemory(pmt,sizeof(*pmt));
581 pmt->lSampleSize = 1;
582 pmt->bFixedSizeSamples = TRUE;
583 pmt->majortype = MEDIATYPE_Audio;
585 ZeroMemory(&wfe,sizeof(wfe));
587 wfe.nSamplesPerSec = 48000;
589 wfe.nAvgBytesPerSec = 32000;
590 wfe.nBlockAlign = 768;
591 wfe.wFormatTag = WAVE_FORMAT_UNKNOWN;
592 wfe.wBitsPerSample = 0;
593 pmt->subtype = MEDIASUBTYPE_DOLBY_AC3;
594 // pmt->subtype = MEDIASUBTYPE_DOLBY_AC3_SPDIF;
595 pmt->formattype = FORMAT_WaveFormatEx;
596 pmt->cbFormat = sizeof(wfe);
597 pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe));
598 memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
599 pmt->lSampleSize = 0;
603 hr=VFW_S_NO_MORE_ITEMS;
609 HRESULT DsSourcePin::GetMediaTypeMpegVideo(int iPosition, AM_MEDIA_TYPE *pmt)
614 ZeroMemory(pmt,sizeof(*pmt));
615 pmt->lSampleSize = 1;
616 pmt->bFixedSizeSamples = TRUE;
617 pmt->majortype = MEDIATYPE_Video;
619 pmt->subtype = MEDIASUBTYPE_MPEG2_VIDEO;
620 pmt->formattype = FORMAT_MPEG2Video;
622 ZeroMemory(&hdr,sizeof(hdr));
623 hdr.dwProfile = AM_MPEG2Profile_Main;
624 hdr.dwLevel = AM_MPEG2Level_Main;
625 hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader);
626 hdr.hdr.bmiHeader.biWidth = 720;
627 hdr.hdr.bmiHeader.biHeight = 568;
628 pmt->cbFormat = sizeof(hdr);
629 pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(hdr));
630 memcpy(pmt->pbFormat,&hdr,sizeof(hdr));
632 hr=VFW_S_NO_MORE_ITEMS;
638 HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt)
642 case MPTYPE_MPEG_AUDIO:
643 return GetMediaTypeMpegAudio(iPosition,pmt);
646 return GetMediaTypeMpegVideo(iPosition,pmt);
648 case MPTYPE_AC3_PRE13:
650 return GetMediaTypeAc3(iPosition,pmt);
654 void DsSourcePin::SetPinMode(int mode) {
656 AM_MEDIA_TYPE amtype;
657 ReleaseMType(&medtype);
658 GetMediaType(0,&medtype);
661 HRESULT DsSourcePin::Inactive() {
662 if (allocator!=NULL) return allocator->Decommit();
663 return VFW_E_NO_ALLOCATOR;
666 HRESULT DsSourcePin::Active() {
667 if (allocator!=NULL) return allocator->Commit();
668 return VFW_E_NO_ALLOCATOR;
672 HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){
677 HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt)
682 case MPTYPE_MPEG_AUDIO:
683 subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO));
684 subtype=(pmt->subtype==MEDIASUBTYPE_MPEG1Payload) || subtype;
685 if (pmt->majortype==MEDIATYPE_Audio && subtype)
695 if (pmt->majortype==MEDIATYPE_Video &&
696 pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO)
705 case MPTYPE_AC3_PRE13:
707 subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3);
708 subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3_SPDIF) || subtype;
709 if (pmt->majortype==MEDIATYPE_Audio && subtype)
722 HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){
725 if (pa==NULL)return E_POINTER;
726 if (all_pp==NULL) return E_POINTER;
728 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
730 //all_pp->cBuffers = 300;//old
731 all_pp->cBuffers = 50;
732 all_pp->cbBuffer = 64*1024;
735 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
737 //all_pp->cBuffers = 300;//old
738 all_pp->cBuffers = 300;
739 all_pp->cbBuffer = 64*1024;
743 ALLOCATOR_PROPERTIES all_pp_cur;
744 hr =pa->SetProperties(all_pp,&all_pp_cur);
749 if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer)