dialog: use new API
[vlc.git] / modules / access / dshow / dshow.cpp
1 /*****************************************************************************
2  * dshow.cpp : DirectShow access and access_demux module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002-2004, 2006, 2008, 2010 the VideoLAN team
5  * $Id$
6  *
7  * Author: Gildas Bazin <gbazin@videolan.org>
8  *         Damien Fouilleul <damienf@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #define CFG_PREFIX "dshow-"
34 #include <inttypes.h>
35 #include <list>
36 #include <string>
37 #include <assert.h>
38
39 #define VLC_MODULE_LICENSE VLC_LICENSE_GPL_2_PLUS
40 #include <vlc_common.h>
41 #include <vlc_plugin.h>
42 #include <vlc_access.h>
43 #include <vlc_demux.h>
44
45 #include <vlc_dialog.h>      /* vlc_dialog_display_error */
46 #include <vlc_charset.h>     /* FromWide */
47
48 #include <initguid.h>
49 #include "vlc_dshow.h"
50
51 #include "access.h"
52 #include "filter.h"
53
54 #define INSTANCEDATA_OF_PROPERTY_PTR(x) ((PKSPROPERTY((x))) + 1)
55 #define INSTANCEDATA_OF_PROPERTY_SIZE(x) (sizeof((x)) - sizeof(KSPROPERTY))
56
57 /*****************************************************************************
58  * Access: local prototypes
59  *****************************************************************************/
60 static block_t *ReadCompressed( access_t * );
61 static int AccessControl ( access_t *, int, va_list );
62
63 static int Demux       ( demux_t * );
64 static int DemuxControl( demux_t *, int, va_list );
65
66 static int OpenDevice( vlc_object_t *, access_sys_t *, std::string, bool );
67 static IBaseFilter *FindCaptureDevice( vlc_object_t *, std::string *,
68                                        std::list<std::string> *, bool );
69 static size_t EnumDeviceCaps( vlc_object_t *, IBaseFilter *,
70                               int, int, int, int, int, int,
71                               AM_MEDIA_TYPE *mt, size_t );
72 static bool ConnectFilters( vlc_object_t *, access_sys_t *,
73                             IBaseFilter *, CaptureFilter * );
74 static int FindDevices( vlc_object_t *, const char *, char ***, char *** );
75
76 static void ShowPropertyPage( IUnknown * );
77 static void ShowDeviceProperties( vlc_object_t *, ICaptureGraphBuilder2 *,
78                                   IBaseFilter *, bool );
79 static void ShowTunerProperties( vlc_object_t *, ICaptureGraphBuilder2 *,
80                                  IBaseFilter *, bool );
81 static void ConfigTuner( vlc_object_t *, ICaptureGraphBuilder2 *,
82                          IBaseFilter * );
83
84 /*****************************************************************************
85  * Module descriptor
86  *****************************************************************************/
87 static const int pi_tuner_input[] = { 0, 1, 2 };
88 static const char *const ppsz_tuner_input_text[] =
89     {N_("Default"), N_("Cable"), N_("Antenna")};
90
91 static const int pi_amtuner_mode[]  = { AMTUNER_MODE_DEFAULT,
92                                         AMTUNER_MODE_TV,
93                                         AMTUNER_MODE_FM_RADIO,
94                                         AMTUNER_MODE_AM_RADIO,
95                                         AMTUNER_MODE_DSS };
96 static const char *const ppsz_amtuner_mode_text[] = { N_("Default"),
97                                           N_("TV"),
98                                           N_("FM radio"),
99                                           N_("AM radio"),
100                                           N_("DSS") };
101
102 static const int i_standards_list[] =
103     {
104         KS_AnalogVideo_None,
105         KS_AnalogVideo_NTSC_M, KS_AnalogVideo_NTSC_M_J, KS_AnalogVideo_NTSC_433,
106         KS_AnalogVideo_PAL_B, KS_AnalogVideo_PAL_D, KS_AnalogVideo_PAL_G,
107         KS_AnalogVideo_PAL_H, KS_AnalogVideo_PAL_I, KS_AnalogVideo_PAL_M,
108         KS_AnalogVideo_PAL_N, KS_AnalogVideo_PAL_60,
109         KS_AnalogVideo_SECAM_B, KS_AnalogVideo_SECAM_D, KS_AnalogVideo_SECAM_G,
110         KS_AnalogVideo_SECAM_H, KS_AnalogVideo_SECAM_K, KS_AnalogVideo_SECAM_K1,
111         KS_AnalogVideo_SECAM_L, KS_AnalogVideo_SECAM_L1,
112         KS_AnalogVideo_PAL_N_COMBO
113     };
114 static const char *const ppsz_standards_list_text[] =
115     {
116         N_("Default"),
117         "NTSC_M", "NTSC_M_J", "NTSC_443",
118         "PAL_B", "PAL_D", "PAL_G",
119         "PAL_H", "PAL_I", "PAL_M",
120         "PAL_N", "PAL_60",
121         "SECAM_B", "SECAM_D", "SECAM_G",
122         "SECAM_H", "SECAM_K", "SECAM_K1",
123         "SECAM_L", "SECAM_L1",
124         "PAL_N_COMBO"
125     };
126
127 #define VDEV_TEXT N_("Video device name")
128 #define VDEV_LONGTEXT N_( \
129     "Name of the video device that will be used by the " \
130     "DirectShow plugin. If you don't specify anything, the default device " \
131     "will be used.")
132 #define ADEV_TEXT N_("Audio device name")
133 #define ADEV_LONGTEXT N_( \
134     "Name of the audio device that will be used by the " \
135     "DirectShow plugin. If you don't specify anything, the default device " \
136     "will be used. ")
137 #define SIZE_TEXT N_("Video size")
138 #define SIZE_LONGTEXT N_( \
139     "Size of the video that will be displayed by the " \
140     "DirectShow plugin. If you don't specify anything the default size for " \
141     "your device will be used. You can specify a standard size (cif, d1, ...) or <width>x<height>.")
142 #define ASPECT_TEXT N_("Picture aspect-ratio n:m")
143 #define ASPECT_LONGTEXT N_("Define input picture aspect-ratio to use. Default is 4:3" )
144 #define CHROMA_TEXT N_("Video input chroma format")
145 #define CHROMA_LONGTEXT N_( \
146     "Force the DirectShow video input to use a specific chroma format " \
147     "(eg. I420 (default), RV24, etc.)")
148 #define FPS_TEXT N_("Video input frame rate")
149 #define FPS_LONGTEXT N_( \
150     "Force the DirectShow video input to use a specific frame rate " \
151     "(eg. 0 means default, 25, 29.97, 50, 59.94, etc.)")
152 #define CONFIG_TEXT N_("Device properties")
153 #define CONFIG_LONGTEXT N_( \
154     "Show the properties dialog of the selected device before starting the " \
155     "stream.")
156 #define TUNER_TEXT N_("Tuner properties")
157 #define TUNER_LONGTEXT N_( \
158     "Show the tuner properties [channel selection] page." )
159 #define CHANNEL_TEXT N_("Tuner TV Channel")
160 #define CHANNEL_LONGTEXT N_( \
161     "Set the TV channel the tuner will set to " \
162     "(0 means default)." )
163 #define TVFREQ_TEXT N_("Tuner Frequency")
164 #define TVFREQ_LONGTEXT N_(  "This overrides the channel. Measured in Hz." )
165 #define STANDARD_TEXT N_( "Video standard" )
166 #define COUNTRY_TEXT N_("Tuner country code")
167 #define COUNTRY_LONGTEXT N_( \
168     "Set the tuner country code that establishes the current " \
169     "channel-to-frequency mapping (0 means default)." )
170 #define TUNER_INPUT_TEXT N_("Tuner input type")
171 #define TUNER_INPUT_LONGTEXT N_( \
172     "Select the tuner input type (Cable/Antenna)." )
173 #define VIDEO_IN_TEXT N_("Video input pin")
174 #define VIDEO_IN_LONGTEXT N_( \
175   "Select the video input source, such as composite, s-video, " \
176   "or tuner. Since these settings are hardware-specific, you should find good " \
177   "settings in the \"Device config\" area, and use those numbers here. -1 " \
178   "means that settings will not be changed.")
179 #define AUDIO_IN_TEXT N_("Audio input pin")
180 #define AUDIO_IN_LONGTEXT N_( \
181   "Select the audio input source. See the \"video input\" option." )
182 #define VIDEO_OUT_TEXT N_("Video output pin")
183 #define VIDEO_OUT_LONGTEXT N_( \
184   "Select the video output type. See the \"video input\" option." )
185 #define AUDIO_OUT_TEXT N_("Audio output pin")
186 #define AUDIO_OUT_LONGTEXT N_( \
187   "Select the audio output type. See the \"video input\" option." )
188
189 #define AMTUNER_MODE_TEXT N_("AM Tuner mode")
190 #define AMTUNER_MODE_LONGTEXT N_( \
191     "AM Tuner mode. Can be one of Default (0), TV (1), " \
192      "AM Radio (2), FM Radio (3) or DSS (4).")
193
194 #define AUDIO_CHANNELS_TEXT N_("Number of audio channels")
195 #define AUDIO_CHANNELS_LONGTEXT N_( \
196     "Select audio input format with the given number of audio channels (if non 0)" )
197
198 #define AUDIO_SAMPLERATE_TEXT N_("Audio sample rate")
199 #define AUDIO_SAMPLERATE_LONGTEXT N_( \
200     "Select audio input format with the given sample rate (if non 0)" )
201
202 #define AUDIO_BITSPERSAMPLE_TEXT N_("Audio bits per sample")
203 #define AUDIO_BITSPERSAMPLE_LONGTEXT N_( \
204     "Select audio input format with the given bits/sample (if non 0)" )
205
206 static int  CommonOpen ( vlc_object_t *, access_sys_t *, bool );
207 static void CommonClose( vlc_object_t *, access_sys_t * );
208
209 static int  AccessOpen ( vlc_object_t * );
210 static void AccessClose( vlc_object_t * );
211
212 static int  DemuxOpen  ( vlc_object_t * );
213 static void DemuxClose ( vlc_object_t * );
214
215 vlc_module_begin ()
216     set_shortname( N_("DirectShow") )
217     set_description( N_("DirectShow input") )
218     set_category( CAT_INPUT )
219     set_subcategory( SUBCAT_INPUT_ACCESS )
220
221     add_string( CFG_PREFIX "vdev", NULL, VDEV_TEXT, VDEV_LONGTEXT, false)
222         change_string_cb( FindDevices )
223
224     add_string( CFG_PREFIX "adev", NULL, ADEV_TEXT, ADEV_LONGTEXT, false)
225         change_string_cb( FindDevices )
226
227     add_string( CFG_PREFIX "size", NULL, SIZE_TEXT, SIZE_LONGTEXT, false)
228         change_safe()
229
230     add_string( CFG_PREFIX "aspect-ratio", "4:3", ASPECT_TEXT, ASPECT_LONGTEXT, false)
231         change_safe()
232
233     add_string( CFG_PREFIX "chroma", NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true )
234         change_safe()
235
236     add_float( CFG_PREFIX "fps", 0.0f, FPS_TEXT, FPS_LONGTEXT, true )
237         change_safe()
238
239     add_bool( CFG_PREFIX "config", false, CONFIG_TEXT, CONFIG_LONGTEXT, true )
240
241     add_bool( CFG_PREFIX "tuner", false, TUNER_TEXT, TUNER_LONGTEXT, true )
242
243     add_integer( CFG_PREFIX "tuner-channel", 0, CHANNEL_TEXT, CHANNEL_LONGTEXT,
244                 true )
245         change_safe()
246
247     add_integer( CFG_PREFIX "tuner-frequency", 0, TVFREQ_TEXT, TVFREQ_LONGTEXT,
248                 true )
249         change_safe()
250
251     add_integer( CFG_PREFIX "tuner-country", 0, COUNTRY_TEXT, COUNTRY_LONGTEXT,
252                 true )
253
254     add_integer( CFG_PREFIX "tuner-standard", 0, STANDARD_TEXT, STANDARD_TEXT,
255                 false )
256         change_integer_list( i_standards_list, ppsz_standards_list_text )
257         change_safe()
258
259     add_integer( CFG_PREFIX "tuner-input", 0, TUNER_INPUT_TEXT,
260                  TUNER_INPUT_LONGTEXT, true )
261         change_integer_list( pi_tuner_input, ppsz_tuner_input_text )
262         change_safe()
263
264     add_integer( CFG_PREFIX "video-input",  -1, VIDEO_IN_TEXT,
265                  VIDEO_IN_LONGTEXT, true )
266         change_safe()
267
268     add_integer( CFG_PREFIX "video-output", -1, VIDEO_OUT_TEXT,
269                  VIDEO_OUT_LONGTEXT, true )
270
271     add_integer( CFG_PREFIX "audio-input",  -1, AUDIO_IN_TEXT,
272                  AUDIO_IN_LONGTEXT, true )
273         change_safe()
274
275     add_integer( CFG_PREFIX "audio-output", -1, AUDIO_OUT_TEXT,
276                  AUDIO_OUT_LONGTEXT, true )
277
278     add_integer( CFG_PREFIX "amtuner-mode", AMTUNER_MODE_TV,
279                 AMTUNER_MODE_TEXT, AMTUNER_MODE_LONGTEXT, false)
280         change_integer_list( pi_amtuner_mode, ppsz_amtuner_mode_text )
281         change_safe()
282
283     add_integer( CFG_PREFIX "audio-channels", 0, AUDIO_CHANNELS_TEXT,
284                  AUDIO_CHANNELS_LONGTEXT, true )
285     add_integer( CFG_PREFIX "audio-samplerate", 0, AUDIO_SAMPLERATE_TEXT,
286                  AUDIO_SAMPLERATE_LONGTEXT, true )
287     add_integer( CFG_PREFIX "audio-bitspersample", 0, AUDIO_BITSPERSAMPLE_TEXT,
288                  AUDIO_BITSPERSAMPLE_LONGTEXT, true )
289
290     add_shortcut( "dshow" )
291     set_capability( "access_demux", 0 )
292     set_callbacks( DemuxOpen, DemuxClose )
293
294     add_submodule ()
295     set_description( N_("DirectShow input") )
296     add_shortcut( "dshow" )
297     set_capability( "access", 0 )
298     set_callbacks( AccessOpen, AccessClose )
299
300 vlc_module_end ()
301
302
303 /*****************************************************************************
304  * DirectShow elementary stream descriptor
305  *****************************************************************************/
306 typedef struct dshow_stream_t
307 {
308     std::string          devicename;
309     IBaseFilter     *p_device_filter;
310     CaptureFilter   *p_capture_filter;
311     AM_MEDIA_TYPE   mt;
312
313     union
314     {
315       VIDEOINFOHEADER video;
316       WAVEFORMATEX    audio;
317
318     } header;
319
320     int             i_fourcc;
321     es_out_id_t     *p_es;
322
323     bool      b_pts;
324
325     std::deque<VLCMediaSample> samples_queue;
326 } dshow_stream_t;
327
328 /*****************************************************************************
329  * DirectShow utility functions
330  *****************************************************************************/
331 static void CreateDirectShowGraph( access_sys_t *p_sys )
332 {
333     p_sys->i_crossbar_route_depth = 0;
334
335     /* Create directshow filter graph */
336     if( SUCCEEDED( CoCreateInstance( CLSID_FilterGraph, 0, CLSCTX_INPROC,
337                        (REFIID)IID_IFilterGraph, (void **)&p_sys->p_graph) ) )
338     {
339         /* Create directshow capture graph builder if available */
340         if( SUCCEEDED( CoCreateInstance( CLSID_CaptureGraphBuilder2, 0,
341                          CLSCTX_INPROC, (REFIID)IID_ICaptureGraphBuilder2,
342                          (void **)&p_sys->p_capture_graph_builder2 ) ) )
343         {
344             p_sys->p_capture_graph_builder2->
345                 SetFiltergraph((IGraphBuilder *)p_sys->p_graph);
346         }
347
348         p_sys->p_graph->QueryInterface( IID_IMediaControl,
349                                         (void **)&p_sys->p_control );
350     }
351 }
352
353 static void DeleteDirectShowGraph( vlc_object_t *p_this, access_sys_t *p_sys )
354 {
355     DeleteCrossbarRoutes( p_sys );
356
357     /* Remove filters from graph */
358     msg_Dbg( p_this, "DeleteDirectShowGraph: Removing filters" );
359     for( int i = 0; i < p_sys->i_streams; i++ )
360     {
361         /* RemoveFilter does an undocumented Release()
362          * but does not set item to NULL */
363         msg_Dbg( p_this, "DeleteDirectShowGraph: Removing capture filter" );
364         p_sys->p_graph->RemoveFilter( p_sys->pp_streams[i]->p_capture_filter );
365         p_sys->pp_streams[i]->p_capture_filter = NULL;
366
367         msg_Dbg( p_this, "DeleteDirectShowGraph: Removing device filter" );
368         p_sys->p_graph->RemoveFilter( p_sys->pp_streams[i]->p_device_filter );
369         p_sys->pp_streams[i]->p_device_filter = NULL;
370     }
371
372     /* Release directshow objects */
373     if( p_sys->p_control )
374     {
375         p_sys->p_control->Release();
376         p_sys->p_control = NULL;
377     }
378     if( p_sys->p_capture_graph_builder2 )
379     {
380         p_sys->p_capture_graph_builder2->Release();
381         p_sys->p_capture_graph_builder2 = NULL;
382     }
383
384     if( p_sys->p_graph )
385     {
386         p_sys->p_graph->Release();
387         p_sys->p_graph = NULL;
388     }
389 }
390
391 /*****************************************************************************
392  * CommonOpen: open direct show device
393  *****************************************************************************/
394 static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys,
395                        bool b_access_demux )
396 {
397     char *psz_val;
398
399     /* Get/parse options and open device(s) */
400     std::string vdevname, adevname;
401     int i_width = 0, i_height = 0;
402     vlc_fourcc_t i_chroma = 0;
403     bool b_use_audio = true;
404     bool b_use_video = true;
405
406     /* Initialize OLE/COM */
407     if( FAILED(CoInitializeEx( NULL, COINIT_APARTMENTTHREADED )) )
408         vlc_assert_unreachable();
409
410     var_Create( p_this,  CFG_PREFIX "config", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
411     var_Create( p_this,  CFG_PREFIX "tuner", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
412     psz_val = var_CreateGetString( p_this, CFG_PREFIX "vdev" );
413     if( psz_val )
414     {
415         msg_Dbg( p_this, "dshow-vdev: %s", psz_val ) ;
416         /* skip none device */
417         if ( strncasecmp( psz_val, "none", 4 ) != 0 )
418             vdevname = std::string( psz_val );
419         else
420             b_use_video = false ;
421     }
422     free( psz_val );
423
424     psz_val = var_CreateGetString( p_this, CFG_PREFIX "adev" );
425     if( psz_val )
426     {
427         msg_Dbg( p_this, "dshow-adev: %s", psz_val ) ;
428         /* skip none device */
429         if ( strncasecmp( psz_val, "none", 4 ) != 0 )
430             adevname = std::string( psz_val );
431         else
432             b_use_audio = false ;
433     }
434     free( psz_val );
435
436     /* DShow Size */
437     static struct {
438         const char *psz_size;
439         int  i_width;
440         int  i_height;
441     } size_table[] =
442     { { "subqcif", 128, 96  },
443       {    "qsif", 160, 120 },
444       {    "qcif", 176, 144 },
445       {     "sif", 320, 240 },
446       {     "cif", 352, 288 },
447       {      "d1", 640, 480 },
448       { 0, 0, 0 },
449     };
450
451     psz_val = var_CreateGetString( p_this, CFG_PREFIX "size" );
452     if( !EMPTY_STR(psz_val) )
453     {
454         int i;
455         for( i = 0; size_table[i].psz_size; i++ )
456         {
457             if( !strcmp( psz_val, size_table[i].psz_size ) )
458             {
459                 i_width = size_table[i].i_width;
460                 i_height = size_table[i].i_height;
461                 break;
462             }
463         }
464         if( !size_table[i].psz_size ) /* Try to parse "WidthxHeight" */
465         {
466             char *psz_parser;
467             i_width = strtol( psz_val, &psz_parser, 0 );
468             if( *psz_parser == 'x' || *psz_parser == 'X')
469             {
470                 i_height = strtol( psz_parser + 1, &psz_parser, 0 );
471             }
472             msg_Dbg( p_this, "width x height %dx%d", i_width, i_height );
473         }
474     }
475     free( psz_val );
476
477     /* Chroma */
478     psz_val = var_CreateGetString( p_this, CFG_PREFIX "chroma" );
479     i_chroma = vlc_fourcc_GetCodecFromString( UNKNOWN_ES, psz_val );
480     p_sys->b_chroma = i_chroma != 0;
481     free( psz_val );
482
483     var_Create( p_this, CFG_PREFIX "fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
484     var_Create( p_this, CFG_PREFIX "tuner-channel",
485                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
486     var_Create( p_this, CFG_PREFIX "tuner-frequency",
487                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
488     var_Create( p_this, CFG_PREFIX "tuner-standard",
489                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
490     var_Create( p_this, CFG_PREFIX "tuner-country",
491                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
492     var_Create( p_this, CFG_PREFIX "tuner-input",
493                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
494
495     var_Create( p_this, CFG_PREFIX "amtuner-mode",
496                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
497
498     var_Create( p_this, CFG_PREFIX "video-input", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
499     var_Create( p_this, CFG_PREFIX "audio-input", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
500     var_Create( p_this, CFG_PREFIX "video-output", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
501     var_Create( p_this, CFG_PREFIX "audio-output", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
502
503
504     /* Initialize some data */
505     p_sys->i_streams = 0;
506     p_sys->pp_streams = NULL;
507     p_sys->i_width = i_width;
508     p_sys->i_height = i_height;
509     p_sys->i_chroma = i_chroma;
510
511     p_sys->p_graph = NULL;
512     p_sys->p_capture_graph_builder2 = NULL;
513     p_sys->p_control = NULL;
514
515     /* Build directshow graph */
516     CreateDirectShowGraph( p_sys );
517
518     vlc_mutex_init( &p_sys->lock );
519     vlc_cond_init( &p_sys->wait );
520
521     if( !b_use_video && !b_use_audio )
522     {
523         vlc_dialog_display_error( p_this, _("Capture failed"),
524                         _("No video or audio device selected.") );
525         return VLC_EGENERIC ;
526     }
527
528     if( !b_use_video )
529         msg_Dbg( p_this, "skipping video device" ) ;
530     bool b_err_video = false ;
531
532     if( b_use_video && OpenDevice( p_this, p_sys, vdevname, 0 ) != VLC_SUCCESS )
533     {
534         msg_Err( p_this, "can't open video device");
535         b_err_video = true ;
536     }
537
538     if ( b_use_video && !b_err_video )
539     {
540         /* Check if we can handle the demuxing ourselves or need to spawn
541          * a demuxer module */
542         dshow_stream_t *p_stream = p_sys->pp_streams[p_sys->i_streams-1];
543
544         if( p_stream->mt.majortype == MEDIATYPE_Video )
545         {
546             if( /* Raw DV stream */
547                 p_stream->i_fourcc == VLC_CODEC_DV ||
548                 /* Raw MPEG video stream */
549                 p_stream->i_fourcc == VLC_CODEC_MPGV )
550             {
551                 b_use_audio = false;
552
553                 if( b_access_demux )
554                 {
555                     /* Let the access (only) take care of that */
556                     return VLC_EGENERIC;
557                 }
558             }
559         }
560
561         if( p_stream->mt.majortype == MEDIATYPE_Stream )
562         {
563             b_use_audio = false;
564
565             if( b_access_demux )
566             {
567                 /* Let the access (only) take care of that */
568                 return VLC_EGENERIC;
569             }
570
571             if( var_GetBool( p_this, CFG_PREFIX "tuner" ) )
572             {
573                 /* FIXME: we do MEDIATYPE_Stream here so we don't do
574                  * it twice. */
575                 ShowTunerProperties( p_this, p_sys->p_capture_graph_builder2,
576                                      p_stream->p_device_filter, 0 );
577             }
578         }
579     }
580
581     if( !b_use_audio )
582         msg_Dbg( p_this, "skipping audio device") ;
583
584     bool b_err_audio = false ;
585
586     if( b_use_audio && OpenDevice( p_this, p_sys, adevname, 1 ) != VLC_SUCCESS )
587     {
588         msg_Err( p_this, "can't open audio device");
589         b_err_audio = true ;
590     }
591
592     if( ( b_use_video && b_err_video && b_use_audio && b_err_audio ) ||
593         ( !b_use_video && b_use_audio && b_err_audio ) ||
594         ( b_use_video && !b_use_audio && b_err_video ) )
595     {
596         msg_Err( p_this, "FATAL: could not open ANY device" ) ;
597         vlc_dialog_display_error( p_this,  _("Capture failed"),
598                         _("VLC cannot open ANY capture device. "
599                           "Check the error log for details.") );
600         return VLC_EGENERIC ;
601     }
602
603     for( int i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i )
604     {
605         int i_val = var_GetInteger( p_this, CFG_PREFIX "video-input" );
606         if( i_val >= 0 )
607             p_sys->crossbar_routes[i].VideoInputIndex = i_val;
608         i_val = var_GetInteger( p_this, CFG_PREFIX "video-output" );
609         if( i_val >= 0 )
610             p_sys->crossbar_routes[i].VideoOutputIndex = i_val;
611         i_val = var_GetInteger( p_this, CFG_PREFIX "audio-input" );
612         if( i_val >= 0 )
613             p_sys->crossbar_routes[i].AudioInputIndex = i_val;
614         i_val = var_GetInteger( p_this, CFG_PREFIX "audio-output" );
615         if( i_val >= 0 )
616             p_sys->crossbar_routes[i].AudioOutputIndex = i_val;
617
618         IAMCrossbar *pXbar = p_sys->crossbar_routes[i].pXbar;
619         LONG VideoInputIndex = p_sys->crossbar_routes[i].VideoInputIndex;
620         LONG VideoOutputIndex = p_sys->crossbar_routes[i].VideoOutputIndex;
621         LONG AudioInputIndex = p_sys->crossbar_routes[i].AudioInputIndex;
622         LONG AudioOutputIndex = p_sys->crossbar_routes[i].AudioOutputIndex;
623
624         if( SUCCEEDED(pXbar->Route(VideoOutputIndex, VideoInputIndex)) )
625         {
626             msg_Dbg( p_this, "crossbar at depth %d, routed video "
627                      "output %ld to video input %ld", i, VideoOutputIndex,
628                      VideoInputIndex );
629
630             if( AudioOutputIndex != -1 && AudioInputIndex != -1 )
631             {
632                 if( SUCCEEDED( pXbar->Route(AudioOutputIndex,
633                                             AudioInputIndex)) )
634                 {
635                     msg_Dbg(p_this, "crossbar at depth %d, routed audio "
636                             "output %ld to audio input %ld", i,
637                             AudioOutputIndex, AudioInputIndex );
638                 }
639             }
640         }
641         else
642             msg_Err( p_this, "crossbar at depth %d could not route video "
643                      "output %ld to input %ld", i, VideoOutputIndex, VideoInputIndex );
644     }
645
646     /*
647     ** Show properties pages from other filters in graph
648     */
649     if( var_GetBool( p_this, CFG_PREFIX "config" ) )
650     {
651         for( int i = p_sys->i_crossbar_route_depth-1; i >= 0 ; --i )
652         {
653             IAMCrossbar *pXbar = p_sys->crossbar_routes[i].pXbar;
654             IBaseFilter *p_XF;
655
656             if( SUCCEEDED( pXbar->QueryInterface( IID_IBaseFilter,
657                                                   (void **)&p_XF ) ) )
658             {
659                 ShowPropertyPage( p_XF );
660                 p_XF->Release();
661             }
662         }
663     }
664
665     /* Initialize some data */
666     p_sys->i_current_stream = 0;
667
668     if( !p_sys->i_streams ) return VLC_EGENERIC;
669
670     return VLC_SUCCESS;
671 }
672
673 /*****************************************************************************
674  * DemuxOpen: open direct show device as an access_demux module
675  *****************************************************************************/
676 static int DemuxOpen( vlc_object_t *p_this )
677 {
678     demux_t      *p_demux = (demux_t *)p_this;
679     access_sys_t *p_sys;
680
681     p_sys = (access_sys_t*)calloc( 1, sizeof( access_sys_t ) );
682     if( !p_sys )
683         return VLC_ENOMEM;
684     p_demux->p_sys = (demux_sys_t *)p_sys;
685
686     if( CommonOpen( p_this, p_sys, true ) != VLC_SUCCESS )
687     {
688         CommonClose( p_this, p_sys );
689         return VLC_EGENERIC;
690     }
691
692     /* Everything is ready. Let's rock baby */
693     msg_Dbg( p_this, "Playing...");
694     p_sys->p_control->Run();
695
696     p_demux->pf_demux   = Demux;
697     p_demux->pf_control = DemuxControl;
698     p_demux->info.i_title = 0;
699     p_demux->info.i_seekpoint = 0;
700
701     for( int i = 0; i < p_sys->i_streams; i++ )
702     {
703         dshow_stream_t *p_stream = p_sys->pp_streams[i];
704         es_format_t fmt;
705
706         if( p_stream->mt.majortype == MEDIATYPE_Video )
707         {
708             char *psz_aspect = var_CreateGetString( p_this, CFG_PREFIX "aspect-ratio" );
709             char *psz_delim = !EMPTY_STR( psz_aspect ) ? strchr( psz_aspect, ':' ) : NULL;
710
711             es_format_Init( &fmt, VIDEO_ES, p_stream->i_fourcc );
712
713             fmt.video.i_width  = p_stream->header.video.bmiHeader.biWidth;
714             fmt.video.i_height = p_stream->header.video.bmiHeader.biHeight;
715
716             if( psz_delim )
717             {
718                 fmt.video.i_sar_num = atoi( psz_aspect ) * fmt.video.i_height;
719                 fmt.video.i_sar_den = atoi( psz_delim + 1 ) * fmt.video.i_width;
720             }
721             else
722             {
723                 fmt.video.i_sar_num = 4 * fmt.video.i_height;
724                 fmt.video.i_sar_den = 3 * fmt.video.i_width;
725             }
726             free( psz_aspect );
727
728             if( !p_stream->header.video.bmiHeader.biCompression )
729             {
730                 /* RGB DIB are coded from bottom to top */
731                 fmt.video.orientation = ORIENT_BOTTOM_LEFT;
732             }
733
734             /* Setup rgb mask for RGB formats */
735             if( p_stream->i_fourcc == VLC_CODEC_RGB24 )
736             {
737                 /* This is in RGB format
738             http://msdn.microsoft.com/en-us/library/dd407253%28VS.85%29.aspx?ppud=4
739                  */
740                 fmt.video.i_rmask = 0x00ff0000;
741                 fmt.video.i_gmask = 0x0000ff00;
742                 fmt.video.i_bmask = 0x000000ff;
743             }
744
745             if( p_stream->header.video.AvgTimePerFrame )
746             {
747                 fmt.video.i_frame_rate = 10000000;
748                 fmt.video.i_frame_rate_base =
749                     p_stream->header.video.AvgTimePerFrame;
750             }
751         }
752         else if( p_stream->mt.majortype == MEDIATYPE_Audio )
753         {
754             es_format_Init( &fmt, AUDIO_ES, p_stream->i_fourcc );
755
756             fmt.audio.i_channels = p_stream->header.audio.nChannels;
757             fmt.audio.i_rate = p_stream->header.audio.nSamplesPerSec;
758             fmt.audio.i_bitspersample = p_stream->header.audio.wBitsPerSample;
759             fmt.audio.i_blockalign = fmt.audio.i_channels *
760                 fmt.audio.i_bitspersample / 8;
761             fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate *
762                 fmt.audio.i_bitspersample;
763         }
764
765         p_stream->p_es = es_out_Add( p_demux->out, &fmt );
766     }
767
768     return VLC_SUCCESS;
769 }
770
771 /*****************************************************************************
772  * AccessOpen: open direct show device as an access module
773  *****************************************************************************/
774 static int AccessOpen( vlc_object_t *p_this )
775 {
776     access_t     *p_access = (access_t*)p_this;
777     access_sys_t *p_sys;
778
779     p_access->p_sys = p_sys = (access_sys_t*)calloc( 1, sizeof( access_sys_t ) );
780     if( !p_sys )
781         return VLC_ENOMEM;
782
783     if( CommonOpen( p_this, p_sys, false ) != VLC_SUCCESS )
784     {
785         CommonClose( p_this, p_sys );
786         return VLC_EGENERIC;
787     }
788
789     /* Setup Access */
790     p_access->pf_read = NULL;
791     p_access->pf_block = ReadCompressed;
792     p_access->pf_control = AccessControl;
793     p_access->pf_seek = NULL;
794     p_access->info.b_eof = false;
795     p_access->p_sys = p_sys;
796
797     /* Everything is ready. Let's rock baby */
798     msg_Dbg( p_this, "Playing...");
799     p_sys->p_control->Run();
800
801     return VLC_SUCCESS;
802 }
803
804 /*****************************************************************************
805  * CommonClose: close device
806  *****************************************************************************/
807 static void CommonClose( vlc_object_t *p_this, access_sys_t *p_sys )
808 {
809     msg_Dbg( p_this, "releasing DirectShow");
810
811     DeleteDirectShowGraph( p_this, p_sys );
812
813     /* Uninitialize OLE/COM */
814     CoUninitialize();
815
816     for( int i = 0; i < p_sys->i_streams; i++ ) delete p_sys->pp_streams[i];
817     if( p_sys->i_streams ) free( p_sys->pp_streams );
818
819     vlc_mutex_destroy( &p_sys->lock );
820     vlc_cond_destroy( &p_sys->wait );
821
822     free( p_sys );
823 }
824
825 /*****************************************************************************
826  * AccessClose: close device
827  *****************************************************************************/
828 static void AccessClose( vlc_object_t *p_this )
829 {
830     access_t     *p_access = (access_t *)p_this;
831     access_sys_t *p_sys    = p_access->p_sys;
832
833     /* Stop capturing stuff */
834     p_sys->p_control->Stop();
835
836     CommonClose( p_this, p_sys );
837 }
838
839 /*****************************************************************************
840  * DemuxClose: close device
841  *****************************************************************************/
842 static void DemuxClose( vlc_object_t *p_this )
843 {
844     demux_t      *p_demux = (demux_t *)p_this;
845     access_sys_t *p_sys   = (access_sys_t *)p_demux->p_sys;
846
847     /* Stop capturing stuff */
848     p_sys->p_control->Stop();
849
850     CommonClose( p_this, p_sys );
851 }
852
853 /****************************************************************************
854  * ConnectFilters
855  ****************************************************************************/
856 static bool ConnectFilters( vlc_object_t *p_this, access_sys_t *p_sys,
857                             IBaseFilter *p_filter,
858                             CaptureFilter *p_capture_filter )
859 {
860     CapturePin *p_input_pin = p_capture_filter->CustomGetPin();
861
862     AM_MEDIA_TYPE mediaType = p_input_pin->CustomGetMediaType();
863
864     if( p_sys->p_capture_graph_builder2 )
865     {
866         if( FAILED(p_sys->p_capture_graph_builder2->
867                 RenderStream( &PIN_CATEGORY_CAPTURE, &mediaType.majortype,
868                               p_filter, 0, (IBaseFilter *)p_capture_filter )) )
869         {
870             return false;
871         }
872
873         // Sort out all the possible video inputs
874         // The class needs to be given the capture filters ANALOGVIDEO input pin
875         IEnumPins *pins = NULL;
876         if( ( mediaType.majortype == MEDIATYPE_Video ||
877               mediaType.majortype == MEDIATYPE_Stream ) &&
878             SUCCEEDED(p_filter->EnumPins(&pins)) )
879         {
880             IPin        *pP = NULL;
881             ULONG        n;
882             PIN_INFO     pinInfo;
883             BOOL         Found = FALSE;
884             IKsPropertySet *pKs = NULL;
885             GUID guid;
886             DWORD dw;
887
888             while( !Found && ( S_OK == pins->Next(1, &pP, &n) ) )
889             {
890                 if( S_OK == pP->QueryPinInfo(&pinInfo) )
891                 {
892                     // is this pin an ANALOGVIDEOIN input pin?
893                     if( pinInfo.dir == PINDIR_INPUT &&
894                         pP->QueryInterface( IID_IKsPropertySet,
895                                             (void **)&pKs ) == S_OK )
896                     {
897                         if( pKs->Get( AMPROPSETID_Pin,
898                                       AMPROPERTY_PIN_CATEGORY, NULL, 0,
899                                       &guid, sizeof(GUID), &dw ) == S_OK )
900                         {
901                             if( guid == PIN_CATEGORY_ANALOGVIDEOIN )
902                             {
903                                 // recursively search crossbar routes
904                                 FindCrossbarRoutes( p_this, p_sys, pP, 0 );
905                                 // found it
906                                 Found = TRUE;
907                             }
908                         }
909                         pKs->Release();
910                     }
911                     pinInfo.pFilter->Release();
912                 }
913                 pP->Release();
914             }
915             pins->Release();
916             msg_Dbg( p_this, "ConnectFilters: graph_builder2 available.") ;
917             if ( !Found )
918                 msg_Warn( p_this, "ConnectFilters: No crossBar routes found (incompatible pin types)" ) ;
919         }
920         return true;
921     }
922     else
923     {
924         IEnumPins *p_enumpins;
925         IPin *p_pin;
926
927         if( S_OK != p_filter->EnumPins( &p_enumpins ) ) return false;
928
929         while( S_OK == p_enumpins->Next( 1, &p_pin, NULL ) )
930         {
931             PIN_DIRECTION pin_dir;
932             p_pin->QueryDirection( &pin_dir );
933
934             if( pin_dir == PINDIR_OUTPUT &&
935                 p_sys->p_graph->ConnectDirect( p_pin, (IPin *)p_input_pin,
936                                                0 ) == S_OK )
937             {
938                 p_pin->Release();
939                 p_enumpins->Release();
940                 return true;
941             }
942             p_pin->Release();
943         }
944
945         p_enumpins->Release();
946         return false;
947     }
948 }
949
950 /*
951  * get fourcc priority from arbritary preference, the higher the better
952  */
953 static int GetFourCCPriority( int i_fourcc )
954 {
955     switch( i_fourcc )
956     {
957     case VLC_CODEC_I420:
958     case VLC_CODEC_FL32:
959         return 9;
960     case VLC_CODEC_YV12:
961     case VLC_FOURCC('a','r','a','w'):
962         return 8;
963     case VLC_CODEC_RGB24:
964         return 7;
965     case VLC_CODEC_YUYV:
966     case VLC_CODEC_RGB32:
967     case VLC_CODEC_RGBA:
968         return 6;
969     }
970
971     return 0;
972 }
973
974 #define MAX_MEDIA_TYPES 32
975
976 static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys,
977                        std::string devicename, bool b_audio )
978 {
979     /* See if device is already opened */
980     for( int i = 0; i < p_sys->i_streams; i++ )
981     {
982         if( devicename.size() &&
983             p_sys->pp_streams[i]->devicename == devicename )
984         {
985             /* Already opened */
986             return VLC_SUCCESS;
987         }
988     }
989
990     std::list<std::string> list_devices;
991
992     /* Enumerate devices and display their names */
993     FindCaptureDevice( p_this, NULL, &list_devices, b_audio );
994     if( list_devices.empty() )
995         return VLC_EGENERIC;
996
997     std::list<std::string>::iterator iter;
998     for( iter = list_devices.begin(); iter != list_devices.end(); ++iter )
999         msg_Dbg( p_this, "found device: %s", iter->c_str() );
1000
1001     /* If no device name was specified, pick the 1st one */
1002     if( devicename.size() == 0 )
1003     {
1004         /* When none selected */
1005         devicename = *list_devices.begin();
1006         msg_Dbg( p_this, "asking for default device: %s", devicename.c_str() ) ;
1007     }
1008     else
1009         msg_Dbg( p_this, "asking for device: %s", devicename.c_str() ) ;
1010     // Use the system device enumerator and class enumerator to find
1011     // a capture/preview device, such as a desktop USB video camera.
1012     IBaseFilter *p_device_filter =
1013         FindCaptureDevice( p_this, &devicename, NULL, b_audio );
1014
1015     if( p_device_filter )
1016         msg_Dbg( p_this, "using device: %s", devicename.c_str() );
1017     else
1018     {
1019         msg_Err( p_this, "can't use device: %s, unsupported device type",
1020                  devicename.c_str() );
1021         vlc_dialog_display_error( p_this, _("Capture failed"),
1022                         _("The device you selected cannot be used, because its "
1023                           "type is not supported.") );
1024         return VLC_EGENERIC;
1025     }
1026
1027     // Retreive acceptable media types supported by device
1028     AM_MEDIA_TYPE media_types[MAX_MEDIA_TYPES];
1029     size_t media_count =
1030         EnumDeviceCaps( p_this, p_device_filter, b_audio ? 0 : p_sys->i_chroma,
1031                         p_sys->i_width, p_sys->i_height,
1032       b_audio ? var_CreateGetInteger( p_this, CFG_PREFIX "audio-channels" ) : 0,
1033       b_audio ? var_CreateGetInteger( p_this, CFG_PREFIX "audio-samplerate" ) : 0,
1034       b_audio ? var_CreateGetInteger( p_this, CFG_PREFIX "audio-bitspersample" ) : 0,
1035       media_types, MAX_MEDIA_TYPES );
1036
1037     AM_MEDIA_TYPE *mt = NULL;
1038
1039     if( media_count > 0 )
1040     {
1041         mt = (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * media_count);
1042
1043         // Order and copy returned media types according to arbitrary
1044         // fourcc priority
1045         for( size_t c = 0; c < media_count; c++ )
1046         {
1047             int slot_priority =
1048                 GetFourCCPriority(GetFourCCFromMediaType(media_types[c]));
1049             size_t slot_copy = c;
1050             for( size_t d = c+1; d < media_count; d++ )
1051             {
1052                 int priority =
1053                     GetFourCCPriority(GetFourCCFromMediaType(media_types[d]));
1054                 if( priority > slot_priority )
1055                 {
1056                     slot_priority = priority;
1057                     slot_copy = d;
1058                 }
1059             }
1060             if( slot_copy != c )
1061             {
1062                 mt[c] = media_types[slot_copy];
1063                 media_types[slot_copy] = media_types[c];
1064             }
1065             else
1066             {
1067                 mt[c] = media_types[c];
1068             }
1069         }
1070     }
1071     else {
1072         /* capture device */
1073         msg_Err( p_this, "capture device '%s' does not support required parameters !", devicename.c_str() );
1074         vlc_dialog_display_error( p_this, _("Capture failed"),
1075                         _("The capture device \"%s\" does not support the "
1076                           "required parameters."), devicename.c_str() );
1077         p_device_filter->Release();
1078         return VLC_EGENERIC;
1079     }
1080
1081     /* Create and add our capture filter */
1082     CaptureFilter *p_capture_filter =
1083         new CaptureFilter( p_this, p_sys, mt, media_count );
1084     p_sys->p_graph->AddFilter( p_capture_filter, 0 );
1085
1086     /* Add the device filter to the graph (seems necessary with VfW before
1087      * accessing pin attributes). */
1088     p_sys->p_graph->AddFilter( p_device_filter, 0 );
1089
1090     /* Attempt to connect one of this device's capture output pins */
1091     msg_Dbg( p_this, "connecting filters" );
1092     if( ConnectFilters( p_this, p_sys, p_device_filter, p_capture_filter ) )
1093     {
1094         /* Success */
1095         msg_Dbg( p_this, "filters connected successfully !" );
1096
1097         dshow_stream_t dshow_stream;
1098         dshow_stream.b_pts = false;
1099         dshow_stream.p_es = 0;
1100         dshow_stream.mt =
1101             p_capture_filter->CustomGetPin()->CustomGetMediaType();
1102
1103         /* Show Device properties. Done here so the VLC stream is setup with
1104          * the proper parameters. */
1105         if( var_GetBool( p_this, CFG_PREFIX "config" ) )
1106         {
1107             ShowDeviceProperties( p_this, p_sys->p_capture_graph_builder2,
1108                                   p_device_filter, b_audio );
1109         }
1110
1111         ConfigTuner( p_this, p_sys->p_capture_graph_builder2,
1112                      p_device_filter );
1113
1114         if( var_GetBool( p_this, CFG_PREFIX "tuner" ) &&
1115             dshow_stream.mt.majortype != MEDIATYPE_Stream )
1116         {
1117             /* FIXME: we do MEDIATYPE_Stream later so we don't do it twice. */
1118             ShowTunerProperties( p_this, p_sys->p_capture_graph_builder2,
1119                                  p_device_filter, b_audio );
1120         }
1121
1122         dshow_stream.mt =
1123             p_capture_filter->CustomGetPin()->CustomGetMediaType();
1124
1125         dshow_stream.i_fourcc = GetFourCCFromMediaType( dshow_stream.mt );
1126         if( dshow_stream.i_fourcc )
1127         {
1128             if( dshow_stream.mt.majortype == MEDIATYPE_Video )
1129             {
1130                 dshow_stream.header.video =
1131                     *(VIDEOINFOHEADER *)dshow_stream.mt.pbFormat;
1132                 msg_Dbg( p_this, "MEDIATYPE_Video" );
1133                 msg_Dbg( p_this, "selected video pin accepts format: %4.4s",
1134                          (char *)&dshow_stream.i_fourcc);
1135             }
1136             else if( dshow_stream.mt.majortype == MEDIATYPE_Audio )
1137             {
1138                 dshow_stream.header.audio =
1139                     *(WAVEFORMATEX *)dshow_stream.mt.pbFormat;
1140                 msg_Dbg( p_this, "MEDIATYPE_Audio" );
1141                 msg_Dbg( p_this, "selected audio pin accepts format: %4.4s",
1142                          (char *)&dshow_stream.i_fourcc);
1143             }
1144             else if( dshow_stream.mt.majortype == MEDIATYPE_Stream )
1145             {
1146                 msg_Dbg( p_this, "MEDIATYPE_Stream" );
1147                 msg_Dbg( p_this, "selected stream pin accepts format: %4.4s",
1148                          (char *)&dshow_stream.i_fourcc);
1149             }
1150             else
1151             {
1152                 msg_Dbg( p_this, "unknown stream majortype" );
1153                 goto fail;
1154             }
1155
1156             /* Add directshow elementary stream to our list */
1157             dshow_stream.p_device_filter = p_device_filter;
1158             dshow_stream.p_capture_filter = p_capture_filter;
1159
1160             p_sys->pp_streams = (dshow_stream_t **)xrealloc( p_sys->pp_streams,
1161                           sizeof(dshow_stream_t *) * (p_sys->i_streams + 1) );
1162             p_sys->pp_streams[p_sys->i_streams] = new dshow_stream_t;
1163             *p_sys->pp_streams[p_sys->i_streams++] = dshow_stream;
1164
1165             return VLC_SUCCESS;
1166         }
1167     }
1168
1169  fail:
1170     /* Remove filters from graph */
1171     msg_Dbg( p_this, "OpenDevice: Removing filters" ) ;
1172     p_sys->p_graph->RemoveFilter( p_device_filter );
1173     p_sys->p_graph->RemoveFilter( p_capture_filter );
1174
1175     /* Release objects */
1176     /* RemoveFilter does an undocumented Release()
1177      * but does not set item to NULL*/
1178
1179     p_device_filter = NULL;
1180     p_capture_filter = NULL;
1181
1182     return VLC_EGENERIC;
1183 }
1184
1185 /* FindCaptureDevices:: This Function had two purposes :
1186     Returns the list of capture devices when p_listdevices != NULL
1187     Creates an IBaseFilter when p_devicename corresponds to an existing devname
1188    These actions *may* be requested whith a single call.
1189 */
1190 static IBaseFilter *
1191 FindCaptureDevice( vlc_object_t *p_this, std::string *p_devicename,
1192                    std::list<std::string> *p_listdevices, bool b_audio )
1193 {
1194     IBaseFilter *p_base_filter = NULL;
1195     IMoniker *p_moniker = NULL;
1196     ULONG i_fetched;
1197     HRESULT hr;
1198     std::list<std::string> devicelist;
1199
1200     /* Create the system device enumerator */
1201     ICreateDevEnum *p_dev_enum = NULL;
1202
1203     hr = CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
1204                            IID_ICreateDevEnum, (void **)&p_dev_enum );
1205     if( FAILED(hr) )
1206     {
1207         msg_Err( p_this, "failed to create the device enumerator (0x%lx)", hr);
1208         return NULL;
1209     }
1210
1211     /* Create an enumerator for the video capture devices */
1212     IEnumMoniker *p_class_enum = NULL;
1213     if( !b_audio )
1214         hr = p_dev_enum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory,
1215                                                 &p_class_enum, 0 );
1216     else
1217         hr = p_dev_enum->CreateClassEnumerator( CLSID_AudioInputDeviceCategory,
1218                                                 &p_class_enum, 0 );
1219     p_dev_enum->Release();
1220     if( FAILED(hr) )
1221     {
1222         msg_Err( p_this, "failed to create the class enumerator (0x%lx)", hr );
1223         return NULL;
1224     }
1225
1226     /* If there are no enumerators for the requested type, then
1227      * CreateClassEnumerator will succeed, but p_class_enum will be NULL */
1228     if( p_class_enum == NULL )
1229     {
1230         msg_Err( p_this, "no %s capture device was detected", ( b_audio ? "audio" : "video" ) );
1231         return NULL;
1232     }
1233
1234     /* Enumerate the devices */
1235
1236     /* Note that if the Next() call succeeds but there are no monikers,
1237      * it will return S_FALSE (which is not a failure). Therefore, we check
1238      * that the return code is S_OK instead of using SUCCEEDED() macro. */
1239
1240     while( p_class_enum->Next( 1, &p_moniker, &i_fetched ) == S_OK )
1241     {
1242         /* Getting the property page to get the device name */
1243         IPropertyBag *p_bag;
1244         hr = p_moniker->BindToStorage( 0, 0, IID_IPropertyBag,
1245                                        (void **)&p_bag );
1246         if( SUCCEEDED(hr) )
1247         {
1248             VARIANT var;
1249             var.vt = VT_BSTR;
1250             hr = p_bag->Read( L"FriendlyName", &var, NULL );
1251             p_bag->Release();
1252             if( SUCCEEDED(hr) )
1253             {
1254                 char *p_buf = FromWide( var.bstrVal );
1255                 std::string devname(p_buf);
1256                 free( p_buf) ;
1257
1258                 int dup = 0;
1259                 /* find out if this name is already used by a previously found device */
1260                 std::list<std::string>::const_iterator iter = devicelist.begin();
1261                 std::list<std::string>::const_iterator end = devicelist.end();
1262                 std::string ordevname = devname ;
1263                 while ( iter != end )
1264                 {
1265                     if( 0 == (*iter).compare( devname ) )
1266                     { /* devname is on the list. Try another name with sequence
1267                          number apended and then rescan until a unique entry is found*/
1268                          char seq[16];
1269                          snprintf(seq, 16, " #%d", ++dup);
1270                          devname = ordevname + seq;
1271                          iter = devicelist.begin();
1272                     }
1273                     else
1274                          ++iter;
1275                 }
1276                 devicelist.push_back( devname );
1277
1278                 if( p_devicename && *p_devicename == devname )
1279                 {
1280                     msg_Dbg( p_this, "asked for %s, binding to %s", p_devicename->c_str() , devname.c_str() ) ;
1281                     /* NULL possibly means we don't need BindMoniker BindCtx ?? */
1282                     hr = p_moniker->BindToObject( NULL, 0, IID_IBaseFilter,
1283                                                   (void **)&p_base_filter );
1284                     if( FAILED(hr) )
1285                     {
1286                         msg_Err( p_this, "couldn't bind moniker to filter "
1287                                  "object (0x%lx)", hr );
1288                         p_moniker->Release();
1289                         p_class_enum->Release();
1290                         return NULL;
1291                     }
1292                     p_moniker->Release();
1293                     p_class_enum->Release();
1294                     return p_base_filter;
1295                 }
1296             }
1297         }
1298
1299         p_moniker->Release();
1300     }
1301
1302     p_class_enum->Release();
1303
1304     if( p_listdevices ) {
1305         devicelist.sort();
1306         *p_listdevices = devicelist;
1307     }
1308     return NULL;
1309 }
1310
1311 static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
1312                               int i_fourcc, int i_width, int i_height,
1313                               int i_channels, int i_samplespersec,
1314                               int i_bitspersample, AM_MEDIA_TYPE *mt,
1315                               size_t mt_max )
1316 {
1317     IEnumPins *p_enumpins;
1318     IPin *p_output_pin;
1319     IEnumMediaTypes *p_enummt;
1320     size_t mt_count = 0;
1321
1322     LONGLONG i_AvgTimePerFrame = 0;
1323     float r_fps = var_GetFloat( p_this, CFG_PREFIX "fps" );
1324     if( r_fps )
1325         i_AvgTimePerFrame = 10000000000LL/(LONGLONG)(r_fps*1000.0f);
1326
1327     if( FAILED(p_filter->EnumPins( &p_enumpins )) )
1328     {
1329         msg_Dbg( p_this, "EnumDeviceCaps failed: no pin enumeration !");
1330         return 0;
1331     }
1332
1333     while( S_OK == p_enumpins->Next( 1, &p_output_pin, NULL ) )
1334     {
1335         PIN_INFO info;
1336
1337         if( S_OK == p_output_pin->QueryPinInfo( &info ) )
1338         {
1339             msg_Dbg( p_this, "EnumDeviceCaps: %s pin: %S",
1340                      info.dir == PINDIR_INPUT ? "input" : "output",
1341                      info.achName );
1342             if( info.pFilter ) info.pFilter->Release();
1343         }
1344
1345         p_output_pin->Release();
1346     }
1347
1348     p_enumpins->Reset();
1349
1350     while( !mt_count && p_enumpins->Next( 1, &p_output_pin, NULL ) == S_OK )
1351     {
1352         PIN_INFO info;
1353
1354         if( S_OK == p_output_pin->QueryPinInfo( &info ) )
1355         {
1356             if( info.pFilter ) info.pFilter->Release();
1357             if( info.dir == PINDIR_INPUT )
1358             {
1359                 p_output_pin->Release();
1360                 continue;
1361             }
1362             msg_Dbg( p_this, "EnumDeviceCaps: trying pin %S", info.achName );
1363         }
1364
1365         AM_MEDIA_TYPE *p_mt;
1366
1367         /*
1368         ** Configure pin with a default compatible media if possible
1369         */
1370
1371         IAMStreamConfig *pSC;
1372         if( SUCCEEDED(p_output_pin->QueryInterface( IID_IAMStreamConfig,
1373                                             (void **)&pSC )) )
1374         {
1375             int piCount, piSize;
1376             if( SUCCEEDED(pSC->GetNumberOfCapabilities(&piCount, &piSize)) )
1377             {
1378                 BYTE *pSCC= (BYTE *)CoTaskMemAlloc(piSize);
1379                 if( NULL != pSCC )
1380                 {
1381                     int i_priority = ES_PRIORITY_NOT_DEFAULTABLE;
1382                     for( int i=0; i<piCount; ++i )
1383                     {
1384                         if( SUCCEEDED(pSC->GetStreamCaps(i, &p_mt, pSCC)) )
1385                         {
1386                             int i_current_fourcc = GetFourCCFromMediaType( *p_mt );
1387                             int i_current_priority = GetFourCCPriority(i_current_fourcc);
1388
1389                             if( (i_fourcc && (i_current_fourcc != i_fourcc))
1390                              || (i_priority > i_current_priority) )
1391                             {
1392                                 // unwanted chroma, try next media type
1393                                 FreeMediaType( *p_mt );
1394                                 CoTaskMemFree( (PVOID)p_mt );
1395                                 continue;
1396                             }
1397
1398                             if( MEDIATYPE_Video == p_mt->majortype
1399                                     && FORMAT_VideoInfo == p_mt->formattype )
1400                             {
1401                                 VIDEO_STREAM_CONFIG_CAPS *pVSCC = reinterpret_cast<VIDEO_STREAM_CONFIG_CAPS*>(pSCC);
1402                                 VIDEOINFOHEADER *pVih = reinterpret_cast<VIDEOINFOHEADER*>(p_mt->pbFormat);
1403
1404                                 if( i_AvgTimePerFrame )
1405                                 {
1406                                     if( pVSCC->MinFrameInterval > i_AvgTimePerFrame
1407                                       || i_AvgTimePerFrame > pVSCC->MaxFrameInterval )
1408                                     {
1409                                         // required frame rate not compatible, try next media type
1410                                         FreeMediaType( *p_mt );
1411                                         CoTaskMemFree( (PVOID)p_mt );
1412                                         continue;
1413                                     }
1414                                     pVih->AvgTimePerFrame = i_AvgTimePerFrame;
1415                                 }
1416
1417                                 if( i_width )
1418                                 {
1419                                     if((   !pVSCC->OutputGranularityX
1420                                            && i_width != pVSCC->MinOutputSize.cx
1421                                            && i_width != pVSCC->MaxOutputSize.cx)
1422                                        ||
1423                                        (   pVSCC->OutputGranularityX
1424                                            && ((i_width % pVSCC->OutputGranularityX)
1425                                                || pVSCC->MinOutputSize.cx > i_width
1426                                                || i_width > pVSCC->MaxOutputSize.cx )))
1427                                     {
1428                                         // required width not compatible, try next media type
1429                                         FreeMediaType( *p_mt );
1430                                         CoTaskMemFree( (PVOID)p_mt );
1431                                         continue;
1432                                     }
1433                                     pVih->bmiHeader.biWidth = i_width;
1434                                 }
1435
1436                                 if( i_height )
1437                                 {
1438                                     if((   !pVSCC->OutputGranularityY
1439                                            && i_height != pVSCC->MinOutputSize.cy
1440                                            && i_height != pVSCC->MaxOutputSize.cy)
1441                                        ||
1442                                        (   pVSCC->OutputGranularityY
1443                                            && ((i_height % pVSCC->OutputGranularityY)
1444                                                || pVSCC->MinOutputSize.cy > i_height
1445                                                || i_height > pVSCC->MaxOutputSize.cy )))
1446                                     {
1447                                         // required height not compatible, try next media type
1448                                         FreeMediaType( *p_mt );
1449                                         CoTaskMemFree( (PVOID)p_mt );
1450                                         continue;
1451                                     }
1452                                     pVih->bmiHeader.biHeight = i_height;
1453                                 }
1454
1455                                 // Set the sample size and image size.
1456                                 // (Round the image width up to a DWORD boundary.)
1457                                 p_mt->lSampleSize = pVih->bmiHeader.biSizeImage =
1458                                     ((pVih->bmiHeader.biWidth + 3) & ~3) *
1459                                     pVih->bmiHeader.biHeight * (pVih->bmiHeader.biBitCount>>3);
1460
1461                                 // no cropping, use full video input buffer
1462                                 memset(&(pVih->rcSource), 0, sizeof(RECT));
1463                                 memset(&(pVih->rcTarget), 0, sizeof(RECT));
1464
1465                                 // select this format as default
1466                                 if( SUCCEEDED( pSC->SetFormat(p_mt) ) )
1467                                 {
1468                                     i_priority = i_current_priority;
1469                                     if( i_fourcc )
1470                                         // no need to check any more media types
1471                                         i = piCount;
1472                                 }
1473                             }
1474                             else if( p_mt->majortype == MEDIATYPE_Audio
1475                                     && p_mt->formattype == FORMAT_WaveFormatEx )
1476                             {
1477                                 AUDIO_STREAM_CONFIG_CAPS *pASCC = reinterpret_cast<AUDIO_STREAM_CONFIG_CAPS*>(pSCC);
1478                                 WAVEFORMATEX *pWfx = reinterpret_cast<WAVEFORMATEX*>(p_mt->pbFormat);
1479
1480                                 if( i_current_fourcc && (WAVE_FORMAT_PCM == pWfx->wFormatTag) )
1481                                 {
1482                                     int val = i_channels;
1483                                     if( ! val )
1484                                         val = 2;
1485
1486                                     if( (   !pASCC->ChannelsGranularity
1487                                             && (unsigned int)val != pASCC->MinimumChannels
1488                                             && (unsigned int)val != pASCC->MaximumChannels)
1489                                         ||
1490                                         (   pASCC->ChannelsGranularity
1491                                             && ((val % pASCC->ChannelsGranularity)
1492                                                 || (unsigned int)val < pASCC->MinimumChannels
1493                                                 || (unsigned int)val > pASCC->MaximumChannels)))
1494                                     {
1495                                         // required number channels not available, try next media type
1496                                         FreeMediaType( *p_mt );
1497                                         CoTaskMemFree( (PVOID)p_mt );
1498                                         continue;
1499                                     }
1500                                     pWfx->nChannels = val;
1501
1502                                     val = i_samplespersec;
1503                                     if( ! val )
1504                                         val = 44100;
1505
1506                                     if( (   !pASCC->SampleFrequencyGranularity
1507                                             && (unsigned int)val != pASCC->MinimumSampleFrequency
1508                                             && (unsigned int)val != pASCC->MaximumSampleFrequency)
1509                                         ||
1510                                         (   pASCC->SampleFrequencyGranularity
1511                                             && ((val % pASCC->SampleFrequencyGranularity)
1512                                                 || (unsigned int)val < pASCC->MinimumSampleFrequency
1513                                                 || (unsigned int)val > pASCC->MaximumSampleFrequency )))
1514                                     {
1515                                         // required sampling rate not available, try next media type
1516                                         FreeMediaType( *p_mt );
1517                                         CoTaskMemFree( (PVOID)p_mt );
1518                                         continue;
1519                                     }
1520                                     pWfx->nSamplesPerSec = val;
1521
1522                                     val = i_bitspersample;
1523                                     if( ! val )
1524                                     {
1525                                         if( VLC_CODEC_FL32 == i_current_fourcc )
1526                                             val = 32;
1527                                         else
1528                                             val = 16;
1529                                     }
1530
1531                                     if( (   !pASCC->BitsPerSampleGranularity
1532                                             && (unsigned int)val != pASCC->MinimumBitsPerSample
1533                                             && (unsigned int)val != pASCC->MaximumBitsPerSample )
1534                                         ||
1535                                         (   pASCC->BitsPerSampleGranularity
1536                                             && ((val % pASCC->BitsPerSampleGranularity)
1537                                                 || (unsigned int)val < pASCC->MinimumBitsPerSample
1538                                                 || (unsigned int)val > pASCC->MaximumBitsPerSample )))
1539                                     {
1540                                         // required sample size not available, try next media type
1541                                         FreeMediaType( *p_mt );
1542                                         CoTaskMemFree( (PVOID)p_mt );
1543                                         continue;
1544                                     }
1545
1546                                     pWfx->wBitsPerSample = val;
1547                                     pWfx->nBlockAlign = (pWfx->wBitsPerSample * pWfx->nChannels)/8;
1548                                     pWfx->nAvgBytesPerSec = pWfx->nSamplesPerSec * pWfx->nBlockAlign;
1549
1550                                     // select this format as default
1551                                     if( SUCCEEDED( pSC->SetFormat(p_mt) ) )
1552                                     {
1553                                         i_priority = i_current_priority;
1554                                     }
1555                                 }
1556                             }
1557                             FreeMediaType( *p_mt );
1558                             CoTaskMemFree( (PVOID)p_mt );
1559                         }
1560                     }
1561                     CoTaskMemFree( (LPVOID)pSCC );
1562                     if( i_priority >= ES_PRIORITY_SELECTABLE_MIN )
1563                         msg_Dbg( p_this, "EnumDeviceCaps: input pin default format configured");
1564                 }
1565             }
1566             pSC->Release();
1567         }
1568
1569         /*
1570         ** Probe pin for available medias (may be a previously configured one)
1571         */
1572
1573         if( FAILED( p_output_pin->EnumMediaTypes( &p_enummt ) ) )
1574         {
1575             p_output_pin->Release();
1576             continue;
1577         }
1578
1579         while( p_enummt->Next( 1, &p_mt, NULL ) == S_OK )
1580         {
1581             int i_current_fourcc = GetFourCCFromMediaType( *p_mt );
1582             if( i_current_fourcc && p_mt->majortype == MEDIATYPE_Video
1583                 && p_mt->formattype == FORMAT_VideoInfo )
1584             {
1585                 int i_current_width = ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biWidth;
1586                 int i_current_height = ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biHeight;
1587                 LONGLONG i_current_atpf = ((VIDEOINFOHEADER *)p_mt->pbFormat)->AvgTimePerFrame;
1588
1589                 if( i_current_height < 0 )
1590                     i_current_height = -i_current_height;
1591
1592                 msg_Dbg( p_this, "EnumDeviceCaps: input pin "
1593                          "accepts chroma: %4.4s, width:%i, height:%i, fps:%f",
1594                          (char *)&i_current_fourcc, i_current_width,
1595                          i_current_height, (10000000.0f/((float)i_current_atpf)) );
1596
1597                 if( ( !i_fourcc || i_fourcc == i_current_fourcc ) &&
1598                     ( !i_width || i_width == i_current_width ) &&
1599                     ( !i_height || i_height == i_current_height ) &&
1600                     ( !i_AvgTimePerFrame || i_AvgTimePerFrame == i_current_atpf ) &&
1601                     mt_count < mt_max )
1602                 {
1603                     /* Pick match */
1604                     mt[mt_count++] = *p_mt;
1605                 }
1606                 else FreeMediaType( *p_mt );
1607             }
1608             else if( i_current_fourcc && p_mt->majortype == MEDIATYPE_Audio
1609                     && p_mt->formattype == FORMAT_WaveFormatEx)
1610             {
1611                 int i_current_channels =
1612                     ((WAVEFORMATEX *)p_mt->pbFormat)->nChannels;
1613                 int i_current_samplespersec =
1614                     ((WAVEFORMATEX *)p_mt->pbFormat)->nSamplesPerSec;
1615                 int i_current_bitspersample =
1616                     ((WAVEFORMATEX *)p_mt->pbFormat)->wBitsPerSample;
1617
1618                 msg_Dbg( p_this, "EnumDeviceCaps: input pin "
1619                          "accepts format: %4.4s, channels:%i, "
1620                          "samples/sec:%i bits/sample:%i",
1621                          (char *)&i_current_fourcc, i_current_channels,
1622                          i_current_samplespersec, i_current_bitspersample);
1623
1624                 if( (!i_channels || i_channels == i_current_channels) &&
1625                     (!i_samplespersec ||
1626                      i_samplespersec == i_current_samplespersec) &&
1627                     (!i_bitspersample ||
1628                      i_bitspersample == i_current_bitspersample) &&
1629                     mt_count < mt_max )
1630                 {
1631                     /* Pick  match */
1632                     mt[mt_count++] = *p_mt;
1633
1634                     /* Setup a few properties like the audio latency */
1635                     IAMBufferNegotiation *p_ambuf;
1636                     if( SUCCEEDED( p_output_pin->QueryInterface(
1637                           IID_IAMBufferNegotiation, (void **)&p_ambuf ) ) )
1638                     {
1639                         ALLOCATOR_PROPERTIES AllocProp;
1640                         AllocProp.cbAlign = -1;
1641
1642                         /* 100 ms of latency */
1643                         AllocProp.cbBuffer = i_current_channels *
1644                           i_current_samplespersec *
1645                           i_current_bitspersample / 8 / 10;
1646
1647                         AllocProp.cbPrefix = -1;
1648                         AllocProp.cBuffers = -1;
1649                         p_ambuf->SuggestAllocatorProperties( &AllocProp );
1650                         p_ambuf->Release();
1651                     }
1652                 }
1653                 else FreeMediaType( *p_mt );
1654             }
1655             else if( i_current_fourcc && p_mt->majortype == MEDIATYPE_Stream )
1656             {
1657                 msg_Dbg( p_this, "EnumDeviceCaps: input pin "
1658                          "accepts stream format: %4.4s",
1659                          (char *)&i_current_fourcc );
1660
1661                 if( ( !i_fourcc || i_fourcc == i_current_fourcc ) &&
1662                     mt_count < mt_max )
1663                 {
1664                     /* Pick match */
1665                     mt[mt_count++] = *p_mt;
1666                     i_fourcc = i_current_fourcc;
1667                 }
1668                 else FreeMediaType( *p_mt );
1669             }
1670             else
1671             {
1672                 const char * psz_type = "unknown";
1673                 if( p_mt->majortype == MEDIATYPE_Video ) psz_type = "video";
1674                 if( p_mt->majortype == MEDIATYPE_Audio ) psz_type = "audio";
1675                 if( p_mt->majortype == MEDIATYPE_Stream ) psz_type = "stream";
1676                 msg_Dbg( p_this, "EnumDeviceCaps: input pin media: unsupported format "
1677                          "(%s %4.4s)", psz_type, (char *)&p_mt->subtype );
1678
1679                 FreeMediaType( *p_mt );
1680             }
1681             CoTaskMemFree( (PVOID)p_mt );
1682         }
1683
1684         if( !mt_count && p_enummt->Reset() == S_OK )
1685         {
1686             // VLC did not find any supported MEDIATYPE for this output pin.
1687             // However the graph builder might insert converter filters in
1688             // the graph if we use a different codec in VLC filter input pin.
1689             // however, in order to avoid nasty surprises, make use of this
1690             // facility only for known unsupported codecs.
1691
1692             while( !mt_count && p_enummt->Next( 1, &p_mt, NULL ) == S_OK )
1693             {
1694                 // the first four bytes of subtype GUID contains the codec FOURCC
1695                 const char *pfcc = (char *)&p_mt->subtype;
1696                 int i_current_fourcc = VLC_FOURCC(pfcc[0], pfcc[1], pfcc[2], pfcc[3]);
1697                 if( VLC_FOURCC('H','C','W','2') == i_current_fourcc
1698                  && p_mt->majortype == MEDIATYPE_Video )
1699                 {
1700                     // output format for 'Hauppauge WinTV PVR PCI II Capture'
1701                     // try I420 as an input format
1702                     i_current_fourcc = VLC_CODEC_I420;
1703                     if( !i_fourcc || i_fourcc == i_current_fourcc )
1704                     {
1705                         // return alternative media type
1706                         AM_MEDIA_TYPE mtr;
1707                         VIDEOINFOHEADER vh;
1708
1709                         mtr.majortype            = MEDIATYPE_Video;
1710                         mtr.subtype              = MEDIASUBTYPE_I420;
1711                         mtr.bFixedSizeSamples    = TRUE;
1712                         mtr.bTemporalCompression = FALSE;
1713                         mtr.pUnk                 = NULL;
1714                         mtr.formattype           = FORMAT_VideoInfo;
1715                         mtr.cbFormat             = sizeof(vh);
1716                         mtr.pbFormat             = (BYTE *)&vh;
1717
1718                         memset(&vh, 0, sizeof(vh));
1719
1720                         vh.bmiHeader.biSize   = sizeof(vh.bmiHeader);
1721                         vh.bmiHeader.biWidth  = i_width > 0 ? i_width :
1722                             ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biWidth;
1723                         vh.bmiHeader.biHeight = i_height > 0 ? i_height :
1724                             ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biHeight;
1725                         vh.bmiHeader.biPlanes      = 3;
1726                         vh.bmiHeader.biBitCount    = 12;
1727                         vh.bmiHeader.biCompression = VLC_CODEC_I420;
1728                         vh.bmiHeader.biSizeImage   = vh.bmiHeader.biWidth * 12 *
1729                             vh.bmiHeader.biHeight / 8;
1730                         mtr.lSampleSize            = vh.bmiHeader.biSizeImage;
1731
1732                         msg_Dbg( p_this, "EnumDeviceCaps: input pin media: using 'I420' in place of unsupported format 'HCW2'");
1733
1734                         if( SUCCEEDED(CopyMediaType(mt+mt_count, &mtr)) )
1735                             ++mt_count;
1736                     }
1737                 }
1738                 FreeMediaType( *p_mt );
1739             }
1740         }
1741
1742         p_enummt->Release();
1743         p_output_pin->Release();
1744     }
1745
1746     p_enumpins->Release();
1747     return mt_count;
1748 }
1749
1750 /*****************************************************************************
1751  * ReadCompressed: reads compressed (MPEG/DV) data from the device.
1752  *****************************************************************************
1753  * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
1754  * bytes.
1755  *****************************************************************************/
1756 static block_t *ReadCompressed( access_t *p_access )
1757 {
1758     access_sys_t   *p_sys = p_access->p_sys;
1759     /* There must be only 1 elementary stream to produce a valid stream
1760      * of MPEG or DV data */
1761     dshow_stream_t *p_stream = p_sys->pp_streams[0];
1762     VLCMediaSample sample;
1763
1764     /* Read 1 DV/MPEG frame (they contain the video and audio data) */
1765
1766     /* Get new sample/frame from the elementary stream (blocking). */
1767     vlc_mutex_lock( &p_sys->lock );
1768
1769     CaptureFilter *p_filter = p_stream->p_capture_filter;
1770
1771     if( p_filter->CustomGetPin()->CustomGetSample(&sample) != S_OK )
1772     {   /* No data available. Wait until some data has arrived */
1773         vlc_cond_wait( &p_sys->wait, &p_sys->lock );
1774         vlc_mutex_unlock( &p_sys->lock );
1775         return NULL;
1776     }
1777     vlc_mutex_unlock( &p_sys->lock );
1778
1779     /*
1780      * We got our sample
1781      */
1782     block_t *p_block = NULL;
1783     uint8_t *p_data;
1784     int i_data_size = sample.p_sample->GetActualDataLength();
1785     if( i_data_size == 0 )
1786         goto out;
1787
1788     p_block = block_Alloc( i_data_size );
1789     if( unlikely(p_block == NULL) )
1790         goto out;
1791
1792     sample.p_sample->GetPointer( &p_data );
1793     memcpy( p_block->p_buffer, p_data, i_data_size );
1794     /* The caller got what he wanted */
1795 out:
1796     sample.p_sample->Release();
1797     return p_block;
1798 }
1799
1800 /****************************************************************************
1801  * Demux:
1802  ****************************************************************************/
1803 static int Demux( demux_t *p_demux )
1804 {
1805     access_sys_t *p_sys = (access_sys_t *)p_demux->p_sys;
1806     int i_found_samples;
1807
1808     i_found_samples = 0;
1809     vlc_mutex_lock( &p_sys->lock );
1810
1811     while ( !i_found_samples )
1812     {
1813         /* Try to grab samples from all streams */
1814         for( int i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
1815         {
1816             dshow_stream_t *p_stream = p_sys->pp_streams[i_stream];
1817             if( p_stream->p_capture_filter &&
1818                 p_stream->p_capture_filter->CustomGetPin()
1819                 ->CustomGetSamples( p_stream->samples_queue ) == S_OK )
1820             {
1821                 i_found_samples = 1;
1822             }
1823         }
1824
1825         if ( !i_found_samples)
1826         {
1827             /* Didn't find any audio nor video sample, just wait till the
1828              * dshow thread pushes some samples */
1829             vlc_cond_wait( &p_sys->wait, &p_sys->lock );
1830             /* Some DShow thread pushed data, or the OS broke the wait all
1831              * by itself. In all cases, it's *strongly* advised to test the
1832              * condition again, so let the loop do the test again */
1833         }
1834     }
1835
1836     vlc_mutex_unlock( &p_sys->lock );
1837
1838     for ( int i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
1839     {
1840         int i_samples;
1841         dshow_stream_t *p_stream = p_sys->pp_streams[i_stream];
1842
1843         i_samples = p_stream->samples_queue.size();
1844         while ( i_samples > 0 )
1845         {
1846             int i_data_size;
1847             uint8_t *p_data;
1848             block_t *p_block;
1849             VLCMediaSample sample;
1850
1851             sample = p_stream->samples_queue.front();
1852             p_stream->samples_queue.pop_front();
1853
1854             i_data_size = sample.p_sample->GetActualDataLength();
1855             sample.p_sample->GetPointer( &p_data );
1856
1857             REFERENCE_TIME i_pts, i_end_date;
1858             HRESULT hr = sample.p_sample->GetTime( &i_pts, &i_end_date );
1859             if( hr != S_OK && hr != VFW_S_NO_STOP_TIME )
1860             {
1861                 if( p_stream->mt.majortype == MEDIATYPE_Video || !p_stream->b_pts )
1862                 {
1863                     /* Use our data timestamp */
1864                     i_pts = sample.i_timestamp;
1865                     p_stream->b_pts = true;
1866                 }
1867                 else
1868                     i_pts = VLC_TS_INVALID;
1869             }
1870
1871             if( i_pts > VLC_TS_INVALID ) {
1872                 i_pts += (i_pts >= 0) ? +5 : -4;
1873                 i_pts /= 10; /* 100-ns to ┬Ás conversion */
1874                 i_pts += VLC_TS_0;
1875             }
1876 #if 0
1877             msg_Dbg( p_demux, "Read() stream: %i, size: %i, PTS: %" PRId64,
1878                      i_stream, i_data_size, i_pts );
1879 #endif
1880
1881             p_block = block_Alloc( i_data_size );
1882             memcpy( p_block->p_buffer, p_data, i_data_size );
1883             p_block->i_pts = p_block->i_dts = i_pts;
1884             sample.p_sample->Release();
1885
1886             if( i_pts > VLC_TS_INVALID )
1887                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_pts );
1888             es_out_Send( p_demux->out, p_stream->p_es, p_block );
1889
1890             i_samples--;
1891         }
1892     }
1893
1894     return 1;
1895 }
1896
1897 /*****************************************************************************
1898  * AccessControl:
1899  *****************************************************************************/
1900 static int AccessControl( access_t *p_access, int i_query, va_list args )
1901 {
1902     bool    *pb_bool;
1903     int64_t *pi_64;
1904
1905     switch( i_query )
1906     {
1907     case ACCESS_CAN_SEEK:
1908     case ACCESS_CAN_FASTSEEK:
1909     case ACCESS_CAN_PAUSE:
1910     case ACCESS_CAN_CONTROL_PACE:
1911         pb_bool = (bool*)va_arg( args, bool* );
1912         *pb_bool = false;
1913         break;
1914
1915     case ACCESS_GET_PTS_DELAY:
1916         pi_64 = (int64_t*)va_arg( args, int64_t * );
1917         *pi_64 =
1918             INT64_C(1000) * var_InheritInteger( p_access, "live-caching" );
1919         break;
1920
1921     case ACCESS_GET_CONTENT_TYPE:
1922     {
1923         dshow_stream_t *p_stream = p_access->p_sys->pp_streams[0];
1924         char **type = va_arg( args, char ** );
1925
1926         /* Check if we need to force demuxers */
1927         if( p_stream->i_fourcc == VLC_CODEC_DV )
1928             *type = strdup( "video/dv" );
1929         else if( p_stream->i_fourcc == VLC_CODEC_MPGV )
1930             *type = strdup( "video/MP2P" );
1931         else
1932             return VLC_EGENERIC;
1933         break;
1934     }
1935
1936     default:
1937         return VLC_EGENERIC;
1938     }
1939
1940     return VLC_SUCCESS;
1941 }
1942
1943 /****************************************************************************
1944  * DemuxControl:
1945  ****************************************************************************/
1946 static int DemuxControl( demux_t *p_demux, int i_query, va_list args )
1947 {
1948     bool    *pb;
1949     int64_t *pi64;
1950
1951     switch( i_query )
1952     {
1953     /* Special for access_demux */
1954     case DEMUX_CAN_PAUSE:
1955     case DEMUX_CAN_SEEK:
1956     case DEMUX_SET_PAUSE_STATE:
1957     case DEMUX_CAN_CONTROL_PACE:
1958         pb = (bool*)va_arg( args, bool * );
1959         *pb = false;
1960         return VLC_SUCCESS;
1961
1962     case DEMUX_GET_PTS_DELAY:
1963         pi64 = (int64_t*)va_arg( args, int64_t * );
1964         *pi64 =
1965             INT64_C(1000) * var_InheritInteger( p_demux, "live-caching" );
1966         return VLC_SUCCESS;
1967
1968     case DEMUX_GET_TIME:
1969         pi64 = (int64_t*)va_arg( args, int64_t * );
1970         *pi64 = mdate();
1971         return VLC_SUCCESS;
1972
1973     /* TODO implement others */
1974     default:
1975         return VLC_EGENERIC;
1976     }
1977
1978     return VLC_EGENERIC;
1979 }
1980
1981 /*****************************************************************************
1982  * config variable callback
1983  *****************************************************************************/
1984 static int FindDevices( vlc_object_t *p_this, const char *psz_name,
1985                             char ***vp, char ***tp )
1986 {
1987     /* Find list of devices */
1988     std::list<std::string> list_devices;
1989     if( SUCCEEDED(CoInitializeEx( NULL, COINIT_MULTITHREADED ))
1990      || SUCCEEDED(CoInitializeEx( NULL, COINIT_APARTMENTTHREADED )) )
1991     {
1992         bool b_audio = !strcmp( psz_name, CFG_PREFIX "adev" );
1993
1994         FindCaptureDevice( p_this, NULL, &list_devices, b_audio );
1995         CoUninitialize();
1996     }
1997
1998     unsigned count = 2 + list_devices.size(), i = 2;
1999     char **values = (char **)xmalloc( count * sizeof(*values) );
2000     char **texts = (char **)xmalloc( count * sizeof(*texts) );
2001
2002     values[0] = strdup( "" );
2003     texts[0] = strdup( N_("Default") );
2004     values[1] = strdup( "none" );
2005     texts[1] = strdup( N_("None") );
2006
2007     for( std::list<std::string>::iterator iter = list_devices.begin();
2008          iter != list_devices.end();
2009          ++iter )
2010     {
2011         assert( i < count );
2012         values[i] = strdup( iter->c_str() );
2013         texts[i] = strdup( iter->c_str() );
2014         i++;
2015     }
2016
2017     *vp = values;
2018     *tp = texts;
2019     return count;
2020 }
2021
2022 /*****************************************************************************
2023  * Properties
2024  *****************************************************************************/
2025
2026 static void ShowPropertyPage( IUnknown *obj )
2027 {
2028     ISpecifyPropertyPages *p_spec;
2029     CAUUID cauuid;
2030
2031     HRESULT hr = obj->QueryInterface( IID_ISpecifyPropertyPages,
2032                                       (void **)&p_spec );
2033     if( FAILED(hr) ) return;
2034
2035     if( SUCCEEDED(p_spec->GetPages( &cauuid )) )
2036     {
2037         if( cauuid.cElems > 0 )
2038         {
2039             HWND hwnd_desktop = ::GetDesktopWindow();
2040
2041             OleCreatePropertyFrame( hwnd_desktop, 30, 30, NULL, 1, &obj,
2042                                     cauuid.cElems, cauuid.pElems, 0, 0, NULL );
2043
2044             CoTaskMemFree( cauuid.pElems );
2045         }
2046         p_spec->Release();
2047     }
2048 }
2049
2050 static void ShowDeviceProperties( vlc_object_t *p_this,
2051                                   ICaptureGraphBuilder2 *p_graph,
2052                                   IBaseFilter *p_device_filter,
2053                                   bool b_audio )
2054 {
2055     HRESULT hr;
2056     msg_Dbg( p_this, "configuring Device Properties" );
2057
2058     /*
2059      * Video or audio capture filter page
2060      */
2061     ShowPropertyPage( p_device_filter );
2062
2063     /*
2064      * Audio capture pin
2065      */
2066     if( p_graph && b_audio )
2067     {
2068         IAMStreamConfig *p_SC;
2069
2070         msg_Dbg( p_this, "showing WDM Audio Configuration Pages" );
2071
2072         hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE,
2073                                      &MEDIATYPE_Audio, p_device_filter,
2074                                      IID_IAMStreamConfig, (void **)&p_SC );
2075         if( SUCCEEDED(hr) )
2076         {
2077             ShowPropertyPage(p_SC);
2078             p_SC->Release();
2079         }
2080
2081         /*
2082          * TV Audio filter
2083          */
2084         IAMTVAudio *p_TVA;
2085         HRESULT hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE,
2086                                              &MEDIATYPE_Audio, p_device_filter,
2087                                              IID_IAMTVAudio, (void **)&p_TVA );
2088         if( SUCCEEDED(hr) )
2089         {
2090             ShowPropertyPage(p_TVA);
2091             p_TVA->Release();
2092         }
2093     }
2094
2095     /*
2096      * Video capture pin
2097      */
2098     if( p_graph && !b_audio )
2099     {
2100         IAMStreamConfig *p_SC;
2101
2102         msg_Dbg( p_this, "showing WDM Video Configuration Pages" );
2103
2104         hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE,
2105                                      &MEDIATYPE_Interleaved, p_device_filter,
2106                                      IID_IAMStreamConfig, (void **)&p_SC );
2107         if( FAILED(hr) )
2108         {
2109             hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE,
2110                                          &MEDIATYPE_Video, p_device_filter,
2111                                          IID_IAMStreamConfig, (void **)&p_SC );
2112         }
2113
2114         if( FAILED(hr) )
2115         {
2116             hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE,
2117                                          &MEDIATYPE_Stream, p_device_filter,
2118                                          IID_IAMStreamConfig, (void **)&p_SC );
2119         }
2120
2121         if( SUCCEEDED(hr) )
2122         {
2123             ShowPropertyPage(p_SC);
2124             p_SC->Release();
2125         }
2126     }
2127 }
2128
2129 static void ShowTunerProperties( vlc_object_t *p_this,
2130                                  ICaptureGraphBuilder2 *p_graph,
2131                                  IBaseFilter *p_device_filter,
2132                                  bool b_audio )
2133 {
2134     HRESULT hr;
2135     msg_Dbg( p_this, "configuring Tuner Properties" );
2136
2137     if( !p_graph || b_audio ) return;
2138
2139     IAMTVTuner *p_TV;
2140     hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE,
2141                                  &MEDIATYPE_Interleaved, p_device_filter,
2142                                  IID_IAMTVTuner, (void **)&p_TV );
2143     if( FAILED(hr) )
2144     {
2145         hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE,
2146                                      &MEDIATYPE_Video, p_device_filter,
2147                                      IID_IAMTVTuner, (void **)&p_TV );
2148     }
2149
2150     if( FAILED(hr) )
2151     {
2152         hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE,
2153                                      &MEDIATYPE_Stream, p_device_filter,
2154                                      IID_IAMTVTuner, (void **)&p_TV );
2155     }
2156
2157     if( SUCCEEDED(hr) )
2158     {
2159         ShowPropertyPage(p_TV);
2160         p_TV->Release();
2161     }
2162 }
2163
2164 static void ConfigTuner( vlc_object_t *p_this, ICaptureGraphBuilder2 *p_graph,
2165                          IBaseFilter *p_device_filter )
2166 {
2167     int i_channel, i_country, i_input, i_amtuner_mode, i_standard;
2168     long l_modes = 0;
2169     unsigned i_frequency;
2170     IAMTVTuner *p_TV;
2171     HRESULT hr;
2172
2173     if( !p_graph ) return;
2174
2175     i_channel =      var_GetInteger( p_this, CFG_PREFIX "tuner-channel" );
2176     i_country =      var_GetInteger( p_this, CFG_PREFIX "tuner-country" );
2177     i_input =        var_GetInteger( p_this, CFG_PREFIX "tuner-input" );
2178     i_amtuner_mode = var_GetInteger( p_this, CFG_PREFIX "amtuner-mode" );
2179     i_frequency =    var_GetInteger( p_this, CFG_PREFIX "tuner-frequency" );
2180     i_standard =     var_GetInteger( p_this, CFG_PREFIX "tuner-standard" );
2181
2182     if( !i_channel && !i_frequency && !i_country && !i_input ) return; /* Nothing to do */
2183
2184     msg_Dbg( p_this, "tuner config: channel %i, frequency %i, country %i, input type %i, standard %s",
2185              i_channel, i_frequency, i_country, i_input, ppsz_standards_list_text[i_standard] );
2186
2187
2188     hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved,
2189                                  p_device_filter, IID_IAMTVTuner,
2190                                  (void **)&p_TV );
2191     if( FAILED(hr) )
2192     {
2193         hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
2194                                      p_device_filter, IID_IAMTVTuner,
2195                                      (void **)&p_TV );
2196     }
2197
2198     if( FAILED(hr) )
2199     {
2200         hr = p_graph->FindInterface( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Stream,
2201                                      p_device_filter, IID_IAMTVTuner,
2202                                      (void **)&p_TV );
2203     }
2204
2205     if( FAILED(hr) )
2206     {
2207         msg_Dbg( p_this, "couldn't find tuner interface" );
2208         return;
2209     }
2210
2211     hr = p_TV->GetAvailableModes( &l_modes );
2212     if( SUCCEEDED(hr) && (l_modes & i_amtuner_mode) )
2213     {
2214         hr = p_TV->put_Mode( (AMTunerModeType)i_amtuner_mode );
2215     }
2216
2217     if( i_input == 1 ) p_TV->put_InputType( 0, TunerInputCable );
2218     else if( i_input == 2 ) p_TV->put_InputType( 0, TunerInputAntenna );
2219
2220     p_TV->put_CountryCode( i_country );
2221
2222     if( i_frequency <= 0 ) p_TV->put_Channel( i_channel, AMTUNER_SUBCHAN_NO_TUNE,
2223                        AMTUNER_SUBCHAN_NO_TUNE );
2224
2225     if( i_frequency > 0 || i_standard > 0) {
2226         IKsPropertySet *pKs = NULL;
2227         DWORD dw_supported = 0;
2228         KSPROPERTY_TUNER_MODE_CAPS_S ModeCaps;
2229         KSPROPERTY_TUNER_FREQUENCY_S Frequency;
2230         KSPROPERTY_TUNER_STANDARD_S Standard;
2231
2232         hr = p_TV->QueryInterface(IID_IKsPropertySet,(void **)&pKs);
2233         if (FAILED(hr))
2234         {
2235             msg_Dbg( p_this, "Couldn't QI for IKsPropertySet" );
2236             p_TV->Release();
2237             return;
2238         }
2239
2240         memset(&ModeCaps,0,sizeof(KSPROPERTY_TUNER_MODE_CAPS_S));
2241         memset(&Frequency,0,sizeof(KSPROPERTY_TUNER_FREQUENCY_S));
2242         memset(&Standard,0,sizeof(KSPROPERTY_TUNER_STANDARD_S));
2243         ModeCaps.Mode = AMTUNER_MODE_TV;
2244
2245         hr = pKs->QuerySupported(PROPSETID_TUNER,
2246                 KSPROPERTY_TUNER_MODE_CAPS,&dw_supported);
2247         if(SUCCEEDED(hr) && dw_supported&KSPROPERTY_SUPPORT_GET)
2248         {
2249             DWORD cbBytes=0;
2250             hr = pKs->Get(PROPSETID_TUNER,KSPROPERTY_TUNER_MODE_CAPS,
2251                 INSTANCEDATA_OF_PROPERTY_PTR(&ModeCaps),
2252                 INSTANCEDATA_OF_PROPERTY_SIZE(ModeCaps),
2253                 &ModeCaps,
2254                 sizeof(ModeCaps),
2255                 &cbBytes);
2256         }
2257         else
2258         {
2259             msg_Dbg( p_this, "KSPROPERTY_TUNER_MODE_CAPS not supported!" );
2260             goto free_on_error;
2261         }
2262
2263         msg_Dbg( p_this, "Frequency range supported from %ld to %ld.",
2264                  ModeCaps.MinFrequency, ModeCaps.MaxFrequency);
2265         msg_Dbg( p_this, "Video standards supported by the tuner: ");
2266         for(size_t i = 0 ; i < ARRAY_SIZE(ppsz_standards_list_text); i++) {
2267             if(ModeCaps.StandardsSupported & i_standards_list[i])
2268                 msg_Dbg( p_this, "%s, ", ppsz_standards_list_text[i]);
2269         }
2270
2271         if(i_frequency > 0) {
2272             Frequency.Frequency=i_frequency;
2273             if(ModeCaps.Strategy==KS_TUNER_STRATEGY_DRIVER_TUNES)
2274                 Frequency.TuningFlags=KS_TUNER_TUNING_FINE;
2275             else
2276                 Frequency.TuningFlags=KS_TUNER_TUNING_EXACT;
2277
2278             if(i_frequency>=ModeCaps.MinFrequency && i_frequency<=ModeCaps.MaxFrequency)
2279             {
2280
2281                 hr = pKs->Set(PROPSETID_TUNER,
2282                     KSPROPERTY_TUNER_FREQUENCY,
2283                     INSTANCEDATA_OF_PROPERTY_PTR(&Frequency),
2284                     INSTANCEDATA_OF_PROPERTY_SIZE(Frequency),
2285                     &Frequency,
2286                     sizeof(Frequency));
2287                 if(FAILED(hr))
2288                 {
2289                     msg_Dbg( p_this, "Couldn't set KSPROPERTY_TUNER_FREQUENCY!" );
2290                     goto free_on_error;
2291                 }
2292             }
2293             else
2294             {
2295                 msg_Dbg( p_this, "Requested frequency exceeds the supported range!" );
2296                 goto free_on_error;
2297             }
2298         }
2299
2300         if(i_standard > 0) {
2301             if(i_standard & ModeCaps.StandardsSupported )
2302             {
2303                 Standard.Standard = i_standard;
2304                 hr = pKs->Set(PROPSETID_TUNER,
2305                     KSPROPERTY_TUNER_STANDARD,
2306                     INSTANCEDATA_OF_PROPERTY_PTR(&Standard),
2307                     INSTANCEDATA_OF_PROPERTY_SIZE(Standard),
2308                     &Standard,
2309                     sizeof(Standard));
2310                 if(FAILED(hr))
2311                 {
2312                     msg_Dbg( p_this, "Couldn't set KSPROPERTY_TUNER_STANDARD!" );
2313                     goto free_on_error;
2314                 }
2315             }
2316             else
2317             {
2318                 msg_Dbg( p_this, "Requested video standard is not supported by the tuner!" );
2319                 goto free_on_error;
2320             }
2321         }
2322 free_on_error:
2323         pKs->Release();
2324     }
2325
2326     p_TV->Release();
2327 }