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"
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)
149 DsSourcePin::~DsSourcePin()
156 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInterface(REFIID id,void ** object){
157 if (object==NULL) return E_POINTER;
158 if (id==IID_IUnknown) {
159 *object=(IUnknown*)this;
160 ((IUnknown*)object)->AddRef();
162 } else if (id==IID_IPin) {
164 ((IPin*)object)->AddRef();
168 return E_NOINTERFACE;
172 ULONG STDMETHODCALLTYPE DsSourcePin::AddRef(){
173 return m_pFilter->AddRef();
176 ULONG STDMETHODCALLTYPE DsSourcePin::Release(){
177 return m_pFilter->Release();
182 HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype) {
183 if (pinempf==NULL) return E_POINTER;
184 EnterCriticalSection(&m_pFilter->filterlock);
186 if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;}
187 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
193 if (CheckMediaType(mtype)==S_OK){
195 if (pinempf->ReceiveConnection((IPin*)this,mtype)==S_OK) {
196 CopyMType(&medtype,mtype);
197 LeaveCriticalSection(&m_pFilter->filterlock);
199 LeaveCriticalSection(&m_pFilter->filterlock);
200 if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat);
202 return VFW_E_TYPE_NOT_ACCEPTED;
206 LeaveCriticalSection(&m_pFilter->filterlock);
207 if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat);
208 return VFW_E_TYPE_NOT_ACCEPTED;
210 CoTaskMemFree(mtype->pbFormat);
212 IEnumMediaTypes * emt;
213 EnumMediaTypes(&emt);
214 AM_MEDIA_TYPE * emtype;
217 while (emt->Next(1,&emtype,&fetched)==S_OK) {
218 if (CheckMediaType(emtype)==S_OK){
220 pinempf->QueryPinInfo(&pini);
221 if (pini.pFilter!=NULL) {
223 pini.pFilter->QueryFilterInfo(&filti);
225 if (filti.pGraph!=NULL) filti.pGraph->Release();
226 char buffer[MAX_FILTER_NAME*2];
227 wcstombs(buffer,filti.achName,MAX_FILTER_NAME*2);
228 MessageBox(0,buffer,"Filter",0);
229 pini.pFilter->Release();
232 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
234 CopyMType(&medtype,emtype);
235 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
237 CoTaskMemFree(emtype);
243 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
244 CoTaskMemFree(emtype);
248 pinempf->EnumMediaTypes(&emt);
249 while (emt->Next(1,&emtype,&fetched)==S_OK) {
250 if (CheckMediaType(emtype)==S_OK){
251 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
253 CopyMType(&medtype,emtype);
254 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
255 CoTaskMemFree(emtype);
261 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
262 CoTaskMemFree(emtype);
267 LeaveCriticalSection(&m_pFilter->filterlock);
268 return VFW_E_NO_ACCEPTABLE_TYPES;
273 if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) {
274 LeaveCriticalSection(&m_pFilter->filterlock);
275 connected->Release();
277 /* connectedinput->Release();
278 connectedinput=NULL;*/
279 return VFW_E_NO_TRANSPORT;
281 ALLOCATOR_PROPERTIES eigenall;
282 ZeroMemory(&eigenall,sizeof(eigenall));
283 connectedinput->GetAllocatorRequirements(&eigenall);
284 if (eigenall.cbAlign==0) eigenall.cbAlign=1;
285 connectedinput->GetAllocator(&allocator);
286 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
287 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
289 LeaveCriticalSection(&m_pFilter->filterlock);
293 if (allocator!=NULL) allocator->Release();
296 if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER,
297 IID_IMemAllocator,(void **)allocator)==S_OK) {
298 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
299 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
301 LeaveCriticalSection(&m_pFilter->filterlock);
306 if (allocator!=NULL) allocator->Release();
308 connected->Release();
310 connectedinput->Release();
312 LeaveCriticalSection(&m_pFilter->filterlock);
313 return VFW_E_NO_TRANSPORT;
319 HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect,
320 const AM_MEDIA_TYPE *mtype){
321 return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins
323 HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() {
324 EnterCriticalSection(&m_pFilter->filterlock);
325 if (connected!=NULL) {
326 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
327 /*TODO: Decommit allocator*/
328 allocator->Decommit();
329 allocator->Release();
331 ReleaseMType(&medtype);
332 connectedinput->Release();
334 connected->Release();
336 LeaveCriticalSection(&m_pFilter->filterlock);
339 LeaveCriticalSection(&m_pFilter->filterlock);
343 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){
344 if (pin==NULL) return E_POINTER;
345 IPin* pinn=connected;
351 return VFW_E_NOT_CONNECTED;
354 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){
355 if (mtype==NULL) return E_POINTER;
356 if (connected!=NULL){
357 CopyMType(mtype,&medtype);
360 ZeroMemory(mtype,sizeof(*mtype));
361 return VFW_E_NOT_CONNECTED;
364 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){
365 if (info==NULL) return E_POINTER;
366 info->dir=PINDIR_OUTPUT;
367 info->pFilter=(IBaseFilter*)m_pFilter;
368 if (m_pFilter) m_pFilter->AddRef();
369 if (isaudiopin) wcscpy(info->achName,L"Audio");
370 else wcscpy(info->achName,L"Video");
374 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryDirection(PIN_DIRECTION *dir){
375 if (dir==NULL) return E_POINTER;
379 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){
380 if (id==NULL) return E_POINTER;
381 *id=(LPWSTR)CoTaskMemAlloc(12);
382 if (*id==NULL) return E_OUTOFMEMORY;
385 if (isaudiopin) wcscpy(*id,L"Audio");
386 else wcscpy(*id, L"Video");
389 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) {
390 if (mtype==NULL) return S_FALSE;
391 if (CheckMediaType(mtype)==S_OK) return S_OK;
394 HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){
395 if (enuma==NULL) return E_POINTER;
396 *enuma=new DsSFEnumMediaTypes( this);
401 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){
404 HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){
405 return E_UNEXPECTED; //we are a output pin!
408 HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){
409 return E_UNEXPECTED;//we are a output pin!
412 HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){
413 if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0);
414 else return E_NOINTERFACE;
417 HRESULT DsSourcePin::deliver(IMediaSample * ms){
418 //EnterCriticalSection(&m_pFilter->filterlock);
420 if (connectedinput!=NULL)hres= connectedinput->Receive(ms);
421 else hres= VFW_E_NOT_CONNECTED;
422 //LeaveCriticalSection(&m_pFilter->filterlock);
427 HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt)
433 ZeroMemory(pmt,sizeof(*pmt));
434 pmt->lSampleSize = 1;
435 pmt->bFixedSizeSamples = TRUE;
436 pmt->majortype=MEDIATYPE_Audio;
438 ZeroMemory(&wfe,sizeof(wfe));
440 wfe.wfx.nSamplesPerSec=48000;
442 wfe.wfx.nAvgBytesPerSec=32000;
443 wfe.wfx.nBlockAlign=768;
444 wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG;
445 wfe.wfx.wBitsPerSample=0;
447 wfe.dwHeadBitrate=256000;
448 wfe.fwHeadMode=ACM_MPEG_STEREO;
451 wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;
452 pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO;
453 pmt->formattype=FORMAT_WaveFormatEx;
454 pmt->cbFormat=sizeof(wfe);
455 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe));
456 memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
462 hr=VFW_S_NO_MORE_ITEMS ;
465 if (iPosition == 0) {
466 ZeroMemory(pmt,sizeof(*pmt));
467 pmt->lSampleSize = 1;
468 pmt->bFixedSizeSamples = TRUE;
469 pmt->majortype=MEDIATYPE_Video;
471 pmt->subtype=MEDIASUBTYPE_MPEG2_VIDEO;
472 pmt->formattype=FORMAT_MPEG2Video;
475 ZeroMemory(&hdr,sizeof(hdr));
476 hdr.dwProfile=AM_MPEG2Profile_Main;
477 hdr.dwLevel=AM_MPEG2Level_Main;
478 hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader);
479 hdr.hdr.bmiHeader.biWidth = 720;
480 hdr.hdr.bmiHeader.biHeight = 568;
481 pmt->cbFormat=sizeof(hdr);
482 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(hdr));
483 memcpy(pmt->pbFormat,&hdr,sizeof(hdr));
486 hr=VFW_S_NO_MORE_ITEMS;
492 HRESULT DsSourcePin::Inactive() {
493 if (allocator!=NULL) return allocator->Decommit();
494 return VFW_E_NO_ALLOCATOR;
497 HRESULT DsSourcePin::Active() {
498 if (allocator!=NULL) return allocator->Commit();
499 return VFW_E_NO_ALLOCATOR;
503 HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){
508 HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt)
514 #if 0 /* For future demands ac3 */
515 subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3);
517 subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO));
518 if (pmt->majortype==MEDIATYPE_Audio && subtype) {
524 if (pmt->majortype==MEDIATYPE_Video &&
525 pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) {
534 HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){
537 if (pa==NULL)return E_POINTER;
538 if (all_pp==NULL) return E_POINTER;
540 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
542 //all_pp->cBuffers = 300;//old
543 all_pp->cBuffers = 10;
544 all_pp->cbBuffer = 64*1024;
547 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
549 //all_pp->cBuffers = 300;//old
550 all_pp->cBuffers = 30;
551 all_pp->cbBuffer = 64*1024;
555 ALLOCATOR_PROPERTIES all_pp_cur;
556 hr =pa->SetProperties(all_pp,&all_pp_cur);
561 if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer)