| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
#ifdef HAVE_CONFIG_H |
|---|
| 30 |
# include "config.h" |
|---|
| 31 |
#endif |
|---|
| 32 |
|
|---|
| 33 |
#define __STDC_FORMAT_MACROS 1 |
|---|
| 34 |
#include <inttypes.h> |
|---|
| 35 |
|
|---|
| 36 |
#include <vlc_common.h> |
|---|
| 37 |
#include <vlc_plugin.h> |
|---|
| 38 |
#include <vlc_input.h> |
|---|
| 39 |
#include <vlc_access.h> |
|---|
| 40 |
#include <vlc_demux.h> |
|---|
| 41 |
#include <vlc_vout.h> |
|---|
| 42 |
#include <vlc_interface.h> |
|---|
| 43 |
|
|---|
| 44 |
#include "common.h" |
|---|
| 45 |
#include "filter.h" |
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
|
|---|
| 50 |
static block_t *ReadCompressed( access_t * ); |
|---|
| 51 |
static int AccessControl ( access_t *, int, va_list ); |
|---|
| 52 |
|
|---|
| 53 |
static int Demux ( demux_t * ); |
|---|
| 54 |
static int DemuxControl( demux_t *, int, va_list ); |
|---|
| 55 |
|
|---|
| 56 |
static int OpenDevice( vlc_object_t *, access_sys_t *, string, bool ); |
|---|
| 57 |
static IBaseFilter *FindCaptureDevice( vlc_object_t *, string *, |
|---|
| 58 |
list<string> *, bool ); |
|---|
| 59 |
static size_t EnumDeviceCaps( vlc_object_t *, IBaseFilter *, |
|---|
| 60 |
int, int, int, int, int, int, |
|---|
| 61 |
AM_MEDIA_TYPE *mt, size_t ); |
|---|
| 62 |
static bool ConnectFilters( vlc_object_t *, access_sys_t *, |
|---|
| 63 |
IBaseFilter *, CaptureFilter * ); |
|---|
| 64 |
static int FindDevicesCallback( vlc_object_t *, char const *, |
|---|
| 65 |
vlc_value_t, vlc_value_t, void * ); |
|---|
| 66 |
static int ConfigDevicesCallback( vlc_object_t *, char const *, |
|---|
| 67 |
vlc_value_t, vlc_value_t, void * ); |
|---|
| 68 |
|
|---|
| 69 |
static void ShowPropertyPage( IUnknown * ); |
|---|
| 70 |
static void ShowDeviceProperties( vlc_object_t *, ICaptureGraphBuilder2 *, |
|---|
| 71 |
IBaseFilter *, bool ); |
|---|
| 72 |
static void ShowTunerProperties( vlc_object_t *, ICaptureGraphBuilder2 *, |
|---|
| 73 |
IBaseFilter *, bool ); |
|---|
| 74 |
static void ConfigTuner( vlc_object_t *, ICaptureGraphBuilder2 *, |
|---|
| 75 |
IBaseFilter * ); |
|---|
| 76 |
|
|---|
| 77 |
|
|---|
| 78 |
|
|---|
| 79 |
|
|---|
| 80 |
static const char *const ppsz_vdev[] = { "", "none" }; |
|---|
| 81 |
static const char *const ppsz_vdev_text[] = { N_("Default"), N_("None") }; |
|---|
| 82 |
static const char *const ppsz_adev[] = { "", "none" }; |
|---|
| 83 |
static const char *const ppsz_adev_text[] = { N_("Default"), N_("None") }; |
|---|
| 84 |
static const int pi_tuner_input[] = { 0, 1, 2 }; |
|---|
| 85 |
static const char *const ppsz_tuner_input_text[] = |
|---|
| 86 |
{N_("Default"), N_("Cable"), N_("Antenna")}; |
|---|
| 87 |
static const int pi_amtuner_mode[] = { AMTUNER_MODE_DEFAULT, |
|---|
| 88 |
AMTUNER_MODE_TV, |
|---|
| 89 |
AMTUNER_MODE_FM_RADIO, |
|---|
| 90 |
AMTUNER_MODE_AM_RADIO, |
|---|
| 91 |
AMTUNER_MODE_DSS }; |
|---|
| 92 |
static const char *const ppsz_amtuner_mode_text[] = { N_("Default"), |
|---|
| 93 |
N_("TV"), |
|---|
| 94 |
N_("FM radio"), |
|---|
| 95 |
N_("AM radio"), |
|---|
| 96 |
N_("DSS") }; |
|---|
| 97 |
|
|---|
| 98 |
#define CACHING_TEXT N_("Caching value in ms") |
|---|
| 99 |
#define CACHING_LONGTEXT N_( \ |
|---|
| 100 |
"Caching value for DirectShow streams. " \ |
|---|
| 101 |
"This value should be set in milliseconds." ) |
|---|
| 102 |
#define VDEV_TEXT N_("Video device name") |
|---|
| 103 |
#define VDEV_LONGTEXT N_( \ |
|---|
| 104 |
"Name of the video device that will be used by the " \ |
|---|
| 105 |
"DirectShow plugin. If you don't specify anything, the default device " \ |
|---|
| 106 |
"will be used.") |
|---|
| 107 |
#define ADEV_TEXT N_("Audio device name") |
|---|
| 108 |
#define ADEV_LONGTEXT N_( \ |
|---|
| 109 |
"Name of the audio device that will be used by the " \ |
|---|
| 110 |
"DirectShow plugin. If you don't specify anything, the default device " \ |
|---|
| 111 |
"will be used. ") |
|---|
| 112 |
#define SIZE_TEXT N_("Video size") |
|---|
| 113 |
#define SIZE_LONGTEXT N_( \ |
|---|
| 114 |
"Size of the video that will be displayed by the " \ |
|---|
| 115 |
"DirectShow plugin. If you don't specify anything the default size for " \ |
|---|
| 116 |
"your device will be used. You can specify a standard size (cif, d1, ...) or <width>x<height>.") |
|---|
| 117 |
#define CHROMA_TEXT N_("Video input chroma format") |
|---|
| 118 |
#define CHROMA_LONGTEXT N_( \ |
|---|
| 119 |
"Force the DirectShow video input to use a specific chroma format " \ |
|---|
| 120 |
"(eg. I420 (default), RV24, etc.)") |
|---|
| 121 |
#define FPS_TEXT N_("Video input frame rate") |
|---|
| 122 |
#define FPS_LONGTEXT N_( \ |
|---|
| 123 |
"Force the DirectShow video input to use a specific frame rate" \ |
|---|
| 124 |
"(eg. 0 means default, 25, 29.97, 50, 59.94, etc.)") |
|---|
| 125 |
#define CONFIG_TEXT N_("Device properties") |
|---|
| 126 |
#define CONFIG_LONGTEXT N_( \ |
|---|
| 127 |
"Show the properties dialog of the selected device before starting the " \ |
|---|
| 128 |
"stream.") |
|---|
| 129 |
#define TUNER_TEXT N_("Tuner properties") |
|---|
| 130 |
#define TUNER_LONGTEXT N_( \ |
|---|
| 131 |
"Show the tuner properties [channel selection] page." ) |
|---|
| 132 |
#define CHANNEL_TEXT N_("Tuner TV Channel") |
|---|
| 133 |
#define CHANNEL_LONGTEXT N_( \ |
|---|
| 134 |
"Set the TV channel the tuner will set to " \ |
|---|
| 135 |
"(0 means default)." ) |
|---|
| 136 |
#define COUNTRY_TEXT N_("Tuner country code") |
|---|
| 137 |
#define COUNTRY_LONGTEXT N_( \ |
|---|
| 138 |
"Set the tuner country code that establishes the current " \ |
|---|
| 139 |
"channel-to-frequency mapping (0 means default)." ) |
|---|
| 140 |
#define TUNER_INPUT_TEXT N_("Tuner input type") |
|---|
| 141 |
#define TUNER_INPUT_LONGTEXT N_( \ |
|---|
| 142 |
"Select the tuner input type (Cable/Antenna)." ) |
|---|
| 143 |
#define VIDEO_IN_TEXT N_("Video input pin") |
|---|
| 144 |
#define VIDEO_IN_LONGTEXT N_( \ |
|---|
| 145 |
"Select the video input source, such as composite, s-video, " \ |
|---|
| 146 |
"or tuner. Since these settings are hardware-specific, you should find good " \ |
|---|
| 147 |
"settings in the \"Device config\" area, and use those numbers here. -1 " \ |
|---|
| 148 |
"means that settings will not be changed.") |
|---|
| 149 |
#define AUDIO_IN_TEXT N_("Audio input pin") |
|---|
| 150 |
#define AUDIO_IN_LONGTEXT N_( \ |
|---|
| 151 |
"Select the audio input source. See the \"video input\" option." ) |
|---|
| 152 |
#define VIDEO_OUT_TEXT N_("Video output pin") |
|---|
| 153 |
#define VIDEO_OUT_LONGTEXT N_( \ |
|---|
| 154 |
"Select the video output type. See the \"video input\" option." ) |
|---|
| 155 |
#define AUDIO_OUT_TEXT N_("Audio output pin") |
|---|
| 156 |
#define AUDIO_OUT_LONGTEXT N_( \ |
|---|
| 157 |
"Select the audio output type. See the \"video input\" option." ) |
|---|
| 158 |
|
|---|
| 159 |
#define AMTUNER_MODE_TEXT N_("AM Tuner mode") |
|---|
| 160 |
#define AMTUNER_MODE_LONGTEXT N_( \ |
|---|
| 161 |
"AM Tuner mode. Can be one of Default (0), TV (1)," \ |
|---|
| 162 |
"AM Radio (2), FM Radio (3) or DSS (4).") |
|---|
| 163 |
|
|---|
| 164 |
#define AUDIO_CHANNELS_TEXT N_("Number of audio channels") |
|---|
| 165 |
#define AUDIO_CHANNELS_LONGTEXT N_( \ |
|---|
| 166 |
"Select audio input format with the given number of audio channels (if non 0)" ) |
|---|
| 167 |
|
|---|
| 168 |
#define AUDIO_SAMPLERATE_TEXT N_("Audio sample rate") |
|---|
| 169 |
#define AUDIO_SAMPLERATE_LONGTEXT N_( \ |
|---|
| 170 |
"Select audio input format with the given sample rate (if non 0)" ) |
|---|
| 171 |
|
|---|
| 172 |
#define AUDIO_BITSPERSAMPLE_TEXT N_("Audio bits per sample") |
|---|
| 173 |
#define AUDIO_BITSPERSAMPLE_LONGTEXT N_( \ |
|---|
| 174 |
"Select audio input format with the given bits/sample (if non 0)" ) |
|---|
| 175 |
|
|---|
| 176 |
static int CommonOpen ( vlc_object_t *, access_sys_t *, bool ); |
|---|
| 177 |
static void CommonClose( vlc_object_t *, access_sys_t * ); |
|---|
| 178 |
|
|---|
| 179 |
static int AccessOpen ( vlc_object_t * ); |
|---|
| 180 |
static void AccessClose( vlc_object_t * ); |
|---|
| 181 |
|
|---|
| 182 |
static int DemuxOpen ( vlc_object_t * ); |
|---|
| 183 |
static void DemuxClose ( vlc_object_t * ); |
|---|
| 184 |
|
|---|
| 185 |
vlc_module_begin(); |
|---|
| 186 |
set_shortname( N_("DirectShow") ); |
|---|
| 187 |
set_description( N_("DirectShow input") ); |
|---|
| 188 |
set_category( CAT_INPUT ); |
|---|
| 189 |
set_subcategory( SUBCAT_INPUT_ACCESS ); |
|---|
| 190 |
add_integer( "dshow-caching", (mtime_t)(0.2*CLOCK_FREQ) / 1000, NULL, |
|---|
| 191 |
CACHING_TEXT, CACHING_LONGTEXT, true ); |
|---|
| 192 |
|
|---|
| 193 |
add_string( "dshow-vdev", NULL, NULL, VDEV_TEXT, VDEV_LONGTEXT, false); |
|---|
| 194 |
change_string_list( ppsz_vdev, ppsz_vdev_text, FindDevicesCallback ); |
|---|
| 195 |
change_action_add( FindDevicesCallback, N_("Refresh list") ); |
|---|
| 196 |
change_action_add( ConfigDevicesCallback, N_("Configure") ); |
|---|
| 197 |
|
|---|
| 198 |
add_string( "dshow-adev", NULL, NULL, ADEV_TEXT, ADEV_LONGTEXT, false); |
|---|
| 199 |
change_string_list( ppsz_adev, ppsz_adev_text, FindDevicesCallback ); |
|---|
| 200 |
change_action_add( FindDevicesCallback, N_("Refresh list") ); |
|---|
| 201 |
change_action_add( ConfigDevicesCallback, N_("Configure") ); |
|---|
| 202 |
|
|---|
| 203 |
add_string( "dshow-size", NULL, NULL, SIZE_TEXT, SIZE_LONGTEXT, false); |
|---|
| 204 |
|
|---|
| 205 |
add_string( "dshow-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, |
|---|
| 206 |
true ); |
|---|
| 207 |
|
|---|
| 208 |
add_float( "dshow-fps", 0.0f, NULL, FPS_TEXT, FPS_LONGTEXT, |
|---|
| 209 |
true ); |
|---|
| 210 |
|
|---|
| 211 |
add_bool( "dshow-config", false, NULL, CONFIG_TEXT, CONFIG_LONGTEXT, |
|---|
| 212 |
true ); |
|---|
| 213 |
|
|---|
| 214 |
add_bool( "dshow-tuner", false, NULL, TUNER_TEXT, TUNER_LONGTEXT, |
|---|
| 215 |
true ); |
|---|
| 216 |
|
|---|
| 217 |
add_integer( "dshow-tuner-channel", 0, NULL, CHANNEL_TEXT, |
|---|
| 218 |
CHANNEL_LONGTEXT, true ); |
|---|
| 219 |
|
|---|
| 220 |
add_integer( "dshow-tuner-country", 0, NULL, COUNTRY_TEXT, |
|---|
| 221 |
COUNTRY_LONGTEXT, true ); |
|---|
| 222 |
|
|---|
| 223 |
add_integer( "dshow-tuner-input", 0, NULL, TUNER_INPUT_TEXT, |
|---|
| 224 |
TUNER_INPUT_LONGTEXT, true ); |
|---|
| 225 |
change_integer_list( pi_tuner_input, ppsz_tuner_input_text, NULL ); |
|---|
| 226 |
|
|---|
| 227 |
add_integer( "dshow-video-input", -1, NULL, VIDEO_IN_TEXT, |
|---|
| 228 |
VIDEO_IN_LONGTEXT, true ); |
|---|
| 229 |
|
|---|
| 230 |
add_integer( "dshow-audio-input", -1, NULL, AUDIO_IN_TEXT, |
|---|
| 231 |
AUDIO_IN_LONGTEXT, true ); |
|---|
| 232 |
|
|---|
| 233 |
add_integer( "dshow-video-output", -1, NULL, VIDEO_OUT_TEXT, |
|---|
| 234 |
VIDEO_OUT_LONGTEXT, true ); |
|---|
| 235 |
|
|---|
| 236 |
add_integer( "dshow-audio-output", -1, NULL, AUDIO_OUT_TEXT, |
|---|
| 237 |
AUDIO_OUT_LONGTEXT, true ); |
|---|
| 238 |
|
|---|
| 239 |
add_integer( "dshow-amtuner-mode", AMTUNER_MODE_TV, NULL, |
|---|
| 240 |
AMTUNER_MODE_TEXT, AMTUNER_MODE_LONGTEXT, false); |
|---|
| 241 |
change_integer_list( pi_amtuner_mode, ppsz_amtuner_mode_text, NULL ); |
|---|
| 242 |
|
|---|
| 243 |
add_integer( "dshow-audio-channels", 0, NULL, AUDIO_CHANNELS_TEXT, |
|---|
| 244 |
AUDIO_CHANNELS_LONGTEXT, true ); |
|---|
| 245 |
add_integer( "dshow-audio-samplerate", 0, NULL, AUDIO_SAMPLERATE_TEXT, |
|---|
| 246 |
AUDIO_SAMPLERATE_LONGTEXT, true ); |
|---|
| 247 |
add_integer( "dshow-audio-bitspersample", 0, NULL, AUDIO_BITSPERSAMPLE_TEXT, |
|---|
| 248 |
AUDIO_BITSPERSAMPLE_LONGTEXT, true ); |
|---|
| 249 |
|
|---|
| 250 |
add_shortcut( "dshow" ); |
|---|
| 251 |
set_capability( "access_demux", 0 ); |
|---|
| 252 |
set_callbacks( DemuxOpen, DemuxClose ); |
|---|
| 253 |
|
|---|
| 254 |
add_submodule(); |
|---|
| 255 |
set_description( N_("DirectShow input") ); |
|---|
| 256 |
set_capability( "access", 0 ); |
|---|
| 257 |
set_callbacks( AccessOpen, AccessClose ); |
|---|
| 258 |
|
|---|
| 259 |
vlc_module_end(); |
|---|
| 260 |
|
|---|
| 261 |
|
|---|
| 262 |
|
|---|
| 263 |
|
|---|
| 264 |
typedef struct dshow_stream_t |
|---|
| 265 |
{ |
|---|
| 266 |
string devicename; |
|---|
| 267 |
IBaseFilter *p_device_filter; |
|---|
| 268 |
CaptureFilter *p_capture_filter; |
|---|
| 269 |
AM_MEDIA_TYPE mt; |
|---|
| 270 |
|
|---|
| 271 |
union |
|---|
| 272 |
{ |
|---|
| 273 |
VIDEOINFOHEADER video; |
|---|
| 274 |
WAVEFORMATEX audio; |
|---|
| 275 |
|
|---|
| 276 |
} header; |
|---|
| 277 |
|
|---|
| 278 |
int i_fourcc; |
|---|
| 279 |
es_out_id_t *p_es; |
|---|
| 280 |
|
|---|
| 281 |
bool b_pts; |
|---|
| 282 |
} dshow_stream_t; |
|---|
| 283 |
|
|---|
| 284 |
|
|---|
| 285 |
|
|---|
| 286 |
|
|---|
| 287 |
static void CreateDirectShowGraph( access_sys_t *p_sys ) |
|---|
| 288 |
{ |
|---|
| 289 |
p_sys->i_crossbar_route_depth = 0; |
|---|
| 290 |
|
|---|
| 291 |
|
|---|
| 292 |
if( SUCCEEDED( CoCreateInstance( CLSID_FilterGraph, 0, CLSCTX_INPROC, |
|---|
| 293 |
(REFIID)IID_IFilterGraph, (void **)&p_sys->p_graph) ) ) |
|---|
| 294 |
{ |
|---|
| 295 |
|
|---|
| 296 |
if( SUCCEEDED( CoCreateInstance( CLSID_CaptureGraphBuilder2, 0, |
|---|
| 297 |
CLSCTX_INPROC, (REFIID)IID_ICaptureGraphBuilder2, |
|---|
| 298 |
(void **)&p_sys->p_capture_graph_builder2 ) ) ) |
|---|
| 299 |
{ |
|---|
| 300 |
p_sys->p_capture_graph_builder2-> |
|---|
| 301 |
SetFiltergraph((IGraphBuilder *)p_sys->p_graph); |
|---|
| 302 |
} |
|---|
| 303 |
|
|---|
| 304 |
p_sys->p_graph->QueryInterface( IID_IMediaControl, |
|---|
| 305 |
(void **)&p_sys->p_control ); |
|---|
| 306 |
} |
|---|
| 307 |
} |
|---|
| 308 |
|
|---|
| 309 |
static void DeleteDirectShowGraph( access_sys_t *p_sys ) |
|---|
| 310 |
{ |
|---|
| 311 |
DeleteCrossbarRoutes( p_sys ); |
|---|
| 312 |
|
|---|
| 313 |
|
|---|
| 314 |
for( int i = 0; i < p_sys->i_streams; i++ ) |
|---|
| 315 |
{ |
|---|
| 316 |
p_sys->p_graph->RemoveFilter( p_sys->pp_streams[i]->p_capture_filter ); |
|---|
| 317 |
p_sys->p_graph->RemoveFilter( p_sys->pp_streams[i]->p_device_filter ); |
|---|
| 318 |
p_sys->pp_streams[i]->p_capture_filter->Release(); |
|---|
| 319 |
p_sys->pp_streams[i]->p_device_filter->Release(); |
|---|
| 320 |
} |
|---|
| 321 |
|
|---|
| 322 |
|
|---|
| 323 |
if( p_sys->p_control ) |
|---|
| 324 |
{ |
|---|
| 325 |
p_sys->p_control->Release(); |
|---|
| 326 |
p_sys->p_control = NULL; |
|---|
| 327 |
} |
|---|
| 328 |
if( p_sys->p_capture_graph_builder2 ) |
|---|
| 329 |
{ |
|---|
| 330 |
p_sys->p_capture_graph_builder2->Release(); |
|---|
| 331 |
p_sys->p_capture_graph_builder2 = NULL; |
|---|
| 332 |
} |
|---|
| 333 |
|
|---|
| 334 |
if( p_sys->p_graph ) |
|---|
| 335 |
{ |
|---|
| 336 |
p_sys->p_graph->Release(); |
|---|
| 337 |
p_sys->p_graph = NULL; |
|---|
| 338 |
} |
|---|
| 339 |
} |
|---|
| 340 |
|
|---|
| 341 |
|
|---|
| 342 |
|
|---|
| 343 |
|
|---|
| 344 |
static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys, |
|---|
| 345 |
bool b_access_demux ) |
|---|
| 346 |
{ |
|---|
| 347 |
vlc_value_t val; |
|---|
| 348 |
int i; |
|---|
| 349 |
|
|---|
| 350 |
|
|---|
| 351 |
string vdevname, adevname; |
|---|
| 352 |
int i_width = 0, i_height = 0, i_chroma = 0; |
|---|
| 353 |
bool b_audio = true; |
|---|
| 354 |
|
|---|
| 355 |
var_Create( p_this, "dshow-config", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); |
|---|
| 356 |
var_Create( p_this, "dshow-tuner", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); |
|---|
| 357 |
var_Create( p_this, "dshow-vdev", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); |
|---|
| 358 |
var_Get( p_this, "dshow-vdev", &val ); |
|---|
| 359 |
if( val.psz_string ) vdevname = string( val.psz_string ); |
|---|
| 360 |
free( val.psz_string ); |
|---|
| 361 |
|
|---|
| 362 |
var_Create( p_this, "dshow-adev", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); |
|---|
| 363 |
var_Get( p_this, "dshow-adev", &val ); |
|---|
| 364 |
if( val.psz_string ) adevname = string( val.psz_string ); |
|---|
| 365 |
free( val.psz_string ); |
|---|
| 366 |
|
|---|
| 367 |
static struct {char *psz_size; int i_width; int i_height;} size_table[] = |
|---|
| 368 |
{ { "subqcif", 128, 96 }, { "qsif", 160, 120 }, { "qcif", 176, 144 }, |
|---|
| 369 |
{ "sif", 320, 240 }, { "cif", 352, 288 }, { "d1", 640, 480 }, |
|---|
| 370 |
{ 0, 0, 0 }, |
|---|
| 371 |
}; |
|---|
| 372 |
|
|---|
| 373 |
var_Create( p_this, "dshow-size", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); |
|---|
| 374 |
var_Get( p_this, "dshow-size", &val ); |
|---|
| 375 |
if( val.psz_string && *val.psz_string ) |
|---|
| 376 |
{ |
|---|
| 377 |
for( i = 0; size_table[i].psz_size; i++ ) |
|---|
| 378 |
{ |
|---|
| 379 |
if( !strcmp( val.psz_string, size_table[i].psz_size ) ) |
|---|
| 380 |
{ |
|---|
| 381 |
i_width = size_table[i].i_width; |
|---|
| 382 |
i_height = size_table[i].i_height; |
|---|
| 383 |
break; |
|---|
| 384 |
} |
|---|
| 385 |
} |
|---|
| 386 |
if( !size_table[i].psz_size ) |
|---|
| 387 |
{ |
|---|
| 388 |
char *psz_parser; |
|---|
| 389 |
i_width = strtol( val.psz_string, &psz_parser, 0 ); |
|---|
| 390 |
if( *psz_parser == 'x' || *psz_parser == 'X') |
|---|
| 391 |
{ |
|---|
| 392 |
i_height = strtol( psz_parser + 1, &psz_parser, 0 ); |
|---|
| 393 |
} |
|---|
| 394 |
msg_Dbg( p_this, "width x height %dx%d", i_width, i_height ); |
|---|
| 395 |
} |
|---|
| 396 |
} |
|---|
| 397 |
free( val.psz_string ); |
|---|
| 398 |
|
|---|
| 399 |
p_sys->b_chroma = false; |
|---|
| 400 |
var_Create( p_this, "dshow-chroma", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); |
|---|
| 401 |
var_Get( p_this, "dshow-chroma", &val ); |
|---|
| 402 |
if( val.psz_string && strlen( val.psz_string ) >= 4 ) |
|---|
| 403 |
{ |
|---|
| 404 |
i_chroma = VLC_FOURCC( val.psz_string[0], val.psz_string[1], |
|---|
| 405 |
val.psz_string[2], val.psz_string[3] ); |
|---|
| 406 |
p_sys->b_chroma = true; |
|---|
| 407 |
} |
|---|
| 408 |
free( val.psz_string ); |
|---|
| 409 |
|
|---|
| 410 |
var_Create( p_this, "dshow-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); |
|---|
| 411 |
var_Create( p_this, "dshow-tuner-channel", |
|---|
| 412 |
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 413 |
var_Create( p_this, "dshow-tuner-country", |
|---|
| 414 |
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 415 |
var_Create( p_this, "dshow-tuner-input", |
|---|
| 416 |
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 417 |
|
|---|
| 418 |
var_Create( p_this, "dshow-amtuner-mode", |
|---|
| 419 |
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 420 |
|
|---|
| 421 |
var_Create( p_this, "dshow-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 422 |
|
|---|
| 423 |
var_Create( p_this, "dshow-video-input", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 424 |
var_Create( p_this, "dshow-audio-input", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 425 |
var_Create( p_this, "dshow-video-output", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 426 |
var_Create( p_this, "dshow-audio-output", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); |
|---|
| 427 |
|
|---|
| 428 |
|
|---|
| 429 |
CoInitialize( 0 ); |
|---|
| 430 |
|
|---|
| 431 |
|
|---|
| 432 |
p_sys->i_streams = 0; |
|---|
| 433 |
p_sys->pp_streams = 0; |
|---|
| 434 |
p_sys->i_width = i_width; |
|---|
| 435 |
p_sys->i_height = i_height; |
|---|
| 436 |
p_sys->i_chroma = i_chroma; |
|---|
| 437 |
|
|---|
| 438 |
p_sys->p_graph = NULL; |
|---|
| 439 |
p_sys->p_capture_graph_builder2 = NULL; |
|---|
| 440 |
p_sys->p_control = NULL; |
|---|
| 441 |
|
|---|
| 442 |
vlc_mutex_init( &p_sys->lock ); |
|---|
| 443 |
vlc_cond_init( &p_sys->wait ); |
|---|
| 444 |
|
|---|
| 445 |
|
|---|
| 446 |
CreateDirectShowGraph( p_sys ); |
|---|
| 447 |
|
|---|
| 448 |
if( OpenDevice( p_this, p_sys, vdevname, 0 ) != VLC_SUCCESS ) |
|---|
| 449 |
{ |
|---|
| 450 |
msg_Err( p_this, "can't open video"); |
|---|
| 451 |
} |
|---|
| 452 |
else |
|---|
| 453 |
{ |
|---|
| 454 |
|
|---|
| 455 |
|
|---|
| 456 |
dshow_stream_t *p_stream = p_sys->pp_streams[p_sys->i_streams-1]; |
|---|
| 457 |
|
|---|
| 458 |
if( p_stream->mt.majortype == MEDIATYPE_Video ) |
|---|
| 459 |
{ |
|---|
| 460 |
if( |
|---|
| 461 |
p_stream->i_fourcc == VLC_FOURCC('d','v','s','l') || |
|---|
| 462 |
p_stream->i_fourcc == VLC_FOURCC('d','v','s','d') || |
|---|
| 463 |
p_stream->i_fourcc == VLC_FOURCC('d','v','h','d') || |
|---|
| 464 |
|
|---|
| 465 |
p_stream->i_fourcc == VLC_FOURCC('m','p','2','v') ) |
|---|
| 466 |
{ |
|---|
| 467 |
b_audio = false; |
|---|
| 468 |
|
|---|
| 469 |
if( b_access_demux ) |
|---|
| 470 |
{ |
|---|
| 471 |
|
|---|
| 472 |
return VLC_EGENERIC; |
|---|
| 473 |
} |
|---|
| 474 |
} |
|---|
| 475 |
} |
|---|
| 476 |
|
|---|
| 477 |
if( p_stream->mt.majortype == MEDIATYPE_Stream ) |
|---|
| 478 |
{ |
|---|
| 479 |
b_audio = false; |
|---|
| 480 |
|
|---|
| 481 |
if( b_access_demux ) |
|---|
| 482 |
{ |
|---|
| 483 |
|
|---|
| 484 |
return VLC_EGENERIC; |
|---|
| 485 |
} |
|---|
| 486 |
|
|---|
| 487 |
var_Get( p_this, "dshow-tuner", &val ); |
|---|
| 488 |
if( val.b_bool ) |
|---|
| 489 |
{ |
|---|
| 490 |
|
|---|
| 491 |
|
|---|
| 492 |
ShowTunerProperties( p_this, p_sys->p_capture_graph_builder2, |
|---|
| 493 |
p_stream->p_device_filter, 0 ); |
|---|
| 494 |
} |
|---|
| 495 |
} |
|---|
| 496 |
} |
|---|
| 497 |
|
|---|
| 498 |
if( b_audio && OpenDevice( p_this, p_sys, adevname, 1 ) != VLC_SUCCESS ) |
|---|
| 499 |
{ |
|---|
| 500 |
msg_Err( p_this, "can't open audio"); |
|---|
| 501 |
} |
|---|
| 502 |
|
|---|
| 503 |
for( i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i ) |
|---|
| 504 |
{ |
|---|
| 505 |
var_Get( p_this, "dshow-video-input", &val ); |
|---|
| 506 |
if( val.i_int >= 0 ) |
|---|
| 507 |
p_sys->crossbar_routes[i].VideoInputIndex=val.i_int; |
|---|
| 508 |
var_Get( p_this, "dshow-video-output", &val ); |
|---|
| 509 |
if( val.i_int >= 0 ) |
|---|
| 510 |
p_sys->crossbar_routes[i].VideoOutputIndex=val.i_int; |
|---|
| 511 |
var_Get( p_this, "dshow-audio-input", &val ); |
|---|
| 512 |
if( val.i_int >= 0 ) |
|---|
| 513 |
p_sys->crossbar_routes[i].AudioInputIndex=val.i_int; |
|---|
| 514 |
var_Get( p_this, "dshow-audio-output", &val ); |
|---|
| 515 |
if( val.i_int >= 0 ) |
|---|
| 516 |
p_sys->crossbar_routes[i].AudioOutputIndex=val.i_int; |
|---|
| 517 |
|
|---|
| 518 |
IAMCrossbar *pXbar = p_sys->crossbar_routes[i].pXbar; |
|---|
| 519 |
LONG VideoInputIndex = p_sys->crossbar_routes[i].VideoInputIndex; |
|---|
| 520 |
LONG VideoOutputIndex = p_sys->crossbar_routes[i].VideoOutputIndex; |
|---|
| 521 |
LONG AudioInputIndex = p_sys->crossbar_routes[i].AudioInputIndex; |
|---|
| 522 |
LONG AudioOutputIndex = p_sys->crossbar_routes[i].AudioOutputIndex; |
|---|
| 523 |
|
|---|
| 524 |
if( SUCCEEDED(pXbar->Route(VideoOutputIndex, VideoInputIndex)) ) |
|---|
| 525 |
{ |
|---|
| 526 |
msg_Dbg( p_this, "crossbar at depth %d, routed video " |
|---|
| 527 |
"output %ld to video input %ld", i, VideoOutputIndex, |
|---|
| 528 |
VideoInputIndex ); |
|---|
| 529 |
|
|---|
| 530 |
if( AudioOutputIndex != -1 && AudioInputIndex != -1 ) |
|---|
| 531 |
{ |
|---|
| 532 |
if( SUCCEEDED( pXbar->Route(AudioOutputIndex, |
|---|
| 533 |
AudioInputIndex)) ) |
|---|
| 534 |
{ |
|---|
| 535 |
msg_Dbg(p_this, "crossbar at depth %d, routed audio " |
|---|
| 536 |
"output %ld to audio input %ld", i, |
|---|
| 537 |
AudioOutputIndex, AudioInputIndex ); |
|---|
| 538 |
} |
|---|
| 539 |
} |
|---|
| 540 |
} |
|---|
| 541 |
} |
|---|
| 542 |
|
|---|
| 543 |
|
|---|
| 544 |
|
|---|
| 545 |
|
|---|
| 546 |
var_Get( p_this, "dshow-config", &val ); |
|---|
| 547 |
if( val.b_bool ) |
|---|
| 548 |
{ |
|---|
| 549 |
for( i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i ) |
|---|
| 550 |
{ |
|---|
| 551 |
IAMCrossbar *pXbar = p_sys->crossbar_routes[i].pXbar; |
|---|
| 552 |
IBaseFilter *p_XF; |
|---|
| 553 |
|
|---|
| 554 |
if( SUCCEEDED( pXbar->QueryInterface( IID_IBaseFilter, |
|---|
| 555 |
(void **)&p_XF ) ) ) |
|---|
| 556 |
{ |
|---|
| 557 |
ShowPropertyPage( p_XF ); |
|---|
| 558 |
p_XF->Release(); |
|---|
| 559 |
} |
|---|
| 560 |
} |
|---|
| 561 |
} |
|---|
| 562 |
|
|---|
| 563 |
|
|---|
| 564 |
p_sys->i_current_stream = 0; |
|---|
| 565 |
|
|---|
| 566 |
if( !p_sys->i_streams ) return VLC_EGENERIC; |
|---|
| 567 |
|
|---|
| 568 |
return VLC_SUCCESS; |
|---|
| 569 |
} |
|---|
| 570 |
|
|---|
| 571 |
|
|---|
| 572 |
|
|---|
| 573 |
|
|---|
| 574 |
static int DemuxOpen( vlc_object_t *p_this ) |
|---|
| 575 |
{ |
|---|
| 576 |
demux_t *p_demux = (demux_t *)p_this; |
|---|
| 577 |
access_sys_t *p_sys; |
|---|
| 578 |
int i; |
|---|
| 579 |
|
|---|
| 580 |
p_sys = (access_sys_t *)malloc( sizeof( access_sys_t ) ); |
|---|
| 581 |
if( !p_sys ) |
|---|
| 582 |
return VLC_ENOMEM; |
|---|
| 583 |
memset( p_sys, 0, sizeof( access_sys_t ) ); |
|---|
| 584 |
p_demux->p_sys = (demux_sys_t *)p_sys; |
|---|
| 585 |
|
|---|
| 586 |
if( CommonOpen( p_this, p_sys, true ) != VLC_SUCCESS ) |
|---|
| 587 |
{ |
|---|
| 588 |
CommonClose( p_this, p_sys ); |
|---|
| 589 |
return VLC_EGENERIC; |
|---|
| 590 |
} |
|---|
| 591 |
|
|---|
| 592 |
|
|---|
| 593 |
msg_Dbg( p_this, "Playing..."); |
|---|
| 594 |
p_sys->p_control->Run(); |
|---|
| 595 |
|
|---|
| 596 |
p_demux->pf_demux = Demux; |
|---|
| 597 |
p_demux->pf_control = DemuxControl; |
|---|
| 598 |
p_demux->info.i_update = 0; |
|---|
| 599 |
p_demux->info.i_title = 0; |
|---|
| 600 |
p_demux->info.i_seekpoint = 0; |
|---|
| 601 |
|
|---|
| 602 |
for( i = 0; i < p_sys->i_streams; i++ ) |
|---|
| 603 |
{ |
|---|
| 604 |
dshow_stream_t *p_stream = p_sys->pp_streams[i]; |
|---|
| 605 |
es_format_t fmt; |
|---|
| 606 |
|
|---|
| 607 |
if( p_stream->mt.majortype == MEDIATYPE_Video ) |
|---|
| 608 |
{ |
|---|
| 609 |
es_format_Init( &fmt, VIDEO_ES, p_stream->i_fourcc ); |
|---|
| 610 |
|
|---|
| 611 |
fmt.video.i_width = p_stream->header.video.bmiHeader.biWidth; |
|---|
| 612 |
fmt.video.i_height = p_stream->header.video.bmiHeader.biHeight; |
|---|
| 613 |
fmt.video.i_aspect = 4 * VOUT_ASPECT_FACTOR / 3; |
|---|
| 614 |
|
|---|
| 615 |
if( !p_stream->header.video.bmiHeader.biCompression ) |
|---|
| 616 |
{ |
|---|
| 617 |
|
|---|
| 618 |
fmt.video.i_height = (unsigned int)(-(int)fmt.video.i_height); |
|---|
| 619 |
} |
|---|
| 620 |
|
|---|
| 621 |
|
|---|
| 622 |
if( p_stream->i_fourcc == VLC_FOURCC('R','V','2','4') ) |
|---|
| 623 |
{ |
|---|
| 624 |
|
|---|
| 625 |
fmt.video.i_bmask = 0x00ff0000; |
|---|
| 626 |
fmt.video.i_gmask = 0x0000ff00; |
|---|
| 627 |
fmt.video.i_rmask = 0x000000ff; |
|---|
| 628 |
} |
|---|
| 629 |
|
|---|
| 630 |
if( p_stream->header.video.AvgTimePerFrame ) |
|---|
| 631 |
{ |
|---|
| 632 |
fmt.video.i_frame_rate = 10000000; |
|---|
| 633 |
fmt.video.i_frame_rate_base = |
|---|
| 634 |
p_stream->header.video.AvgTimePerFrame; |
|---|
| 635 |
} |
|---|
| 636 |
} |
|---|
| 637 |
else if( p_stream->mt.majortype == MEDIATYPE_Audio ) |
|---|
| 638 |
{ |
|---|
| 639 |
es_format_Init( &fmt, AUDIO_ES, p_stream->i_fourcc ); |
|---|
| 640 |
|
|---|
| 641 |
fmt.audio.i_channels = p_stream->header.audio.nChannels; |
|---|
| 642 |
fmt.audio.i_rate = p_stream->header.audio.nSamplesPerSec; |
|---|
| 643 |
fmt.audio.i_bitspersample = p_stream->header.audio.wBitsPerSample; |
|---|
| 644 |
fmt.audio.i_blockalign = fmt.audio.i_channels * |
|---|
| 645 |
fmt.audio.i_bitspersample / 8; |
|---|
| 646 |
fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate * |
|---|
| 647 |
fmt.audio.i_bitspersample; |
|---|
| 648 |
} |
|---|
| 649 |
|
|---|
| 650 |
p_stream->p_es = es_out_Add( p_demux->out, &fmt ); |
|---|
| 651 |
} |
|---|
| 652 |
|
|---|
| 653 |
return VLC_SUCCESS; |
|---|
| 654 |
} |
|---|
| 655 |
|
|---|
| 656 |
|
|---|
| 657 |
|
|---|
| 658 |
|
|---|
| 659 |
static int AccessOpen( vlc_object_t *p_this ) |
|---|
| 660 |
{ |
|---|
| 661 |
access_t *p_access = (access_t*)p_this; |
|---|
| 662 |
access_sys_t *p_sys; |
|---|
| 663 |
|
|---|
| 664 |
p_access->p_sys = p_sys = (access_sys_t *)malloc( sizeof( access_sys_t ) ); |
|---|
| 665 |
if( !p_sys ) |
|---|
| 666 |
return VLC_ENOMEM; |
|---|
| 667 |
memset( p_sys, 0, sizeof( access_sys_t ) ); |
|---|
| 668 |
|
|---|
| 669 |
if( CommonOpen( p_this, p_sys, false ) != VLC_SUCCESS ) |
|---|
| 670 |
{ |
|---|
| 671 |
CommonClose( p_this, p_sys ); |
|---|
| 672 |
return VLC_EGENERIC; |
|---|
| 673 |
} |
|---|
| 674 |
|
|---|
| 675 |
dshow_stream_t *p_stream = p_sys->pp_streams[0]; |
|---|
| 676 |
|
|---|
| 677 |
|
|---|
| 678 |
if( !p_access->psz_demux || !*p_access->psz_demux ) |
|---|
| 679 |
{ |
|---|
| 680 |
if( p_stream->i_fourcc == VLC_FOURCC('d','v','s','l') || |
|---|
| 681 |
p_stream->i_fourcc == VLC_FOURCC('d','v','s','d') || |
|---|
| 682 |
p_stream->i_fourcc == VLC_FOURCC('d','v','h','d') ) |
|---|
| 683 |
{ |
|---|
| 684 |
free( p_access->psz_demux ); |
|---|
| 685 |
p_access->psz_demux = strdup( "rawdv" ); |
|---|
| 686 |
} |
|---|
| 687 |
else if( p_stream->i_fourcc == VLC_FOURCC('m','p','2','v') ) |
|---|
| 688 |
{ |
|---|
| 689 |
free( p_access->psz_demux ); |
|---|
| 690 |
p_access->psz_demux = strdup( "mpgv" ); |
|---|
| 691 |
} |
|---|
| 692 |
} |
|---|
| 693 |
|
|---|
| 694 |
|
|---|
| 695 |
p_access->pf_read = NULL; |
|---|
| 696 |
p_access->pf_block = ReadCompressed; |
|---|
| 697 |
p_access->pf_control = AccessControl; |
|---|
| 698 |
p_access->pf_seek = NULL; |
|---|
| 699 |
p_access->info.i_update = 0; |
|---|
| 700 |
p_access->info.i_size = 0; |
|---|
| 701 |
p_access->info.i_pos = 0; |
|---|
| 702 |
p_access->info.b_eof = false; |
|---|
| 703 |
p_access->info.i_title = 0; |
|---|
| 704 |
p_access->info.i_seekpoint = 0; |
|---|
| 705 |
p_access->p_sys = p_sys; |
|---|
| 706 |
|
|---|
| 707 |
|
|---|
| 708 |
msg_Dbg( p_this, "Playing..."); |
|---|
| 709 |
p_sys->p_control->Run(); |
|---|
| 710 |
|
|---|
| 711 |
return VLC_SUCCESS; |
|---|
| 712 |
} |
|---|
| 713 |
|
|---|
| 714 |
|
|---|
| 715 |
|
|---|
| 716 |
|
|---|
| 717 |
static void CommonClose( vlc_object_t *p_this, access_sys_t *p_sys ) |
|---|
| 718 |
{ |
|---|
| 719 |
msg_Dbg( p_this, "releasing DirectShow"); |
|---|
| 720 |
|
|---|
| 721 |
DeleteDirectShowGraph( p_sys ); |
|---|
| 722 |
|
|---|
| 723 |
|
|---|
| 724 |
CoUninitialize(); |
|---|
| 725 |
|
|---|
| 726 |
for( int i = 0; i < p_sys->i_streams; i++ ) delete p_sys->pp_streams[i]; |
|---|
| 727 |
if( p_sys->i_streams ) free( p_sys->pp_streams ); |
|---|
| 728 |
|
|---|
| 729 |
vlc_mutex_destroy( &p_sys->lock ); |
|---|
| 730 |
vlc_cond_destroy( &p_sys->wait ); |
|---|
| 731 |
|
|---|
| 732 |
free( p_sys ); |
|---|
| 733 |
} |
|---|
| 734 |
|
|---|
| 735 |
|
|---|
| 736 |
|
|---|
| 737 |
|
|---|
| 738 |
static void AccessClose( vlc_object_t *p_this ) |
|---|
| 739 |
{ |
|---|
| 740 |
access_t *p_access = (access_t *)p_this; |
|---|
| 741 |
access_sys_t *p_sys = p_access->p_sys; |
|---|
| 742 |
|
|---|
| 743 |
|
|---|
| 744 |
p_sys->p_control->Stop(); |
|---|
| 745 |
|
|---|
| 746 |
CommonClose( p_this, p_sys ); |
|---|
| 747 |
} |
|---|
| 748 |
|
|---|
| 749 |
|
|---|
| 750 |
|
|---|
| 751 |
|
|---|
| 752 |
static void DemuxClose( vlc_object_t *p_this ) |
|---|
| 753 |
{ |
|---|
| 754 |
demux_t *p_demux = (demux_t *)p_this; |
|---|
| 755 |
access_sys_t *p_sys = (access_sys_t *)p_demux->p_sys; |
|---|
| 756 |
|
|---|
| 757 |
|
|---|
| 758 |
p_sys->p_control->Stop(); |
|---|
| 759 |
|
|---|
| 760 |
CommonClose( p_this, p_sys ); |
|---|
| 761 |
} |
|---|
| 762 |
|
|---|
| 763 |
|
|---|
| 764 |
|
|---|
| 765 |
|
|---|
| 766 |
static bool ConnectFilters( vlc_object_t *p_this, access_sys_t *p_sys, |
|---|
| 767 |
IBaseFilter *p_filter, |
|---|
| 768 |
CaptureFilter *p_capture_filter ) |
|---|
| 769 |
{ |
|---|
| 770 |
CapturePin *p_input_pin = p_capture_filter->CustomGetPin(); |
|---|
| 771 |
|
|---|
| 772 |
AM_MEDIA_TYPE mediaType = p_input_pin->CustomGetMediaType(); |
|---|
| 773 |
|
|---|
| 774 |
if( p_sys->p_capture_graph_builder2 ) |
|---|
| 775 |
{ |
|---|
| 776 |
if( FAILED(p_sys->p_capture_graph_builder2-> |
|---|
| 777 |
RenderStream( &PIN_CATEGORY_CAPTURE, &mediaType.majortype, |
|---|
| 778 |
p_filter, 0, (IBaseFilter *)p_capture_filter )) ) |
|---|
| 779 |
{ |
|---|
| 780 |
return false; |
|---|
| 781 |
} |
|---|
| 782 |
|
|---|
| 783 |
|
|---|
| 784 |
|
|---|
| 785 |
IEnumPins *pins = 0; |
|---|
| 786 |
if( ( mediaType.majortype == MEDIATYPE_Video || |
|---|
| 787 |
mediaType.majortype == MEDIATYPE_Stream ) && |
|---|
| 788 |
SUCCEEDED(p_filter->EnumPins(&pins)) ) |
|---|
| 789 |
{ |
|---|
| 790 |
IPin *pP = 0; |
|---|
| 791 |
ULONG n; |
|---|
| 792 |
PIN_INFO pinInfo; |
|---|
| 793 |
BOOL Found = FALSE; |
|---|
| 794 |
IKsPropertySet *pKs=0; |
|---|
| 795 |
GUID guid; |
|---|
| 796 |
DWORD dw; |
|---|
| 797 |
|
|---|
| 798 |
while( !Found && ( S_OK == pins->Next(1, &pP, &n) ) ) |
|---|
| 799 |
{ |
|---|
| 800 |
if( S_OK == pP->QueryPinInfo(&pinInfo) ) |
|---|
| 801 |
{ |
|---|
| 802 |
|
|---|
| 803 |
if( pinInfo.dir == PINDIR_INPUT && |
|---|
| 804 |
pP->QueryInterface( IID_IKsPropertySet, |
|---|
| 805 |
(void **)&pKs ) == S_OK ) |
|---|
| 806 |
{ |
|---|
| 807 |
if( pKs->Get( AMPROPSETID_Pin, |
|---|
| 808 |
AMPROPERTY_PIN_CATEGORY, NULL, 0, |
|---|
| 809 |
&guid, sizeof(GUID), &dw ) == S_OK ) |
|---|
| 810 |
{ |
|---|
| 811 |
if( guid == PIN_CATEGORY_ANALOGVIDEOIN ) |
|---|
| 812 |
{ |
|---|
| 813 |
|
|---|
| 814 |
FindCrossbarRoutes( p_this, p_sys, pP, 0 ); |
|---|
| 815 |
|
|---|
| 816 |
Found = TRUE; |
|---|
| 817 |
} |
|---|
| 818 |
} |
|---|
| 819 |
pKs->Release(); |
|---|
| 820 |
} |
|---|
| 821 |
pinInfo.pFilter->Release(); |
|---|
| 822 |
} |
|---|
| 823 |
pP->Release(); |
|---|
| 824 |
} |
|---|
| 825 |
pins->Release(); |
|---|
| 826 |
} |
|---|
| 827 |
return true; |
|---|
| 828 |
} |
|---|
| 829 |
else |
|---|
| 830 |
{ |
|---|
| 831 |
IEnumPins *p_enumpins; |
|---|
| 832 |
IPin *p_pin; |
|---|
| 833 |
|
|---|
| 834 |
if( S_OK != p_filter->EnumPins( &p_enumpins ) ) return false; |
|---|
| 835 |
|
|---|
| 836 |
while( S_OK == p_enumpins->Next( 1, &p_pin, NULL ) ) |
|---|
| 837 |
{ |
|---|
| 838 |
PIN_DIRECTION pin_dir; |
|---|
| 839 |
p_pin->QueryDirection( &pin_dir ); |
|---|
| 840 |
|
|---|
| 841 |
if( pin_dir == PINDIR_OUTPUT && |
|---|
| 842 |
p_sys->p_graph->ConnectDirect( p_pin, (IPin *)p_input_pin, |
|---|
| 843 |
|
|---|