1 /*****************************************************************************
2 * filter.c : 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"
46 #define FILTER_NAME L"VideoLAN Capture Filter"
47 #define PIN_NAME L"Capture"
49 void WINAPI
FreeMediaType( AM_MEDIA_TYPE
& mt
)
51 if( mt
.cbFormat
!= 0 )
53 CoTaskMemFree( (PVOID
)mt
.pbFormat
);
64 HRESULT WINAPI
CopyMediaType( AM_MEDIA_TYPE
*pmtTarget
,
65 const AM_MEDIA_TYPE
*pmtSource
)
67 *pmtTarget
= *pmtSource
;
69 if( !pmtSource
|| !pmtTarget
) return S_FALSE
;
71 if( pmtSource
->cbFormat
&& pmtSource
->pbFormat
)
73 pmtTarget
->pbFormat
= (PBYTE
)CoTaskMemAlloc( pmtSource
->cbFormat
);
74 if( pmtTarget
->pbFormat
== NULL
)
76 pmtTarget
->cbFormat
= 0;
81 CopyMemory( (PVOID
)pmtTarget
->pbFormat
, (PVOID
)pmtSource
->pbFormat
,
82 pmtTarget
->cbFormat
);
85 if( pmtTarget
->pUnk
!= NULL
)
87 pmtTarget
->pUnk
->AddRef();
93 int GetFourCCFromMediaType( const AM_MEDIA_TYPE
&media_type
)
97 if( media_type
.majortype
== MEDIATYPE_Video
)
99 /* currently only support this type of video info format */
100 if( 1 /* media_type.formattype == FORMAT_VideoInfo */ )
102 /* Packed RGB formats */
103 if( media_type
.subtype
== MEDIASUBTYPE_RGB1
)
104 i_fourcc
= VLC_FOURCC( 'R', 'G', 'B', '1' );
105 else if( media_type
.subtype
== MEDIASUBTYPE_RGB4
)
106 i_fourcc
= VLC_FOURCC( 'R', 'G', 'B', '4' );
107 else if( media_type
.subtype
== MEDIASUBTYPE_RGB8
)
108 i_fourcc
= VLC_FOURCC( 'R', 'G', 'B', '8' );
109 else if( media_type
.subtype
== MEDIASUBTYPE_RGB555
)
110 i_fourcc
= VLC_CODEC_RGB15
;
111 else if( media_type
.subtype
== MEDIASUBTYPE_RGB565
)
112 i_fourcc
= VLC_CODEC_RGB16
;
113 else if( media_type
.subtype
== MEDIASUBTYPE_RGB24
)
114 i_fourcc
= VLC_CODEC_RGB24
;
115 else if( media_type
.subtype
== MEDIASUBTYPE_RGB32
)
116 i_fourcc
= VLC_CODEC_RGB32
;
117 else if( media_type
.subtype
== MEDIASUBTYPE_ARGB32
)
118 i_fourcc
= VLC_CODEC_RGBA
;
120 /* Planar YUV formats */
121 else if( media_type
.subtype
== MEDIASUBTYPE_I420
)
122 i_fourcc
= VLC_CODEC_I420
;
123 else if( media_type
.subtype
== MEDIASUBTYPE_Y41P
)
124 i_fourcc
= VLC_CODEC_I411
;
125 else if( media_type
.subtype
== MEDIASUBTYPE_YV12
)
126 i_fourcc
= VLC_CODEC_YV12
;
127 else if( media_type
.subtype
== MEDIASUBTYPE_IYUV
)
128 i_fourcc
= VLC_CODEC_YV12
;
129 else if( media_type
.subtype
== MEDIASUBTYPE_YVU9
)
130 i_fourcc
= VLC_CODEC_I410
;
132 /* Packed YUV formats */
133 else if( media_type
.subtype
== MEDIASUBTYPE_YVYU
)
134 i_fourcc
= VLC_CODEC_YVYU
;
135 else if( media_type
.subtype
== MEDIASUBTYPE_YUYV
)
136 i_fourcc
= VLC_CODEC_YUYV
;
137 else if( media_type
.subtype
== MEDIASUBTYPE_Y411
)
138 i_fourcc
= VLC_FOURCC( 'I', '4', '1', 'N' );
139 else if( media_type
.subtype
== MEDIASUBTYPE_Y211
)
140 i_fourcc
= VLC_CODEC_Y211
;
141 else if( media_type
.subtype
== MEDIASUBTYPE_YUY2
)
142 i_fourcc
= VLC_CODEC_YUYV
;
143 else if( media_type
.subtype
== MEDIASUBTYPE_UYVY
)
144 i_fourcc
= VLC_CODEC_UYVY
;
145 /* HDYC uses UYVY sample positions but Rec709 colourimetry */
146 /* FIXME: When VLC understands colourspace, something will need
147 * to be added / changed here. Until then, just make it behave
149 else if( media_type
.subtype
== MEDIASUBTYPE_HDYC
)
150 i_fourcc
= VLC_CODEC_UYVY
;
152 /* MPEG2 video elementary stream */
153 else if( media_type
.subtype
== MEDIASUBTYPE_MPEG2_VIDEO
)
154 i_fourcc
= VLC_CODEC_MPGV
;
157 else if( media_type
.subtype
== MEDIASUBTYPE_DIVX
)
158 i_fourcc
= VLC_CODEC_MP4V
;
161 else if( media_type
.subtype
== MEDIASUBTYPE_dvsl
)
162 i_fourcc
= VLC_CODEC_DV
;
163 else if( media_type
.subtype
== MEDIASUBTYPE_dvsd
)
164 i_fourcc
= VLC_CODEC_DV
;
165 else if( media_type
.subtype
== MEDIASUBTYPE_dvhd
)
166 i_fourcc
= VLC_CODEC_DV
;
169 else if( media_type
.subtype
== MEDIASUBTYPE_MJPG
)
170 i_fourcc
= VLC_CODEC_MJPG
;
174 else if( media_type
.majortype
== MEDIATYPE_Audio
)
176 /* currently only support this type of audio info format */
177 if( media_type
.formattype
== FORMAT_WaveFormatEx
)
179 if( media_type
.subtype
== MEDIASUBTYPE_PCM
)
180 i_fourcc
= VLC_FOURCC( 'a', 'r', 'a', 'w' );
181 else if( media_type
.subtype
== MEDIASUBTYPE_IEEE_FLOAT
)
182 i_fourcc
= VLC_CODEC_FL32
;
185 else if( media_type
.majortype
== MEDIATYPE_Stream
)
187 if( media_type
.subtype
== MEDIASUBTYPE_MPEG2_PROGRAM
)
188 i_fourcc
= VLC_FOURCC( 'm', 'p', '2', 'p' );
189 else if( media_type
.subtype
== MEDIASUBTYPE_MPEG2_TRANSPORT
)
190 i_fourcc
= VLC_FOURCC( 'm', 'p', '2', 't' );
196 /****************************************************************************
197 * Implementation of our dummy directshow filter pin class
198 ****************************************************************************/
200 CapturePin::CapturePin( vlc_object_t
*_p_input
, access_sys_t
*_p_sys
,
201 CaptureFilter
*_p_filter
,
202 AM_MEDIA_TYPE
*mt
, size_t mt_count
)
203 : p_input( _p_input
), p_sys( _p_sys
), p_filter( _p_filter
),
204 p_connected_pin( NULL
), media_types(mt
), media_type_count(mt_count
),
207 cx_media_type
.majortype
= mt
[0].majortype
;
208 cx_media_type
.subtype
= GUID_NULL
;
209 cx_media_type
.pbFormat
= NULL
;
210 cx_media_type
.cbFormat
= 0;
211 cx_media_type
.pUnk
= NULL
;
214 CapturePin::~CapturePin()
217 msg_Dbg( p_input
, "CapturePin::~CapturePin" );
219 for( size_t c
=0; c
<media_type_count
; c
++ )
221 FreeMediaType(media_types
[c
]);
223 FreeMediaType(cx_media_type
);
227 * Returns the complete queue of samples that have been received so far.
228 * Lock the p_sys->lock before calling this function.
229 * @param samples_queue [out] Empty queue that will get all elements from
231 * @return S_OK if a sample was available, S_FALSE if no sample was
234 HRESULT
CapturePin::CustomGetSamples( deque
<VLCMediaSample
> &external_queue
)
236 #if 0 //def DEBUG_DSHOW
237 msg_Dbg( p_input
, "CapturePin::CustomGetSamples: %d samples in the queue", samples_queue
.size());
240 if( !samples_queue
.empty() )
242 external_queue
.swap(samples_queue
);
249 * Returns a sample from its sample queue. Proper locking must be done prior
250 * to this call. Current dshow code protects the access to any sample queue
251 * (audio and video) with the p_sys->lock
252 * @param vlc_sample [out] Address of a sample if sucessfull. Undefined
254 * @return S_OK if a sample was available, S_FALSE if no sample was
257 HRESULT
CapturePin::CustomGetSample( VLCMediaSample
*vlc_sample
)
259 #if 0 //def DEBUG_DSHOW
260 msg_Dbg( p_input
, "CapturePin::CustomGetSample" );
263 if( !samples_queue
.empty() )
265 *vlc_sample
= samples_queue
.back();
266 samples_queue
.pop_back();
272 AM_MEDIA_TYPE
&CapturePin::CustomGetMediaType()
274 return cx_media_type
;
277 /* IUnknown methods */
278 STDMETHODIMP
CapturePin::QueryInterface(REFIID riid
, void **ppv
)
280 #ifdef DEBUG_DSHOW_L1
281 msg_Dbg( p_input
, "CapturePin::QueryInterface" );
284 if( riid
== IID_IUnknown
||
291 if( riid
== IID_IMemInputPin
)
294 *ppv
= (IMemInputPin
*)this;
299 #ifdef DEBUG_DSHOW_L1
300 msg_Dbg( p_input
, "CapturePin::QueryInterface() failed for: "
301 "%04X-%02X-%02X-%02X%02X%02X%02X%02X%02X%02X%02X",
302 (int)riid
.Data1
, (int)riid
.Data2
, (int)riid
.Data3
,
303 static_cast<int>(riid
.Data4
[0]), (int)riid
.Data4
[1],
304 (int)riid
.Data4
[2], (int)riid
.Data4
[3],
305 (int)riid
.Data4
[4], (int)riid
.Data4
[5],
306 (int)riid
.Data4
[6], (int)riid
.Data4
[7] );
309 return E_NOINTERFACE
;
313 STDMETHODIMP_(ULONG
) CapturePin::AddRef()
315 #ifdef DEBUG_DSHOW_L1
316 msg_Dbg( p_input
, "CapturePin::AddRef (ref: %i)", i_ref
);
321 STDMETHODIMP_(ULONG
) CapturePin::Release()
323 #ifdef DEBUG_DSHOW_L1
324 msg_Dbg( p_input
, "CapturePin::Release (ref: %i)", i_ref
);
327 if( !InterlockedDecrement(&i_ref
) ) delete this;
333 STDMETHODIMP
CapturePin::Connect( IPin
*,
334 const AM_MEDIA_TYPE
*pmt
)
336 if( State_Running
== p_filter
->state
)
338 msg_Dbg( p_input
, "CapturePin::Connect [not stopped]" );
339 return VFW_E_NOT_STOPPED
;
342 if( p_connected_pin
)
344 msg_Dbg( p_input
, "CapturePin::Connect [already connected]" );
345 return VFW_E_ALREADY_CONNECTED
;
348 if( !pmt
) return S_OK
;
350 if( GUID_NULL
!= pmt
->majortype
&&
351 media_types
[0].majortype
!= pmt
->majortype
)
353 msg_Dbg( p_input
, "CapturePin::Connect [media major type mismatch]" );
357 if( GUID_NULL
!= pmt
->subtype
&& !GetFourCCFromMediaType(*pmt
) )
359 msg_Dbg( p_input
, "CapturePin::Connect [media subtype type "
364 if( pmt
->pbFormat
&& pmt
->majortype
== MEDIATYPE_Video
)
366 if( !((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biHeight
||
367 !((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biWidth
)
369 msg_Dbg( p_input
, "CapturePin::Connect "
370 "[video width/height == 0 ]" );
375 msg_Dbg( p_input
, "CapturePin::Connect [OK]" );
378 STDMETHODIMP
CapturePin::ReceiveConnection( IPin
* pConnector
,
379 const AM_MEDIA_TYPE
*pmt
)
381 if( State_Stopped
!= p_filter
->state
)
383 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [not stopped]" );
384 return VFW_E_NOT_STOPPED
;
387 if( !pConnector
|| !pmt
)
389 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [null pointer]" );
393 if( p_connected_pin
)
395 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [already connected]");
396 return VFW_E_ALREADY_CONNECTED
;
399 if( S_OK
!= QueryAccept(pmt
) )
401 msg_Dbg( p_input
, "CapturePin::ReceiveConnection "
402 "[media type not accepted]" );
403 return VFW_E_TYPE_NOT_ACCEPTED
;
406 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [OK]" );
408 p_connected_pin
= pConnector
;
409 p_connected_pin
->AddRef();
411 FreeMediaType( cx_media_type
);
412 return CopyMediaType( &cx_media_type
, pmt
);
414 STDMETHODIMP
CapturePin::Disconnect()
416 if( ! p_connected_pin
)
418 msg_Dbg( p_input
, "CapturePin::Disconnect [not connected]" );
422 msg_Dbg( p_input
, "CapturePin::Disconnect [OK]" );
424 /* samples_queue was already flushed in EndFlush() */
426 p_connected_pin
->Release();
427 p_connected_pin
= NULL
;
428 //FreeMediaType( cx_media_type );
429 //cx_media_type.subtype = GUID_NULL;
433 STDMETHODIMP
CapturePin::ConnectedTo( IPin
**pPin
)
435 if( !p_connected_pin
)
437 msg_Dbg( p_input
, "CapturePin::ConnectedTo [not connected]" );
438 return VFW_E_NOT_CONNECTED
;
441 p_connected_pin
->AddRef();
442 *pPin
= p_connected_pin
;
444 msg_Dbg( p_input
, "CapturePin::ConnectedTo [OK]" );
448 STDMETHODIMP
CapturePin::ConnectionMediaType( AM_MEDIA_TYPE
*pmt
)
450 if( !p_connected_pin
)
452 msg_Dbg( p_input
, "CapturePin::ConnectionMediaType [not connected]" );
453 return VFW_E_NOT_CONNECTED
;
456 return CopyMediaType( pmt
, &cx_media_type
);
458 STDMETHODIMP
CapturePin::QueryPinInfo( PIN_INFO
* pInfo
)
461 msg_Dbg( p_input
, "CapturePin::QueryPinInfo" );
464 pInfo
->pFilter
= p_filter
;
465 if( p_filter
) p_filter
->AddRef();
467 memcpy(pInfo
->achName
, PIN_NAME
, sizeof(PIN_NAME
));
468 pInfo
->dir
= PINDIR_INPUT
;
472 STDMETHODIMP
CapturePin::QueryDirection( PIN_DIRECTION
* pPinDir
)
475 msg_Dbg( p_input
, "CapturePin::QueryDirection" );
478 *pPinDir
= PINDIR_INPUT
;
481 STDMETHODIMP
CapturePin::QueryId( LPWSTR
* Id
)
484 msg_Dbg( p_input
, "CapturePin::QueryId" );
487 *Id
= (LPWSTR
)L
"VLC Capture Pin";
491 STDMETHODIMP
CapturePin::QueryAccept( const AM_MEDIA_TYPE
*pmt
)
493 if( State_Stopped
!= p_filter
->state
)
495 msg_Dbg( p_input
, "CapturePin::QueryAccept [not stopped]" );
499 if( media_types
[0].majortype
!= pmt
->majortype
)
501 msg_Dbg( p_input
, "CapturePin::QueryAccept [media type mismatch]" );
505 int i_fourcc
= GetFourCCFromMediaType(*pmt
);
508 msg_Dbg( p_input
, "CapturePin::QueryAccept "
509 "[media type not supported]" );
513 if( pmt
->majortype
== MEDIATYPE_Video
)
516 ( (((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biHeight
== 0) ||
517 (((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biWidth
== 0) ) )
519 msg_Dbg( p_input
, "CapturePin::QueryAccept [video size wxh == 0]");
523 msg_Dbg( p_input
, "CapturePin::QueryAccept [OK] "
524 "(width=%ld, height=%ld, chroma=%4.4s, fps=%f)",
525 ((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biWidth
,
526 ((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biHeight
,
528 10000000.0f
/((float)((VIDEOINFOHEADER
*)pmt
->pbFormat
)->AvgTimePerFrame
) );
530 else if( pmt
->majortype
== MEDIATYPE_Audio
)
532 msg_Dbg( p_input
, "CapturePin::QueryAccept [OK] (channels=%d, "
533 "samples/sec=%lu, bits/samples=%d, format=%4.4s)",
534 ((WAVEFORMATEX
*)pmt
->pbFormat
)->nChannels
,
535 ((WAVEFORMATEX
*)pmt
->pbFormat
)->nSamplesPerSec
,
536 ((WAVEFORMATEX
*)pmt
->pbFormat
)->wBitsPerSample
,
541 msg_Dbg( p_input
, "CapturePin::QueryAccept [OK] (stream format=%4.4s)",
545 if( p_connected_pin
)
547 FreeMediaType( cx_media_type
);
548 CopyMediaType( &cx_media_type
, pmt
);
553 STDMETHODIMP
CapturePin::EnumMediaTypes( IEnumMediaTypes
**ppEnum
)
555 #ifdef DEBUG_DSHOW_L1
556 msg_Dbg( p_input
, "CapturePin::EnumMediaTypes" );
559 *ppEnum
= new CaptureEnumMediaTypes( p_input
, this, NULL
);
561 if( *ppEnum
== NULL
) return E_OUTOFMEMORY
;
565 STDMETHODIMP
CapturePin::QueryInternalConnections( IPin
**, ULONG
* )
567 #ifdef DEBUG_DSHOW_L1
568 msg_Dbg( p_input
, "CapturePin::QueryInternalConnections" );
572 STDMETHODIMP
CapturePin::EndOfStream( void )
575 msg_Dbg( p_input
, "CapturePin::EndOfStream" );
579 STDMETHODIMP
CapturePin::BeginFlush( void )
582 msg_Dbg( p_input
, "CapturePin::BeginFlush" );
586 STDMETHODIMP
CapturePin::EndFlush( void )
589 msg_Dbg( p_input
, "CapturePin::EndFlush" );
592 VLCMediaSample vlc_sample
;
594 vlc_mutex_lock( &p_sys
->lock
);
595 while( !samples_queue
.empty() )
597 vlc_sample
= samples_queue
.back();
598 samples_queue
.pop_back();
599 vlc_sample
.p_sample
->Release();
601 vlc_mutex_unlock( &p_sys
->lock
);
605 STDMETHODIMP
CapturePin::NewSegment( REFERENCE_TIME
, REFERENCE_TIME
, double )
608 msg_Dbg( p_input
, "CapturePin::NewSegment" );
613 /* IMemInputPin methods */
614 STDMETHODIMP
CapturePin::GetAllocator( IMemAllocator
** )
617 msg_Dbg( p_input
, "CapturePin::GetAllocator" );
620 return VFW_E_NO_ALLOCATOR
;
622 STDMETHODIMP
CapturePin::NotifyAllocator( IMemAllocator
*, BOOL
)
625 msg_Dbg( p_input
, "CapturePin::NotifyAllocator" );
630 STDMETHODIMP
CapturePin::GetAllocatorRequirements( ALLOCATOR_PROPERTIES
* )
633 msg_Dbg( p_input
, "CapturePin::GetAllocatorRequirements" );
638 STDMETHODIMP
CapturePin::Receive( IMediaSample
*pSample
)
640 #if 0 //def DEBUG_DSHOW
641 msg_Dbg( p_input
, "CapturePin::Receive" );
645 mtime_t i_timestamp
= mdate() * 10;
646 VLCMediaSample vlc_sample
= {pSample
, i_timestamp
};
648 vlc_mutex_lock( &p_sys
->lock
);
649 samples_queue
.push_front( vlc_sample
);
651 /* Make sure we don't cache too many samples */
652 if( samples_queue
.size() > 10 )
654 vlc_sample
= samples_queue
.back();
655 samples_queue
.pop_back();
656 msg_Dbg( p_input
, "CapturePin::Receive trashing late input sample" );
657 vlc_sample
.p_sample
->Release();
660 vlc_cond_signal( &p_sys
->wait
);
661 vlc_mutex_unlock( &p_sys
->lock
);
665 STDMETHODIMP
CapturePin::ReceiveMultiple( IMediaSample
**pSamples
,
667 long *nSamplesProcessed
)
671 *nSamplesProcessed
= 0;
672 while( nSamples
-- > 0 )
674 hr
= Receive( pSamples
[*nSamplesProcessed
] );
675 if( hr
!= S_OK
) break;
676 (*nSamplesProcessed
)++;
680 STDMETHODIMP
CapturePin::ReceiveCanBlock( void )
683 msg_Dbg( p_input
, "CapturePin::ReceiveCanBlock" );
686 return S_FALSE
; /* Thou shalt not block */
689 /****************************************************************************
690 * Implementation of our dummy directshow filter class
691 ****************************************************************************/
692 CaptureFilter::CaptureFilter( vlc_object_t
*_p_input
, access_sys_t
*p_sys
,
693 AM_MEDIA_TYPE
*mt
, size_t mt_count
)
694 : p_input( _p_input
),
695 p_pin( new CapturePin( _p_input
, p_sys
, this, mt
, mt_count
) ),
696 state( State_Stopped
), i_ref( 1 )
700 CaptureFilter::~CaptureFilter()
703 msg_Dbg( p_input
, "CaptureFilter::~CaptureFilter" );
708 /* IUnknown methods */
709 STDMETHODIMP
CaptureFilter::QueryInterface( REFIID riid
, void **ppv
)
711 #ifdef DEBUG_DSHOW_L1
712 msg_Dbg( p_input
, "CaptureFilter::QueryInterface" );
715 if( riid
== IID_IUnknown
)
718 *ppv
= (IUnknown
*)this;
721 if( riid
== IID_IPersist
)
724 *ppv
= (IPersist
*)this;
727 if( riid
== IID_IMediaFilter
)
730 *ppv
= (IMediaFilter
*)this;
733 if( riid
== IID_IBaseFilter
)
736 *ppv
= (IBaseFilter
*)this;
741 #ifdef DEBUG_DSHOW_L1
742 msg_Dbg( p_input
, "CaptureFilter::QueryInterface() failed for: "
743 "%04X-%02X-%02X-%02X%02X%02X%02X%02X%02X%02X%02X",
744 (int)riid
.Data1
, (int)riid
.Data2
, (int)riid
.Data3
,
745 static_cast<int>(riid
.Data4
[0]), (int)riid
.Data4
[1],
746 (int)riid
.Data4
[2], (int)riid
.Data4
[3],
747 (int)riid
.Data4
[4], (int)riid
.Data4
[5],
748 (int)riid
.Data4
[6], (int)riid
.Data4
[7] );
751 return E_NOINTERFACE
;
754 STDMETHODIMP_(ULONG
) CaptureFilter::AddRef()
756 #ifdef DEBUG_DSHOW_L1
757 msg_Dbg( p_input
, "CaptureFilter::AddRef (ref: %i)", i_ref
);
762 STDMETHODIMP_(ULONG
) CaptureFilter::Release()
764 #ifdef DEBUG_DSHOW_L1
765 msg_Dbg( p_input
, "CaptureFilter::Release (ref: %i)", i_ref
);
768 if( !InterlockedDecrement(&i_ref
) ) delete this;
773 /* IPersist method */
774 STDMETHODIMP
CaptureFilter::GetClassID(CLSID
*)
777 msg_Dbg( p_input
, "CaptureFilter::GetClassID" );
782 /* IMediaFilter methods */
783 STDMETHODIMP
CaptureFilter::GetState(DWORD
, FILTER_STATE
*State
)
786 msg_Dbg( p_input
, "CaptureFilter::GetState %i", state
);
792 STDMETHODIMP
CaptureFilter::SetSyncSource(IReferenceClock
*)
795 msg_Dbg( p_input
, "CaptureFilter::SetSyncSource" );
800 STDMETHODIMP
CaptureFilter::GetSyncSource(IReferenceClock
**pClock
)
803 msg_Dbg( p_input
, "CaptureFilter::GetSyncSource" );
809 STDMETHODIMP
CaptureFilter::Stop()
812 msg_Dbg( p_input
, "CaptureFilter::Stop" );
817 state
= State_Stopped
;
820 STDMETHODIMP
CaptureFilter::Pause()
823 msg_Dbg( p_input
, "CaptureFilter::Pause" );
826 state
= State_Paused
;
829 STDMETHODIMP
CaptureFilter::Run(REFERENCE_TIME
)
832 msg_Dbg( p_input
, "CaptureFilter::Run" );
835 state
= State_Running
;
839 /* IBaseFilter methods */
840 STDMETHODIMP
CaptureFilter::EnumPins( IEnumPins
** ppEnum
)
843 msg_Dbg( p_input
, "CaptureFilter::EnumPins" );
846 /* Create a new ref counted enumerator */
847 *ppEnum
= new CaptureEnumPins( p_input
, this, NULL
);
848 return *ppEnum
== NULL
? E_OUTOFMEMORY
: NOERROR
;
850 STDMETHODIMP
CaptureFilter::FindPin( LPCWSTR
, IPin
** )
853 msg_Dbg( p_input
, "CaptureFilter::FindPin" );
857 STDMETHODIMP
CaptureFilter::QueryFilterInfo( FILTER_INFO
* pInfo
)
860 msg_Dbg( p_input
, "CaptureFilter::QueryFilterInfo" );
863 memcpy(pInfo
->achName
, FILTER_NAME
, sizeof(FILTER_NAME
));
865 pInfo
->pGraph
= p_graph
;
866 if( p_graph
) p_graph
->AddRef();
870 STDMETHODIMP
CaptureFilter::JoinFilterGraph( IFilterGraph
* pGraph
,
874 msg_Dbg( p_input
, "CaptureFilter::JoinFilterGraph" );
881 STDMETHODIMP
CaptureFilter::QueryVendorInfo( LPWSTR
* )
884 msg_Dbg( p_input
, "CaptureFilter::QueryVendorInfo" );
890 CapturePin
*CaptureFilter::CustomGetPin()
895 /****************************************************************************
896 * Implementation of our dummy directshow enumpins class
897 ****************************************************************************/
899 CaptureEnumPins::CaptureEnumPins( vlc_object_t
*_p_input
,
900 CaptureFilter
*_p_filter
,
901 CaptureEnumPins
*pEnumPins
)
902 : p_input( _p_input
), p_filter( _p_filter
), i_ref( 1 )
904 /* Hold a reference count on our filter */
907 /* Are we creating a new enumerator */
909 if( pEnumPins
== NULL
)
915 i_position
= pEnumPins
->i_position
;
919 CaptureEnumPins::~CaptureEnumPins()
921 #ifdef DEBUG_DSHOW_L1
922 msg_Dbg( p_input
, "CaptureEnumPins::~CaptureEnumPins" );
927 /* IUnknown methods */
928 STDMETHODIMP
CaptureEnumPins::QueryInterface( REFIID riid
, void **ppv
)
930 #ifdef DEBUG_DSHOW_L1
931 msg_Dbg( p_input
, "CaptureEnumPins::QueryInterface" );
934 if( riid
== IID_IUnknown
||
935 riid
== IID_IEnumPins
)
938 *ppv
= (IEnumPins
*)this;
944 return E_NOINTERFACE
;
947 STDMETHODIMP_(ULONG
) CaptureEnumPins::AddRef()
949 #ifdef DEBUG_DSHOW_L1
950 msg_Dbg( p_input
, "CaptureEnumPins::AddRef (ref: %i)", i_ref
);
955 STDMETHODIMP_(ULONG
) CaptureEnumPins::Release()
957 #ifdef DEBUG_DSHOW_L1
958 msg_Dbg( p_input
, "CaptureEnumPins::Release (ref: %i)", i_ref
);
961 if( !InterlockedDecrement(&i_ref
) ) delete this;
967 STDMETHODIMP
CaptureEnumPins::Next( ULONG cPins
, IPin
** ppPins
,
970 #ifdef DEBUG_DSHOW_L1
971 msg_Dbg( p_input
, "CaptureEnumPins::Next" );
974 unsigned int i_fetched
= 0;
976 if( i_position
< 1 && cPins
> 0 )
978 IPin
*pPin
= p_filter
->CustomGetPin();
985 if( pcFetched
) *pcFetched
= i_fetched
;
987 return (i_fetched
== cPins
) ? S_OK
: S_FALSE
;
989 STDMETHODIMP
CaptureEnumPins::Skip( ULONG cPins
)
991 #ifdef DEBUG_DSHOW_L1
992 msg_Dbg( p_input
, "CaptureEnumPins::Skip" );
1004 STDMETHODIMP
CaptureEnumPins::Reset()
1006 #ifdef DEBUG_DSHOW_L1
1007 msg_Dbg( p_input
, "CaptureEnumPins::Reset" );
1013 STDMETHODIMP
CaptureEnumPins::Clone( IEnumPins
**ppEnum
)
1015 #ifdef DEBUG_DSHOW_L1
1016 msg_Dbg( p_input
, "CaptureEnumPins::Clone" );
1019 *ppEnum
= new CaptureEnumPins( p_input
, p_filter
, this );
1020 if( *ppEnum
== NULL
) return E_OUTOFMEMORY
;
1025 /****************************************************************************
1026 * Implementation of our dummy directshow enummediatypes class
1027 ****************************************************************************/
1028 CaptureEnumMediaTypes::CaptureEnumMediaTypes( vlc_object_t
*_p_input
,
1029 CapturePin
*_p_pin
, CaptureEnumMediaTypes
*pEnumMediaTypes
)
1030 : p_input( _p_input
), p_pin( _p_pin
), i_ref( 1 )
1032 /* Hold a reference count on our filter */
1035 /* Are we creating a new enumerator */
1036 if( pEnumMediaTypes
== NULL
)
1038 CopyMediaType(&cx_media_type
, &p_pin
->cx_media_type
);
1043 CopyMediaType(&cx_media_type
, &pEnumMediaTypes
->cx_media_type
);
1044 i_position
= pEnumMediaTypes
->i_position
;
1048 CaptureEnumMediaTypes::~CaptureEnumMediaTypes()
1050 #ifdef DEBUG_DSHOW_L1
1051 msg_Dbg( p_input
, "CaptureEnumMediaTypes::~CaptureEnumMediaTypes" );
1053 FreeMediaType(cx_media_type
);
1057 /* IUnknown methods */
1058 STDMETHODIMP
CaptureEnumMediaTypes::QueryInterface( REFIID riid
, void **ppv
)
1060 #ifdef DEBUG_DSHOW_L1
1061 msg_Dbg( p_input
, "CaptureEnumMediaTypes::QueryInterface" );
1064 if( riid
== IID_IUnknown
||
1065 riid
== IID_IEnumMediaTypes
)
1068 *ppv
= (IEnumMediaTypes
*)this;
1074 return E_NOINTERFACE
;
1077 STDMETHODIMP_(ULONG
) CaptureEnumMediaTypes::AddRef()
1079 #ifdef DEBUG_DSHOW_L1
1080 msg_Dbg( p_input
, "CaptureEnumMediaTypes::AddRef (ref: %i)", i_ref
);
1085 STDMETHODIMP_(ULONG
) CaptureEnumMediaTypes::Release()
1087 #ifdef DEBUG_DSHOW_L1
1088 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Release (ref: %i)", i_ref
);
1091 if( !InterlockedDecrement(&i_ref
) ) delete this;
1096 /* IEnumMediaTypes */
1097 STDMETHODIMP
CaptureEnumMediaTypes::Next( ULONG cMediaTypes
,
1098 AM_MEDIA_TYPE
** ppMediaTypes
,
1101 #ifdef DEBUG_DSHOW_L1
1102 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Next " );
1106 ULONG max
= p_pin
->media_type_count
;
1108 if( ! ppMediaTypes
)
1111 if( (! pcFetched
) && (cMediaTypes
> 1) )
1115 ** use connection media type as first entry in iterator if it exists
1118 if( cx_media_type
.subtype
!= GUID_NULL
)
1121 if( i_position
== 0 )
1123 ppMediaTypes
[copied
] =
1124 (AM_MEDIA_TYPE
*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
1125 if( CopyMediaType(ppMediaTypes
[copied
], &cx_media_type
) != S_OK
)
1126 return E_OUTOFMEMORY
;
1132 while( (copied
< cMediaTypes
) && (i_position
< max
) )
1134 ppMediaTypes
[copied
] =
1135 (AM_MEDIA_TYPE
*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
1136 if( CopyMediaType( ppMediaTypes
[copied
],
1137 &p_pin
->media_types
[i_position
-offset
]) != S_OK
)
1138 return E_OUTOFMEMORY
;
1144 if( pcFetched
) *pcFetched
= copied
;
1146 return (copied
== cMediaTypes
) ? S_OK
: S_FALSE
;
1148 STDMETHODIMP
CaptureEnumMediaTypes::Skip( ULONG cMediaTypes
)
1150 ULONG max
= p_pin
->media_type_count
;
1151 if( cx_media_type
.subtype
!= GUID_NULL
)
1155 #ifdef DEBUG_DSHOW_L1
1156 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Skip" );
1159 i_position
+= cMediaTypes
;
1160 return (i_position
< max
) ? S_OK
: S_FALSE
;
1162 STDMETHODIMP
CaptureEnumMediaTypes::Reset()
1164 #ifdef DEBUG_DSHOW_L1
1165 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Reset" );
1168 FreeMediaType(cx_media_type
);
1169 CopyMediaType(&cx_media_type
, &p_pin
->cx_media_type
);
1173 STDMETHODIMP
CaptureEnumMediaTypes::Clone( IEnumMediaTypes
**ppEnum
)
1175 #ifdef DEBUG_DSHOW_L1
1176 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Clone" );
1179 *ppEnum
= new CaptureEnumMediaTypes( p_input
, p_pin
, this );
1180 if( *ppEnum
== NULL
) return E_OUTOFMEMORY
;