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) {
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) return S_FALSE;
65 if (fetched!=NULL) (*fetched)++;
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){
87 if (object==NULL) return E_POINTER;
88 if (id==IID_IUnknown ||id == IID_IEnumMediaTypes) {
89 *object=(IUnknown*)this;
90 ((IUnknown*)object)->AddRef();
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){
154 if (object==NULL) return E_POINTER;
155 if (id==IID_IUnknown) {
156 *object=(IUnknown*)this;
157 ((IUnknown*)object)->AddRef();
159 } else if (id==IID_IPin) {
161 ((IPin*)object)->AddRef();
165 return E_NOINTERFACE;
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_np;
\r
212 AM_MEDIA_TYPE * emtype;
\r
216 while (emt->Next(1,&emtype,&fetched)==S_OK) {
\r
217 if (CheckMediaType(emtype)==S_OK){
\r
218 if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {
\r
220 CopyMType(&medtype,emtype);
\r
221 CoTaskMemFree(emtype->pbFormat);
\r
227 CoTaskMemFree(emtype->pbFormat);
\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
243 CoTaskMemFree(emtype->pbFormat);
\r
246 if (gotmt==false) {
\r
247 pinempf->Release();
\r
248 LeaveCriticalSection(&m_pFilter->filterlock);
\r
249 return VFW_E_NO_ACCEPTABLE_TYPES;
\r
254 if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) {
\r
255 LeaveCriticalSection(&m_pFilter->filterlock);
\r
256 connected->Release();
\r
258 /* connectedinput->Release();
\r
259 connectedinput=NULL;*/
\r
260 return VFW_E_NO_TRANSPORT;
\r
262 ALLOCATOR_PROPERTIES eigenall;
\r
263 ZeroMemory(&eigenall,sizeof(eigenall));
\r
264 connectedinput->GetAllocatorRequirements(&eigenall);
\r
265 if (eigenall.cbAlign==0) eigenall.cbAlign=1;
\r
266 connectedinput->GetAllocator(&allocator);
\r
267 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
\r
268 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
\r
270 LeaveCriticalSection(&m_pFilter->filterlock);
\r
274 if (allocator!=NULL) allocator->Release();
\r
277 if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER,
\r
278 IID_IMemAllocator,(void **)allocator)==S_OK) {
\r
279 if (DecideBufferSize(allocator,&eigenall)==S_OK) {
\r
280 if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){
\r
282 LeaveCriticalSection(&m_pFilter->filterlock);
\r
287 if (allocator!=NULL) allocator->Release();
\r
289 connected->Release();
\r
291 connectedinput->Release();
\r
292 connectedinput=NULL;
\r
293 LeaveCriticalSection(&m_pFilter->filterlock);
\r
294 return VFW_E_NO_TRANSPORT;
\r
300 HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect,
\r
301 const AM_MEDIA_TYPE *mtype){
\r
302 return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins
\r
304 HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() {
\r
305 EnterCriticalSection(&m_pFilter->filterlock);
\r
306 if (connected!=NULL) {
\r
307 if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}
\r
308 /*TODO: Decommit allocator*/
\r
309 allocator->Decommit();
\r
310 allocator->Release();
\r
312 ReleaseMType(&medtype);
\r
313 connectedinput->Release();
\r
314 connectedinput=NULL;
\r
315 connected->Release();
\r
317 LeaveCriticalSection(&m_pFilter->filterlock);
\r
320 LeaveCriticalSection(&m_pFilter->filterlock);
\r
324 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){
\r
325 if (pin==NULL) return E_POINTER;
\r
326 IPin* pinn=connected;
\r
332 return VFW_E_NOT_CONNECTED;
\r
335 HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){
\r
336 if (mtype==NULL) return E_POINTER;
\r
337 if (connected!=NULL){
\r
338 CopyMType(mtype,&medtype);
\r
341 ZeroMemory(mtype,sizeof(mtype));
\r
342 return VFW_E_NOT_CONNECTED;
\r
345 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){
\r
346 if (info==NULL) return E_POINTER;
\r
347 info->dir=PINDIR_OUTPUT;
\r
348 info->pFilter=(IBaseFilter*)m_pFilter;
\r
349 if (m_pFilter) m_pFilter->AddRef();
\r
350 if (isaudiopin) wcscpy(info->achName,L"Audio");
\r
351 else wcscpy(info->achName,L"Video");
\r
355 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryDirection(PIN_DIRECTION *dir){
\r
356 if (dir==NULL) return E_POINTER;
\r
357 *dir=PINDIR_OUTPUT;
\r
360 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){
\r
361 if (id==NULL) return E_POINTER;
\r
362 *id=(LPWSTR)CoTaskMemAlloc(12);
\r
363 if (*id==NULL) return E_OUTOFMEMORY;
\r
366 if (isaudiopin) wcscpy(*id,L"Audio");
\r
367 else wcscpy(*id, L"Video");
\r
370 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) {
\r
371 if (mtype==NULL) return S_FALSE;
\r
372 if (CheckMediaType(mtype)==S_OK) return S_OK;
\r
373 else return S_FALSE;
\r
375 HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){
\r
376 if (enuma==NULL) return E_POINTER;
377 *enuma=new DsSFEnumMediaTypes( this);
382 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){
\r
385 HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){
\r
386 return E_UNEXPECTED; //we are a output pin!
\r
389 HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){
\r
390 return E_UNEXPECTED;//we are a output pin!
\r
393 HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){
\r
394 if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0);
\r
395 else return E_NOINTERFACE;
\r
398 HRESULT DsSourcePin::deliver(IMediaSample * ms){
\r
399 //EnterCriticalSection(&m_pFilter->filterlock);
\r
401 if (connectedinput!=NULL)hres= connectedinput->Receive(ms);
\r
402 else hres= VFW_E_NOT_CONNECTED;
\r
403 //LeaveCriticalSection(&m_pFilter->filterlock);
\r
408 HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt)
\r
413 if (iPosition==0) {
\r
414 ZeroMemory(pmt,sizeof(*pmt));
\r
415 pmt->lSampleSize = 1;
\r
416 pmt->bFixedSizeSamples = TRUE;
\r
417 pmt->majortype=MEDIATYPE_Audio;
\r
418 MPEG1WAVEFORMAT wfe;
\r
419 ZeroMemory(&wfe,sizeof(wfe));
\r
421 wfe.wfx.nSamplesPerSec=48000;
\r
422 wfe.wfx.nChannels=2;
\r
423 wfe.wfx.nAvgBytesPerSec=32000;
\r
424 wfe.wfx.nBlockAlign=768;
\r
425 wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG;
\r
427 wfe.dwHeadBitrate=256000;
\r
428 wfe.fwHeadMode=ACM_MPEG_STEREO;
\r
429 wfe.fwHeadModeExt=1;
\r
430 wfe.wHeadEmphasis=1;
\r
431 wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;
\r
432 pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO;
\r
433 pmt->formattype=FORMAT_WaveFormatEx;
\r
434 pmt->cbFormat=sizeof(wfe);
\r
435 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe));
\r
436 memcpy(pmt->pbFormat,&wfe,sizeof(wfe));
\r
437 pmt->lSampleSize=0;
\r
442 hr=VFW_S_NO_MORE_ITEMS ;
\r
445 if (iPosition == 0) {
\r
446 ZeroMemory(pmt,sizeof(*pmt));
\r
447 pmt->lSampleSize = 1;
\r
448 pmt->bFixedSizeSamples = TRUE;
\r
449 pmt->majortype=MEDIATYPE_Video;
\r
451 pmt->subtype=MEDIASUBTYPE_MPEG2_VIDEO;
\r
452 pmt->formattype=FORMAT_MPEG2Video;
\r
454 MPEG2VIDEOINFO hdr;
\r
455 ZeroMemory(&hdr,sizeof(hdr));
\r
456 hdr.dwProfile=AM_MPEG2Profile_Main;
\r
457 hdr.dwLevel=AM_MPEG2Level_Main;
\r
458 hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader);
\r
459 hdr.hdr.bmiHeader.biWidth = 720;
\r
460 hdr.hdr.bmiHeader.biHeight = 568;
\r
461 pmt->cbFormat=sizeof(hdr);
\r
462 pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(hdr));
\r
463 memcpy(pmt->pbFormat,&hdr,sizeof(hdr));
\r
466 hr=VFW_S_NO_MORE_ITEMS;
\r
472 HRESULT DsSourcePin::Inactive() {
\r
473 if (allocator!=NULL) return allocator->Decommit();
\r
474 return VFW_E_NO_ALLOCATOR;
\r
477 HRESULT DsSourcePin::Active() {
\r
478 if (allocator!=NULL) return allocator->Commit();
\r
479 return VFW_E_NO_ALLOCATOR;
\r
483 HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){
\r
488 HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt)
\r
493 bool subtype=false;
\r
494 #if 0 /* For future demands ac3 */
\r
495 subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3);
\r
497 subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO));
\r
498 if (pmt->majortype==MEDIATYPE_Audio && subtype) {
\r
504 if (pmt->majortype==MEDIATYPE_Video &&
\r
505 pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) {
\r
514 HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){
\r
517 if (pa==NULL)return E_POINTER;
\r
518 if (all_pp==NULL) return E_POINTER;
\r
520 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
\r
522 //all_pp->cBuffers = 300;//old
\r
523 all_pp->cBuffers = 10;
\r
524 all_pp->cbBuffer = 64*1024;
\r
527 if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
\r
529 //all_pp->cBuffers = 300;//old
\r
530 all_pp->cBuffers = 30;
\r
531 all_pp->cbBuffer = 64*1024;
\r
535 ALLOCATOR_PROPERTIES all_pp_cur;
\r
536 hr =pa->SetProperties(all_pp,&all_pp_cur);
\r
541 if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer)
\r