Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

filter.cpp

00001 /*****************************************************************************
00002  * filter.c : DirectShow access module for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2002 the VideoLAN team
00005  * $Id: filter.cpp 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Author: Gildas Bazin <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
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     /* Work-around a bug in w32api-2.5 */
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  * DirectShow GUIDs.
00050  * Easier to define them hear as mingw doesn't provide them all.
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 //const GUID IID_IPropertyBag = {0x55272A00, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}};
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 //const GUID IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46}};
00063 extern const GUID IID_IUnknown;
00064 //const GUID IID_IPersist = {0x0000010c, 0x0000, 0x0000, {0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46}};
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 //const GUID IID_ISpecifyPropertyPages = {0xb196b28b, 0xbab4, 0x101a, {0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07}};
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 /* Video Format */
00096 
00097 const GUID FORMAT_VideoInfo  = {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
00098 /*
00099  * MEDIATYPEs and MEDIASUBTYPEs
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 /* Packed RGB formats */
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 /* Packed YUV formats */
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 /* Planar YUV formats */
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}}; /* identical to YV12 */
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 /* DV formats */
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 /* MPEG2 formats */
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 /* Analog Video */
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 //const GUID GUID_NULL = {0x0000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
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         /* currently only support this type of video info format */
00228         if( 1 /* media_type.formattype == FORMAT_VideoInfo */ )
00229         {
00230             /* Packed RGB formats */
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             /* Planar YUV formats */
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             /* Packed YUV formats */
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             /* MPEG2 video elementary stream */
00275             else if( media_type.subtype == MEDIASUBTYPE_MPEG2_VIDEO )
00276                i_fourcc = VLC_FOURCC( 'm', 'p', '2', 'v' );
00277 
00278             /* DV formats */
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         /* currently only support this type of audio info format */
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  * Implementation of our dummy directshow filter pin class
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 /* IUnknown methods */
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 /* IPin methods */
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     /* samples_queue was already flushed in EndFlush() */
00510 
00511     p_connected_pin->Release();
00512     p_connected_pin = NULL;
00513     //FreeMediaType( cx_media_type );
00514     //cx_media_type.subtype = GUID_NULL;
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 /* IMemInputPin methods */
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     /* Make sure we don't cache too many samples */
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; /* Thou shalt not block */
00774 }
00775 
00776 /****************************************************************************
00777  * Implementation of our dummy directshow filter class
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 /* IUnknown methods */
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 /* IPersist method */
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 /* IMediaFilter methods */
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 /* IBaseFilter methods */
00927 STDMETHODIMP CaptureFilter::EnumPins( IEnumPins ** ppEnum )
00928 {
00929 #ifdef DEBUG_DSHOW
00930     msg_Dbg( p_input, "CaptureFilter::EnumPins" );
00931 #endif
00932 
00933     /* Create a new ref counted enumerator */
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 /* Custom methods */
00977 CapturePin *CaptureFilter::CustomGetPin()
00978 {
00979     return p_pin;
00980 }
00981 
00982 /****************************************************************************
00983  * Implementation of our dummy directshow enumpins class
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     /* Hold a reference count on our filter */
00992     p_filter->AddRef();
00993 
00994     /* Are we creating a new enumerator */
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 /* IUnknown methods */
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 /* IEnumPins */
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  * Implementation of our dummy directshow enummediatypes class
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     /* Hold a reference count on our filter */
01120     p_pin->AddRef();
01121 
01122     /* Are we creating a new enumerator */
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 /* IUnknown methods */
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 /* IEnumMediaTypes */
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     ** use connection media type as first entry in iterator if it exists
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 };

Generated on Tue Dec 20 10:14:24 2005 for vlc-0.8.4a by  doxygen 1.4.2