00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030
00031 #include <vlc/vlc.h>
00032 #include <vlc/input.h>
00033 #include <vlc/vout.h>
00034
00035 #ifndef _MSC_VER
00036
00037 # define QACONTAINERFLAGS QACONTAINERFLAGS_SOMETHINGELSE
00038 #endif
00039
00040 #include "common.h"
00041 #include "filter.h"
00042
00043 #define DEBUG_DSHOW 1
00044
00045 #define FILTER_NAME L"VideoLAN Capture Filter"
00046 #define PIN_NAME L"Capture"
00047
00048
00049
00050
00051
00052 const GUID CLSID_SystemDeviceEnum = {0x62be5d10, 0x60eb, 0x11d0, {0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86}};
00053 const GUID CLSID_VideoInputDeviceCategory = {0x860BB310,0x5D01,0x11d0,{0xBD,0x3B,0x00,0xA0,0xC9,0x11,0xCE,0x86}};
00054 const GUID CLSID_AudioInputDeviceCategory = {0x33d9a762, 0x90c8, 0x11d0, {0xbd, 0x43, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86}};
00055
00056 extern const GUID IID_IPropertyBag;
00057 const GUID IID_ICreateDevEnum = {0x29840822, 0x5b84, 0x11d0, {0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86}};
00058 const GUID IID_IFilterGraph = {0x56a8689f, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00059 const GUID IID_IMediaControl = {0x56a868b1, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00060 const GUID CLSID_FilterGraph = {0xe436ebb3, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00061
00062
00063 extern const GUID IID_IUnknown;
00064
00065 extern const GUID IID_IPersist;
00066 const GUID IID_IMediaFilter = {0x56a86899, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}};
00067 const GUID IID_IBaseFilter = {0x56a86895, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00068 const GUID IID_IPin = {0x56a86891, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}};
00069 const GUID IID_IMemInputPin = {0x56a8689d, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}};
00070 extern const GUID IID_IMemInputPin;
00071
00072 const GUID IID_IEnumPins = {0x56a86892, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}};
00073 const GUID IID_IEnumMediaTypes = {0x89c31040, 0x846b, 0x11ce, {0x97,0xd3, 0x00,0xaa,0x00,0x55,0x59,0x5a}};
00074
00075 const GUID IID_IAMBufferNegotiation = {0x56ed71a0, 0xaf5f, 0x11d0, {0xb3, 0xf0, 0x00, 0xaa, 0x00, 0x37, 0x61, 0xc5}};
00076
00077
00078 extern const GUID IID_ISpecifyPropertyPages;
00079
00080 const GUID IID_IQualityControl = {0x56a868a5, 0x0ad4, 0x11ce, {0xb, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00081
00082 const GUID CLSID_CaptureGraphBuilder2 = {0xBF87B6E1, 0x8C27, 0x11d0, {0xB3, 0xF0, 0x0, 0xAA, 0x00, 0x37, 0x61, 0xC5}};
00083
00084 const GUID IID_IGraphBuilder = {0x56a868a9, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00085
00086 const GUID IID_ICaptureGraphBuilder2 = {0x93E5A4E0, 0x2D50, 0x11d2, {0xAB, 0xFA, 0x00, 0xA0, 0xC9, 0xC6, 0xE3, 0x8D}};
00087
00088 const GUID IID_IAMTVAudio = {0x83EC1C30, 0x23D1, 0x11d1, {0x99, 0xE6, 0x00, 0xA0, 0xC9, 0x56, 0x02, 0x66}};
00089 const GUID IID_IAMStreamConfig = {0xC6E13340, 0x30AC, 0x11d0, {0xA1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56}};
00090 const GUID IID_IAMCrossbar = {0xC6E13380, 0x30AC, 0x11d0, {0xA1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56}};
00091 const GUID IID_IAMTVTuner = {0x211A8766, 0x03AC, 0x11d1, {0x8D, 0x13, 0x00, 0xAA, 0x00, 0xBD, 0x83, 0x39}};
00092
00093 const GUID IID_IKsPropertySet = {0x31EFAC30, 0x515C, 0x11d0, {0xA9, 0xAA, 0x00, 0xAA, 0x00, 0x61, 0xBE, 0x93}};
00094
00095
00096
00097 const GUID FORMAT_VideoInfo = {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
00098
00099
00100
00101 const GUID MEDIATYPE_Video = {0x73646976, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00102 const GUID MEDIATYPE_Interleaved = {0x73766169, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00103 const GUID MEDIATYPE_Stream = {0xe436eb83, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00104 const GUID MEDIASUBTYPE_PREVIEW_VIDEO = {0x2859e1da, 0xb81f, 0x4fbd, {0x94, 0x3b, 0xe2, 0x37, 0x24, 0xa1, 0xab, 0xb3}};
00105
00106
00107 const GUID MEDIASUBTYPE_RGB1 = {0xe436eb78, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00108 const GUID MEDIASUBTYPE_RGB4 = {0xe436eb79, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00109 const GUID MEDIASUBTYPE_RGB8 = {0xe436eb7a, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00110 const GUID MEDIASUBTYPE_RGB565 = {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00111 const GUID MEDIASUBTYPE_RGB555 = {0xe436eb7c, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00112 const GUID MEDIASUBTYPE_RGB24 = {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00113 const GUID MEDIASUBTYPE_RGB32 = {0xe436eb7e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
00114 const GUID MEDIASUBTYPE_ARGB32 = {0x773c9ac0, 0x3274, 0x11d0, {0xb7, 0x24, 0x0, 0xaa, 0x0, 0x6c, 0x1a, 0x1}};
00115
00116
00117 const GUID MEDIASUBTYPE_YUYV = {0x56595559, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00118 const GUID MEDIASUBTYPE_Y411 = {0x31313459, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00119 const GUID MEDIASUBTYPE_Y211 = {0x31313259, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00120 const GUID MEDIASUBTYPE_YUY2 = {0x32595559, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00121 const GUID MEDIASUBTYPE_YVYU = {0x55595659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00122 const GUID MEDIASUBTYPE_UYVY = {0x59565955, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00123
00124
00125 const GUID MEDIASUBTYPE_YVU9 = {0x39555659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00126 const GUID MEDIASUBTYPE_YV12 = {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00127 const GUID MEDIASUBTYPE_IYUV = {0x56555949, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00128 const GUID MEDIASUBTYPE_Y41P = {0x50313459, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00129 const GUID MEDIASUBTYPE_I420 = {0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00130
00131 const GUID MEDIATYPE_Audio = {0x73647561, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00132 const GUID FORMAT_WaveFormatEx = {0x05589f81, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
00133 const GUID MEDIASUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00134 const GUID MEDIASUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00135
00136
00137 const GUID MEDIASUBTYPE_dvsd = {0x64737664, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00138 const GUID MEDIASUBTYPE_dvhd = {0x64687664, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00139 const GUID MEDIASUBTYPE_dvsl = {0x6c737664, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
00140
00141
00142 const GUID MEDIASUBTYPE_MPEG2_VIDEO = {0xe06d8026, 0xdb46, 0x11cf, {0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea}};
00143 const GUID MEDIASUBTYPE_MPEG2_PROGRAM = {0xe06d8022, 0xdb46, 0x11cf, {0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea}};
00144 const GUID MEDIASUBTYPE_MPEG2_TRANSPORT = {0xe06d8023, 0xdb46, 0x11cf, {0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea}};
00145 const GUID FORMAT_MPEG2Video = {0xe06d80e3, 0xdb46, 0x11cf, {0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea}};
00146
00147
00148 const GUID FORMAT_AnalogVideo = {0x482dde0, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00149
00150 const GUID MEDIATYPE_AnalogVideo = {0x482dde1, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xab, 0x0, 0x6e, 0xcb, 0x65}};
00151
00152 const GUID MEDIASUBTYPE_AnalogVideo_NTSC_M = {0x482dde2, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00153 const GUID MEDIASUBTYPE_AnalogVideo_PAL_B = {0x482dde5, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00154 const GUID MEDIASUBTYPE_AnalogVideo_PAL_D = {0x482dde6, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00155 const GUID MEDIASUBTYPE_AnalogVideo_PAL_G = {0x482dde7, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00156 const GUID MEDIASUBTYPE_AnalogVideo_PAL_H = {0x482dde8, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00157 const GUID MEDIASUBTYPE_AnalogVideo_PAL_I = {0x482dde9, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00158 const GUID MEDIASUBTYPE_AnalogVideo_PAL_M = {0x482ddea, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00159 const GUID MEDIASUBTYPE_AnalogVideo_PAL_N = {0x482ddeb, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00160 const GUID MEDIASUBTYPE_AnalogVideo_PAL_N_COMBO = {0x482ddec, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00161 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_B = {0x482ddf0, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00162 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_D = {0x482ddf1, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00163 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_G = {0x482ddf2, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00164 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_H = {0x482ddf3, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00165 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_K = {0x482ddf4, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00166 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_K1 = {0x482ddf5, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00167 const GUID MEDIASUBTYPE_AnalogVideo_SECAM_L = {0x482ddf6, 0x7817, 0x11cf, {0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65}};
00168
00169 const GUID AMPROPSETID_Pin= {0x9b00f101, 0x1567, 0x11d1, {0xb3, 0xf1, 0x0, 0xaa, 0x0, 0x37, 0x61, 0xc5}};
00170 const GUID PIN_CATEGORY_ANALOGVIDEOIN= {0xfb6c4283, 0x0353, 0x11d1, {0x90, 0x5f, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba}};
00171 const GUID PIN_CATEGORY_CAPTURE= {0xfb6c4281, 0x0353, 0x11d1, {0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba}};
00172 const GUID LOOK_UPSTREAM_ONLY= {0xac798be0, 0x98e3, 0x11d1, {0xb3, 0xf1, 0x0, 0xaa, 0x0, 0x37, 0x61, 0xc}};
00173
00174
00175 extern const GUID GUID_NULL;
00176
00177 void WINAPI FreeMediaType( AM_MEDIA_TYPE& mt )
00178 {
00179 if( mt.cbFormat != 0 )
00180 {
00181 CoTaskMemFree( (PVOID)mt.pbFormat );
00182 mt.cbFormat = 0;
00183 mt.pbFormat = NULL;
00184 }
00185 if( mt.pUnk != NULL )
00186 {
00187 mt.pUnk->Release();
00188 mt.pUnk = NULL;
00189 }
00190 }
00191
00192 HRESULT WINAPI CopyMediaType( AM_MEDIA_TYPE *pmtTarget,
00193 const AM_MEDIA_TYPE *pmtSource )
00194 {
00195 *pmtTarget = *pmtSource;
00196
00197 if( !pmtSource || !pmtTarget ) return S_FALSE;
00198
00199 if( pmtSource->cbFormat && pmtSource->pbFormat )
00200 {
00201 pmtTarget->pbFormat = (PBYTE)CoTaskMemAlloc( pmtSource->cbFormat );
00202 if( pmtTarget->pbFormat == NULL )
00203 {
00204 pmtTarget->cbFormat = 0;
00205 return E_OUTOFMEMORY;
00206 }
00207 else
00208 {
00209 CopyMemory( (PVOID)pmtTarget->pbFormat, (PVOID)pmtSource->pbFormat,
00210 pmtTarget->cbFormat );
00211 }
00212 }
00213 if( pmtTarget->pUnk != NULL )
00214 {
00215 pmtTarget->pUnk->AddRef();
00216 }
00217
00218 return S_OK;
00219 }
00220
00221 int GetFourCCFromMediaType( const AM_MEDIA_TYPE &media_type )
00222 {
00223 int i_fourcc = 0;
00224
00225 if( media_type.majortype == MEDIATYPE_Video )
00226 {
00227
00228 if( 1 )
00229 {
00230
00231 if( media_type.subtype == MEDIASUBTYPE_RGB1 )
00232 i_fourcc = VLC_FOURCC( 'R', 'G', 'B', '1' );
00233 else if( media_type.subtype == MEDIASUBTYPE_RGB4 )
00234 i_fourcc = VLC_FOURCC( 'R', 'G', 'B', '4' );
00235 else if( media_type.subtype == MEDIASUBTYPE_RGB8 )
00236 i_fourcc = VLC_FOURCC( 'R', 'G', 'B', '8' );
00237 else if( media_type.subtype == MEDIASUBTYPE_RGB555 )
00238 i_fourcc = VLC_FOURCC( 'R', 'V', '1', '5' );
00239 else if( media_type.subtype == MEDIASUBTYPE_RGB565 )
00240 i_fourcc = VLC_FOURCC( 'R', 'V', '1', '6' );
00241 else if( media_type.subtype == MEDIASUBTYPE_RGB24 )
00242 i_fourcc = VLC_FOURCC( 'R', 'V', '2', '4' );
00243 else if( media_type.subtype == MEDIASUBTYPE_RGB32 )
00244 i_fourcc = VLC_FOURCC( 'R', 'V', '3', '2' );
00245 else if( media_type.subtype == MEDIASUBTYPE_ARGB32 )
00246 i_fourcc = VLC_FOURCC( 'R', 'G', 'B', 'A' );
00247
00248
00249 else if( media_type.subtype == MEDIASUBTYPE_I420 )
00250 i_fourcc = VLC_FOURCC( 'I', '4', '2', '0' );
00251 else if( media_type.subtype == MEDIASUBTYPE_Y41P )
00252 i_fourcc = VLC_FOURCC( 'I', '4', '1', '1' );
00253 else if( media_type.subtype == MEDIASUBTYPE_YV12 )
00254 i_fourcc = VLC_FOURCC( 'Y', 'V', '1', '2' );
00255 else if( media_type.subtype == MEDIASUBTYPE_IYUV )
00256 i_fourcc = VLC_FOURCC( 'Y', 'V', '1', '2' );
00257 else if( media_type.subtype == MEDIASUBTYPE_YVU9 )
00258 i_fourcc = VLC_FOURCC( 'Y', 'V', 'U', '9' );
00259
00260
00261 else if( media_type.subtype == MEDIASUBTYPE_YVYU )
00262 i_fourcc = VLC_FOURCC( 'Y', 'V', 'Y', 'U' );
00263 else if( media_type.subtype == MEDIASUBTYPE_YUYV )
00264 i_fourcc = VLC_FOURCC( 'Y', 'U', 'Y', '2' );
00265 else if( media_type.subtype == MEDIASUBTYPE_Y411 )
00266 i_fourcc = VLC_FOURCC( 'I', '4', '1', 'N' );
00267 else if( media_type.subtype == MEDIASUBTYPE_Y211 )
00268 i_fourcc = VLC_FOURCC( 'Y', '2', '1', '1' );
00269 else if( media_type.subtype == MEDIASUBTYPE_YUY2 )
00270 i_fourcc = VLC_FOURCC( 'Y', 'U', 'Y', '2' );
00271 else if( media_type.subtype == MEDIASUBTYPE_UYVY )
00272 i_fourcc = VLC_FOURCC( 'U', 'Y', 'V', 'Y' );
00273
00274
00275 else if( media_type.subtype == MEDIASUBTYPE_MPEG2_VIDEO )
00276 i_fourcc = VLC_FOURCC( 'm', 'p', '2', 'v' );
00277
00278
00279 else if( media_type.subtype == MEDIASUBTYPE_dvsl )
00280 i_fourcc = VLC_FOURCC( 'd', 'v', 's', 'l' );
00281 else if( media_type.subtype == MEDIASUBTYPE_dvsd )
00282 i_fourcc = VLC_FOURCC( 'd', 'v', 's', 'd' );
00283 else if( media_type.subtype == MEDIASUBTYPE_dvhd )
00284 i_fourcc = VLC_FOURCC( 'd', 'v', 'h', 'd' );
00285 }
00286 }
00287 else if( media_type.majortype == MEDIATYPE_Audio )
00288 {
00289
00290 if( media_type.formattype == FORMAT_WaveFormatEx )
00291 {
00292 if( media_type.subtype == MEDIASUBTYPE_PCM )
00293 i_fourcc = VLC_FOURCC( 'a', 'r', 'a', 'w' );
00294 else if( media_type.subtype == MEDIASUBTYPE_IEEE_FLOAT )
00295 i_fourcc = VLC_FOURCC( 'f', 'l', '3', '2' );
00296 }
00297 }
00298 else if( media_type.majortype == MEDIATYPE_Stream )
00299 {
00300 if( media_type.subtype == MEDIASUBTYPE_MPEG2_PROGRAM )
00301 i_fourcc = VLC_FOURCC( 'm', 'p', '2', 'p' );
00302 else if( media_type.subtype == MEDIASUBTYPE_MPEG2_TRANSPORT )
00303 i_fourcc = VLC_FOURCC( 'm', 'p', '2', 't' );
00304 }
00305
00306 return i_fourcc;
00307 }
00308
00309
00310
00311
00312
00313 CapturePin::CapturePin( vlc_object_t *_p_input, access_sys_t *_p_sys,
00314 CaptureFilter *_p_filter,
00315 AM_MEDIA_TYPE *mt, size_t mt_count )
00316 : p_input( _p_input ), p_sys( _p_sys ), p_filter( _p_filter ),
00317 p_connected_pin( NULL ), media_types(mt), media_type_count(mt_count),
00318 i_ref( 1 )
00319 {
00320 cx_media_type.majortype = mt[0].majortype;
00321 cx_media_type.subtype = GUID_NULL;
00322 cx_media_type.pbFormat = NULL;
00323 cx_media_type.cbFormat = 0;
00324 cx_media_type.pUnk = NULL;
00325 }
00326
00327 CapturePin::~CapturePin()
00328 {
00329 #ifdef DEBUG_DSHOW
00330 msg_Dbg( p_input, "CapturePin::~CapturePin" );
00331 #endif
00332 for( size_t c=0; c<media_type_count; c++ )
00333 {
00334 FreeMediaType(media_types[c]);
00335 }
00336 FreeMediaType(cx_media_type);
00337 }
00338
00339 HRESULT CapturePin::CustomGetSample( VLCMediaSample *vlc_sample )
00340 {
00341 #if 0 //def DEBUG_DSHOW
00342 msg_Dbg( p_input, "CapturePin::CustomGetSample" );
00343 #endif
00344
00345 vlc_mutex_lock( &p_sys->lock );
00346 if( samples_queue.size() )
00347 {
00348 *vlc_sample = samples_queue.back();
00349 samples_queue.pop_back();
00350 vlc_mutex_unlock( &p_sys->lock );
00351 return S_OK;
00352 }
00353 vlc_mutex_unlock( &p_sys->lock );
00354 return S_FALSE;
00355 }
00356
00357 AM_MEDIA_TYPE &CapturePin::CustomGetMediaType()
00358 {
00359 return cx_media_type;
00360 }
00361
00362
00363 STDMETHODIMP CapturePin::QueryInterface(REFIID riid, void **ppv)
00364 {
00365 #ifdef DEBUG_DSHOW_L1
00366 msg_Dbg( p_input, "CapturePin::QueryInterface" );
00367 #endif
00368
00369 if( riid == IID_IUnknown ||
00370 riid == IID_IPin )
00371 {
00372 AddRef();
00373 *ppv = (IPin *)this;
00374 return NOERROR;
00375 }
00376 if( riid == IID_IMemInputPin )
00377 {
00378 AddRef();
00379 *ppv = (IMemInputPin *)this;
00380 return NOERROR;
00381 }
00382 else
00383 {
00384 #ifdef DEBUG_DSHOW_L1
00385 msg_Dbg( p_input, "CapturePin::QueryInterface() failed for: "
00386 "%04X-%02X-%02X-%02X%02X%02X%02X%02X%02X%02X%02X",
00387 (int)riid.Data1, (int)riid.Data2, (int)riid.Data3,
00388 static_cast<int>(riid.Data4[0]), (int)riid.Data4[1],
00389 (int)riid.Data4[2], (int)riid.Data4[3],
00390 (int)riid.Data4[4], (int)riid.Data4[5],
00391 (int)riid.Data4[6], (int)riid.Data4[7] );
00392 #endif
00393 *ppv = NULL;
00394 return E_NOINTERFACE;
00395 }
00396 }
00397
00398 STDMETHODIMP_(ULONG) CapturePin::AddRef()
00399 {
00400 #ifdef DEBUG_DSHOW_L1
00401 msg_Dbg( p_input, "CapturePin::AddRef (ref: %i)", i_ref );
00402 #endif
00403
00404 return i_ref++;
00405 };
00406 STDMETHODIMP_(ULONG) CapturePin::Release()
00407 {
00408 #ifdef DEBUG_DSHOW_L1
00409 msg_Dbg( p_input, "CapturePin::Release (ref: %i)", i_ref );
00410 #endif
00411
00412 if( !InterlockedDecrement(&i_ref) ) delete this;
00413
00414 return 0;
00415 };
00416
00417
00418 STDMETHODIMP CapturePin::Connect( IPin * pReceivePin,
00419 const AM_MEDIA_TYPE *pmt )
00420 {
00421 if( State_Running == p_filter->state )
00422 {
00423 msg_Dbg( p_input, "CapturePin::Connect [not stopped]" );
00424 return VFW_E_NOT_STOPPED;
00425 }
00426
00427 if( p_connected_pin )
00428 {
00429 msg_Dbg( p_input, "CapturePin::Connect [already connected]" );
00430 return VFW_E_ALREADY_CONNECTED;
00431 }
00432
00433 if( !pmt ) return S_OK;
00434
00435 if( GUID_NULL != pmt->majortype &&
00436 media_types[0].majortype != pmt->majortype )
00437 {
00438 msg_Dbg( p_input, "CapturePin::Connect [media major type mismatch]" );
00439 return S_FALSE;
00440 }
00441
00442 if( GUID_NULL != pmt->subtype && !GetFourCCFromMediaType(*pmt) )
00443 {
00444 msg_Dbg( p_input, "CapturePin::Connect [media subtype type "
00445 "not supported]" );
00446 return S_FALSE;
00447 }
00448
00449 if( pmt->pbFormat && pmt->majortype == MEDIATYPE_Video )
00450 {
00451 if( !((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biHeight ||
00452 !((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biWidth )
00453 {
00454 msg_Dbg( p_input, "CapturePin::Connect "
00455 "[video width/height == 0 ]" );
00456 return S_FALSE;
00457 }
00458 }
00459
00460 msg_Dbg( p_input, "CapturePin::Connect [OK]" );
00461 return S_OK;
00462 }
00463 STDMETHODIMP CapturePin::ReceiveConnection( IPin * pConnector,
00464 const AM_MEDIA_TYPE *pmt )
00465 {
00466 if( State_Stopped != p_filter->state )
00467 {
00468 msg_Dbg( p_input, "CapturePin::ReceiveConnection [not stopped]" );
00469 return VFW_E_NOT_STOPPED;
00470 }
00471
00472 if( !pConnector || !pmt )
00473 {
00474 msg_Dbg( p_input, "CapturePin::ReceiveConnection [null pointer]" );
00475 return E_POINTER;
00476 }
00477
00478 if( p_connected_pin )
00479 {
00480 msg_Dbg( p_input, "CapturePin::ReceiveConnection [already connected]");
00481 return VFW_E_ALREADY_CONNECTED;
00482 }
00483
00484 if( S_OK != QueryAccept(pmt) )
00485 {
00486 msg_Dbg( p_input, "CapturePin::ReceiveConnection "
00487 "[media type not accepted]" );
00488 return VFW_E_TYPE_NOT_ACCEPTED;
00489 }
00490
00491 msg_Dbg( p_input, "CapturePin::ReceiveConnection [OK]" );
00492
00493 p_connected_pin = pConnector;
00494 p_connected_pin->AddRef();
00495
00496 FreeMediaType( cx_media_type );
00497 return CopyMediaType( &cx_media_type, pmt );
00498 }
00499 STDMETHODIMP CapturePin::Disconnect()
00500 {
00501 if( ! p_connected_pin )
00502 {
00503 msg_Dbg( p_input, "CapturePin::Disconnect [not connected]" );
00504 return S_FALSE;
00505 }
00506
00507 msg_Dbg( p_input, "CapturePin::Disconnect [OK]" );
00508
00509
00510
00511 p_connected_pin->Release();
00512 p_connected_pin = NULL;
00513
00514
00515
00516 return S_OK;
00517 }
00518 STDMETHODIMP CapturePin::ConnectedTo( IPin **pPin )
00519 {
00520 if( !p_connected_pin )
00521 {
00522 msg_Dbg( p_input, "CapturePin::ConnectedTo [not connected]" );
00523 return VFW_E_NOT_CONNECTED;
00524 }
00525
00526 p_connected_pin->AddRef();
00527 *pPin = p_connected_pin;
00528
00529 msg_Dbg( p_input, "CapturePin::ConnectedTo [OK]" );
00530
00531 return S_OK;
00532 }
00533 STDMETHODIMP CapturePin::ConnectionMediaType( AM_MEDIA_TYPE *pmt )
00534 {
00535 if( !p_connected_pin )
00536 {
00537 msg_Dbg( p_input, "CapturePin::ConnectionMediaType [not connected]" );
00538 return VFW_E_NOT_CONNECTED;
00539 }
00540
00541 return CopyMediaType( pmt, &cx_media_type );
00542 }
00543 STDMETHODIMP CapturePin::QueryPinInfo( PIN_INFO * pInfo )
00544 {
00545 #ifdef DEBUG_DSHOW
00546 msg_Dbg( p_input, "CapturePin::QueryPinInfo" );
00547 #endif
00548
00549 pInfo->pFilter = p_filter;
00550 if( p_filter ) p_filter->AddRef();
00551
00552 memcpy(pInfo->achName, PIN_NAME, sizeof(PIN_NAME));
00553 pInfo->dir = PINDIR_INPUT;
00554
00555 return NOERROR;
00556 }
00557 STDMETHODIMP CapturePin::QueryDirection( PIN_DIRECTION * pPinDir )
00558 {
00559 #ifdef DEBUG_DSHOW
00560 msg_Dbg( p_input, "CapturePin::QueryDirection" );
00561 #endif
00562
00563 *pPinDir = PINDIR_INPUT;
00564 return NOERROR;
00565 }
00566 STDMETHODIMP CapturePin::QueryId( LPWSTR * Id )
00567 {
00568 #ifdef DEBUG_DSHOW
00569 msg_Dbg( p_input, "CapturePin::QueryId" );
00570 #endif
00571
00572 *Id = L"VideoLAN Capture Pin";
00573
00574 return S_OK;
00575 }
00576 STDMETHODIMP CapturePin::QueryAccept( const AM_MEDIA_TYPE *pmt )
00577 {
00578 if( State_Stopped != p_filter->state )
00579 {
00580 msg_Dbg( p_input, "CapturePin::QueryAccept [not stopped]" );
00581 return S_FALSE;
00582 }
00583
00584 if( media_types[0].majortype != pmt->majortype )
00585 {
00586 msg_Dbg( p_input, "CapturePin::QueryAccept [media type mismatch]" );
00587 return S_FALSE;
00588 }
00589
00590 int i_fourcc = GetFourCCFromMediaType(*pmt);
00591 if( !i_fourcc )
00592 {
00593 msg_Dbg( p_input, "CapturePin::QueryAccept "
00594 "[media type not supported]" );
00595 return S_FALSE;
00596 }
00597
00598 if( pmt->majortype == MEDIATYPE_Video )
00599 {
00600 if( pmt->pbFormat &&
00601 ( (((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biHeight == 0) ||
00602 (((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biWidth == 0) ) )
00603 {
00604 msg_Dbg( p_input, "CapturePin::QueryAccept [video size wxh == 0]");
00605 return S_FALSE;
00606 }
00607
00608 msg_Dbg( p_input, "CapturePin::QueryAccept [OK] "
00609 "(width=%ld, height=%ld, chroma=%4.4s)",
00610 ((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biWidth,
00611 ((VIDEOINFOHEADER *)pmt->pbFormat)->bmiHeader.biHeight,
00612 (char *)&i_fourcc );
00613 }
00614 else if( pmt->majortype == MEDIATYPE_Audio )
00615 {
00616 msg_Dbg( p_input, "CapturePin::QueryAccept [OK] (channels=%d, "
00617 "samples/sec=%lu, bits/samples=%d, format=%4.4s)",
00618 ((WAVEFORMATEX *)pmt->pbFormat)->nChannels,
00619 ((WAVEFORMATEX *)pmt->pbFormat)->nSamplesPerSec,
00620 ((WAVEFORMATEX *)pmt->pbFormat)->wBitsPerSample,
00621 (char *)&i_fourcc );
00622 }
00623 else
00624 {
00625 msg_Dbg( p_input, "CapturePin::QueryAccept [OK] (stream format=%4.4s)",
00626 (char *)&i_fourcc );
00627 }
00628
00629 if( p_connected_pin )
00630 {
00631 FreeMediaType( cx_media_type );
00632 CopyMediaType( &cx_media_type, pmt );
00633 }
00634
00635 return S_OK;
00636 }
00637 STDMETHODIMP CapturePin::EnumMediaTypes( IEnumMediaTypes **ppEnum )
00638 {
00639 #ifdef DEBUG_DSHOW_L1
00640 msg_Dbg( p_input, "CapturePin::EnumMediaTypes" );
00641 #endif
00642
00643 *ppEnum = new CaptureEnumMediaTypes( p_input, this, NULL );
00644
00645 if( *ppEnum == NULL ) return E_OUTOFMEMORY;
00646
00647 return NOERROR;
00648 }
00649 STDMETHODIMP CapturePin::QueryInternalConnections( IPin* *apPin, ULONG *nPin )
00650 {
00651 #ifdef DEBUG_DSHOW_L1
00652 msg_Dbg( p_input, "CapturePin::QueryInternalConnections" );
00653 #endif
00654 return E_NOTIMPL;
00655 }
00656 STDMETHODIMP CapturePin::EndOfStream( void )
00657 {
00658 #ifdef DEBUG_DSHOW
00659 msg_Dbg( p_input, "CapturePin::EndOfStream" );
00660 #endif
00661 return S_OK;
00662 }
00663 STDMETHODIMP CapturePin::BeginFlush( void )
00664 {
00665 #ifdef DEBUG_DSHOW
00666 msg_Dbg( p_input, "CapturePin::BeginFlush" );
00667 #endif
00668 return S_OK;
00669 }
00670 STDMETHODIMP CapturePin::EndFlush( void )
00671 {
00672 #ifdef DEBUG_DSHOW
00673 msg_Dbg( p_input, "CapturePin::EndFlush" );
00674 #endif
00675
00676 VLCMediaSample vlc_sample;
00677
00678 vlc_mutex_lock( &p_sys->lock );
00679 while( samples_queue.size() )
00680 {
00681 vlc_sample = samples_queue.back();
00682 samples_queue.pop_back();
00683 vlc_sample.p_sample->Release();
00684 }
00685 vlc_mutex_unlock( &p_sys->lock );
00686
00687 return S_OK;
00688 }
00689 STDMETHODIMP CapturePin::NewSegment( REFERENCE_TIME tStart,
00690 REFERENCE_TIME tStop,
00691 double dRate )
00692 {
00693 #ifdef DEBUG_DSHOW
00694 msg_Dbg( p_input, "CapturePin::NewSegment" );
00695 #endif
00696 return S_OK;
00697 }
00698
00699
00700 STDMETHODIMP CapturePin::GetAllocator( IMemAllocator **ppAllocator )
00701 {
00702 #ifdef DEBUG_DSHOW
00703 msg_Dbg( p_input, "CapturePin::GetAllocator" );
00704 #endif
00705
00706 return VFW_E_NO_ALLOCATOR;
00707 }
00708 STDMETHODIMP CapturePin::NotifyAllocator( IMemAllocator *pAllocator,
00709 BOOL bReadOnly )
00710 {
00711 #ifdef DEBUG_DSHOW
00712 msg_Dbg( p_input, "CapturePin::NotifyAllocator" );
00713 #endif
00714
00715 return S_OK;
00716 }
00717 STDMETHODIMP CapturePin::GetAllocatorRequirements( ALLOCATOR_PROPERTIES *pProps )
00718 {
00719 #ifdef DEBUG_DSHOW
00720 msg_Dbg( p_input, "CapturePin::GetAllocatorRequirements" );
00721 #endif
00722
00723 return E_NOTIMPL;
00724 }
00725 STDMETHODIMP CapturePin::Receive( IMediaSample *pSample )
00726 {
00727 #if 0 //def DEBUG_DSHOW
00728 msg_Dbg( p_input, "CapturePin::Receive" );
00729 #endif
00730
00731 pSample->AddRef();
00732 mtime_t i_timestamp = mdate() * 10;
00733 VLCMediaSample vlc_sample = {pSample, i_timestamp};
00734
00735 vlc_mutex_lock( &p_sys->lock );
00736 samples_queue.push_front( vlc_sample );
00737
00738
00739 if( samples_queue.size() > 10 )
00740 {
00741 vlc_sample = samples_queue.back();
00742 samples_queue.pop_back();
00743 msg_Dbg( p_input, "CapturePin::Receive trashing late input sample" );
00744 vlc_sample.p_sample->Release();
00745 }
00746
00747 vlc_cond_signal( &p_sys->wait );
00748 vlc_mutex_unlock( &p_sys->lock );
00749
00750 return S_OK;
00751 }
00752 STDMETHODIMP CapturePin::ReceiveMultiple( IMediaSample **pSamples,
00753 long nSamples,
00754 long *nSamplesProcessed )
00755 {
00756 HRESULT hr = S_OK;
00757
00758 *nSamplesProcessed = 0;
00759 while( nSamples-- > 0 )
00760 {
00761 hr = Receive( pSamples[*nSamplesProcessed] );
00762 if( hr != S_OK ) break;
00763 (*nSamplesProcessed)++;
00764 }
00765 return hr;
00766 }
00767 STDMETHODIMP CapturePin::ReceiveCanBlock( void )
00768 {
00769 #ifdef DEBUG_DSHOW
00770 msg_Dbg( p_input, "CapturePin::ReceiveCanBlock" );
00771 #endif
00772
00773 return S_FALSE;
00774 }
00775
00776
00777
00778
00779 CaptureFilter::CaptureFilter( vlc_object_t *_p_input, access_sys_t *p_sys,
00780 AM_MEDIA_TYPE *mt, size_t mt_count )
00781 : p_input( _p_input ),
00782 p_pin( new CapturePin( _p_input, p_sys, this, mt, mt_count ) ),
00783 state( State_Stopped ), i_ref( 1 )
00784 {
00785 }
00786
00787 CaptureFilter::~CaptureFilter()
00788 {
00789 #ifdef DEBUG_DSHOW
00790 msg_Dbg( p_input, "CaptureFilter::~CaptureFilter" );
00791 #endif
00792 p_pin->Release();
00793 }
00794
00795
00796 STDMETHODIMP CaptureFilter::QueryInterface( REFIID riid, void **ppv )
00797 {
00798 #ifdef DEBUG_DSHOW_L1
00799 msg_Dbg( p_input, "CaptureFilter::QueryInterface" );
00800 #endif
00801
00802 if( riid == IID_IUnknown )
00803 {
00804 AddRef();
00805 *ppv = (IUnknown *)this;
00806 return NOERROR;
00807 }
00808 if( riid == IID_IPersist )
00809 {
00810 AddRef();
00811 *ppv = (IPersist *)this;
00812 return NOERROR;
00813 }
00814 if( riid == IID_IMediaFilter )
00815 {
00816 AddRef();
00817 *ppv = (IMediaFilter *)this;
00818 return NOERROR;
00819 }
00820 if( riid == IID_IBaseFilter )
00821 {
00822 AddRef();
00823 *ppv = (IBaseFilter *)this;
00824 return NOERROR;
00825 }
00826 else
00827 {
00828 #ifdef DEBUG_DSHOW_L1
00829 msg_Dbg( p_input, "CaptureFilter::QueryInterface() failed for: "
00830 "%04X-%02X-%02X-%02X%02X%02X%02X%02X%02X%02X%02X",
00831 (int)riid.Data1, (int)riid.Data2, (int)riid.Data3,
00832 static_cast<int>(riid.Data4[0]), (int)riid.Data4[1],
00833 (int)riid.Data4[2], (int)riid.Data4[3],
00834 (int)riid.Data4[4], (int)riid.Data4[5],
00835 (int)riid.Data4[6], (int)riid.Data4[7] );
00836 #endif
00837 *ppv = NULL;
00838 return E_NOINTERFACE;
00839 }
00840 };
00841 STDMETHODIMP_(ULONG) CaptureFilter::AddRef()
00842 {
00843 #ifdef DEBUG_DSHOW_L1
00844 msg_Dbg( p_input, "CaptureFilter::AddRef (ref: %i)", i_ref );
00845 #endif
00846
00847 return i_ref++;
00848 };
00849 STDMETHODIMP_(ULONG) CaptureFilter::Release()
00850 {
00851 #ifdef DEBUG_DSHOW_L1
00852 msg_Dbg( p_input, "CaptureFilter::Release (ref: %i)", i_ref );
00853 #endif
00854
00855 if( !InterlockedDecrement(&i_ref) ) delete this;
00856
00857 return 0;
00858 };
00859
00860
00861 STDMETHODIMP CaptureFilter::GetClassID(CLSID *pClsID)
00862 {
00863 #ifdef DEBUG_DSHOW
00864 msg_Dbg( p_input, "CaptureFilter::GetClassID" );
00865 #endif
00866 return E_NOTIMPL;
00867 };
00868
00869
00870 STDMETHODIMP CaptureFilter::GetState(DWORD dwMSecs, FILTER_STATE *State)
00871 {
00872 #ifdef DEBUG_DSHOW
00873 msg_Dbg( p_input, "CaptureFilter::GetState %i", state );
00874 #endif
00875
00876 *State = state;
00877 return S_OK;
00878 };
00879 STDMETHODIMP CaptureFilter::SetSyncSource(IReferenceClock *pClock)
00880 {
00881 #ifdef DEBUG_DSHOW
00882 msg_Dbg( p_input, "CaptureFilter::SetSyncSource" );
00883 #endif
00884
00885 return S_OK;
00886 };
00887 STDMETHODIMP CaptureFilter::GetSyncSource(IReferenceClock **pClock)
00888 {
00889 #ifdef DEBUG_DSHOW
00890 msg_Dbg( p_input, "CaptureFilter::GetSyncSource" );
00891 #endif
00892
00893 *pClock = NULL;
00894 return NOERROR;
00895 };
00896 STDMETHODIMP CaptureFilter::Stop()
00897 {
00898 #ifdef DEBUG_DSHOW
00899 msg_Dbg( p_input, "CaptureFilter::Stop" );
00900 #endif
00901
00902 p_pin->EndFlush();
00903
00904 state = State_Stopped;
00905 return S_OK;
00906 };
00907 STDMETHODIMP CaptureFilter::Pause()
00908 {
00909 #ifdef DEBUG_DSHOW
00910 msg_Dbg( p_input, "CaptureFilter::Pause" );
00911 #endif
00912
00913 state = State_Paused;
00914 return S_OK;
00915 };
00916 STDMETHODIMP CaptureFilter::Run(REFERENCE_TIME tStart)
00917 {
00918 #ifdef DEBUG_DSHOW
00919 msg_Dbg( p_input, "CaptureFilter::Run" );
00920 #endif
00921
00922 state = State_Running;
00923 return S_OK;
00924 };
00925
00926
00927 STDMETHODIMP CaptureFilter::EnumPins( IEnumPins ** ppEnum )
00928 {
00929 #ifdef DEBUG_DSHOW
00930 msg_Dbg( p_input, "CaptureFilter::EnumPins" );
00931 #endif
00932
00933
00934 *ppEnum = new CaptureEnumPins( p_input, this, NULL );
00935 return *ppEnum == NULL ? E_OUTOFMEMORY : NOERROR;
00936 };
00937 STDMETHODIMP CaptureFilter::FindPin( LPCWSTR Id, IPin ** ppPin )
00938 {
00939 #ifdef DEBUG_DSHOW
00940 msg_Dbg( p_input, "CaptureFilter::FindPin" );
00941 #endif
00942 return E_NOTIMPL;
00943 };
00944 STDMETHODIMP CaptureFilter::QueryFilterInfo( FILTER_INFO * pInfo )
00945 {
00946 #ifdef DEBUG_DSHOW
00947 msg_Dbg( p_input, "CaptureFilter::QueryFilterInfo" );
00948 #endif
00949
00950 memcpy(pInfo->achName, FILTER_NAME, sizeof(FILTER_NAME));
00951
00952 pInfo->pGraph = p_graph;
00953 if( p_graph ) p_graph->AddRef();
00954
00955 return NOERROR;
00956 };
00957 STDMETHODIMP CaptureFilter::JoinFilterGraph( IFilterGraph * pGraph,
00958 LPCWSTR pName )
00959 {
00960 #ifdef DEBUG_DSHOW
00961 msg_Dbg( p_input, "CaptureFilter::JoinFilterGraph" );
00962 #endif
00963
00964 p_graph = pGraph;
00965
00966 return NOERROR;
00967 };
00968 STDMETHODIMP CaptureFilter::QueryVendorInfo( LPWSTR* pVendorInfo )
00969 {
00970 #ifdef DEBUG_DSHOW
00971 msg_Dbg( p_input, "CaptureFilter::QueryVendorInfo" );
00972 #endif
00973 return E_NOTIMPL;
00974 };
00975
00976
00977 CapturePin *CaptureFilter::CustomGetPin()
00978 {
00979 return p_pin;
00980 }
00981
00982
00983
00984
00985
00986 CaptureEnumPins::CaptureEnumPins( vlc_object_t *_p_input,
00987 CaptureFilter *_p_filter,
00988 CaptureEnumPins *pEnumPins )
00989 : p_input( _p_input ), p_filter( _p_filter ), i_ref( 1 )
00990 {
00991
00992 p_filter->AddRef();
00993
00994
00995
00996 if( pEnumPins == NULL )
00997 {
00998 i_position = 0;
00999 }
01000 else
01001 {
01002 i_position = pEnumPins->i_position;
01003 }
01004 }
01005
01006 CaptureEnumPins::~CaptureEnumPins()
01007 {
01008 #ifdef DEBUG_DSHOW_L1
01009 msg_Dbg( p_input, "CaptureEnumPins::~CaptureEnumPins" );
01010 #endif
01011 p_filter->Release();
01012 }
01013
01014
01015 STDMETHODIMP CaptureEnumPins::QueryInterface( REFIID riid, void **ppv )
01016 {
01017 #ifdef DEBUG_DSHOW_L1
01018 msg_Dbg( p_input, "CaptureEnumPins::QueryInterface" );
01019 #endif
01020
01021 if( riid == IID_IUnknown ||
01022 riid == IID_IEnumPins )
01023 {
01024 AddRef();
01025 *ppv = (IEnumPins *)this;
01026 return NOERROR;
01027 }
01028 else
01029 {
01030 *ppv = NULL;
01031 return E_NOINTERFACE;
01032 }
01033 };
01034 STDMETHODIMP_(ULONG) CaptureEnumPins::AddRef()
01035 {
01036 #ifdef DEBUG_DSHOW_L1
01037 msg_Dbg( p_input, "CaptureEnumPins::AddRef (ref: %i)", i_ref );
01038 #endif
01039
01040 return i_ref++;
01041 };
01042 STDMETHODIMP_(ULONG) CaptureEnumPins::Release()
01043 {
01044 #ifdef DEBUG_DSHOW_L1
01045 msg_Dbg( p_input, "CaptureEnumPins::Release (ref: %i)", i_ref );
01046 #endif
01047
01048 if( !InterlockedDecrement(&i_ref) ) delete this;
01049
01050 return 0;
01051 };
01052
01053
01054 STDMETHODIMP CaptureEnumPins::Next( ULONG cPins, IPin ** ppPins,
01055 ULONG * pcFetched )
01056 {
01057 #ifdef DEBUG_DSHOW_L1
01058 msg_Dbg( p_input, "CaptureEnumPins::Next" );
01059 #endif
01060
01061 unsigned int i_fetched = 0;
01062
01063 if( i_position < 1 && cPins > 0 )
01064 {
01065 IPin *pPin = p_filter->CustomGetPin();
01066 *ppPins = pPin;
01067 pPin->AddRef();
01068 i_fetched = 1;
01069 i_position++;
01070 }
01071
01072 if( pcFetched ) *pcFetched = i_fetched;
01073
01074 return (i_fetched == cPins) ? S_OK : S_FALSE;
01075 };
01076 STDMETHODIMP CaptureEnumPins::Skip( ULONG cPins )
01077 {
01078 #ifdef DEBUG_DSHOW_L1
01079 msg_Dbg( p_input, "CaptureEnumPins::Skip" );
01080 #endif
01081
01082 i_position += cPins;
01083
01084 if( i_position > 1 )
01085 {
01086 return S_FALSE;
01087 }
01088
01089 return S_OK;
01090 };
01091 STDMETHODIMP CaptureEnumPins::Reset()
01092 {
01093 #ifdef DEBUG_DSHOW_L1
01094 msg_Dbg( p_input, "CaptureEnumPins::Reset" );
01095 #endif
01096
01097 i_position = 0;
01098 return S_OK;
01099 };
01100 STDMETHODIMP CaptureEnumPins::Clone( IEnumPins **ppEnum )
01101 {
01102 #ifdef DEBUG_DSHOW_L1
01103 msg_Dbg( p_input, "CaptureEnumPins::Clone" );
01104 #endif
01105
01106 *ppEnum = new CaptureEnumPins( p_input, p_filter, this );
01107 if( *ppEnum == NULL ) return E_OUTOFMEMORY;
01108
01109 return NOERROR;
01110 };
01111
01112
01113
01114
01115 CaptureEnumMediaTypes::CaptureEnumMediaTypes( vlc_object_t *_p_input,
01116 CapturePin *_p_pin, CaptureEnumMediaTypes *pEnumMediaTypes )
01117 : p_input( _p_input ), p_pin( _p_pin ), i_ref( 1 )
01118 {
01119
01120 p_pin->AddRef();
01121
01122
01123 if( pEnumMediaTypes == NULL )
01124 {
01125 CopyMediaType(&cx_media_type, &p_pin->cx_media_type);
01126 i_position = 0;
01127 }
01128 else
01129 {
01130 CopyMediaType(&cx_media_type, &pEnumMediaTypes->cx_media_type);
01131 i_position = pEnumMediaTypes->i_position;
01132 }
01133 }
01134
01135 CaptureEnumMediaTypes::~CaptureEnumMediaTypes()
01136 {
01137 #ifdef DEBUG_DSHOW_L1
01138 msg_Dbg( p_input, "CaptureEnumMediaTypes::~CaptureEnumMediaTypes" );
01139 #endif
01140 FreeMediaType(cx_media_type);
01141 p_pin->Release();
01142 }
01143
01144
01145 STDMETHODIMP CaptureEnumMediaTypes::QueryInterface( REFIID riid, void **ppv )
01146 {
01147 #ifdef DEBUG_DSHOW_L1
01148 msg_Dbg( p_input, "CaptureEnumMediaTypes::QueryInterface" );
01149 #endif
01150
01151 if( riid == IID_IUnknown ||
01152 riid == IID_IEnumMediaTypes )
01153 {
01154 AddRef();
01155 *ppv = (IEnumMediaTypes *)this;
01156 return NOERROR;
01157 }
01158 else
01159 {
01160 *ppv = NULL;
01161 return E_NOINTERFACE;
01162 }
01163 };
01164 STDMETHODIMP_(ULONG) CaptureEnumMediaTypes::AddRef()
01165 {
01166 #ifdef DEBUG_DSHOW_L1
01167 msg_Dbg( p_input, "CaptureEnumMediaTypes::AddRef (ref: %i)", i_ref );
01168 #endif
01169
01170 return i_ref++;
01171 };
01172 STDMETHODIMP_(ULONG) CaptureEnumMediaTypes::Release()
01173 {
01174 #ifdef DEBUG_DSHOW_L1
01175 msg_Dbg( p_input, "CaptureEnumMediaTypes::Release (ref: %i)", i_ref );
01176 #endif
01177
01178 if( !InterlockedDecrement(&i_ref) ) delete this;
01179
01180 return 0;
01181 };
01182
01183
01184 STDMETHODIMP CaptureEnumMediaTypes::Next( ULONG cMediaTypes,
01185 AM_MEDIA_TYPE ** ppMediaTypes,
01186 ULONG * pcFetched )
01187 {
01188 #ifdef DEBUG_DSHOW_L1
01189 msg_Dbg( p_input, "CaptureEnumMediaTypes::Next " );
01190 #endif
01191 ULONG copied = 0;
01192 ULONG offset = 0;
01193 ULONG max = p_pin->media_type_count;
01194
01195 if( ! ppMediaTypes )
01196 return E_POINTER;
01197
01198 if( (! pcFetched) && (cMediaTypes > 1) )
01199 return E_POINTER;
01200
01201
01202
01203
01204 copied = 0;
01205 if( cx_media_type.subtype != GUID_NULL )
01206 {
01207 ++max;
01208 if( i_position == 0 )
01209 {
01210 ppMediaTypes[copied] =
01211 (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
01212 if( CopyMediaType(ppMediaTypes[copied], &cx_media_type) != S_OK )
01213 return E_OUTOFMEMORY;
01214 ++i_position;
01215 ++copied;
01216 }
01217 }
01218
01219 while( (copied < cMediaTypes) && (i_position < max) )
01220 {
01221 ppMediaTypes[copied] =
01222 (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
01223 if( CopyMediaType( ppMediaTypes[copied],
01224 &p_pin->media_types[i_position-offset]) != S_OK )
01225 return E_OUTOFMEMORY;
01226
01227 ++copied;
01228 ++i_position;
01229 }
01230
01231 if( pcFetched ) *pcFetched = copied;
01232
01233 return (copied == cMediaTypes) ? S_OK : S_FALSE;
01234 };
01235 STDMETHODIMP CaptureEnumMediaTypes::Skip( ULONG cMediaTypes )
01236 {
01237 ULONG max = p_pin->media_type_count;
01238 if( cx_media_type.subtype != GUID_NULL )
01239 {
01240 max = 1;
01241 }
01242 #ifdef DEBUG_DSHOW_L1
01243 msg_Dbg( p_input, "CaptureEnumMediaTypes::Skip" );
01244 #endif
01245
01246 i_position += cMediaTypes;
01247 return (i_position < max) ? S_OK : S_FALSE;
01248 };
01249 STDMETHODIMP CaptureEnumMediaTypes::Reset()
01250 {
01251 #ifdef DEBUG_DSHOW_L1
01252 msg_Dbg( p_input, "CaptureEnumMediaTypes::Reset" );
01253 #endif
01254
01255 FreeMediaType(cx_media_type);
01256 CopyMediaType(&cx_media_type, &p_pin->cx_media_type);
01257 i_position = 0;
01258 return S_OK;
01259 };
01260 STDMETHODIMP CaptureEnumMediaTypes::Clone( IEnumMediaTypes **ppEnum )
01261 {
01262 #ifdef DEBUG_DSHOW_L1
01263 msg_Dbg( p_input, "CaptureEnumMediaTypes::Clone" );
01264 #endif
01265
01266 *ppEnum = new CaptureEnumMediaTypes( p_input, p_pin, this );
01267 if( *ppEnum == NULL ) return E_OUTOFMEMORY;
01268
01269 return NOERROR;
01270 };