2 Copyright 2004-2005 Chris Tallon
\r
4 This file is part of VOMP.
\r
6 VOMP is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 VOMP is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with VOMP; if not, write to the Free Software
\r
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 #include "dssourcepin.h"
\r
21 #include "dssourcefilter.h"
\r
22 #include <Dvdmedia.h>
\r
26 class DsSFEnumMediaTypes: public IEnumMediaTypes {
\r
28 DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos=0);
\r
29 virtual ~DsSFEnumMediaTypes();
\r
30 virtual HRESULT STDMETHODCALLTYPE Next(ULONG nummedia, AM_MEDIA_TYPE **pins,ULONG *fetched);
\r
31 virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin);
\r
32 virtual HRESULT STDMETHODCALLTYPE Reset();
\r
33 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **enuma);
\r
34 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object);
\r
35 virtual ULONG STDMETHODCALLTYPE AddRef();
\r
36 virtual ULONG STDMETHODCALLTYPE Release();
\r
38 DsSourcePin* parent;
\r
43 DsSFEnumMediaTypes::DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos){
\r
50 DsSFEnumMediaTypes::~DsSFEnumMediaTypes(){
\r
54 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Next(ULONG numpin, AM_MEDIA_TYPE **pins,ULONG *fetched) {
\r
57 if (pins==NULL) return E_POINTER;
\r
58 if (numpin!=1 && fetched==NULL) return E_INVALIDARG;
\r
61 for (i=0;(i<numpin);i++) {
\r
62 pins[i]=(AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
\r
63 if (parent->GetMediaType(curpos+i,pins[i])!=S_OK) {
\r
64 CoTaskMemFree(pins[i]);
\r
68 if (fetched!=NULL) (*fetched)++;
\r
73 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Skip(ULONG numpin){
\r
75 if (curpos>1) return S_FALSE;
\r
78 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Reset(){
\r
82 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Clone(IEnumMediaTypes **enuma){
\r
83 if (enuma==NULL) return E_POINTER;
\r
84 *enuma=new DsSFEnumMediaTypes(parent,curpos);
\r
89 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::QueryInterface(REFIID id,void ** object){
\r
90 if (object==NULL) return E_POINTER;
\r
91 if (id==IID_IUnknown ||id == IID_IEnumMediaTypes) {
\r
92 *object=(IUnknown*)this;
\r
93 ((IUnknown*)object)->AddRef();
\r
97 return E_NOINTERFACE;
\r
103 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::AddRef(){
\r
104 InterlockedIncrement(&refs);
\r
106 if (tempref>1) return tempref;
\r
110 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::Release(){
\r
111 long tempref=InterlockedDecrement(&refs);
\r
118 if (tempref>1) return tempref;
\r
124 void CopyMType(AM_MEDIA_TYPE* dest,const AM_MEDIA_TYPE*source) {
\r
125 memcpy(dest,source,sizeof(AM_MEDIA_TYPE));
\r
126 if (source->pbFormat!=NULL) {
\r
127 dest->pbFormat=(BYTE*)CoTaskMemAlloc(dest->cbFormat);
\r
128 memcpy(dest->pbFormat,source->pbFormat,dest->cbFormat);
\r
131 void ReleaseMType(AM_MEDIA_TYPE* free) {
\r
132 if (free->cbFormat!=NULL) CoTaskMemFree(free->pbFormat);
\r
133 free->pbFormat=NULL;
\r
136 DsSourcePin::DsSourcePin(DsSourceFilter *pFilter,
\r
137 HRESULT *phr,LPCWSTR pName,bool audio)
\r
142 connectedinput=NULL;
\r
149 DsSourcePin::~DsSourcePin()
\r
156 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInterface(REFIID id,void ** object){
\r
157 if (object==NULL) return E_POINTER;
\r
158 if (id==IID_IUnknown) {
\r
159 *object=(IUnknown*)this;
\r
160 ((IUnknown*)object)->AddRef();
\r
162 } else if (id==IID_IPin) {
\r
163 *object=(IPin*)this;
\r
164 ((IPin*)object)->AddRef();
\r
168 return E_NOINTERFACE;
\r
172 ULONG STDMETHODCALLTYPE DsSourcePin::AddRef(){
\r
173 return m_pFilter->AddRef();
\r
176 ULONG STDMETHODCALLTYPE DsSourcePin::Release(){
\r
177 return m_pFilter->Release();
\r
182 HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype) {
\r
183 if (pinempf==NULL) return E_POINTER;
\r
184 EnterCriticalSection(&m_pFilter->filterlock);
\r
186 if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;}
\r
187 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
\r
193 if (CheckMediaType(mtype)==S_OK){
\r
195 if (pinempf->ReceiveConnection((IPin*)this,mtype)==S_OK) {
\r
196 CopyMType(&medtype,mtype);
\r
197 LeaveCriticalSection(&m_pFilter->filterlock);
\r
199 LeaveCriticalSection(&m_pFilter->filterlock);
\r
200 if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat);
\r
201 pinempf->Release();
\r
202 return VFW_E_TYPE_NOT_ACCEPTED;
\r
206 LeaveCriticalSection(&m_pFilter->filterlock);
\r
207 if (mtype->pbFormat!=NULL) CoTaskMemFree(mtype->pbFormat);
\r
208 return VFW_E_TYPE_NOT_ACCEPTED;
\r
210 CoTaskMemFree(mtype->pbFormat);
\r
212 IEnumMediaTypes * emt;
\r
213 EnumMediaTypes(&emt);
\r
214 AM_MEDIA_TYPE * emtype;
\r
217 while (emt->Next(1,&emtype,&fetched)==S_OK) {
\r
218 if (CheckMediaType(emtype)==S_OK){
\r
220 pinempf->QueryPinInfo(&pini);
\r
221 if (pini.pFilter!=NULL) {
\r
223 pini.pFilter->QueryFilterInfo(&filti);
\r
225 if (filti.pGraph!=NULL) filti.pGraph->Release();
\r
226 char buffer[MAX_FILTER_NAME*2];
\r
227 wcstombs(buffer,filti.achName,MAX_FILTER_NAME*2);
\r
228 MessageBox(0,buffer,"Filter",0);
\r
229 pini.pFilter->Release();
\r
232 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
\r
234 CopyMType(&medtype,emtype);
\r
235 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
\r
237 CoTaskMemFree(emtype);
\r
243 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
\r
244 CoTaskMemFree(emtype);
\r
247 if (gotmt==false) {
\r
248 pinempf->EnumMediaTypes(&emt);
\r
249 while (emt->Next(1,&emtype,&fetched)==S_OK) {
\r
250 if (CheckMediaType(emtype)==S_OK){
\r
251 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
\r
253 CopyMType(&medtype,emtype);
\r
254 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
\r
255 CoTaskMemFree(emtype);
\r
261 if (emtype->pbFormat!=NULL) CoTaskMemFree(emtype->pbFormat);
\r
262 CoTaskMemFree(emtype);
\r
265 if (gotmt==false) {
\r
266 pinempf->Release();
\r
267 LeaveCriticalSection(&m_pFilter->filterlock);
\r
268 return VFW_E_NO_ACCEPTABLE_TYPES;
\r
273 if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) {
\r
274 LeaveCriticalSection(&m_pFilter->filterlock);
\r
275 connected->Release();
\r
277 /* connectedinput->Release();
\r
278 connectedinput=NULL;*/
\r
279 return VFW_E_NO_TRANSPORT;
\r
281 ALLOCATOR_PROPERTIES eigenall;
\r
282 ZeroMemory(&eigenall,sizeof(eigenall));
\r
283 connectedinput->GetAllocatorRequirements(&eigenall);
\r
284 if (eigenall.cbAlign==0) eigenall.cbAlign=1;
\r
285 connectedinput->GetAllocator(&allocator);
\r
286 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
\r
287 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
\r
289 LeaveCriticalSection(&m_pFilter->filterlock);
\r
293 if (allocator!=NULL) allocator->Release();
\r
296 if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER,
\r
297 IID_IMemAllocator,(void **)allocator)==S_OK) {
\r
298 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
\r
299 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
\r
301 LeaveCriticalSection(&m_pFilter->filterlock);
\r
306 if (allocator!=NULL) allocator->Release();
\r
308 connected->Release();
\r
310 connectedinput->Release();
\r
311 connectedinput=NULL;
\r
312 LeaveCriticalSection(&m_pFilter->filterlock);
\r
313 return VFW_E_NO_TRANSPORT;
\r
319 HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect,
\r
320 const AM_MEDIA_TYPE *mtype){
\r
321 return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins
\r
323 HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() {
\r
324 EnterCriticalSection(&m_pFilter->filterlock);
\r
325 if (connected!=NULL) {
\r
326 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
\r
327 /*TODO: Decommit allocator*/
\r
328 allocator->Decommit();
\r
329 allocator->Release();
\r
331 ReleaseMType(&medtype);
\r
332 connectedinput->Release();
\r
333 connectedinput=NULL;
\r
334 connected->Release();
\r
336 LeaveCriticalSection(&m_pFilter->filterlock);
\r
339 LeaveCriticalSection(&m_pFilter->filterlock);
\r
343 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){
\r
344 if (pin==NULL) return E_POINTER;
\r
345 IPin* pinn=connected;
\r
351 return VFW_E_NOT_CONNECTED;
\r
354 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){
\r
355 if (mtype==NULL) return E_POINTER;
\r
356 if (connected!=NULL){
\r
357 CopyMType(mtype,&medtype);
\r
360 ZeroMemory(mtype,sizeof(*mtype));
\r
361 return VFW_E_NOT_CONNECTED;
\r
364 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){
\r
365 if (info==NULL) return E_POINTER;
\r
366 info->dir=PINDIR_OUTPUT;
\r
367 info->pFilter=(IBaseFilter*)m_pFilter;
\r
368 if (m_pFilter) m_pFilter->AddRef();
\r
369 if (isaudiopin) wcscpy(info->achName,L"Audio");
\r
370 else wcscpy(info->achName,L"Video");
\r
374 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryDirection(PIN_DIRECTION *dir){
\r
375 if (dir==NULL) return E_POINTER;
\r
376 *dir=PINDIR_OUTPUT;
\r
379 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){
\r
380 if (id==NULL) return E_POINTER;
\r
381 *id=(LPWSTR)CoTaskMemAlloc(12);
\r
382 if (*id==NULL) return E_OUTOFMEMORY;
\r
385 if (isaudiopin) wcscpy(*id,L"Audio");
\r
386 else wcscpy(*id, L"Video");
\r
389 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) {
\r
390 if (mtype==NULL) return S_FALSE;
\r
391 if (CheckMediaType(mtype)==S_OK) return S_OK;
\r
392 else return S_FALSE;
\r
394 HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){
\r
395 if (enuma==NULL) return E_POINTER;
\r
396 *enuma=new DsSFEnumMediaTypes( this);
\r
397 (*enuma)->AddRef();
\r
401 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){
\r
404 HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){
\r
405 return E_UNEXPECTED; //we are a output pin!
\r
408 HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){
\r
409 return E_UNEXPECTED;//we are a output pin!
\r
412 HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){
\r
413 if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0);
\r
414 else return E_NOINTERFACE;
\r
417 HRESULT DsSourcePin::deliver(IMediaSample * ms){
\r
418 //EnterCriticalSection(&m_pFilter->filterlock);
\r
420 if (connectedinput!=NULL)hres= connectedinput->Receive(ms);
\r
421 else hres= VFW_E_NOT_CONNECTED;
\r
422 //LeaveCriticalSection(&m_pFilter->filterlock);
\r
427 HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt)
\r
432 if (iPosition==0) {
\r
433 ZeroMemory(pmt,sizeof(*pmt));
\r
434 pmt->lSampleSize = 1;
\r
435 pmt->bFixedSizeSamples = TRUE;
\r
436 pmt->majortype=MEDIATYPE_Audio;
\r
437 MPEG1WAVEFORMAT wfe;
\r
438 ZeroMemory(&wfe,sizeof(wfe));
\r
440 wfe.wfx.nSamplesPerSec=48000;
\r
441 wfe.wfx.nChannels=2;
\r
442 wfe.wfx.nAvgBytesPerSec=32000;
\r
443 wfe.wfx.nBlockAlign=768;
\r
444 wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG;
\r
445 wfe.wfx.wBitsPerSample=0;
\r
447 wfe.dwHeadBitrate=256000;
\r
448 wfe.fwHeadMode=ACM_MPEG_STEREO;
\r
449 wfe.fwHeadModeExt=1;
\r
450 wfe.wHeadEmphasis=1;
\r
451 wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;
\r
452 pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO;
\r
453 pmt->formattype=FORMAT_WaveFormatEx;
\r
454 pmt->cbFormat=sizeof(wfe);
\r
455 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe));
\r
456 memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
\r
457 pmt->lSampleSize=0;
\r
462 hr=VFW_S_NO_MORE_ITEMS ;
\r
465 if (iPosition == 0) {
\r
466 ZeroMemory(pmt,sizeof(*pmt));
\r
467 pmt->lSampleSize = 1;
\r
468 pmt->bFixedSizeSamples = TRUE;
\r
469 pmt->majortype=MEDIATYPE_Video;
\r
471 pmt->subtype=MEDIASUBTYPE_MPEG2_VIDEO;
\r
472 pmt->formattype=FORMAT_MPEG2Video;
\r
474 MPEG2VIDEOINFO hdr;
\r
475 ZeroMemory(&hdr,sizeof(hdr));
\r
476 hdr.dwProfile=AM_MPEG2Profile_Main;
\r
477 hdr.dwLevel=AM_MPEG2Level_Main;
\r
478 hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader);
\r
479 hdr.hdr.bmiHeader.biWidth = 720;
\r
480 hdr.hdr.bmiHeader.biHeight = 568;
\r
481 pmt->cbFormat=sizeof(hdr);
\r
482 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(hdr));
\r
483 memcpy(pmt->pbFormat,&hdr,sizeof(hdr));
\r
486 hr=VFW_S_NO_MORE_ITEMS;
\r
492 HRESULT DsSourcePin::Inactive() {
\r
493 if (allocator!=NULL) return allocator->Decommit();
\r
494 return VFW_E_NO_ALLOCATOR;
\r
497 HRESULT DsSourcePin::Active() {
\r
498 if (allocator!=NULL) return allocator->Commit();
\r
499 return VFW_E_NO_ALLOCATOR;
\r
503 HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){
\r
508 HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt)
\r
513 bool subtype=false;
\r
514 #if 0 /* For future demands ac3 */
\r
515 subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3);
\r
517 subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO));
\r
518 if (pmt->majortype==MEDIATYPE_Audio && subtype) {
\r
524 if (pmt->majortype==MEDIATYPE_Video &&
\r
525 pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) {
\r
534 HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){
\r
537 if (pa==NULL)return E_POINTER;
\r
538 if (all_pp==NULL) return E_POINTER;
\r
540 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
\r
542 //all_pp->cBuffers = 300;//old
\r
543 all_pp->cBuffers = 10;
\r
544 all_pp->cbBuffer = 64*1024;
\r
547 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
\r
549 //all_pp->cBuffers = 300;//old
\r
550 all_pp->cBuffers = 30;
\r
551 all_pp->cbBuffer = 64*1024;
\r
555 ALLOCATOR_PROPERTIES all_pp_cur;
\r
556 hr =pa->SetProperties(all_pp,&all_pp_cur);
\r
561 if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer)
\r