1 /*****************************************************************************
2 * filter.c : DirectShow access module for vlc
3 *****************************************************************************
4 * Copyright (C) 2002 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>
36 /* Work-around a bug in w32api-2.5 */
37 # define QACONTAINERFLAGS QACONTAINERFLAGS_SOMETHINGELSE
45 #define FILTER_NAME L"VideoLAN Capture Filter"
46 #define PIN_NAME L"Capture"
48 /*****************************************************************************
50 * Easier to define them here as mingw doesn't provide them all.
51 *****************************************************************************/
52 const GUID CLSID_SystemDeviceEnum
= {0x62be5d10, 0x60eb, 0x11d0, {0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86}};
53 const GUID CLSID_VideoInputDeviceCategory
= {0x860BB310,0x5D01,0x11d0,{0xBD,0x3B,0x00,0xA0,0xC9,0x11,0xCE,0x86}};
54 const GUID CLSID_AudioInputDeviceCategory
= {0x33d9a762, 0x90c8, 0x11d0, {0xbd, 0x43, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86}};
55 //const GUID IID_IPropertyBag = {0x55272A00, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}};
56 extern const GUID IID_IPropertyBag
;
57 const GUID IID_ICreateDevEnum
= {0x29840822, 0x5b84, 0x11d0, {0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86}};
58 const GUID IID_IFilterGraph
= {0x56a8689f, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
59 const GUID IID_IMediaControl
= {0x56a868b1, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
60 const GUID CLSID_FilterGraph
= {0xe436ebb3, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
62 //const GUID IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46}};
63 extern const GUID IID_IUnknown
;
64 //const GUID IID_IPersist = {0x0000010c, 0x0000, 0x0000, {0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46}};
65 extern const GUID IID_IPersist
;
66 const GUID IID_IMediaFilter
= {0x56a86899, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}};
67 const GUID IID_IBaseFilter
= {0x56a86895, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
68 const GUID IID_IPin
= {0x56a86891, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}};
69 const GUID IID_IMemInputPin
= {0x56a8689d, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}};
70 extern const GUID IID_IMemInputPin
;
72 const GUID IID_IEnumPins
= {0x56a86892, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}};
73 const GUID IID_IEnumMediaTypes
= {0x89c31040, 0x846b, 0x11ce, {0x97,0xd3, 0x00,0xaa,0x00,0x55,0x59,0x5a}};
75 const GUID IID_IAMBufferNegotiation
= {0x56ed71a0, 0xaf5f, 0x11d0, {0xb3, 0xf0, 0x00, 0xaa, 0x00, 0x37, 0x61, 0xc5}};
77 //const GUID IID_ISpecifyPropertyPages = {0xb196b28b, 0xbab4, 0x101a, {0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07}};
78 extern const GUID IID_ISpecifyPropertyPages
;
80 const GUID IID_IQualityControl
= {0x56a868a5, 0x0ad4, 0x11ce, {0xb, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
82 const GUID CLSID_CaptureGraphBuilder2
= {0xBF87B6E1, 0x8C27, 0x11d0, {0xB3, 0xF0, 0x0, 0xAA, 0x00, 0x37, 0x61, 0xC5}};
84 const GUID IID_IGraphBuilder
= {0x56a868a9, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
86 const GUID IID_ICaptureGraphBuilder2
= {0x93E5A4E0, 0x2D50, 0x11d2, {0xAB, 0xFA, 0x00, 0xA0, 0xC9, 0xC6, 0xE3, 0x8D}};
88 const GUID IID_IAMTVAudio
= {0x83EC1C30, 0x23D1, 0x11d1, {0x99, 0xE6, 0x00, 0xA0, 0xC9, 0x56, 0x02, 0x66}};
89 const GUID IID_IAMStreamConfig
= {0xC6E13340, 0x30AC, 0x11d0, {0xA1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56}};
90 const GUID IID_IAMCrossbar
= {0xC6E13380, 0x30AC, 0x11d0, {0xA1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56}};
91 const GUID IID_IAMTVTuner
= {0x211A8766, 0x03AC, 0x11d1, {0x8D, 0x13, 0x00, 0xAA, 0x00, 0xBD, 0x83, 0x39}};
93 const GUID IID_IKsPropertySet
= {0x31EFAC30, 0x515C, 0x11d0, {0xA9, 0xAA, 0x00, 0xAA, 0x00, 0x61, 0xBE, 0x93}};
97 const GUID FORMAT_VideoInfo
= {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
99 * MEDIATYPEs and MEDIASUBTYPEs
101 const GUID MEDIATYPE_Video
= {0x73646976, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
102 const GUID MEDIATYPE_Interleaved
= {0x73766169, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
103 const GUID MEDIATYPE_Stream
= {0xe436eb83, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
104 const GUID MEDIASUBTYPE_PREVIEW_VIDEO
= {0x2859e1da, 0xb81f, 0x4fbd, {0x94, 0x3b, 0xe2, 0x37, 0x24, 0xa1, 0xab, 0xb3}};
106 /* Packed RGB formats */
107 const GUID MEDIASUBTYPE_RGB1
= {0xe436eb78, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
108 const GUID MEDIASUBTYPE_RGB4
= {0xe436eb79, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
109 const GUID MEDIASUBTYPE_RGB8
= {0xe436eb7a, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
110 const GUID MEDIASUBTYPE_RGB565
= {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
111 const GUID MEDIASUBTYPE_RGB555
= {0xe436eb7c, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
112 const GUID MEDIASUBTYPE_RGB24
= {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
113 const GUID MEDIASUBTYPE_RGB32
= {0xe436eb7e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
114 const GUID MEDIASUBTYPE_ARGB32
= {0x773c9ac0, 0x3274, 0x11d0, {0xb7, 0x24, 0x0, 0xaa, 0x0, 0x6c, 0x1a, 0x1}};
116 /* Packed YUV formats */
117 const GUID MEDIASUBTYPE_YUYV
= {0x56595559, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
118 const GUID MEDIASUBTYPE_Y411
= {0x31313459, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
119 const GUID MEDIASUBTYPE_Y211
= {0x31313259, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
120 const GUID MEDIASUBTYPE_YUY2
= {0x32595559, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
121 const GUID MEDIASUBTYPE_YVYU
= {0x55595659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
122 const GUID MEDIASUBTYPE_UYVY
= {0x59565955, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
124 /* Planar YUV formats */
125 const GUID MEDIASUBTYPE_YVU9
= {0x39555659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
126 const GUID MEDIASUBTYPE_YV12
= {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
127 const GUID MEDIASUBTYPE_IYUV
= {0x56555949, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; /* identical to YV12 */
128 const GUID MEDIASUBTYPE_Y41P
= {0x50313459, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
129 const GUID MEDIASUBTYPE_I420
= {0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
131 const GUID MEDIATYPE_Audio
= {0x73647561, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
132 const GUID FORMAT_WaveFormatEx
= {0x05589f81, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
133 const GUID MEDIASUBTYPE_PCM
= {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
134 const GUID MEDIASUBTYPE_IEEE_FLOAT
= {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
137 const GUID MEDIASUBTYPE_dvsd
= {0x64737664, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
138 const GUID MEDIASUBTYPE_dvhd
= {0x64687664, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
139 const GUID MEDIASUBTYPE_dvsl
= {0x6c737664, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
142 const GUID MEDIASUBTYPE_MPEG2_VIDEO
= {0xe06d8026, 0xdb46, 0x11cf, {0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea}};
143 const GUID MEDIASUBTYPE_MPEG2_PROGRAM
= {0xe06d8022, 0xdb46, 0x11cf, {0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea}};
144 const GUID MEDIASUBTYPE_MPEG2_TRANSPORT
= {0xe06d8023, 0xdb46, 0x11cf, {0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea}};
145 const GUID FORMAT_MPEG2Video
= {0xe06d80e3, 0xdb46, 0x11cf, {0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea}};
148 const GUID MEDIASUBTYPE_MJPG
= {0x47504A4D, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
151 const GUID MEDIASUBTYPE_DIVX
= {0x58564944, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
154 const GUID FORMAT_AnalogVideo
= {0x482dde0, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
156 const GUID MEDIATYPE_AnalogVideo
= {0x482dde1, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xab, 0x0, 0x6e, 0xcb, 0x65}};
158 const GUID MEDIASUBTYPE_AnalogVideo_NTSC_M
= {0x482dde2, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
159 const GUID MEDIASUBTYPE_AnalogVideo_PAL_B
= {0x482dde5, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
160 const GUID MEDIASUBTYPE_AnalogVideo_PAL_D
= {0x482dde6, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
161 const GUID MEDIASUBTYPE_AnalogVideo_PAL_G
= {0x482dde7, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
162 const GUID MEDIASUBTYPE_AnalogVideo_PAL_H
= {0x482dde8, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
163 const GUID MEDIASUBTYPE_AnalogVideo_PAL_I
= {0x482dde9, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
164 const GUID MEDIASUBTYPE_AnalogVideo_PAL_M
= {0x482ddea, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
165 const GUID MEDIASUBTYPE_AnalogVideo_PAL_N
= {0x482ddeb, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
166 const GUID MEDIASUBTYPE_AnalogVideo_PAL_N_COMBO
= {0x482ddec, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
167 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_B
= {0x482ddf0, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
168 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_D
= {0x482ddf1, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
169 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_G
= {0x482ddf2, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
170 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_H
= {0x482ddf3, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
171 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_K
= {0x482ddf4, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
172 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_K1
= {0x482ddf5, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
173 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_L
= {0x482ddf6, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
175 const GUID AMPROPSETID_Pin
= {0x9b00f101, 0x1567, 0x11d1, {0xb3, 0xf1, 0x0, 0xaa, 0x0, 0x37, 0x61, 0xc5}};
176 const GUID PIN_CATEGORY_ANALOGVIDEOIN
= {0xfb6c4283, 0x0353, 0x11d1, {0x90, 0x5f, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba}};
177 const GUID PIN_CATEGORY_CAPTURE
= {0xfb6c4281, 0x0353, 0x11d1, {0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba}};
178 const GUID LOOK_UPSTREAM_ONLY
= {0xac798be0, 0x98e3, 0x11d1, {0xb3, 0xf1, 0x0, 0xaa, 0x0, 0x37, 0x61, 0xc}};
180 //const GUID GUID_NULL = {0x0000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
181 extern const GUID GUID_NULL
;
183 void WINAPI
FreeMediaType( AM_MEDIA_TYPE
& mt
)
185 if( mt
.cbFormat
!= 0 )
187 CoTaskMemFree( (PVOID
)mt
.pbFormat
);
191 if( mt
.pUnk
!= NULL
)
198 HRESULT WINAPI
CopyMediaType( AM_MEDIA_TYPE
*pmtTarget
,
199 const AM_MEDIA_TYPE
*pmtSource
)
201 *pmtTarget
= *pmtSource
;
203 if( !pmtSource
|| !pmtTarget
) return S_FALSE
;
205 if( pmtSource
->cbFormat
&& pmtSource
->pbFormat
)
207 pmtTarget
->pbFormat
= (PBYTE
)CoTaskMemAlloc( pmtSource
->cbFormat
);
208 if( pmtTarget
->pbFormat
== NULL
)
210 pmtTarget
->cbFormat
= 0;
211 return E_OUTOFMEMORY
;
215 CopyMemory( (PVOID
)pmtTarget
->pbFormat
, (PVOID
)pmtSource
->pbFormat
,
216 pmtTarget
->cbFormat
);
219 if( pmtTarget
->pUnk
!= NULL
)
221 pmtTarget
->pUnk
->AddRef();
227 int GetFourCCFromMediaType( const AM_MEDIA_TYPE
&media_type
)
231 if( media_type
.majortype
== MEDIATYPE_Video
)
233 /* currently only support this type of video info format */
234 if( 1 /* media_type.formattype == FORMAT_VideoInfo */ )
236 /* Packed RGB formats */
237 if( media_type
.subtype
== MEDIASUBTYPE_RGB1
)
238 i_fourcc
= VLC_FOURCC( 'R', 'G', 'B', '1' );
239 else if( media_type
.subtype
== MEDIASUBTYPE_RGB4
)
240 i_fourcc
= VLC_FOURCC( 'R', 'G', 'B', '4' );
241 else if( media_type
.subtype
== MEDIASUBTYPE_RGB8
)
242 i_fourcc
= VLC_FOURCC( 'R', 'G', 'B', '8' );
243 else if( media_type
.subtype
== MEDIASUBTYPE_RGB555
)
244 i_fourcc
= VLC_FOURCC( 'R', 'V', '1', '5' );
245 else if( media_type
.subtype
== MEDIASUBTYPE_RGB565
)
246 i_fourcc
= VLC_FOURCC( 'R', 'V', '1', '6' );
247 else if( media_type
.subtype
== MEDIASUBTYPE_RGB24
)
248 i_fourcc
= VLC_FOURCC( 'R', 'V', '2', '4' );
249 else if( media_type
.subtype
== MEDIASUBTYPE_RGB32
)
250 i_fourcc
= VLC_FOURCC( 'R', 'V', '3', '2' );
251 else if( media_type
.subtype
== MEDIASUBTYPE_ARGB32
)
252 i_fourcc
= VLC_FOURCC( 'R', 'G', 'B', 'A' );
254 /* Planar YUV formats */
255 else if( media_type
.subtype
== MEDIASUBTYPE_I420
)
256 i_fourcc
= VLC_FOURCC( 'I', '4', '2', '0' );
257 else if( media_type
.subtype
== MEDIASUBTYPE_Y41P
)
258 i_fourcc
= VLC_FOURCC( 'I', '4', '1', '1' );
259 else if( media_type
.subtype
== MEDIASUBTYPE_YV12
)
260 i_fourcc
= VLC_FOURCC( 'Y', 'V', '1', '2' );
261 else if( media_type
.subtype
== MEDIASUBTYPE_IYUV
)
262 i_fourcc
= VLC_FOURCC( 'Y', 'V', '1', '2' );
263 else if( media_type
.subtype
== MEDIASUBTYPE_YVU9
)
264 i_fourcc
= VLC_FOURCC( 'Y', 'V', 'U', '9' );
266 /* Packed YUV formats */
267 else if( media_type
.subtype
== MEDIASUBTYPE_YVYU
)
268 i_fourcc
= VLC_FOURCC( 'Y', 'V', 'Y', 'U' );
269 else if( media_type
.subtype
== MEDIASUBTYPE_YUYV
)
270 i_fourcc
= VLC_FOURCC( 'Y', 'U', 'Y', '2' );
271 else if( media_type
.subtype
== MEDIASUBTYPE_Y411
)
272 i_fourcc
= VLC_FOURCC( 'I', '4', '1', 'N' );
273 else if( media_type
.subtype
== MEDIASUBTYPE_Y211
)
274 i_fourcc
= VLC_FOURCC( 'Y', '2', '1', '1' );
275 else if( media_type
.subtype
== MEDIASUBTYPE_YUY2
)
276 i_fourcc
= VLC_FOURCC( 'Y', 'U', 'Y', '2' );
277 else if( media_type
.subtype
== MEDIASUBTYPE_UYVY
)
278 i_fourcc
= VLC_FOURCC( 'U', 'Y', 'V', 'Y' );
280 /* MPEG2 video elementary stream */
281 else if( media_type
.subtype
== MEDIASUBTYPE_MPEG2_VIDEO
)
282 i_fourcc
= VLC_FOURCC( 'm', 'p', '2', 'v' );
285 else if( media_type
.subtype
== MEDIASUBTYPE_DIVX
)
286 i_fourcc
= VLC_FOURCC( 'D', 'I', 'V', 'X' );
289 else if( media_type
.subtype
== MEDIASUBTYPE_dvsl
)
290 i_fourcc
= VLC_FOURCC( 'd', 'v', 's', 'l' );
291 else if( media_type
.subtype
== MEDIASUBTYPE_dvsd
)
292 i_fourcc
= VLC_FOURCC( 'd', 'v', 's', 'd' );
293 else if( media_type
.subtype
== MEDIASUBTYPE_dvhd
)
294 i_fourcc
= VLC_FOURCC( 'd', 'v', 'h', 'd' );
297 else if( media_type
.subtype
== MEDIASUBTYPE_MJPG
)
298 i_fourcc
= VLC_FOURCC( 'M', 'J', 'P', 'G' );
302 else if( media_type
.majortype
== MEDIATYPE_Audio
)
304 /* currently only support this type of audio info format */
305 if( media_type
.formattype
== FORMAT_WaveFormatEx
)
307 if( media_type
.subtype
== MEDIASUBTYPE_PCM
)
308 i_fourcc
= VLC_FOURCC( 'a', 'r', 'a', 'w' );
309 else if( media_type
.subtype
== MEDIASUBTYPE_IEEE_FLOAT
)
310 i_fourcc
= VLC_FOURCC( 'f', 'l', '3', '2' );
313 else if( media_type
.majortype
== MEDIATYPE_Stream
)
315 if( media_type
.subtype
== MEDIASUBTYPE_MPEG2_PROGRAM
)
316 i_fourcc
= VLC_FOURCC( 'm', 'p', '2', 'p' );
317 else if( media_type
.subtype
== MEDIASUBTYPE_MPEG2_TRANSPORT
)
318 i_fourcc
= VLC_FOURCC( 'm', 'p', '2', 't' );
324 /****************************************************************************
325 * Implementation of our dummy directshow filter pin class
326 ****************************************************************************/
328 CapturePin::CapturePin( vlc_object_t
*_p_input
, access_sys_t
*_p_sys
,
329 CaptureFilter
*_p_filter
,
330 AM_MEDIA_TYPE
*mt
, size_t mt_count
)
331 : p_input( _p_input
), p_sys( _p_sys
), p_filter( _p_filter
),
332 p_connected_pin( NULL
), media_types(mt
), media_type_count(mt_count
),
335 cx_media_type
.majortype
= mt
[0].majortype
;
336 cx_media_type
.subtype
= GUID_NULL
;
337 cx_media_type
.pbFormat
= NULL
;
338 cx_media_type
.cbFormat
= 0;
339 cx_media_type
.pUnk
= NULL
;
342 CapturePin::~CapturePin()
345 msg_Dbg( p_input
, "CapturePin::~CapturePin" );
347 for( size_t c
=0; c
<media_type_count
; c
++ )
349 FreeMediaType(media_types
[c
]);
351 FreeMediaType(cx_media_type
);
355 * Returns the complete queue of samples that have been received so far.
356 * Lock the p_sys->lock before calling this function.
357 * @param samples_queue [out] Empty queue that will get all elements from
359 * @return S_OK if a sample was available, S_FALSE if no sample was
362 HRESULT
CapturePin::CustomGetSamples( deque
<VLCMediaSample
> &external_queue
)
364 #if 0 //def DEBUG_DSHOW
365 msg_Dbg( p_input
, "CapturePin::CustomGetSamples: %d samples in the queue", samples_queue
.size());
368 if( !samples_queue
.empty() )
370 external_queue
.swap(samples_queue
);
377 * Returns a sample from its sample queue. Proper locking must be done prior
378 * to this call. Current dshow code protects the access to any sample queue
379 * (audio and video) with the p_sys->lock
380 * @param vlc_sample [out] Address of a sample if sucessfull. Undefined
382 * @return S_OK if a sample was available, S_FALSE if no sample was
385 HRESULT
CapturePin::CustomGetSample( VLCMediaSample
*vlc_sample
)
387 #if 0 //def DEBUG_DSHOW
388 msg_Dbg( p_input
, "CapturePin::CustomGetSample" );
391 if( samples_queue
.size() )
393 *vlc_sample
= samples_queue
.back();
394 samples_queue
.pop_back();
400 AM_MEDIA_TYPE
&CapturePin::CustomGetMediaType()
402 return cx_media_type
;
405 /* IUnknown methods */
406 STDMETHODIMP
CapturePin::QueryInterface(REFIID riid
, void **ppv
)
408 #ifdef DEBUG_DSHOW_L1
409 msg_Dbg( p_input
, "CapturePin::QueryInterface" );
412 if( riid
== IID_IUnknown
||
419 if( riid
== IID_IMemInputPin
)
422 *ppv
= (IMemInputPin
*)this;
427 #ifdef DEBUG_DSHOW_L1
428 msg_Dbg( p_input
, "CapturePin::QueryInterface() failed for: "
429 "%04X-%02X-%02X-%02X%02X%02X%02X%02X%02X%02X%02X",
430 (int)riid
.Data1
, (int)riid
.Data2
, (int)riid
.Data3
,
431 static_cast<int>(riid
.Data4
[0]), (int)riid
.Data4
[1],
432 (int)riid
.Data4
[2], (int)riid
.Data4
[3],
433 (int)riid
.Data4
[4], (int)riid
.Data4
[5],
434 (int)riid
.Data4
[6], (int)riid
.Data4
[7] );
437 return E_NOINTERFACE
;
441 STDMETHODIMP_(ULONG
) CapturePin::AddRef()
443 #ifdef DEBUG_DSHOW_L1
444 msg_Dbg( p_input
, "CapturePin::AddRef (ref: %i)", i_ref
);
449 STDMETHODIMP_(ULONG
) CapturePin::Release()
451 #ifdef DEBUG_DSHOW_L1
452 msg_Dbg( p_input
, "CapturePin::Release (ref: %i)", i_ref
);
455 if( !InterlockedDecrement(&i_ref
) ) delete this;
461 STDMETHODIMP
CapturePin::Connect( IPin
* pReceivePin
,
462 const AM_MEDIA_TYPE
*pmt
)
464 if( State_Running
== p_filter
->state
)
466 msg_Dbg( p_input
, "CapturePin::Connect [not stopped]" );
467 return VFW_E_NOT_STOPPED
;
470 if( p_connected_pin
)
472 msg_Dbg( p_input
, "CapturePin::Connect [already connected]" );
473 return VFW_E_ALREADY_CONNECTED
;
476 if( !pmt
) return S_OK
;
478 if( GUID_NULL
!= pmt
->majortype
&&
479 media_types
[0].majortype
!= pmt
->majortype
)
481 msg_Dbg( p_input
, "CapturePin::Connect [media major type mismatch]" );
485 if( GUID_NULL
!= pmt
->subtype
&& !GetFourCCFromMediaType(*pmt
) )
487 msg_Dbg( p_input
, "CapturePin::Connect [media subtype type "
492 if( pmt
->pbFormat
&& pmt
->majortype
== MEDIATYPE_Video
)
494 if( !((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biHeight
||
495 !((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biWidth
)
497 msg_Dbg( p_input
, "CapturePin::Connect "
498 "[video width/height == 0 ]" );
503 msg_Dbg( p_input
, "CapturePin::Connect [OK]" );
506 STDMETHODIMP
CapturePin::ReceiveConnection( IPin
* pConnector
,
507 const AM_MEDIA_TYPE
*pmt
)
509 if( State_Stopped
!= p_filter
->state
)
511 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [not stopped]" );
512 return VFW_E_NOT_STOPPED
;
515 if( !pConnector
|| !pmt
)
517 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [null pointer]" );
521 if( p_connected_pin
)
523 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [already connected]");
524 return VFW_E_ALREADY_CONNECTED
;
527 if( S_OK
!= QueryAccept(pmt
) )
529 msg_Dbg( p_input
, "CapturePin::ReceiveConnection "
530 "[media type not accepted]" );
531 return VFW_E_TYPE_NOT_ACCEPTED
;
534 msg_Dbg( p_input
, "CapturePin::ReceiveConnection [OK]" );
536 p_connected_pin
= pConnector
;
537 p_connected_pin
->AddRef();
539 FreeMediaType( cx_media_type
);
540 return CopyMediaType( &cx_media_type
, pmt
);
542 STDMETHODIMP
CapturePin::Disconnect()
544 if( ! p_connected_pin
)
546 msg_Dbg( p_input
, "CapturePin::Disconnect [not connected]" );
550 msg_Dbg( p_input
, "CapturePin::Disconnect [OK]" );
552 /* samples_queue was already flushed in EndFlush() */
554 p_connected_pin
->Release();
555 p_connected_pin
= NULL
;
556 //FreeMediaType( cx_media_type );
557 //cx_media_type.subtype = GUID_NULL;
561 STDMETHODIMP
CapturePin::ConnectedTo( IPin
**pPin
)
563 if( !p_connected_pin
)
565 msg_Dbg( p_input
, "CapturePin::ConnectedTo [not connected]" );
566 return VFW_E_NOT_CONNECTED
;
569 p_connected_pin
->AddRef();
570 *pPin
= p_connected_pin
;
572 msg_Dbg( p_input
, "CapturePin::ConnectedTo [OK]" );
576 STDMETHODIMP
CapturePin::ConnectionMediaType( AM_MEDIA_TYPE
*pmt
)
578 if( !p_connected_pin
)
580 msg_Dbg( p_input
, "CapturePin::ConnectionMediaType [not connected]" );
581 return VFW_E_NOT_CONNECTED
;
584 return CopyMediaType( pmt
, &cx_media_type
);
586 STDMETHODIMP
CapturePin::QueryPinInfo( PIN_INFO
* pInfo
)
589 msg_Dbg( p_input
, "CapturePin::QueryPinInfo" );
592 pInfo
->pFilter
= p_filter
;
593 if( p_filter
) p_filter
->AddRef();
595 memcpy(pInfo
->achName
, PIN_NAME
, sizeof(PIN_NAME
));
596 pInfo
->dir
= PINDIR_INPUT
;
600 STDMETHODIMP
CapturePin::QueryDirection( PIN_DIRECTION
* pPinDir
)
603 msg_Dbg( p_input
, "CapturePin::QueryDirection" );
606 *pPinDir
= PINDIR_INPUT
;
609 STDMETHODIMP
CapturePin::QueryId( LPWSTR
* Id
)
612 msg_Dbg( p_input
, "CapturePin::QueryId" );
615 *Id
= L
"VideoLAN Capture Pin";
619 STDMETHODIMP
CapturePin::QueryAccept( const AM_MEDIA_TYPE
*pmt
)
621 if( State_Stopped
!= p_filter
->state
)
623 msg_Dbg( p_input
, "CapturePin::QueryAccept [not stopped]" );
627 if( media_types
[0].majortype
!= pmt
->majortype
)
629 msg_Dbg( p_input
, "CapturePin::QueryAccept [media type mismatch]" );
633 int i_fourcc
= GetFourCCFromMediaType(*pmt
);
636 msg_Dbg( p_input
, "CapturePin::QueryAccept "
637 "[media type not supported]" );
641 if( pmt
->majortype
== MEDIATYPE_Video
)
644 ( (((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biHeight
== 0) ||
645 (((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biWidth
== 0) ) )
647 msg_Dbg( p_input
, "CapturePin::QueryAccept [video size wxh == 0]");
651 msg_Dbg( p_input
, "CapturePin::QueryAccept [OK] "
652 "(width=%ld, height=%ld, chroma=%4.4s, fps=%f)",
653 ((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biWidth
,
654 ((VIDEOINFOHEADER
*)pmt
->pbFormat
)->bmiHeader
.biHeight
,
656 10000000.0f
/((float)((VIDEOINFOHEADER
*)pmt
->pbFormat
)->AvgTimePerFrame
) );
658 else if( pmt
->majortype
== MEDIATYPE_Audio
)
660 msg_Dbg( p_input
, "CapturePin::QueryAccept [OK] (channels=%d, "
661 "samples/sec=%lu, bits/samples=%d, format=%4.4s)",
662 ((WAVEFORMATEX
*)pmt
->pbFormat
)->nChannels
,
663 ((WAVEFORMATEX
*)pmt
->pbFormat
)->nSamplesPerSec
,
664 ((WAVEFORMATEX
*)pmt
->pbFormat
)->wBitsPerSample
,
669 msg_Dbg( p_input
, "CapturePin::QueryAccept [OK] (stream format=%4.4s)",
673 if( p_connected_pin
)
675 FreeMediaType( cx_media_type
);
676 CopyMediaType( &cx_media_type
, pmt
);
681 STDMETHODIMP
CapturePin::EnumMediaTypes( IEnumMediaTypes
**ppEnum
)
683 #ifdef DEBUG_DSHOW_L1
684 msg_Dbg( p_input
, "CapturePin::EnumMediaTypes" );
687 *ppEnum
= new CaptureEnumMediaTypes( p_input
, this, NULL
);
689 if( *ppEnum
== NULL
) return E_OUTOFMEMORY
;
693 STDMETHODIMP
CapturePin::QueryInternalConnections( IPin
* *apPin
, ULONG
*nPin
)
695 #ifdef DEBUG_DSHOW_L1
696 msg_Dbg( p_input
, "CapturePin::QueryInternalConnections" );
700 STDMETHODIMP
CapturePin::EndOfStream( void )
703 msg_Dbg( p_input
, "CapturePin::EndOfStream" );
707 STDMETHODIMP
CapturePin::BeginFlush( void )
710 msg_Dbg( p_input
, "CapturePin::BeginFlush" );
714 STDMETHODIMP
CapturePin::EndFlush( void )
717 msg_Dbg( p_input
, "CapturePin::EndFlush" );
720 VLCMediaSample vlc_sample
;
722 vlc_mutex_lock( &p_sys
->lock
);
723 while( samples_queue
.size() )
725 vlc_sample
= samples_queue
.back();
726 samples_queue
.pop_back();
727 vlc_sample
.p_sample
->Release();
729 vlc_mutex_unlock( &p_sys
->lock
);
733 STDMETHODIMP
CapturePin::NewSegment( REFERENCE_TIME tStart
,
734 REFERENCE_TIME tStop
,
738 msg_Dbg( p_input
, "CapturePin::NewSegment" );
743 /* IMemInputPin methods */
744 STDMETHODIMP
CapturePin::GetAllocator( IMemAllocator
**ppAllocator
)
747 msg_Dbg( p_input
, "CapturePin::GetAllocator" );
750 return VFW_E_NO_ALLOCATOR
;
752 STDMETHODIMP
CapturePin::NotifyAllocator( IMemAllocator
*pAllocator
,
756 msg_Dbg( p_input
, "CapturePin::NotifyAllocator" );
761 STDMETHODIMP
CapturePin::GetAllocatorRequirements( ALLOCATOR_PROPERTIES
*pProps
)
764 msg_Dbg( p_input
, "CapturePin::GetAllocatorRequirements" );
769 STDMETHODIMP
CapturePin::Receive( IMediaSample
*pSample
)
771 #if 0 //def DEBUG_DSHOW
772 msg_Dbg( p_input
, "CapturePin::Receive" );
776 mtime_t i_timestamp
= mdate() * 10;
777 VLCMediaSample vlc_sample
= {pSample
, i_timestamp
};
779 vlc_mutex_lock( &p_sys
->lock
);
780 samples_queue
.push_front( vlc_sample
);
782 /* Make sure we don't cache too many samples */
783 if( samples_queue
.size() > 10 )
785 vlc_sample
= samples_queue
.back();
786 samples_queue
.pop_back();
787 msg_Dbg( p_input
, "CapturePin::Receive trashing late input sample" );
788 vlc_sample
.p_sample
->Release();
791 vlc_cond_signal( &p_sys
->wait
);
792 vlc_mutex_unlock( &p_sys
->lock
);
796 STDMETHODIMP
CapturePin::ReceiveMultiple( IMediaSample
**pSamples
,
798 long *nSamplesProcessed
)
802 *nSamplesProcessed
= 0;
803 while( nSamples
-- > 0 )
805 hr
= Receive( pSamples
[*nSamplesProcessed
] );
806 if( hr
!= S_OK
) break;
807 (*nSamplesProcessed
)++;
811 STDMETHODIMP
CapturePin::ReceiveCanBlock( void )
814 msg_Dbg( p_input
, "CapturePin::ReceiveCanBlock" );
817 return S_FALSE
; /* Thou shalt not block */
820 /****************************************************************************
821 * Implementation of our dummy directshow filter class
822 ****************************************************************************/
823 CaptureFilter::CaptureFilter( vlc_object_t
*_p_input
, access_sys_t
*p_sys
,
824 AM_MEDIA_TYPE
*mt
, size_t mt_count
)
825 : p_input( _p_input
),
826 p_pin( new CapturePin( _p_input
, p_sys
, this, mt
, mt_count
) ),
827 state( State_Stopped
), i_ref( 1 )
831 CaptureFilter::~CaptureFilter()
834 msg_Dbg( p_input
, "CaptureFilter::~CaptureFilter" );
839 /* IUnknown methods */
840 STDMETHODIMP
CaptureFilter::QueryInterface( REFIID riid
, void **ppv
)
842 #ifdef DEBUG_DSHOW_L1
843 msg_Dbg( p_input
, "CaptureFilter::QueryInterface" );
846 if( riid
== IID_IUnknown
)
849 *ppv
= (IUnknown
*)this;
852 if( riid
== IID_IPersist
)
855 *ppv
= (IPersist
*)this;
858 if( riid
== IID_IMediaFilter
)
861 *ppv
= (IMediaFilter
*)this;
864 if( riid
== IID_IBaseFilter
)
867 *ppv
= (IBaseFilter
*)this;
872 #ifdef DEBUG_DSHOW_L1
873 msg_Dbg( p_input
, "CaptureFilter::QueryInterface() failed for: "
874 "%04X-%02X-%02X-%02X%02X%02X%02X%02X%02X%02X%02X",
875 (int)riid
.Data1
, (int)riid
.Data2
, (int)riid
.Data3
,
876 static_cast<int>(riid
.Data4
[0]), (int)riid
.Data4
[1],
877 (int)riid
.Data4
[2], (int)riid
.Data4
[3],
878 (int)riid
.Data4
[4], (int)riid
.Data4
[5],
879 (int)riid
.Data4
[6], (int)riid
.Data4
[7] );
882 return E_NOINTERFACE
;
885 STDMETHODIMP_(ULONG
) CaptureFilter::AddRef()
887 #ifdef DEBUG_DSHOW_L1
888 msg_Dbg( p_input
, "CaptureFilter::AddRef (ref: %i)", i_ref
);
893 STDMETHODIMP_(ULONG
) CaptureFilter::Release()
895 #ifdef DEBUG_DSHOW_L1
896 msg_Dbg( p_input
, "CaptureFilter::Release (ref: %i)", i_ref
);
899 if( !InterlockedDecrement(&i_ref
) ) delete this;
904 /* IPersist method */
905 STDMETHODIMP
CaptureFilter::GetClassID(CLSID
*pClsID
)
908 msg_Dbg( p_input
, "CaptureFilter::GetClassID" );
913 /* IMediaFilter methods */
914 STDMETHODIMP
CaptureFilter::GetState(DWORD dwMSecs
, FILTER_STATE
*State
)
917 msg_Dbg( p_input
, "CaptureFilter::GetState %i", state
);
923 STDMETHODIMP
CaptureFilter::SetSyncSource(IReferenceClock
*pClock
)
926 msg_Dbg( p_input
, "CaptureFilter::SetSyncSource" );
931 STDMETHODIMP
CaptureFilter::GetSyncSource(IReferenceClock
**pClock
)
934 msg_Dbg( p_input
, "CaptureFilter::GetSyncSource" );
940 STDMETHODIMP
CaptureFilter::Stop()
943 msg_Dbg( p_input
, "CaptureFilter::Stop" );
948 state
= State_Stopped
;
951 STDMETHODIMP
CaptureFilter::Pause()
954 msg_Dbg( p_input
, "CaptureFilter::Pause" );
957 state
= State_Paused
;
960 STDMETHODIMP
CaptureFilter::Run(REFERENCE_TIME tStart
)
963 msg_Dbg( p_input
, "CaptureFilter::Run" );
966 state
= State_Running
;
970 /* IBaseFilter methods */
971 STDMETHODIMP
CaptureFilter::EnumPins( IEnumPins
** ppEnum
)
974 msg_Dbg( p_input
, "CaptureFilter::EnumPins" );
977 /* Create a new ref counted enumerator */
978 *ppEnum
= new CaptureEnumPins( p_input
, this, NULL
);
979 return *ppEnum
== NULL
? E_OUTOFMEMORY
: NOERROR
;
981 STDMETHODIMP
CaptureFilter::FindPin( LPCWSTR Id
, IPin
** ppPin
)
984 msg_Dbg( p_input
, "CaptureFilter::FindPin" );
988 STDMETHODIMP
CaptureFilter::QueryFilterInfo( FILTER_INFO
* pInfo
)
991 msg_Dbg( p_input
, "CaptureFilter::QueryFilterInfo" );
994 memcpy(pInfo
->achName
, FILTER_NAME
, sizeof(FILTER_NAME
));
996 pInfo
->pGraph
= p_graph
;
997 if( p_graph
) p_graph
->AddRef();
1001 STDMETHODIMP
CaptureFilter::JoinFilterGraph( IFilterGraph
* pGraph
,
1005 msg_Dbg( p_input
, "CaptureFilter::JoinFilterGraph" );
1012 STDMETHODIMP
CaptureFilter::QueryVendorInfo( LPWSTR
* pVendorInfo
)
1015 msg_Dbg( p_input
, "CaptureFilter::QueryVendorInfo" );
1020 /* Custom methods */
1021 CapturePin
*CaptureFilter::CustomGetPin()
1026 /****************************************************************************
1027 * Implementation of our dummy directshow enumpins class
1028 ****************************************************************************/
1030 CaptureEnumPins::CaptureEnumPins( vlc_object_t
*_p_input
,
1031 CaptureFilter
*_p_filter
,
1032 CaptureEnumPins
*pEnumPins
)
1033 : p_input( _p_input
), p_filter( _p_filter
), i_ref( 1 )
1035 /* Hold a reference count on our filter */
1038 /* Are we creating a new enumerator */
1040 if( pEnumPins
== NULL
)
1046 i_position
= pEnumPins
->i_position
;
1050 CaptureEnumPins::~CaptureEnumPins()
1052 #ifdef DEBUG_DSHOW_L1
1053 msg_Dbg( p_input
, "CaptureEnumPins::~CaptureEnumPins" );
1055 p_filter
->Release();
1058 /* IUnknown methods */
1059 STDMETHODIMP
CaptureEnumPins::QueryInterface( REFIID riid
, void **ppv
)
1061 #ifdef DEBUG_DSHOW_L1
1062 msg_Dbg( p_input
, "CaptureEnumPins::QueryInterface" );
1065 if( riid
== IID_IUnknown
||
1066 riid
== IID_IEnumPins
)
1069 *ppv
= (IEnumPins
*)this;
1075 return E_NOINTERFACE
;
1078 STDMETHODIMP_(ULONG
) CaptureEnumPins::AddRef()
1080 #ifdef DEBUG_DSHOW_L1
1081 msg_Dbg( p_input
, "CaptureEnumPins::AddRef (ref: %i)", i_ref
);
1086 STDMETHODIMP_(ULONG
) CaptureEnumPins::Release()
1088 #ifdef DEBUG_DSHOW_L1
1089 msg_Dbg( p_input
, "CaptureEnumPins::Release (ref: %i)", i_ref
);
1092 if( !InterlockedDecrement(&i_ref
) ) delete this;
1098 STDMETHODIMP
CaptureEnumPins::Next( ULONG cPins
, IPin
** ppPins
,
1101 #ifdef DEBUG_DSHOW_L1
1102 msg_Dbg( p_input
, "CaptureEnumPins::Next" );
1105 unsigned int i_fetched
= 0;
1107 if( i_position
< 1 && cPins
> 0 )
1109 IPin
*pPin
= p_filter
->CustomGetPin();
1116 if( pcFetched
) *pcFetched
= i_fetched
;
1118 return (i_fetched
== cPins
) ? S_OK
: S_FALSE
;
1120 STDMETHODIMP
CaptureEnumPins::Skip( ULONG cPins
)
1122 #ifdef DEBUG_DSHOW_L1
1123 msg_Dbg( p_input
, "CaptureEnumPins::Skip" );
1126 i_position
+= cPins
;
1128 if( i_position
> 1 )
1135 STDMETHODIMP
CaptureEnumPins::Reset()
1137 #ifdef DEBUG_DSHOW_L1
1138 msg_Dbg( p_input
, "CaptureEnumPins::Reset" );
1144 STDMETHODIMP
CaptureEnumPins::Clone( IEnumPins
**ppEnum
)
1146 #ifdef DEBUG_DSHOW_L1
1147 msg_Dbg( p_input
, "CaptureEnumPins::Clone" );
1150 *ppEnum
= new CaptureEnumPins( p_input
, p_filter
, this );
1151 if( *ppEnum
== NULL
) return E_OUTOFMEMORY
;
1156 /****************************************************************************
1157 * Implementation of our dummy directshow enummediatypes class
1158 ****************************************************************************/
1159 CaptureEnumMediaTypes::CaptureEnumMediaTypes( vlc_object_t
*_p_input
,
1160 CapturePin
*_p_pin
, CaptureEnumMediaTypes
*pEnumMediaTypes
)
1161 : p_input( _p_input
), p_pin( _p_pin
), i_ref( 1 )
1163 /* Hold a reference count on our filter */
1166 /* Are we creating a new enumerator */
1167 if( pEnumMediaTypes
== NULL
)
1169 CopyMediaType(&cx_media_type
, &p_pin
->cx_media_type
);
1174 CopyMediaType(&cx_media_type
, &pEnumMediaTypes
->cx_media_type
);
1175 i_position
= pEnumMediaTypes
->i_position
;
1179 CaptureEnumMediaTypes::~CaptureEnumMediaTypes()
1181 #ifdef DEBUG_DSHOW_L1
1182 msg_Dbg( p_input
, "CaptureEnumMediaTypes::~CaptureEnumMediaTypes" );
1184 FreeMediaType(cx_media_type
);
1188 /* IUnknown methods */
1189 STDMETHODIMP
CaptureEnumMediaTypes::QueryInterface( REFIID riid
, void **ppv
)
1191 #ifdef DEBUG_DSHOW_L1
1192 msg_Dbg( p_input
, "CaptureEnumMediaTypes::QueryInterface" );
1195 if( riid
== IID_IUnknown
||
1196 riid
== IID_IEnumMediaTypes
)
1199 *ppv
= (IEnumMediaTypes
*)this;
1205 return E_NOINTERFACE
;
1208 STDMETHODIMP_(ULONG
) CaptureEnumMediaTypes::AddRef()
1210 #ifdef DEBUG_DSHOW_L1
1211 msg_Dbg( p_input
, "CaptureEnumMediaTypes::AddRef (ref: %i)", i_ref
);
1216 STDMETHODIMP_(ULONG
) CaptureEnumMediaTypes::Release()
1218 #ifdef DEBUG_DSHOW_L1
1219 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Release (ref: %i)", i_ref
);
1222 if( !InterlockedDecrement(&i_ref
) ) delete this;
1227 /* IEnumMediaTypes */
1228 STDMETHODIMP
CaptureEnumMediaTypes::Next( ULONG cMediaTypes
,
1229 AM_MEDIA_TYPE
** ppMediaTypes
,
1232 #ifdef DEBUG_DSHOW_L1
1233 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Next " );
1237 ULONG max
= p_pin
->media_type_count
;
1239 if( ! ppMediaTypes
)
1242 if( (! pcFetched
) && (cMediaTypes
> 1) )
1246 ** use connection media type as first entry in iterator if it exists
1249 if( cx_media_type
.subtype
!= GUID_NULL
)
1252 if( i_position
== 0 )
1254 ppMediaTypes
[copied
] =
1255 (AM_MEDIA_TYPE
*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
1256 if( CopyMediaType(ppMediaTypes
[copied
], &cx_media_type
) != S_OK
)
1257 return E_OUTOFMEMORY
;
1263 while( (copied
< cMediaTypes
) && (i_position
< max
) )
1265 ppMediaTypes
[copied
] =
1266 (AM_MEDIA_TYPE
*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
1267 if( CopyMediaType( ppMediaTypes
[copied
],
1268 &p_pin
->media_types
[i_position
-offset
]) != S_OK
)
1269 return E_OUTOFMEMORY
;
1275 if( pcFetched
) *pcFetched
= copied
;
1277 return (copied
== cMediaTypes
) ? S_OK
: S_FALSE
;
1279 STDMETHODIMP
CaptureEnumMediaTypes::Skip( ULONG cMediaTypes
)
1281 ULONG max
= p_pin
->media_type_count
;
1282 if( cx_media_type
.subtype
!= GUID_NULL
)
1286 #ifdef DEBUG_DSHOW_L1
1287 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Skip" );
1290 i_position
+= cMediaTypes
;
1291 return (i_position
< max
) ? S_OK
: S_FALSE
;
1293 STDMETHODIMP
CaptureEnumMediaTypes::Reset()
1295 #ifdef DEBUG_DSHOW_L1
1296 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Reset" );
1299 FreeMediaType(cx_media_type
);
1300 CopyMediaType(&cx_media_type
, &p_pin
->cx_media_type
);
1304 STDMETHODIMP
CaptureEnumMediaTypes::Clone( IEnumMediaTypes
**ppEnum
)
1306 #ifdef DEBUG_DSHOW_L1
1307 msg_Dbg( p_input
, "CaptureEnumMediaTypes::Clone" );
1310 *ppEnum
= new CaptureEnumMediaTypes( p_input
, p_pin
, this );
1311 if( *ppEnum
== NULL
) return E_OUTOFMEMORY
;