1 /*****************************************************************************
2 * filter.cpp : DirectShow access module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2010 VLC authors and VideoLAN
7 * Author: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * 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"
48 DEFINE_GUID(MEDIASUBTYPE_HDYC
,0x43594448 /* CYDH */ , 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
49 DEFINE_GUID(MEDIASUBTYPE_DIVX
,0x58564944 /* XVID */ , 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
54 #define FILTER_NAME L"VideoLAN Capture Filter"
55 #define PIN_NAME L"Capture"
57 void WINAPI
FreeMediaType( AM_MEDIA_TYPE
& mt
)
59 if( mt
.cbFormat
!= 0 )
61 CoTaskMemFree( (PVOID
)mt
.pbFormat
);
72 HRESULT WINAPI
CopyMediaType( AM_MEDIA_TYPE
*pmtTarget
,
73 const AM_MEDIA_TYPE
*pmtSource
)
75 if( !pmtSource
|| !pmtTarget
) return S_FALSE
;
77 *pmtTarget
= *pmtSource
;
79 if( pmtSource
->cbFormat
&& pmtSource
->pbFormat
)
81 pmtTarget
->pbFormat
= (PBYTE
)CoTaskMemAlloc( pmtSource
->cbFormat
);
82 if( pmtTarget
->pbFormat
== NULL
)
84 pmtTarget
->cbFormat
= 0;
89 CopyMemory( (PVOID
)pmtTarget
->pbFormat
, (PVOID
)pmtSource
->pbFormat
,
90 pmtTarget
->cbFormat
);
93 if( pmtTarget
->pUnk
!= NULL
)
95 pmtTarget
->pUnk
->AddRef();
101 int GetFourCCFromMediaType( const AM_MEDIA_TYPE
&media_type
)
105 if( media_type
.majortype
== MEDIATYPE_Video
)
107 /* currently only support this type of video info format */
108 if( 1 /* media_type.formattype == FORMAT_VideoInfo */ )
110 /* Packed RGB formats */
111 if( media_type
.subtype
== MEDIASUBTYPE_RGB1
)
112 i_fourcc
= VLC_FOURCC( 'R', 'G', 'B', '1' );
113 else if( media_type
.subtype
== MEDIASUBTYPE_RGB4
)
114 i_fourcc
= VLC_FOURCC( 'R', 'G', 'B', '4' );
115 else if( media_type
.subtype
== MEDIASUBTYPE_RGB8
)
116 i_fourcc
= VLC_FOURCC( 'R', 'G', 'B', '8' );
117 else if( media_type
.subtype
== MEDIASUBTYPE_RGB555
)
118 i_fourcc
= VLC_CODEC_RGB15
;
119 else if( media_type
.subtype
== MEDIASUBTYPE_RGB565
)
120 i_fourcc
= VLC_CODEC_RGB16
;
121 else if( media_type
.subtype
== MEDIASUBTYPE_RGB24
)
122 i_fourcc
= VLC_CODEC_RGB24
;
123 else if( media_type
.subtype
== MEDIASUBTYPE_RGB32
)
124 i_fourcc
= VLC_CODEC_RGB32
;
125 else if( media_type
.subtype
== MEDIASUBTYPE_ARGB32
)
126 i_fourcc
= VLC_CODEC_RGBA
;
128 /* Planar YUV formats */
129 else if( media_type
.subtype
== MEDIASUBTYPE_I420
)
130 i_fourcc
= VLC_CODEC_I420
;
131 else if( media_type
.subtype
== MEDIASUBTYPE_Y41P
)
132 i_fourcc
= VLC_CODEC_I411
;
133 else if( media_type
.subtype
== MEDIASUBTYPE_YV12
)
134 i_fourcc
= VLC_CODEC_YV12
;
135 else if( media_type
.subtype
== MEDIASUBTYPE_IYUV
)
136 i_fourcc
= VLC_CODEC_YV12
;
137 else if( media_type
.subtype
== MEDIASUBTYPE_YVU9
)
138 i_fourcc
= VLC_CODEC_I410
;
140 /* Packed YUV formats */
141 else if( media_type
.subtype
== MEDIASUBTYPE_YVYU
)
142 i_fourcc
= VLC_CODEC_YVYU
;
143 else if( media_type
.subtype
== MEDIASUBTYPE_YUYV
)
144 i_fourcc
= VLC_CODEC_YUYV
;
145 else if( media_type
.subtype
== MEDIASUBTYPE_Y411
)
146 i_fourcc
= VLC_FOURCC( 'I', '4', '1', 'N' );
147 else if( media_type
.subtype
== MEDIASUBTYPE_Y211
)
148 i_fourcc
= VLC_CODEC_Y211
;
149 else if( media_type
.subtype
== MEDIASUBTYPE_YUY2
)
150 i_fourcc
= VLC_CODEC_YUYV
;
151 else if( media_type
.subtype
== MEDIASUBTYPE_UYVY
)
152 i_fourcc
= VLC_CODEC_UYVY
;
153 /* HDYC uses UYVY sample positions but Rec709 colourimetry */
154 /* FIXME: When VLC understands colourspace, something will need
155 * to be added / changed here. Until then, just make it behave
157 else if( media_type
.subtype
== MEDIASUBTYPE_HDYC
)
158 i_fourcc
= VLC_CODEC_UYVY
;
160 /* MPEG2 video elementary stream */
161 else if( media_type
.subtype
== MEDIASUBTYPE_MPEG2_VIDEO
)
162 i_fourcc
= VLC_CODEC_MPGV
;
165 else if( media_type
.subtype
== MEDIASUBTYPE_DIVX
)
166 i_fourcc
= VLC_CODEC_MP4V
;
169 else if( media_type
.subtype
== MEDIASUBTYPE_dvsl
)
170 i_fourcc
= VLC_CODEC_DV
;
171 else if( media_type
.subtype
== MEDIASUBTYPE_dvsd
)
172 i_fourcc
= VLC_CODEC_DV
;
173 else if( media_type
.subtype
== MEDIASUBTYPE_dvhd
)
174 i_fourcc
= VLC_CODEC_DV
;
177 else if( media_type
.subtype
== MEDIASUBTYPE_MJPG
)
178 i_fourcc
= VLC_CODEC_MJPG
;
182 else if( media_type
.majortype
== MEDIATYPE_Audio
)
184 /* currently only support this type of audio info format */
185 if( media_type
.formattype
== FORMAT_WaveFormatEx
)
187 if( media_type
.subtype
== MEDIASUBTYPE_PCM
)
188 i_fourcc
= VLC_FOURCC( 'a', 'r', 'a', 'w' );
189 else if( media_type
.subtype
== MEDIASUBTYPE_IEEE_FLOAT
)
190 i_fourcc
= VLC_CODEC_FL32
;
193 else if( media_type
.majortype
== MEDIATYPE_Stream
)
195 if( media_type
.subtype
== MEDIASUBTYPE_MPEG2_PROGRAM
)
196 i_fourcc
= VLC_FOURCC( 'm', 'p', '2', 'p' );
197 else if( media_type
.subtype
== MEDIASUBTYPE_MPEG2_TRANSPORT
)
198 i_fourcc
= VLC_FOURCC( 'm', 'p', '2', 't' );
204 /****************************************************************************
205 * Implementation of our dummy directshow filter pin class
206 ****************************************************************************/
208 CapturePin::CapturePin( vlc_object_t
*_p_input
, access_sys_t
*_p_sys
,
209 CaptureFilter
* _p_filter
,
210 AM_MEDIA_TYPE
*mt
, size_t mt_count
)
211 : p_input( _p_input
), p_sys( _p_sys
), p_filter( _p_filter
),
212 p_connected_pin( NULL
), media_types(mt
), media_type_count(mt_count
),
213 cx_media_type(), i_ref( 0 )
215 cx_media_type
.majortype
= mt
[0].majortype
;
218 CapturePin::~CapturePin()
221 msg_Dbg( p_input
, "CapturePin::~CapturePin" );
223 for( size_t c
=0; c
<media_type_count
; c
++ )
225 FreeMediaType(media_types
[c
]);
227 FreeMediaType(cx_media_type
);
231 * Returns the complete queue of samples that have been received so far.
232 * Lock the p_sys->lock before calling this function.
233 * @param samples_queue [out] Empty queue that will get all elements from
235 * @return S_OK if a sample was available, S_FALSE if no sample was
238 HRESULT
CapturePin::CustomGetSamples( std::deque
<VLCMediaSample
> &external_queue
)
240 #if 0 //def DEBUG_DSHOW
241 msg_Dbg( p_input
, "CapturePin::CustomGetSamples: %d samples in the queue", samples_queue
.size());
244 if( !samples_queue
.empty() )
246 external_queue
.swap(samples_queue
);
253 * Returns a sample from its sample queue. Proper locking must be done prior
254 * to this call. Current dshow code protects the access to any sample queue
255 * (audio and video) with the p_sys->lock
256 * @param vlc_sample [out] Address of a sample if sucessfull. Undefined
258 * @return S_OK if a sample was available, S_FALSE if no sample was
261 HRESULT
CapturePin::CustomGetSample( VLCMediaSample
*vlc_sample
)
263 #if 0 //def DEBUG_DSHOW
264 msg_Dbg( p_input
, "CapturePin::CustomGetSample" );
267 if( !samples_queue
.empty() )
269 *vlc_sample
= samples_queue
.back();
270 samples_queue
.pop_back();
276 AM_MEDIA_TYPE
&CapturePin::CustomGetMediaType()
278 return cx_media_type
;
281 /* IUnknown methods */
282 STDMETHODIMP
CapturePin::QueryInterface(REFIID riid
, void **ppv
)
284 #ifdef DEBUG_DSHOW_L1
285 msg_Dbg( p_input
, "CapturePin::QueryInterface" );
288 if( riid
== IID_IUnknown
||
295 if( riid
== IID_IMemInputPin
)
298 *ppv
= (IMemInputPin
*)this;
303 #ifdef DEBUG_DSHOW_L1
304 msg_Dbg( p_input
, "CapturePin::QueryInterface() failed for: "
305 "%04X-%02X-%02X-%02X%02X%02X%02X%02X%02X%02X%02X",
306 (int)riid
.Data1
, (int)riid
.Data2
, (int)riid
.Data3
,
307 static_cast<int>(riid
.Data4
[0]), (int)riid
.Data4
[1],
308 (int)riid
.Data4
[2], (int)riid
.Data4
[3],
309 (int)riid
.Data4
[4], (int)riid
.Data4
[5],
310 (int)riid
.Data4
[6], (int)riid
.Data4
[7] );
313 return E_NOINTERFACE
;
317 STDMETHODIMP_(ULONG
) CapturePin::AddRef()
319 #ifdef DEBUG_DSHOW_L1
320 msg_Dbg( p_input
, "CapturePin::AddRef (ref: %i)", i_ref
);
325 STDMETHODIMP_(ULONG
) CapturePin::Release()
327 #ifdef DEBUG_DSHOW_L1
328 msg_Dbg( p_input
, "CapturePin::Release (ref: %i)", i_ref
);
331 if( !InterlockedDecrement(&i_ref
) ) delete this;
337 STDMETHODIMP
CapturePin::Connect( IPin
*,
338 const AM_MEDIA_TYPE
*pmt
)
340 if( State_Running
== p_filter
->state
)
342 msg_Dbg( p_input
, "CapturePin::Connect [not stopped]" );
343 return VFW_E_NOT_STOPPED
;
346 if( p_connected_pin
)
348 msg_Dbg( p_input
, "CapturePin::Connect [already connected]" );
349 return VFW_E_ALREADY_CONNECTED
;
352 if( !pmt
) return S_OK
;
354 if( GUID_NULL
!= pmt
->majortype
&&
355 media_types
[0].majortype
!= pmt
->majortype
)
357 msg_Dbg( p_input
, "CapturePin::Connect [media major type mismatch]" );
361 if( GUID_NULL
!= pmt
->subtype
&& !GetFourCCFromMediaType(*pmt
) )
363 msg_Dbg( p_input
, "CapturePin::Connect [media subtype type "
368 if( pmt
->pbFormat
&& pmt
->majortype
== MEDIATYPE_Video
)
370 if( !((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biHeight
||
371 !((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biWidth
)
373 msg_Dbg( p_input
, "CapturePin::Connect "
374 "[video width/height == 0 ]" );
379 msg_Dbg( p_input
, "CapturePin::Connect [OK]" );
382 STDMETHODIMP
CapturePin::ReceiveConnection( IPin
* pConnector
,
383 const AM_MEDIA_TYPE
*pmt
)
385 if( State_Stopped
!= p_filter
->state
)
387 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [not stopped]" );
388 return VFW_E_NOT_STOPPED
;
391 if( !pConnector
|| !pmt
)
393 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [null pointer]" );
397 if( p_connected_pin
)
399 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [already connected]");
400 return VFW_E_ALREADY_CONNECTED
;
403 if( S_OK
!= QueryAccept(pmt
) )
405 msg_Dbg( p_input
, "CapturePin::ReceiveConnection "
406 "[media type not accepted]" );
407 return VFW_E_TYPE_NOT_ACCEPTED
;
410 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [OK]" );
412 p_connected_pin
= pConnector
;
414 FreeMediaType( cx_media_type
);
415 return CopyMediaType( &cx_media_type
, pmt
);
417 STDMETHODIMP
CapturePin::Disconnect()
419 if( ! p_connected_pin
)
421 msg_Dbg( p_input
, "CapturePin::Disconnect [not connected]" );
425 msg_Dbg( p_input
, "CapturePin::Disconnect [OK]" );
427 /* samples_queue was already flushed in EndFlush() */
429 p_connected_pin
.Reset();
430 //FreeMediaType( cx_media_type );
431 //cx_media_type.subtype = GUID_NULL;
435 STDMETHODIMP
CapturePin::ConnectedTo( IPin
**pPin
)
437 if( !p_connected_pin
)
439 msg_Dbg( p_input
, "CapturePin::ConnectedTo [not connected]" );
440 return VFW_E_NOT_CONNECTED
;
443 p_connected_pin
.CopyTo( pPin
);
445 msg_Dbg( p_input
, "CapturePin::ConnectedTo [OK]" );
449 STDMETHODIMP
CapturePin::ConnectionMediaType( AM_MEDIA_TYPE
*pmt
)
451 if( !p_connected_pin
)
453 msg_Dbg( p_input
, "CapturePin::ConnectionMediaType [not connected]" );
454 return VFW_E_NOT_CONNECTED
;
457 return CopyMediaType( pmt
, &cx_media_type
);
459 STDMETHODIMP
CapturePin::QueryPinInfo( PIN_INFO
* pInfo
)
462 msg_Dbg( p_input
, "CapturePin::QueryPinInfo" );
465 pInfo
->pFilter
= p_filter
;
468 memcpy(pInfo
->achName
, PIN_NAME
, sizeof(PIN_NAME
));
469 pInfo
->dir
= PINDIR_INPUT
;
473 STDMETHODIMP
CapturePin::QueryDirection( PIN_DIRECTION
* pPinDir
)
476 msg_Dbg( p_input
, "CapturePin::QueryDirection" );
479 *pPinDir
= PINDIR_INPUT
;
482 STDMETHODIMP
CapturePin::QueryId( LPWSTR
* Id
)
485 msg_Dbg( p_input
, "CapturePin::QueryId" );
488 *Id
= (LPWSTR
)L
"VLC Capture Pin";
492 STDMETHODIMP
CapturePin::QueryAccept( const AM_MEDIA_TYPE
*pmt
)
494 if( State_Stopped
!= p_filter
->state
)
496 msg_Dbg( p_input
, "CapturePin::QueryAccept [not stopped]" );
500 if( media_types
[0].majortype
!= pmt
->majortype
)
502 msg_Dbg( p_input
, "CapturePin::QueryAccept [media type mismatch]" );
506 int i_fourcc
= GetFourCCFromMediaType(*pmt
);
509 msg_Dbg( p_input
, "CapturePin::QueryAccept "
510 "[media type not supported]" );
514 if( pmt
->majortype
== MEDIATYPE_Video
)
517 ( (((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biHeight
== 0) ||
518 (((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biWidth
== 0) ) )
520 msg_Dbg( p_input
, "CapturePin::QueryAccept [video size wxh == 0]");
524 msg_Dbg( p_input
, "CapturePin::QueryAccept [OK] "
525 "(width=%ld, height=%ld, chroma=%4.4s, fps=%f)",
526 ((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biWidth
,
527 ((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biHeight
,
529 10000000.0f
/((float)((VIDEOINFOHEADER
*)pmt
->pbFormat
)->AvgTimePerFrame
) );
531 else if( pmt
->majortype
== MEDIATYPE_Audio
)
533 msg_Dbg( p_input
, "CapturePin::QueryAccept [OK] (channels=%d, "
534 "samples/sec=%lu, bits/samples=%d, format=%4.4s)",
535 ((WAVEFORMATEX
*)pmt
->pbFormat
)->nChannels
,
536 ((WAVEFORMATEX
*)pmt
->pbFormat
)->nSamplesPerSec
,
537 ((WAVEFORMATEX
*)pmt
->pbFormat
)->wBitsPerSample
,
542 msg_Dbg( p_input
, "CapturePin::QueryAccept [OK] (stream format=%4.4s)",
546 if( p_connected_pin
)
548 FreeMediaType( cx_media_type
);
549 CopyMediaType( &cx_media_type
, pmt
);
554 STDMETHODIMP
CapturePin::EnumMediaTypes( IEnumMediaTypes
**ppEnum
)
556 #ifdef DEBUG_DSHOW_L1
557 msg_Dbg( p_input
, "CapturePin::EnumMediaTypes" );
560 *ppEnum
= new (std::nothrow
) CaptureEnumMediaTypes( p_input
, this, NULL
);
562 if( *ppEnum
== NULL
) return E_OUTOFMEMORY
;
566 STDMETHODIMP
CapturePin::QueryInternalConnections( IPin
**, ULONG
* )
568 #ifdef DEBUG_DSHOW_L1
569 msg_Dbg( p_input
, "CapturePin::QueryInternalConnections" );
573 STDMETHODIMP
CapturePin::EndOfStream( void )
576 msg_Dbg( p_input
, "CapturePin::EndOfStream" );
580 STDMETHODIMP
CapturePin::BeginFlush( void )
583 msg_Dbg( p_input
, "CapturePin::BeginFlush" );
587 STDMETHODIMP
CapturePin::EndFlush( void )
590 msg_Dbg( p_input
, "CapturePin::EndFlush" );
593 vlc_mutex_lock( &p_sys
->lock
);
594 while( !samples_queue
.empty() )
596 samples_queue
.pop_back();
598 vlc_mutex_unlock( &p_sys
->lock
);
602 STDMETHODIMP
CapturePin::NewSegment( REFERENCE_TIME
, REFERENCE_TIME
, double )
605 msg_Dbg( p_input
, "CapturePin::NewSegment" );
610 /* IMemInputPin methods */
611 STDMETHODIMP
CapturePin::GetAllocator( IMemAllocator
** )
614 msg_Dbg( p_input
, "CapturePin::GetAllocator" );
617 return VFW_E_NO_ALLOCATOR
;
619 STDMETHODIMP
CapturePin::NotifyAllocator( IMemAllocator
*, BOOL
)
622 msg_Dbg( p_input
, "CapturePin::NotifyAllocator" );
627 STDMETHODIMP
CapturePin::GetAllocatorRequirements( ALLOCATOR_PROPERTIES
* )
630 msg_Dbg( p_input
, "CapturePin::GetAllocatorRequirements" );
635 STDMETHODIMP
CapturePin::Receive( IMediaSample
*pSample
)
637 #if 0 //def DEBUG_DSHOW
638 msg_Dbg( p_input
, "CapturePin::Receive" );
641 mtime_t i_timestamp
= mdate() * 10;
642 VLCMediaSample vlc_sample
= {pSample
, i_timestamp
};
644 vlc_mutex_lock( &p_sys
->lock
);
645 samples_queue
.push_front( vlc_sample
);
647 /* Make sure we don't cache too many samples */
648 if( samples_queue
.size() > 10 )
650 samples_queue
.pop_back();
651 msg_Dbg( p_input
, "CapturePin::Receive trashing late input sample" );
654 vlc_cond_signal( &p_sys
->wait
);
655 vlc_mutex_unlock( &p_sys
->lock
);
659 STDMETHODIMP
CapturePin::ReceiveMultiple( IMediaSample
**pSamples
,
661 long *nSamplesProcessed
)
665 *nSamplesProcessed
= 0;
666 while( nSamples
-- > 0 )
668 hr
= Receive( pSamples
[*nSamplesProcessed
] );
669 if( hr
!= S_OK
) break;
670 (*nSamplesProcessed
)++;
674 STDMETHODIMP
CapturePin::ReceiveCanBlock( void )
677 msg_Dbg( p_input
, "CapturePin::ReceiveCanBlock" );
680 return S_FALSE
; /* Thou shalt not block */
683 /****************************************************************************
684 * Implementation of our dummy directshow filter class
685 ****************************************************************************/
686 CaptureFilter::CaptureFilter( vlc_object_t
*_p_input
, access_sys_t
*p_sys
,
687 AM_MEDIA_TYPE
*mt
, size_t mt_count
)
688 : p_input( _p_input
),
689 p_pin( new CapturePin( _p_input
, p_sys
, this, mt
, mt_count
) ),
690 state( State_Stopped
), i_ref( 0 )
694 CaptureFilter::~CaptureFilter()
697 msg_Dbg( p_input
, "CaptureFilter::~CaptureFilter" );
701 /* IUnknown methods */
702 STDMETHODIMP
CaptureFilter::QueryInterface( REFIID riid
, void **ppv
)
704 #ifdef DEBUG_DSHOW_L1
705 msg_Dbg( p_input
, "CaptureFilter::QueryInterface" );
708 if( riid
== IID_IUnknown
)
711 *ppv
= (IUnknown
*)this;
714 if( riid
== IID_IPersist
)
717 *ppv
= (IPersist
*)this;
720 if( riid
== IID_IMediaFilter
)
723 *ppv
= (IMediaFilter
*)this;
726 if( riid
== IID_IBaseFilter
)
729 *ppv
= (IBaseFilter
*)this;
734 #ifdef DEBUG_DSHOW_L1
735 msg_Dbg( p_input
, "CaptureFilter::QueryInterface() failed for: "
736 "%04X-%02X-%02X-%02X%02X%02X%02X%02X%02X%02X%02X",
737 (int)riid
.Data1
, (int)riid
.Data2
, (int)riid
.Data3
,
738 static_cast<int>(riid
.Data4
[0]), (int)riid
.Data4
[1],
739 (int)riid
.Data4
[2], (int)riid
.Data4
[3],
740 (int)riid
.Data4
[4], (int)riid
.Data4
[5],
741 (int)riid
.Data4
[6], (int)riid
.Data4
[7] );
744 return E_NOINTERFACE
;
747 STDMETHODIMP_(ULONG
) CaptureFilter::AddRef()
749 #ifdef DEBUG_DSHOW_L1
750 msg_Dbg( p_input
, "CaptureFilter::AddRef (ref: %i)", i_ref
);
755 STDMETHODIMP_(ULONG
) CaptureFilter::Release()
757 #ifdef DEBUG_DSHOW_L1
758 msg_Dbg( p_input
, "CaptureFilter::Release (ref: %i)", i_ref
);
761 if( !InterlockedDecrement(&i_ref
) ) delete this;
766 /* IPersist method */
767 STDMETHODIMP
CaptureFilter::GetClassID(CLSID
*)
770 msg_Dbg( p_input
, "CaptureFilter::GetClassID" );
775 /* IMediaFilter methods */
776 STDMETHODIMP
CaptureFilter::GetState(DWORD
, FILTER_STATE
*State
)
779 msg_Dbg( p_input
, "CaptureFilter::GetState %i", state
);
785 STDMETHODIMP
CaptureFilter::SetSyncSource(IReferenceClock
*)
788 msg_Dbg( p_input
, "CaptureFilter::SetSyncSource" );
793 STDMETHODIMP
CaptureFilter::GetSyncSource(IReferenceClock
**pClock
)
796 msg_Dbg( p_input
, "CaptureFilter::GetSyncSource" );
802 STDMETHODIMP
CaptureFilter::Stop()
805 msg_Dbg( p_input
, "CaptureFilter::Stop" );
810 state
= State_Stopped
;
813 STDMETHODIMP
CaptureFilter::Pause()
816 msg_Dbg( p_input
, "CaptureFilter::Pause" );
819 state
= State_Paused
;
822 STDMETHODIMP
CaptureFilter::Run(REFERENCE_TIME
)
825 msg_Dbg( p_input
, "CaptureFilter::Run" );
828 state
= State_Running
;
832 /* IBaseFilter methods */
833 STDMETHODIMP
CaptureFilter::EnumPins( IEnumPins
** ppEnum
)
836 msg_Dbg( p_input
, "CaptureFilter::EnumPins" );
839 /* Create a new ref counted enumerator */
840 *ppEnum
= new (std::nothrow
) CaptureEnumPins( p_input
, this, NULL
);
841 if ( *ppEnum
== NULL
) return E_OUTOFMEMORY
;
845 STDMETHODIMP
CaptureFilter::FindPin( LPCWSTR
, IPin
** )
848 msg_Dbg( p_input
, "CaptureFilter::FindPin" );
852 STDMETHODIMP
CaptureFilter::QueryFilterInfo( FILTER_INFO
* pInfo
)
855 msg_Dbg( p_input
, "CaptureFilter::QueryFilterInfo" );
858 memcpy(pInfo
->achName
, FILTER_NAME
, sizeof(FILTER_NAME
));
860 p_graph
.CopyTo( &pInfo
->pGraph
);
864 STDMETHODIMP
CaptureFilter::JoinFilterGraph( IFilterGraph
* pGraph
,
868 msg_Dbg( p_input
, "CaptureFilter::JoinFilterGraph" );
875 STDMETHODIMP
CaptureFilter::QueryVendorInfo( LPWSTR
* )
878 msg_Dbg( p_input
, "CaptureFilter::QueryVendorInfo" );
884 ComPtr
<CapturePin
>& CaptureFilter::CustomGetPin()
889 /****************************************************************************
890 * Implementation of our dummy directshow enumpins class
891 ****************************************************************************/
893 CaptureEnumPins::CaptureEnumPins( vlc_object_t
*_p_input
,
894 ComPtr
<CaptureFilter
> _p_filter
,
895 ComPtr
<CaptureEnumPins
> pEnumPins
)
896 : p_input( _p_input
), p_filter( _p_filter
), i_ref( 0 )
898 /* Are we creating a new enumerator */
900 if( pEnumPins
== NULL
)
906 i_position
= pEnumPins
->i_position
;
910 CaptureEnumPins::~CaptureEnumPins()
912 #ifdef DEBUG_DSHOW_L1
913 msg_Dbg( p_input
, "CaptureEnumPins::~CaptureEnumPins" );
917 /* IUnknown methods */
918 STDMETHODIMP
CaptureEnumPins::QueryInterface( REFIID riid
, void **ppv
)
920 #ifdef DEBUG_DSHOW_L1
921 msg_Dbg( p_input
, "CaptureEnumPins::QueryInterface" );
924 if( riid
== IID_IUnknown
||
925 riid
== IID_IEnumPins
)
928 *ppv
= (IEnumPins
*)this;
934 return E_NOINTERFACE
;
937 STDMETHODIMP_(ULONG
) CaptureEnumPins::AddRef()
939 #ifdef DEBUG_DSHOW_L1
940 msg_Dbg( p_input
, "CaptureEnumPins::AddRef (ref: %i)", i_ref
);
945 STDMETHODIMP_(ULONG
) CaptureEnumPins::Release()
947 #ifdef DEBUG_DSHOW_L1
948 msg_Dbg( p_input
, "CaptureEnumPins::Release (ref: %i)", i_ref
);
951 if( !InterlockedDecrement(&i_ref
) ) delete this;
957 STDMETHODIMP
CaptureEnumPins::Next( ULONG cPins
, IPin
** ppPins
,
960 #ifdef DEBUG_DSHOW_L1
961 msg_Dbg( p_input
, "CaptureEnumPins::Next" );
964 unsigned int i_fetched
= 0;
966 if( i_position
< 1 && cPins
> 0 )
968 ComPtr
<CapturePin
> pPin
= p_filter
->CustomGetPin();
969 pPin
.CopyTo( ppPins
);
974 if( pcFetched
) *pcFetched
= i_fetched
;
976 return (i_fetched
== cPins
) ? S_OK
: S_FALSE
;
978 STDMETHODIMP
CaptureEnumPins::Skip( ULONG cPins
)
980 #ifdef DEBUG_DSHOW_L1
981 msg_Dbg( p_input
, "CaptureEnumPins::Skip" );
993 STDMETHODIMP
CaptureEnumPins::Reset()
995 #ifdef DEBUG_DSHOW_L1
996 msg_Dbg( p_input
, "CaptureEnumPins::Reset" );
1002 STDMETHODIMP
CaptureEnumPins::Clone( IEnumPins
**ppEnum
)
1004 #ifdef DEBUG_DSHOW_L1
1005 msg_Dbg( p_input
, "CaptureEnumPins::Clone" );
1008 *ppEnum
= new (std::nothrow
) CaptureEnumPins( p_input
, p_filter
, this );
1009 if( *ppEnum
== NULL
) return E_OUTOFMEMORY
;
1010 (*ppEnum
)->AddRef();
1014 /****************************************************************************
1015 * Implementation of our dummy directshow enummediatypes class
1016 ****************************************************************************/
1017 CaptureEnumMediaTypes::CaptureEnumMediaTypes( vlc_object_t
*_p_input
,
1018 ComPtr
<CapturePin
> _p_pin
, CaptureEnumMediaTypes
*pEnumMediaTypes
)
1019 : p_input( _p_input
), p_pin( _p_pin
), i_ref( 1 )
1021 /* Are we creating a new enumerator */
1022 if( pEnumMediaTypes
== NULL
)
1024 CopyMediaType(&cx_media_type
, &p_pin
->cx_media_type
);
1029 CopyMediaType(&cx_media_type
, &pEnumMediaTypes
->cx_media_type
);
1030 i_position
= pEnumMediaTypes
->i_position
;
1034 CaptureEnumMediaTypes::~CaptureEnumMediaTypes()
1036 #ifdef DEBUG_DSHOW_L1
1037 msg_Dbg( p_input
, "CaptureEnumMediaTypes::~CaptureEnumMediaTypes" );
1039 FreeMediaType(cx_media_type
);
1042 /* IUnknown methods */
1043 STDMETHODIMP
CaptureEnumMediaTypes::QueryInterface( REFIID riid
, void **ppv
)
1045 #ifdef DEBUG_DSHOW_L1
1046 msg_Dbg( p_input
, "CaptureEnumMediaTypes::QueryInterface" );
1049 if( riid
== IID_IUnknown
||
1050 riid
== IID_IEnumMediaTypes
)
1053 *ppv
= (IEnumMediaTypes
*)this;
1059 return E_NOINTERFACE
;
1062 STDMETHODIMP_(ULONG
) CaptureEnumMediaTypes::AddRef()
1064 #ifdef DEBUG_DSHOW_L1
1065 msg_Dbg( p_input
, "CaptureEnumMediaTypes::AddRef (ref: %i)", i_ref
);
1070 STDMETHODIMP_(ULONG
) CaptureEnumMediaTypes::Release()
1072 #ifdef DEBUG_DSHOW_L1
1073 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Release (ref: %i)", i_ref
);
1076 if( !InterlockedDecrement(&i_ref
) ) delete this;
1081 /* IEnumMediaTypes */
1082 STDMETHODIMP
CaptureEnumMediaTypes::Next( ULONG cMediaTypes
,
1083 AM_MEDIA_TYPE
** ppMediaTypes
,
1086 #ifdef DEBUG_DSHOW_L1
1087 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Next " );
1091 ULONG max
= p_pin
->media_type_count
;
1093 if( ! ppMediaTypes
)
1096 if( (! pcFetched
) && (cMediaTypes
> 1) )
1100 ** use connection media type as first entry in iterator if it exists
1103 if( cx_media_type
.subtype
!= GUID_NULL
)
1106 if( i_position
== 0 )
1108 ppMediaTypes
[copied
] =
1109 (AM_MEDIA_TYPE
*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
1110 if( CopyMediaType(ppMediaTypes
[copied
], &cx_media_type
) != S_OK
)
1111 return E_OUTOFMEMORY
;
1117 while( (copied
< cMediaTypes
) && (i_position
< max
) )
1119 ppMediaTypes
[copied
] =
1120 (AM_MEDIA_TYPE
*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
1121 if( CopyMediaType( ppMediaTypes
[copied
],
1122 &p_pin
->media_types
[i_position
-offset
]) != S_OK
)
1123 return E_OUTOFMEMORY
;
1129 if( pcFetched
) *pcFetched
= copied
;
1131 return (copied
== cMediaTypes
) ? S_OK
: S_FALSE
;
1133 STDMETHODIMP
CaptureEnumMediaTypes::Skip( ULONG cMediaTypes
)
1135 ULONG max
= p_pin
->media_type_count
;
1136 if( cx_media_type
.subtype
!= GUID_NULL
)
1140 #ifdef DEBUG_DSHOW_L1
1141 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Skip" );
1144 i_position
+= cMediaTypes
;
1145 return (i_position
< max
) ? S_OK
: S_FALSE
;
1147 STDMETHODIMP
CaptureEnumMediaTypes::Reset()
1149 #ifdef DEBUG_DSHOW_L1
1150 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Reset" );
1153 FreeMediaType(cx_media_type
);
1154 CopyMediaType(&cx_media_type
, &p_pin
->cx_media_type
);
1158 STDMETHODIMP
CaptureEnumMediaTypes::Clone( IEnumMediaTypes
**ppEnum
)
1160 #ifdef DEBUG_DSHOW_L1
1161 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Clone" );
1164 *ppEnum
= new (std::nothrow
) CaptureEnumMediaTypes( p_input
, p_pin
, this );
1165 if( *ppEnum
== NULL
) return E_OUTOFMEMORY
;