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) return S_FALSE;
\r
65 if (fetched!=NULL) (*fetched)++;
\r
70 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Skip(ULONG numpin){
\r
72 if (curpos>1) return S_FALSE;
\r
75 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Reset(){
\r
79 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Clone(IEnumMediaTypes **enuma){
\r
80 if (enuma==NULL) return E_POINTER;
\r
81 *enuma=new DsSFEnumMediaTypes(parent,curpos);
\r
86 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::QueryInterface(REFIID id,void ** object){
\r
87 if (object==NULL) return E_POINTER;
\r
88 if (id==IID_IUnknown ||id == IID_IEnumMediaTypes) {
\r
89 *object=(IUnknown*)this;
\r
90 ((IUnknown*)object)->AddRef();
\r
94 return E_NOINTERFACE;
\r
100 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::AddRef(){
\r
101 InterlockedIncrement(&refs);
\r
103 if (tempref>1) return tempref;
\r
107 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::Release(){
\r
108 long tempref=InterlockedDecrement(&refs);
\r
115 if (tempref>1) return tempref;
\r
121 void CopyMType(AM_MEDIA_TYPE* dest,const AM_MEDIA_TYPE*source) {
\r
122 memcpy(dest,source,sizeof(AM_MEDIA_TYPE));
\r
123 if (source->pbFormat!=NULL) {
\r
124 dest->pbFormat=(BYTE*)CoTaskMemAlloc(dest->cbFormat);
\r
125 memcpy(dest->pbFormat,source->pbFormat,dest->cbFormat);
\r
128 void ReleaseMType(AM_MEDIA_TYPE* free) {
\r
129 if (free->cbFormat!=NULL) CoTaskMemFree(free->pbFormat);
\r
130 free->pbFormat=NULL;
\r
133 DsSourcePin::DsSourcePin(DsSourceFilter *pFilter,
\r
134 HRESULT *phr,LPCWSTR pName,bool audio)
\r
139 connectedinput=NULL;
\r
146 DsSourcePin::~DsSourcePin()
\r
153 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInterface(REFIID id,void ** object){
\r
154 if (object==NULL) return E_POINTER;
\r
155 if (id==IID_IUnknown) {
\r
156 *object=(IUnknown*)this;
\r
157 ((IUnknown*)object)->AddRef();
\r
159 } else if (id==IID_IPin) {
\r
160 *object=(IPin*)this;
\r
161 ((IPin*)object)->AddRef();
\r
165 return E_NOINTERFACE;
\r
169 ULONG STDMETHODCALLTYPE DsSourcePin::AddRef(){
\r
170 return m_pFilter->AddRef();
\r
173 ULONG STDMETHODCALLTYPE DsSourcePin::Release(){
\r
174 return m_pFilter->Release();
\r
179 HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype) {
\r
180 if (pinempf==NULL) return E_POINTER;
\r
181 EnterCriticalSection(&m_pFilter->filterlock);
\r
183 if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;}
\r
184 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
\r
190 if (CheckMediaType(mtype)==S_OK){
\r
192 if (pinempf->ReceiveConnection((IPin*)this,mtype)==S_OK) {
\r
193 CopyMType(&medtype,mtype);
\r
194 LeaveCriticalSection(&m_pFilter->filterlock);
\r
196 LeaveCriticalSection(&m_pFilter->filterlock);
\r
197 CoTaskMemFree(mtype->pbFormat);
\r
198 pinempf->Release();
\r
199 return VFW_E_TYPE_NOT_ACCEPTED;
\r
203 LeaveCriticalSection(&m_pFilter->filterlock);
\r
204 CoTaskMemFree(mtype->pbFormat);
\r
205 return VFW_E_TYPE_NOT_ACCEPTED;
\r
207 CoTaskMemFree(mtype->pbFormat);
\r
209 IEnumMediaTypes * emt;
\r
210 EnumMediaTypes(&emt);
\r
211 AM_MEDIA_TYPE * emtype;
\r
214 while (emt->Next(1,&emtype,&fetched)==S_OK) {
\r
215 if (CheckMediaType(emtype)==S_OK){
\r
216 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
\r
218 CopyMType(&medtype,emtype);
\r
219 CoTaskMemFree(emtype->pbFormat);
\r
220 CoTaskMemFree(emtype);
\r
226 CoTaskMemFree(emtype->pbFormat);
\r
227 CoTaskMemFree(emtype);
\r
230 if (gotmt==false) {
\r
231 pinempf->EnumMediaTypes(&emt);
\r
232 while (emt->Next(1,&emtype,&fetched)==S_OK) {
\r
233 if (CheckMediaType(emtype)==S_OK){
\r
234 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
\r
236 CopyMType(&medtype,emtype);
\r
237 CoTaskMemFree(emtype->pbFormat);
\r
238 CoTaskMemFree(emtype);
\r
244 CoTaskMemFree(emtype->pbFormat);
\r
245 CoTaskMemFree(emtype);
\r
248 if (gotmt==false) {
\r
249 pinempf->Release();
\r
250 LeaveCriticalSection(&m_pFilter->filterlock);
\r
251 return VFW_E_NO_ACCEPTABLE_TYPES;
\r
256 if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) {
\r
257 LeaveCriticalSection(&m_pFilter->filterlock);
\r
258 connected->Release();
\r
260 /* connectedinput->Release();
\r
261 connectedinput=NULL;*/
\r
262 return VFW_E_NO_TRANSPORT;
\r
264 ALLOCATOR_PROPERTIES eigenall;
\r
265 ZeroMemory(&eigenall,sizeof(eigenall));
\r
266 connectedinput->GetAllocatorRequirements(&eigenall);
\r
267 if (eigenall.cbAlign==0) eigenall.cbAlign=1;
\r
268 connectedinput->GetAllocator(&allocator);
\r
269 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
\r
270 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
\r
272 LeaveCriticalSection(&m_pFilter->filterlock);
\r
276 if (allocator!=NULL) allocator->Release();
\r
279 if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER,
\r
280 IID_IMemAllocator,(void **)allocator)==S_OK) {
\r
281 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
\r
282 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
\r
284 LeaveCriticalSection(&m_pFilter->filterlock);
\r
289 if (allocator!=NULL) allocator->Release();
\r
291 connected->Release();
\r
293 connectedinput->Release();
\r
294 connectedinput=NULL;
\r
295 LeaveCriticalSection(&m_pFilter->filterlock);
\r
296 return VFW_E_NO_TRANSPORT;
\r
302 HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect,
\r
303 const AM_MEDIA_TYPE *mtype){
\r
304 return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins
\r
306 HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() {
\r
307 EnterCriticalSection(&m_pFilter->filterlock);
\r
308 if (connected!=NULL) {
\r
309 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
\r
310 /*TODO: Decommit allocator*/
\r
311 allocator->Decommit();
\r
312 allocator->Release();
\r
314 ReleaseMType(&medtype);
\r
315 connectedinput->Release();
\r
316 connectedinput=NULL;
\r
317 connected->Release();
\r
319 LeaveCriticalSection(&m_pFilter->filterlock);
\r
322 LeaveCriticalSection(&m_pFilter->filterlock);
\r
326 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){
\r
327 if (pin==NULL) return E_POINTER;
\r
328 IPin* pinn=connected;
\r
334 return VFW_E_NOT_CONNECTED;
\r
337 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){
\r
338 if (mtype==NULL) return E_POINTER;
\r
339 if (connected!=NULL){
\r
340 CopyMType(mtype,&medtype);
\r
343 ZeroMemory(mtype,sizeof(mtype));
\r
344 return VFW_E_NOT_CONNECTED;
\r
347 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){
\r
348 if (info==NULL) return E_POINTER;
\r
349 info->dir=PINDIR_OUTPUT;
\r
350 info->pFilter=(IBaseFilter*)m_pFilter;
\r
351 if (m_pFilter) m_pFilter->AddRef();
\r
352 if (isaudiopin) wcscpy(info->achName,L"Audio");
\r
353 else wcscpy(info->achName,L"Video");
\r
357 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryDirection(PIN_DIRECTION *dir){
\r
358 if (dir==NULL) return E_POINTER;
\r
359 *dir=PINDIR_OUTPUT;
\r
362 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){
\r
363 if (id==NULL) return E_POINTER;
\r
364 *id=(LPWSTR)CoTaskMemAlloc(12);
\r
365 if (*id==NULL) return E_OUTOFMEMORY;
\r
368 if (isaudiopin) wcscpy(*id,L"Audio");
\r
369 else wcscpy(*id, L"Video");
\r
372 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) {
\r
373 if (mtype==NULL) return S_FALSE;
\r
374 if (CheckMediaType(mtype)==S_OK) return S_OK;
\r
375 else return S_FALSE;
\r
377 HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){
\r
378 if (enuma==NULL) return E_POINTER;
\r
379 *enuma=new DsSFEnumMediaTypes( this);
\r
380 (*enuma)->AddRef();
\r
384 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){
\r
387 HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){
\r
388 return E_UNEXPECTED; //we are a output pin!
\r
391 HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){
\r
392 return E_UNEXPECTED;//we are a output pin!
\r
395 HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){
\r
396 if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0);
\r
397 else return E_NOINTERFACE;
\r
400 HRESULT DsSourcePin::deliver(IMediaSample * ms){
\r
401 //EnterCriticalSection(&m_pFilter->filterlock);
\r
403 if (connectedinput!=NULL)hres= connectedinput->Receive(ms);
\r
404 else hres= VFW_E_NOT_CONNECTED;
\r
405 //LeaveCriticalSection(&m_pFilter->filterlock);
\r
410 HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt)
\r
415 if (iPosition==0) {
\r
416 ZeroMemory(pmt,sizeof(*pmt));
\r
417 pmt->lSampleSize = 1;
\r
418 pmt->bFixedSizeSamples = TRUE;
\r
419 pmt->majortype=MEDIATYPE_Audio;
\r
420 MPEG1WAVEFORMAT wfe;
\r
421 ZeroMemory(&wfe,sizeof(wfe));
\r
423 wfe.wfx.nSamplesPerSec=48000;
\r
424 wfe.wfx.nChannels=2;
\r
425 wfe.wfx.nAvgBytesPerSec=32000;
\r
426 wfe.wfx.nBlockAlign=768;
\r
427 wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG;
\r
429 wfe.dwHeadBitrate=256000;
\r
430 wfe.fwHeadMode=ACM_MPEG_STEREO;
\r
431 wfe.fwHeadModeExt=1;
\r
432 wfe.wHeadEmphasis=1;
\r
433 wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;
\r
434 pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO;
\r
435 pmt->formattype=FORMAT_WaveFormatEx;
\r
436 pmt->cbFormat=sizeof(wfe);
\r
437 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe));
\r
438 memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
\r
439 pmt->lSampleSize=0;
\r
444 hr=VFW_S_NO_MORE_ITEMS ;
\r
447 if (iPosition == 0) {
\r
448 ZeroMemory(pmt,sizeof(*pmt));
\r
449 pmt->lSampleSize = 1;
\r
450 pmt->bFixedSizeSamples = TRUE;
\r
451 pmt->majortype=MEDIATYPE_Video;
\r
453 pmt->subtype=MEDIASUBTYPE_MPEG2_VIDEO;
\r
454 pmt->formattype=FORMAT_MPEG2Video;
\r
456 MPEG2VIDEOINFO hdr;
\r
457 ZeroMemory(&hdr,sizeof(hdr));
\r
458 hdr.dwProfile=AM_MPEG2Profile_Main;
\r
459 hdr.dwLevel=AM_MPEG2Level_Main;
\r
460 hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader);
\r
461 hdr.hdr.bmiHeader.biWidth = 720;
\r
462 hdr.hdr.bmiHeader.biHeight = 568;
\r
463 pmt->cbFormat=sizeof(hdr);
\r
464 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(hdr));
\r
465 memcpy(pmt->pbFormat,&hdr,sizeof(hdr));
\r
468 hr=VFW_S_NO_MORE_ITEMS;
\r
474 HRESULT DsSourcePin::Inactive() {
\r
475 if (allocator!=NULL) return allocator->Decommit();
\r
476 return VFW_E_NO_ALLOCATOR;
\r
479 HRESULT DsSourcePin::Active() {
\r
480 if (allocator!=NULL) return allocator->Commit();
\r
481 return VFW_E_NO_ALLOCATOR;
\r
485 HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){
\r
490 HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt)
\r
495 bool subtype=false;
\r
496 #if 0 /* For future demands ac3 */
\r
497 subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3);
\r
499 subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO));
\r
500 if (pmt->majortype==MEDIATYPE_Audio && subtype) {
\r
506 if (pmt->majortype==MEDIATYPE_Video &&
\r
507 pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) {
\r
516 HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){
\r
519 if (pa==NULL)return E_POINTER;
\r
520 if (all_pp==NULL) return E_POINTER;
\r
522 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
\r
524 //all_pp->cBuffers = 300;//old
\r
525 all_pp->cBuffers = 10;
\r
526 all_pp->cbBuffer = 64*1024;
\r
529 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
\r
531 //all_pp->cBuffers = 300;//old
\r
532 all_pp->cBuffers = 30;
\r
533 all_pp->cbBuffer = 64*1024;
\r
537 ALLOCATOR_PROPERTIES all_pp_cur;
\r
538 hr =pa->SetProperties(all_pp,&all_pp_cur);
\r
543 if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer)
\r