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 {
28 DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos=0);
29 virtual ~DsSFEnumMediaTypes();
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);
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(){
54 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Next(ULONG numpin, AM_MEDIA_TYPE **pins,ULONG *fetched) {
\r
56 if (fetched==NULL) return E_POINTER;
\r
57 if (pins==NULL) return E_POINTER;
\r
60 for (i=0;(i<numpin);i++) {
\r
61 if (parent->GetMediaType(curpos+i,pins[i])!=S_OK) return S_FALSE;
\r
68 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Skip(ULONG numpin){
\r
70 if (curpos>1) return S_FALSE;
\r
73 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Reset(){
\r
77 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Clone(IEnumMediaTypes **enuma){
\r
78 if (enuma==NULL) return E_POINTER;
\r
79 *enuma=new DsSFEnumMediaTypes(parent,curpos);
\r
84 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::QueryInterface(REFIID id,void ** object){
85 if (object==NULL) return E_POINTER;
86 if (id==IID_IUnknown ||id == IID_IEnumMediaTypes) {
87 *object=(IUnknown*)this;
88 ((IUnknown*)object)->AddRef();
98 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::AddRef(){
\r
99 InterlockedIncrement(&refs);
\r
101 if (tempref>1) return tempref;
\r
105 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::Release(){
\r
106 long tempref=InterlockedDecrement(&refs);
\r
113 if (tempref>1) return tempref;
\r
119 void CopyMType(AM_MEDIA_TYPE* dest,const AM_MEDIA_TYPE*source) {
\r
120 memcpy(dest,source,sizeof(AM_MEDIA_TYPE));
\r
121 if (source->pbFormat!=NULL) {
\r
122 dest->pbFormat=(BYTE*)CoTaskMemAlloc(dest->cbFormat);
\r
123 memcpy(dest->pbFormat,source->pbFormat,dest->cbFormat);
\r
126 void ReleaseMType(AM_MEDIA_TYPE* free) {
\r
127 if (free->cbFormat!=NULL) CoTaskMemFree(free->pbFormat);
\r
128 free->pbFormat=NULL;
\r
131 DsSourcePin::DsSourcePin(DsSourceFilter *pFilter,
\r
132 HRESULT *phr,LPCWSTR pName,bool audio)
\r
137 connectedinput=NULL;
\r
144 DsSourcePin::~DsSourcePin()
\r
150 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInterface(REFIID id,void ** object){
151 if (object==NULL) return E_POINTER;
152 if (id==IID_IUnknown) {
153 *object=(IUnknown*)this;
154 ((IUnknown*)object)->AddRef();
156 } else if (id==IID_IPin) {
158 ((IPin*)object)->AddRef();
162 return E_NOINTERFACE;
166 ULONG STDMETHODCALLTYPE DsSourcePin::AddRef(){
\r
167 return m_pFilter->AddRef();
\r
170 ULONG STDMETHODCALLTYPE DsSourcePin::Release(){
\r
171 return m_pFilter->Release();
\r
176 HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype) {
\r
177 if (pinempf==NULL) return E_POINTER;
\r
178 EnterCriticalSection(&m_pFilter->filterlock);
\r
180 if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;}
\r
181 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
\r
187 if (CheckMediaType(mtype)==S_OK){
\r
188 if (pinempf->ReceiveConnection((IPin*)this,mtype)==S_OK) {
\r
189 CopyMType(&medtype,mtype);
\r
190 LeaveCriticalSection(&m_pFilter->filterlock);
\r
192 LeaveCriticalSection(&m_pFilter->filterlock);
\r
193 CoTaskMemFree(mtype->pbFormat);
\r
194 return VFW_E_TYPE_NOT_ACCEPTED;
\r
198 LeaveCriticalSection(&m_pFilter->filterlock);
\r
199 CoTaskMemFree(mtype->pbFormat);
\r
200 return VFW_E_TYPE_NOT_ACCEPTED;
\r
202 CoTaskMemFree(mtype->pbFormat);
\r
204 IEnumMediaTypes * emt;
\r
205 EnumMediaTypes(&emt);
\r
206 AM_MEDIA_TYPE emtype_np;
\r
207 AM_MEDIA_TYPE * emtype;
\r
210 while (emt->Next(1,&emtype,&fetched)==S_OK) {
\r
211 if (CheckMediaType(emtype)==S_OK){
\r
212 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
\r
214 CopyMType(&medtype,emtype);
\r
215 CoTaskMemFree(emtype->pbFormat);
\r
221 CoTaskMemFree(emtype->pbFormat);
\r
224 if (gotmt==false) {
\r
225 pinempf->EnumMediaTypes(&emt);
\r
226 while (emt->Next(1,&emtype,&fetched)==S_OK) {
\r
227 if (CheckMediaType(emtype)==S_OK){
\r
228 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
\r
230 CopyMType(&medtype,emtype);
\r
231 CoTaskMemFree(emtype->pbFormat);
\r
237 CoTaskMemFree(emtype->pbFormat);
\r
240 if (gotmt==false) {
\r
241 LeaveCriticalSection(&m_pFilter->filterlock);
\r
242 return VFW_E_NO_ACCEPTABLE_TYPES;
\r
247 if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) {
\r
248 LeaveCriticalSection(&m_pFilter->filterlock);
\r
249 connectedinput->Release();
\r
250 connectedinput=NULL;
\r
251 return VFW_E_NO_TRANSPORT;
\r
253 ALLOCATOR_PROPERTIES eigenall;
\r
254 ZeroMemory(&eigenall,sizeof(eigenall));
\r
255 connectedinput->GetAllocatorRequirements(&eigenall);
\r
256 if (eigenall.cbAlign==0) eigenall.cbAlign=1;
\r
257 connectedinput->GetAllocator(&allocator);
\r
258 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
\r
259 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
\r
261 LeaveCriticalSection(&m_pFilter->filterlock);
\r
265 if (allocator!=NULL) allocator->Release();
\r
268 if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER,
\r
269 IID_IMemAllocator,(void **)allocator)==S_OK) {
\r
270 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
\r
271 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
\r
273 LeaveCriticalSection(&m_pFilter->filterlock);
\r
278 if (allocator!=NULL) allocator->Release();
\r
280 LeaveCriticalSection(&m_pFilter->filterlock);
\r
281 return VFW_E_NO_TRANSPORT;
\r
287 HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect,
\r
288 const AM_MEDIA_TYPE *mtype){
\r
289 return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins
\r
291 HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() {
\r
292 EnterCriticalSection(&m_pFilter->filterlock);
\r
293 if (connected!=NULL) {
\r
294 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
\r
295 /*TODO: Decommit allocator*/
\r
296 allocator->Decommit();
\r
297 allocator->Release();
\r
299 ReleaseMType(&medtype);
\r
300 connectedinput->Release();
\r
301 connectedinput=NULL;
\r
302 connected->Release();
\r
304 LeaveCriticalSection(&m_pFilter->filterlock);
\r
307 LeaveCriticalSection(&m_pFilter->filterlock);
\r
311 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){
\r
312 if (pin==NULL) return E_POINTER;
\r
313 IPin* pinn=connected;
\r
315 if (connected!=NULL) {
\r
319 return VFW_E_NOT_CONNECTED;
\r
322 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){
\r
323 if (mtype==NULL) return E_POINTER;
\r
324 if (connected!=NULL){
\r
325 CopyMType(mtype,&medtype);
\r
328 ZeroMemory(mtype,sizeof(mtype));
\r
329 return VFW_E_NOT_CONNECTED;
\r
332 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){
\r
333 if (info==NULL) return E_POINTER;
\r
334 info->dir=PINDIR_OUTPUT;
\r
335 info->pFilter=(IBaseFilter*)m_pFilter;
\r
336 if (isaudiopin) wcscpy(info->achName,L"Audio");
\r
337 else wcscpy(info->achName,L"Video");
\r
341 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryDirection(PIN_DIRECTION *dir){
\r
342 if (dir==NULL) return E_POINTER;
\r
343 *dir=PINDIR_OUTPUT;
\r
346 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){
\r
347 if (id==NULL) return E_POINTER;
\r
348 *id=(LPWSTR)CoTaskMemAlloc(12);
\r
349 if (*id==NULL) return E_OUTOFMEMORY;
\r
352 if (isaudiopin) wcscpy(*id,L"Audio");
\r
353 else wcscpy(*id, L"Video");
\r
356 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) {
\r
357 if (mtype==NULL) return S_FALSE;
\r
358 if (CheckMediaType(mtype)==S_OK) return S_OK;
\r
359 else return S_FALSE;
\r
361 HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){
\r
362 if (enuma==NULL) return E_POINTER;
363 *enuma=new DsSFEnumMediaTypes( this);
368 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){
\r
371 HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){
\r
372 return E_UNEXPECTED; //we are a output pin!
\r
375 HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){
\r
376 return E_UNEXPECTED;//we are a output pin!
\r
379 HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){
\r
380 if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0);
\r
381 else return E_NOINTERFACE;
\r
384 HRESULT DsSourcePin::deliver(IMediaSample * ms){
\r
385 //EnterCriticalSection(&m_pFilter->filterlock);
\r
387 if (connectedinput!=NULL)hres= connectedinput->Receive(ms);
\r
388 else hres= VFW_E_NOT_CONNECTED;
\r
389 //LeaveCriticalSection(&m_pFilter->filterlock);
\r
394 HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt)
\r
399 if (iPosition==0) {
\r
400 ZeroMemory(pmt,sizeof(*pmt));
\r
401 pmt->lSampleSize = 1;
\r
402 pmt->bFixedSizeSamples = TRUE;
\r
403 pmt->majortype=MEDIATYPE_Audio;
\r
404 MPEG1WAVEFORMAT wfe;
\r
405 ZeroMemory(&wfe,sizeof(wfe));
\r
407 wfe.wfx.nSamplesPerSec=48000;
\r
408 wfe.wfx.nChannels=2;
\r
409 wfe.wfx.nAvgBytesPerSec=32000;
\r
410 wfe.wfx.nBlockAlign=768;
\r
411 wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG;
\r
413 wfe.dwHeadBitrate=256000;
\r
414 wfe.fwHeadMode=ACM_MPEG_STEREO;
\r
415 wfe.fwHeadModeExt=1;
\r
416 wfe.wHeadEmphasis=1;
\r
417 wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;
\r
418 pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO;
\r
419 pmt->formattype=FORMAT_WaveFormatEx;
\r
420 pmt->cbFormat=sizeof(wfe);
\r
421 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe));
\r
422 memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
\r
423 pmt->lSampleSize=0;
\r
428 hr=VFW_S_NO_MORE_ITEMS ;
\r
431 if (iPosition == 0) {
\r
432 ZeroMemory(pmt,sizeof(*pmt));
\r
433 pmt->lSampleSize = 1;
\r
434 pmt->bFixedSizeSamples = TRUE;
\r
435 pmt->majortype=MEDIATYPE_Video;
\r
437 pmt->subtype=MEDIASUBTYPE_MPEG2_VIDEO;
\r
438 pmt->formattype=FORMAT_MPEG2Video;
\r
440 MPEG2VIDEOINFO hdr;
\r
441 ZeroMemory(&hdr,sizeof(hdr));
\r
442 hdr.dwProfile=AM_MPEG2Profile_Main;
\r
443 hdr.dwLevel=AM_MPEG2Level_Main;
\r
444 hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader);
\r
445 hdr.hdr.bmiHeader.biWidth = 720;
\r
446 hdr.hdr.bmiHeader.biHeight = 568;
\r
447 pmt->cbFormat=sizeof(hdr);
\r
448 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(hdr));
\r
449 memcpy(pmt->pbFormat,&hdr,sizeof(hdr));
\r
452 hr=VFW_S_NO_MORE_ITEMS;
\r
458 HRESULT DsSourcePin::Inactive() {
\r
459 if (allocator!=NULL) return allocator->Decommit();
\r
460 return VFW_E_NO_ALLOCATOR;
\r
463 HRESULT DsSourcePin::Active() {
\r
464 if (allocator!=NULL) return allocator->Commit();
\r
465 return VFW_E_NO_ALLOCATOR;
\r
469 HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){
\r
474 HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt)
\r
479 bool subtype=false;
\r
480 #if 0 /* For future demands ac3 */
\r
481 subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3);
\r
483 subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO));
\r
484 if (pmt->majortype==MEDIATYPE_Audio && subtype) {
\r
490 if (pmt->majortype==MEDIATYPE_Video &&
\r
491 pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) {
\r
500 HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){
\r
503 if (pa==NULL)return E_POINTER;
\r
504 if (all_pp==NULL) return E_POINTER;
\r
506 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
\r
508 //all_pp->cBuffers = 300;//old
\r
509 all_pp->cBuffers = 10;
\r
510 all_pp->cbBuffer = 64*1024;
\r
513 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
\r
515 //all_pp->cBuffers = 300;//old
\r
516 all_pp->cBuffers = 30;
\r
517 all_pp->cbBuffer = 64*1024;
\r
521 ALLOCATOR_PROPERTIES all_pp_cur;
\r
522 hr =pa->SetProperties(all_pp,&all_pp_cur);
\r
527 if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer)
\r