1 /*****************************************************************************
2 * filter.cpp : DirectShow access module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2010 the VideoLAN team
7 * Author: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_fourcc.h>
36 /* Work-around a bug in w32api-2.5 */
37 # define QACONTAINERFLAGS QACONTAINERFLAGS_SOMETHINGELSE
42 #include "vlc_dshow.h"
45 DEFINE_GUID(MEDIASUBTYPE_HDYC ,0x43594448 /* CYDH */ , 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
46 DEFINE_GUID(MEDIASUBTYPE_DIVX ,0x58564944 /* XVID */ , 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
51 #define FILTER_NAME L"VideoLAN Capture Filter"
52 #define PIN_NAME L"Capture"
54 void WINAPI FreeMediaType( AM_MEDIA_TYPE& mt )
56 if( mt.cbFormat != 0 )
58 CoTaskMemFree( (PVOID)mt.pbFormat );
69 HRESULT WINAPI CopyMediaType( AM_MEDIA_TYPE *pmtTarget,
70 const AM_MEDIA_TYPE *pmtSource )
72 *pmtTarget = *pmtSource;
74 if( !pmtSource || !pmtTarget ) return S_FALSE;
76 if( pmtSource->cbFormat && pmtSource->pbFormat )
78 pmtTarget->pbFormat = (PBYTE)CoTaskMemAlloc( pmtSource->cbFormat );
79 if( pmtTarget->pbFormat == NULL )
81 pmtTarget->cbFormat = 0;
86 CopyMemory( (PVOID)pmtTarget->pbFormat, (PVOID)pmtSource->pbFormat,
87 pmtTarget->cbFormat );
90 if( pmtTarget->pUnk != NULL )
92 pmtTarget->pUnk->AddRef();
98 int GetFourCCFromMediaType( const AM_MEDIA_TYPE &media_type )
102 if( media_type.majortype == MEDIATYPE_Video )
104 /* currently only support this type of video info format */
105 if( 1 /* media_type.formattype == FORMAT_VideoInfo */ )
107 /* Packed RGB formats */
108 if( media_type.subtype == MEDIASUBTYPE_RGB1 )
109 i_fourcc = VLC_FOURCC( 'R', 'G', 'B', '1' );
110 else if( media_type.subtype == MEDIASUBTYPE_RGB4 )
111 i_fourcc = VLC_FOURCC( 'R', 'G', 'B', '4' );
112 else if( media_type.subtype == MEDIASUBTYPE_RGB8 )
113 i_fourcc = VLC_FOURCC( 'R', 'G', 'B', '8' );
114 else if( media_type.subtype == MEDIASUBTYPE_RGB555 )
115 i_fourcc = VLC_CODEC_RGB15;
116 else if( media_type.subtype == MEDIASUBTYPE_RGB565 )
117 i_fourcc = VLC_CODEC_RGB16;
118 else if( media_type.subtype == MEDIASUBTYPE_RGB24 )
119 i_fourcc = VLC_CODEC_RGB24;
120 else if( media_type.subtype == MEDIASUBTYPE_RGB32 )
121 i_fourcc = VLC_CODEC_RGB32;
122 else if( media_type.subtype == MEDIASUBTYPE_ARGB32 )
123 i_fourcc = VLC_CODEC_RGBA;
125 /* Planar YUV formats */
126 else if( media_type.subtype == MEDIASUBTYPE_I420 )
127 i_fourcc = VLC_CODEC_I420;
128 else if( media_type.subtype == MEDIASUBTYPE_Y41P )
129 i_fourcc = VLC_CODEC_I411;
130 else if( media_type.subtype == MEDIASUBTYPE_YV12 )
131 i_fourcc = VLC_CODEC_YV12;
132 else if( media_type.subtype == MEDIASUBTYPE_IYUV )
133 i_fourcc = VLC_CODEC_YV12;
134 else if( media_type.subtype == MEDIASUBTYPE_YVU9 )
135 i_fourcc = VLC_CODEC_I410;
137 /* Packed YUV formats */
138 else if( media_type.subtype == MEDIASUBTYPE_YVYU )
139 i_fourcc = VLC_CODEC_YVYU;
140 else if( media_type.subtype == MEDIASUBTYPE_YUYV )
141 i_fourcc = VLC_CODEC_YUYV;
142 else if( media_type.subtype == MEDIASUBTYPE_Y411 )
143 i_fourcc = VLC_FOURCC( 'I', '4', '1', 'N' );
144 else if( media_type.subtype == MEDIASUBTYPE_Y211 )
145 i_fourcc = VLC_CODEC_Y211;
146 else if( media_type.subtype == MEDIASUBTYPE_YUY2 )
147 i_fourcc = VLC_CODEC_YUYV;
148 else if( media_type.subtype == MEDIASUBTYPE_UYVY )
149 i_fourcc = VLC_CODEC_UYVY;
150 /* HDYC uses UYVY sample positions but Rec709 colourimetry */
151 /* FIXME: When VLC understands colourspace, something will need
152 * to be added / changed here. Until then, just make it behave
154 else if( media_type.subtype == MEDIASUBTYPE_HDYC )
155 i_fourcc = VLC_CODEC_UYVY;
157 /* MPEG2 video elementary stream */
158 else if( media_type.subtype == MEDIASUBTYPE_MPEG2_VIDEO )
159 i_fourcc = VLC_CODEC_MPGV;
162 else if( media_type.subtype == MEDIASUBTYPE_DIVX )
163 i_fourcc = VLC_CODEC_MP4V;
166 else if( media_type.subtype == MEDIASUBTYPE_dvsl )
167 i_fourcc = VLC_CODEC_DV;
168 else if( media_type.subtype == MEDIASUBTYPE_dvsd )
169 i_fourcc = VLC_CODEC_DV;
170 else if( media_type.subtype == MEDIASUBTYPE_dvhd )
171 i_fourcc = VLC_CODEC_DV;
174 else if( media_type.subtype == MEDIASUBTYPE_MJPG )
175 i_fourcc = VLC_CODEC_MJPG;
179 else if( media_type.majortype == MEDIATYPE_Audio )
181 /* currently only support this type of audio info format */
182 if( media_type.formattype == FORMAT_WaveFormatEx )
184 if( media_type.subtype == MEDIASUBTYPE_PCM )
185 i_fourcc = VLC_FOURCC( 'a', 'r', 'a', 'w' );
186 else if( media_type.subtype == MEDIASUBTYPE_IEEE_FLOAT )
187 i_fourcc = VLC_CODEC_FL32;
190 else if( media_type.majortype == MEDIATYPE_Stream )
192 if( media_type.subtype == MEDIASUBTYPE_MPEG2_PROGRAM )
193 i_fourcc = VLC_FOURCC( 'm', 'p', '2', 'p' );
194 else if( media_type.subtype == MEDIASUBTYPE_MPEG2_TRANSPORT )
195 i_fourcc = VLC_FOURCC( 'm', 'p', '2', 't' );
201 /****************************************************************************
202 * Implementation of our dummy directshow filter pin class
203 ****************************************************************************/
205 CapturePin::CapturePin( vlc_object_t *_p_input, access_sys_t *_p_sys,
206 CaptureFilter *_p_filter,
207 AM_MEDIA_TYPE *mt, size_t mt_count )
208 : p_input( _p_input ), p_sys( _p_sys ), p_filter( _p_filter ),
209 p_connected_pin( NULL ), media_types(mt), media_type_count(mt_count),
212 cx_media_type.majortype = mt[0].majortype;
213 cx_media_type.subtype = GUID_NULL;
214 cx_media_type.pbFormat = NULL;
215 cx_media_type.cbFormat = 0;
216 cx_media_type.pUnk = NULL;
219 CapturePin::~CapturePin()
222 msg_Dbg( p_input, "CapturePin::~CapturePin" );
224 for( size_t c=0; c<media_type_count; c++ )
226 FreeMediaType(media_types[c]);
228 FreeMediaType(cx_media_type);
232 * Returns the complete queue of samples that have been received so far.
233 * Lock the p_sys->lock before calling this function.
234 * @param samples_queue [out] Empty queue that will get all elements from
236 * @return S_OK if a sample was available, S_FALSE if no sample was
239 HRESULT CapturePin::CustomGetSamples( deque<VLCMediaSample> &external_queue )
241 #if 0 //def DEBUG_DSHOW
242 msg_Dbg( p_input, "CapturePin::CustomGetSamples: %d samples in the queue", samples_queue.size());
245 if( !samples_queue.empty() )
247 external_queue.swap(samples_queue);
254 * Returns a sample from its sample queue. Proper locking must be done prior
255 * to this call. Current dshow code protects the access to any sample queue
256 * (audio and video) with the p_sys->lock
257 * @param vlc_sample [out] Address of a sample if sucessfull. Undefined
259 * @return S_OK if a sample was available, S_FALSE if no sample was
262 HRESULT CapturePin::CustomGetSample( VLCMediaSample *vlc_sample )
264 #if 0 //def DEBUG_DSHOW
265 msg_Dbg( p_input, "CapturePin::CustomGetSample" );
268 if( !samples_queue.empty() )
270 *vlc_sample = samples_queue.back();
271 samples_queue.pop_back();
277 AM_MEDIA_TYPE &CapturePin::CustomGetMediaType()
279 return cx_media_type;
282 /* IUnknown methods */
283 STDMETHODIMP CapturePin::QueryInterface(REFIID riid, void **ppv)
285 #ifdef DEBUG_DSHOW_L1
286 msg_Dbg( p_input, "CapturePin::QueryInterface" );
289 if( riid == IID_IUnknown ||
296 if( riid == IID_IMemInputPin )
299 *ppv = (IMemInputPin *)this;
304 #ifdef DEBUG_DSHOW_L1
305 msg_Dbg( p_input, "CapturePin::QueryInterface() failed for: "
306 "%04X-%02X-%02X-%02X%02X%02X%02X%02X%02X%02X%02X",
307 (int)riid.Data1, (int)riid.Data2, (int)riid.Data3,
308 static_cast<int>(riid.Data4[0]), (int)riid.Data4[1],
309 (int)riid.Data4[2], (int)riid.Data4[3],
310 (int)riid.Data4[4], (int)riid.Data4[5],
311 (int)riid.Data4[6], (int)riid.Data4[7] );
314 return E_NOINTERFACE;
318 STDMETHODIMP_(ULONG) CapturePin::AddRef()
320 #ifdef DEBUG_DSHOW_L1
321 msg_Dbg( p_input, "CapturePin::AddRef (ref: %i)", i_ref );
326 STDMETHODIMP_(ULONG) CapturePin::Release()
328 #ifdef DEBUG_DSHOW_L1
329 msg_Dbg( p_input, "CapturePin::Release (ref: %i)", i_ref );
332 if( !InterlockedDecrement(&i_ref) ) delete this;
338 STDMETHODIMP CapturePin::Connect( IPin *,
339 const AM_MEDIA_TYPE *pmt )
341 if( State_Running == p_filter->state )
343 msg_Dbg( p_input, "CapturePin::Connect [not stopped]" );
344 return VFW_E_NOT_STOPPED;
347 if( p_connected_pin )
349 msg_Dbg( p_input, "CapturePin::Connect [already connected]" );
350 return VFW_E_ALREADY_CONNECTED;
353 if( !pmt ) return S_OK;
355 if( GUID_NULL != pmt->majortype &&
356 media_types[0].majortype != pmt->majortype )
358 msg_Dbg( p_input, "CapturePin::Connect [media major type mismatch]" );
362 if( GUID_NULL != pmt->subtype && !GetFourCCFromMediaType(*pmt) )
364 msg_Dbg( p_input, "CapturePin::Connect [media subtype type "
369 if( pmt->pbFormat && pmt->majortype == MEDIATYPE_Video )
371 if( !((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biHeight ||
372 !((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biWidth )
374 msg_Dbg( p_input, "CapturePin::Connect "
375 "[video width/height == 0 ]" );
380 msg_Dbg( p_input, "CapturePin::Connect [OK]" );
383 STDMETHODIMP CapturePin::ReceiveConnection( IPin * pConnector,
384 const AM_MEDIA_TYPE *pmt )
386 if( State_Stopped != p_filter->state )
388 msg_Dbg( p_input, "CapturePin::ReceiveConnection [not stopped]" );
389 return VFW_E_NOT_STOPPED;
392 if( !pConnector || !pmt )
394 msg_Dbg( p_input, "CapturePin::ReceiveConnection [null pointer]" );
398 if( p_connected_pin )
400 msg_Dbg( p_input, "CapturePin::ReceiveConnection [already connected]");
401 return VFW_E_ALREADY_CONNECTED;
404 if( S_OK != QueryAccept(pmt) )
406 msg_Dbg( p_input, "CapturePin::ReceiveConnection "
407 "[media type not accepted]" );
408 return VFW_E_TYPE_NOT_ACCEPTED;
411 msg_Dbg( p_input, "CapturePin::ReceiveConnection [OK]" );
413 p_connected_pin = pConnector;
414 p_connected_pin->AddRef();
416 FreeMediaType( cx_media_type );
417 return CopyMediaType( &cx_media_type, pmt );
419 STDMETHODIMP CapturePin::Disconnect()
421 if( ! p_connected_pin )
423 msg_Dbg( p_input, "CapturePin::Disconnect [not connected]" );
427 msg_Dbg( p_input, "CapturePin::Disconnect [OK]" );
429 /* samples_queue was already flushed in EndFlush() */
431 p_connected_pin->Release();
432 p_connected_pin = NULL;
433 //FreeMediaType( cx_media_type );
434 //cx_media_type.subtype = GUID_NULL;
438 STDMETHODIMP CapturePin::ConnectedTo( IPin **pPin )
440 if( !p_connected_pin )
442 msg_Dbg( p_input, "CapturePin::ConnectedTo [not connected]" );
443 return VFW_E_NOT_CONNECTED;
446 p_connected_pin->AddRef();
447 *pPin = p_connected_pin;
449 msg_Dbg( p_input, "CapturePin::ConnectedTo [OK]" );
453 STDMETHODIMP CapturePin::ConnectionMediaType( AM_MEDIA_TYPE *pmt )
455 if( !p_connected_pin )
457 msg_Dbg( p_input, "CapturePin::ConnectionMediaType [not connected]" );
458 return VFW_E_NOT_CONNECTED;
461 return CopyMediaType( pmt, &cx_media_type );
463 STDMETHODIMP CapturePin::QueryPinInfo( PIN_INFO * pInfo )
466 msg_Dbg( p_input, "CapturePin::QueryPinInfo" );
469 pInfo->pFilter = p_filter;
470 if( p_filter ) p_filter->AddRef();
472 memcpy(pInfo->achName, PIN_NAME, sizeof(PIN_NAME));
473 pInfo->dir = PINDIR_INPUT;
477 STDMETHODIMP CapturePin::QueryDirection( PIN_DIRECTION * pPinDir )
480 msg_Dbg( p_input, "CapturePin::QueryDirection" );
483 *pPinDir = PINDIR_INPUT;
486 STDMETHODIMP CapturePin::QueryId( LPWSTR * Id )
489 msg_Dbg( p_input, "CapturePin::QueryId" );
492 *Id = (LPWSTR)L"VLC Capture Pin";
496 STDMETHODIMP CapturePin::QueryAccept( const AM_MEDIA_TYPE *pmt )
498 if( State_Stopped != p_filter->state )
500 msg_Dbg( p_input, "CapturePin::QueryAccept [not stopped]" );
504 if( media_types[0].majortype != pmt->majortype )
506 msg_Dbg( p_input, "CapturePin::QueryAccept [media type mismatch]" );
510 int i_fourcc = GetFourCCFromMediaType(*pmt);
513 msg_Dbg( p_input, "CapturePin::QueryAccept "
514 "[media type not supported]" );
518 if( pmt->majortype == MEDIATYPE_Video )
521 ( (((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biHeight == 0) ||
522 (((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biWidth == 0) ) )
524 msg_Dbg( p_input, "CapturePin::QueryAccept [video size wxh == 0]");
528 msg_Dbg( p_input, "CapturePin::QueryAccept [OK] "
529 "(width=%ld, height=%ld, chroma=%4.4s, fps=%f)",
530 ((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biWidth,
531 ((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biHeight,
533 10000000.0f/((float)((VIDEOINFOHEADER *)pmt->pbFormat)->AvgTimePerFrame) );
535 else if( pmt->majortype == MEDIATYPE_Audio )
537 msg_Dbg( p_input, "CapturePin::QueryAccept [OK] (channels=%d, "
538 "samples/sec=%lu, bits/samples=%d, format=%4.4s)",
539 ((WAVEFORMATEX *)pmt->pbFormat)->nChannels,
540 ((WAVEFORMATEX *)pmt->pbFormat)->nSamplesPerSec,
541 ((WAVEFORMATEX *)pmt->pbFormat)->wBitsPerSample,
546 msg_Dbg( p_input, "CapturePin::QueryAccept [OK] (stream format=%4.4s)",
550 if( p_connected_pin )
552 FreeMediaType( cx_media_type );
553 CopyMediaType( &cx_media_type, pmt );
558 STDMETHODIMP CapturePin::EnumMediaTypes( IEnumMediaTypes **ppEnum )
560 #ifdef DEBUG_DSHOW_L1
561 msg_Dbg( p_input, "CapturePin::EnumMediaTypes" );
564 *ppEnum = new CaptureEnumMediaTypes( p_input, this, NULL );
566 if( *ppEnum == NULL ) return E_OUTOFMEMORY;
570 STDMETHODIMP CapturePin::QueryInternalConnections( IPin**, ULONG * )
572 #ifdef DEBUG_DSHOW_L1
573 msg_Dbg( p_input, "CapturePin::QueryInternalConnections" );
577 STDMETHODIMP CapturePin::EndOfStream( void )
580 msg_Dbg( p_input, "CapturePin::EndOfStream" );
584 STDMETHODIMP CapturePin::BeginFlush( void )
587 msg_Dbg( p_input, "CapturePin::BeginFlush" );
591 STDMETHODIMP CapturePin::EndFlush( void )
594 msg_Dbg( p_input, "CapturePin::EndFlush" );
597 VLCMediaSample vlc_sample;
599 vlc_mutex_lock( &p_sys->lock );
600 while( !samples_queue.empty() )
602 vlc_sample = samples_queue.back();
603 samples_queue.pop_back();
604 vlc_sample.p_sample->Release();
606 vlc_mutex_unlock( &p_sys->lock );
610 STDMETHODIMP CapturePin::NewSegment( REFERENCE_TIME, REFERENCE_TIME, double )
613 msg_Dbg( p_input, "CapturePin::NewSegment" );
618 /* IMemInputPin methods */
619 STDMETHODIMP CapturePin::GetAllocator( IMemAllocator ** )
622 msg_Dbg( p_input, "CapturePin::GetAllocator" );
625 return VFW_E_NO_ALLOCATOR;
627 STDMETHODIMP CapturePin::NotifyAllocator( IMemAllocator *, BOOL )
630 msg_Dbg( p_input, "CapturePin::NotifyAllocator" );
635 STDMETHODIMP CapturePin::GetAllocatorRequirements( ALLOCATOR_PROPERTIES * )
638 msg_Dbg( p_input, "CapturePin::GetAllocatorRequirements" );
643 STDMETHODIMP CapturePin::Receive( IMediaSample *pSample )
645 #if 0 //def DEBUG_DSHOW
646 msg_Dbg( p_input, "CapturePin::Receive" );
650 mtime_t i_timestamp = mdate() * 10;
651 VLCMediaSample vlc_sample = {pSample, i_timestamp};
653 vlc_mutex_lock( &p_sys->lock );
654 samples_queue.push_front( vlc_sample );
656 /* Make sure we don't cache too many samples */
657 if( samples_queue.size() > 10 )
659 vlc_sample = samples_queue.back();
660 samples_queue.pop_back();
661 msg_Dbg( p_input, "CapturePin::Receive trashing late input sample" );
662 vlc_sample.p_sample->Release();
665 vlc_cond_signal( &p_sys->wait );
666 vlc_mutex_unlock( &p_sys->lock );
670 STDMETHODIMP CapturePin::ReceiveMultiple( IMediaSample **pSamples,
672 long *nSamplesProcessed )
676 *nSamplesProcessed = 0;
677 while( nSamples-- > 0 )
679 hr = Receive( pSamples[*nSamplesProcessed] );
680 if( hr != S_OK ) break;
681 (*nSamplesProcessed)++;
685 STDMETHODIMP CapturePin::ReceiveCanBlock( void )
688 msg_Dbg( p_input, "CapturePin::ReceiveCanBlock" );
691 return S_FALSE; /* Thou shalt not block */
694 /****************************************************************************
695 * Implementation of our dummy directshow filter class
696 ****************************************************************************/
697 CaptureFilter::CaptureFilter( vlc_object_t *_p_input, access_sys_t *p_sys,
698 AM_MEDIA_TYPE *mt, size_t mt_count )
699 : p_input( _p_input ),
700 p_pin( new CapturePin( _p_input, p_sys, this, mt, mt_count ) ),
701 state( State_Stopped ), i_ref( 1 )
705 CaptureFilter::~CaptureFilter()
708 msg_Dbg( p_input, "CaptureFilter::~CaptureFilter" );
713 /* IUnknown methods */
714 STDMETHODIMP CaptureFilter::QueryInterface( REFIID riid, void **ppv )
716 #ifdef DEBUG_DSHOW_L1
717 msg_Dbg( p_input, "CaptureFilter::QueryInterface" );
720 if( riid == IID_IUnknown )
723 *ppv = (IUnknown *)this;
726 if( riid == IID_IPersist )
729 *ppv = (IPersist *)this;
732 if( riid == IID_IMediaFilter )
735 *ppv = (IMediaFilter *)this;
738 if( riid == IID_IBaseFilter )
741 *ppv = (IBaseFilter *)this;
746 #ifdef DEBUG_DSHOW_L1
747 msg_Dbg( p_input, "CaptureFilter::QueryInterface() failed for: "
748 "%04X-%02X-%02X-%02X%02X%02X%02X%02X%02X%02X%02X",
749 (int)riid.Data1, (int)riid.Data2, (int)riid.Data3,
750 static_cast<int>(riid.Data4[0]), (int)riid.Data4[1],
751 (int)riid.Data4[2], (int)riid.Data4[3],
752 (int)riid.Data4[4], (int)riid.Data4[5],
753 (int)riid.Data4[6], (int)riid.Data4[7] );
756 return E_NOINTERFACE;
759 STDMETHODIMP_(ULONG) CaptureFilter::AddRef()
761 #ifdef DEBUG_DSHOW_L1
762 msg_Dbg( p_input, "CaptureFilter::AddRef (ref: %i)", i_ref );
767 STDMETHODIMP_(ULONG) CaptureFilter::Release()
769 #ifdef DEBUG_DSHOW_L1
770 msg_Dbg( p_input, "CaptureFilter::Release (ref: %i)", i_ref );
773 if( !InterlockedDecrement(&i_ref) ) delete this;
778 /* IPersist method */
779 STDMETHODIMP CaptureFilter::GetClassID(CLSID *)
782 msg_Dbg( p_input, "CaptureFilter::GetClassID" );
787 /* IMediaFilter methods */
788 STDMETHODIMP CaptureFilter::GetState(DWORD, FILTER_STATE *State)
791 msg_Dbg( p_input, "CaptureFilter::GetState %i", state );
797 STDMETHODIMP CaptureFilter::SetSyncSource(IReferenceClock *)
800 msg_Dbg( p_input, "CaptureFilter::SetSyncSource" );
805 STDMETHODIMP CaptureFilter::GetSyncSource(IReferenceClock **pClock)
808 msg_Dbg( p_input, "CaptureFilter::GetSyncSource" );
814 STDMETHODIMP CaptureFilter::Stop()
817 msg_Dbg( p_input, "CaptureFilter::Stop" );
822 state = State_Stopped;
825 STDMETHODIMP CaptureFilter::Pause()
828 msg_Dbg( p_input, "CaptureFilter::Pause" );
831 state = State_Paused;
834 STDMETHODIMP CaptureFilter::Run(REFERENCE_TIME)
837 msg_Dbg( p_input, "CaptureFilter::Run" );
840 state = State_Running;
844 /* IBaseFilter methods */
845 STDMETHODIMP CaptureFilter::EnumPins( IEnumPins ** ppEnum )
848 msg_Dbg( p_input, "CaptureFilter::EnumPins" );
851 /* Create a new ref counted enumerator */
852 *ppEnum = new CaptureEnumPins( p_input, this, NULL );
853 return *ppEnum == NULL ? E_OUTOFMEMORY : NOERROR;
855 STDMETHODIMP CaptureFilter::FindPin( LPCWSTR, IPin ** )
858 msg_Dbg( p_input, "CaptureFilter::FindPin" );
862 STDMETHODIMP CaptureFilter::QueryFilterInfo( FILTER_INFO * pInfo )
865 msg_Dbg( p_input, "CaptureFilter::QueryFilterInfo" );
868 memcpy(pInfo->achName, FILTER_NAME, sizeof(FILTER_NAME));
870 pInfo->pGraph = p_graph;
871 if( p_graph ) p_graph->AddRef();
875 STDMETHODIMP CaptureFilter::JoinFilterGraph( IFilterGraph * pGraph,
879 msg_Dbg( p_input, "CaptureFilter::JoinFilterGraph" );
886 STDMETHODIMP CaptureFilter::QueryVendorInfo( LPWSTR* )
889 msg_Dbg( p_input, "CaptureFilter::QueryVendorInfo" );
895 CapturePin *CaptureFilter::CustomGetPin()
900 /****************************************************************************
901 * Implementation of our dummy directshow enumpins class
902 ****************************************************************************/
904 CaptureEnumPins::CaptureEnumPins( vlc_object_t *_p_input,
905 CaptureFilter *_p_filter,
906 CaptureEnumPins *pEnumPins )
907 : p_input( _p_input ), p_filter( _p_filter ), i_ref( 1 )
909 /* Hold a reference count on our filter */
912 /* Are we creating a new enumerator */
914 if( pEnumPins == NULL )
920 i_position = pEnumPins->i_position;
924 CaptureEnumPins::~CaptureEnumPins()
926 #ifdef DEBUG_DSHOW_L1
927 msg_Dbg( p_input, "CaptureEnumPins::~CaptureEnumPins" );
932 /* IUnknown methods */
933 STDMETHODIMP CaptureEnumPins::QueryInterface( REFIID riid, void **ppv )
935 #ifdef DEBUG_DSHOW_L1
936 msg_Dbg( p_input, "CaptureEnumPins::QueryInterface" );
939 if( riid == IID_IUnknown ||
940 riid == IID_IEnumPins )
943 *ppv = (IEnumPins *)this;
949 return E_NOINTERFACE;
952 STDMETHODIMP_(ULONG) CaptureEnumPins::AddRef()
954 #ifdef DEBUG_DSHOW_L1
955 msg_Dbg( p_input, "CaptureEnumPins::AddRef (ref: %i)", i_ref );
960 STDMETHODIMP_(ULONG) CaptureEnumPins::Release()
962 #ifdef DEBUG_DSHOW_L1
963 msg_Dbg( p_input, "CaptureEnumPins::Release (ref: %i)", i_ref );
966 if( !InterlockedDecrement(&i_ref) ) delete this;
972 STDMETHODIMP CaptureEnumPins::Next( ULONG cPins, IPin ** ppPins,
975 #ifdef DEBUG_DSHOW_L1
976 msg_Dbg( p_input, "CaptureEnumPins::Next" );
979 unsigned int i_fetched = 0;
981 if( i_position < 1 && cPins > 0 )
983 IPin *pPin = p_filter->CustomGetPin();
990 if( pcFetched ) *pcFetched = i_fetched;
992 return (i_fetched == cPins) ? S_OK : S_FALSE;
994 STDMETHODIMP CaptureEnumPins::Skip( ULONG cPins )
996 #ifdef DEBUG_DSHOW_L1
997 msg_Dbg( p_input, "CaptureEnumPins::Skip" );
1000 i_position += cPins;
1002 if( i_position > 1 )
1009 STDMETHODIMP CaptureEnumPins::Reset()
1011 #ifdef DEBUG_DSHOW_L1
1012 msg_Dbg( p_input, "CaptureEnumPins::Reset" );
1018 STDMETHODIMP CaptureEnumPins::Clone( IEnumPins **ppEnum )
1020 #ifdef DEBUG_DSHOW_L1
1021 msg_Dbg( p_input, "CaptureEnumPins::Clone" );
1024 *ppEnum = new CaptureEnumPins( p_input, p_filter, this );
1025 if( *ppEnum == NULL ) return E_OUTOFMEMORY;
1030 /****************************************************************************
1031 * Implementation of our dummy directshow enummediatypes class
1032 ****************************************************************************/
1033 CaptureEnumMediaTypes::CaptureEnumMediaTypes( vlc_object_t *_p_input,
1034 CapturePin *_p_pin, CaptureEnumMediaTypes *pEnumMediaTypes )
1035 : p_input( _p_input ), p_pin( _p_pin ), i_ref( 1 )
1037 /* Hold a reference count on our filter */
1040 /* Are we creating a new enumerator */
1041 if( pEnumMediaTypes == NULL )
1043 CopyMediaType(&cx_media_type, &p_pin->cx_media_type);
1048 CopyMediaType(&cx_media_type, &pEnumMediaTypes->cx_media_type);
1049 i_position = pEnumMediaTypes->i_position;
1053 CaptureEnumMediaTypes::~CaptureEnumMediaTypes()
1055 #ifdef DEBUG_DSHOW_L1
1056 msg_Dbg( p_input, "CaptureEnumMediaTypes::~CaptureEnumMediaTypes" );
1058 FreeMediaType(cx_media_type);
1062 /* IUnknown methods */
1063 STDMETHODIMP CaptureEnumMediaTypes::QueryInterface( REFIID riid, void **ppv )
1065 #ifdef DEBUG_DSHOW_L1
1066 msg_Dbg( p_input, "CaptureEnumMediaTypes::QueryInterface" );
1069 if( riid == IID_IUnknown ||
1070 riid == IID_IEnumMediaTypes )
1073 *ppv = (IEnumMediaTypes *)this;
1079 return E_NOINTERFACE;
1082 STDMETHODIMP_(ULONG) CaptureEnumMediaTypes::AddRef()
1084 #ifdef DEBUG_DSHOW_L1
1085 msg_Dbg( p_input, "CaptureEnumMediaTypes::AddRef (ref: %i)", i_ref );
1090 STDMETHODIMP_(ULONG) CaptureEnumMediaTypes::Release()
1092 #ifdef DEBUG_DSHOW_L1
1093 msg_Dbg( p_input, "CaptureEnumMediaTypes::Release (ref: %i)", i_ref );
1096 if( !InterlockedDecrement(&i_ref) ) delete this;
1101 /* IEnumMediaTypes */
1102 STDMETHODIMP CaptureEnumMediaTypes::Next( ULONG cMediaTypes,
1103 AM_MEDIA_TYPE ** ppMediaTypes,
1106 #ifdef DEBUG_DSHOW_L1
1107 msg_Dbg( p_input, "CaptureEnumMediaTypes::Next " );
1111 ULONG max = p_pin->media_type_count;
1113 if( ! ppMediaTypes )
1116 if( (! pcFetched) && (cMediaTypes > 1) )
1120 ** use connection media type as first entry in iterator if it exists
1123 if( cx_media_type.subtype != GUID_NULL )
1126 if( i_position == 0 )
1128 ppMediaTypes[copied] =
1129 (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
1130 if( CopyMediaType(ppMediaTypes[copied], &cx_media_type) != S_OK )
1131 return E_OUTOFMEMORY;
1137 while( (copied < cMediaTypes) && (i_position < max) )
1139 ppMediaTypes[copied] =
1140 (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
1141 if( CopyMediaType( ppMediaTypes[copied],
1142 &p_pin->media_types[i_position-offset]) != S_OK )
1143 return E_OUTOFMEMORY;
1149 if( pcFetched ) *pcFetched = copied;
1151 return (copied == cMediaTypes) ? S_OK : S_FALSE;
1153 STDMETHODIMP CaptureEnumMediaTypes::Skip( ULONG cMediaTypes )
1155 ULONG max = p_pin->media_type_count;
1156 if( cx_media_type.subtype != GUID_NULL )
1160 #ifdef DEBUG_DSHOW_L1
1161 msg_Dbg( p_input, "CaptureEnumMediaTypes::Skip" );
1164 i_position += cMediaTypes;
1165 return (i_position < max) ? S_OK : S_FALSE;
1167 STDMETHODIMP CaptureEnumMediaTypes::Reset()
1169 #ifdef DEBUG_DSHOW_L1
1170 msg_Dbg( p_input, "CaptureEnumMediaTypes::Reset" );
1173 FreeMediaType(cx_media_type);
1174 CopyMediaType(&cx_media_type, &p_pin->cx_media_type);
1178 STDMETHODIMP CaptureEnumMediaTypes::Clone( IEnumMediaTypes **ppEnum )
1180 #ifdef DEBUG_DSHOW_L1
1181 msg_Dbg( p_input, "CaptureEnumMediaTypes::Clone" );
1184 *ppEnum = new CaptureEnumMediaTypes( p_input, p_pin, this );
1185 if( *ppEnum == NULL ) return E_OUTOFMEMORY;