]> git.sesse.net Git - vlc/blobdiff - modules/access/dshow/dshow.cpp
Another time "Remove useless test before a free".
[vlc] / modules / access / dshow / dshow.cpp
index e25372c20a5da929d7cabb870bce121a14019d07..404d8282a15d70962b2f5ff399fbbe5aa852d8b0 100644 (file)
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
 
 #include <vlc/vlc.h>
-#include <vlc/input.h>
-#include <vlc/vout.h>
+#include <vlc_input.h>
+#include <vlc_access.h>
+#include <vlc_demux.h>
+#include <vlc_vout.h>
+#include <vlc_interface.h>
 
 #include "common.h"
 #include "filter.h"
@@ -59,9 +63,9 @@ static int ConfigDevicesCallback( vlc_object_t *, char const *,
                                   vlc_value_t, vlc_value_t, void * );
 
 static void ShowPropertyPage( IUnknown * );
-static void ShowDeviceProperties( vlc_object_t *, ICaptureGraphBuilder2 *, 
+static void ShowDeviceProperties( vlc_object_t *, ICaptureGraphBuilder2 *,
                                   IBaseFilter *, vlc_bool_t );
-static void ShowTunerProperties( vlc_object_t *, ICaptureGraphBuilder2 *, 
+static void ShowTunerProperties( vlc_object_t *, ICaptureGraphBuilder2 *,
                                  IBaseFilter *, vlc_bool_t );
 static void ConfigTuner( vlc_object_t *, ICaptureGraphBuilder2 *,
                          IBaseFilter * );
@@ -69,19 +73,19 @@ static void ConfigTuner( vlc_object_t *, ICaptureGraphBuilder2 *,
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
-static char *ppsz_vdev[] = { "", "none" };
-static char *ppsz_vdev_text[] = { N_("Default"), N_("None") };
-static char *ppsz_adev[] = { "", "none" };
-static char *ppsz_adev_text[] = { N_("Default"), N_("None") };
+static const char *ppsz_vdev[] = { "", "none" };
+static const char *ppsz_vdev_text[] = { N_("Default"), N_("None") };
+static const char *ppsz_adev[] = { "", "none" };
+static const char *ppsz_adev_text[] = { N_("Default"), N_("None") };
 static int  pi_tuner_input[] = { 0, 1, 2 };
-static char *ppsz_tuner_input_text[] =
+static const char *ppsz_tuner_input_text[] =
     {N_("Default"), N_("Cable"), N_("Antenna")};
-static int pi_amtuner_mode[] = { AMTUNER_MODE_DEFAULT,
+static const int pi_amtuner_mode[]  = { AMTUNER_MODE_DEFAULT,
                                  AMTUNER_MODE_TV,
                                  AMTUNER_MODE_FM_RADIO,
                                  AMTUNER_MODE_AM_RADIO,
                                  AMTUNER_MODE_DSS };
-static char *ppsz_amtuner_mode_text[] = { N_("Default"),
+static const char *ppsz_amtuner_mode_text[] = { N_("Default"),
                                           N_("TV"),
                                           N_("FM radio"),
                                           N_("AM radio"),
@@ -96,17 +100,16 @@ static char *ppsz_amtuner_mode_text[] = { N_("Default"),
     "Name of the video device that will be used by the " \
     "DirectShow plugin. If you don't specify anything, the default device " \
     "will be used.")
-/// \bug [String] size stuff should be on video !
 #define ADEV_TEXT N_("Audio device name")
 #define ADEV_LONGTEXT N_( \
     "Name of the audio device that will be used by the " \
     "DirectShow plugin. If you don't specify anything, the default device " \
-    "will be used. You can specify a standard size (cif, d1, ...) or <width>x<height>")
+    "will be used. ")
 #define SIZE_TEXT N_("Video size")
 #define SIZE_LONGTEXT N_( \
     "Size of the video that will be displayed by the " \
     "DirectShow plugin. If you don't specify anything the default size for " \
-    "your device will be used.")
+    "your device will be used. You can specify a standard size (cif, d1, ...) or <width>x<height>.")
 #define CHROMA_TEXT N_("Video input chroma format")
 #define CHROMA_LONGTEXT N_( \
     "Force the DirectShow video input to use a specific chroma format " \
@@ -136,7 +139,7 @@ static char *ppsz_amtuner_mode_text[] = { N_("Default"),
 #define VIDEO_IN_TEXT N_("Video input pin")
 #define VIDEO_IN_LONGTEXT N_( \
   "Select the video input source, such as composite, s-video, " \
-  "or tuner. Since these settings are hardware-specfic, you should find good " \
+  "or tuner. Since these settings are hardware-specific, you should find good " \
   "settings in the \"Device config\" area, and use those numbers here. -1 " \
   "means that settings will not be changed.")
 #define AUDIO_IN_TEXT N_("Audio input pin")
@@ -226,7 +229,6 @@ vlc_module_begin();
 
     add_submodule();
     set_description( _("DirectShow input") );
-    add_shortcut( "dshow" );
     set_capability( "access2", 0 );
     set_callbacks( AccessOpen, AccessClose );
 
@@ -331,12 +333,12 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys,
     var_Create( p_this, "dshow-vdev", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
     var_Get( p_this, "dshow-vdev", &val );
     if( val.psz_string ) vdevname = string( val.psz_string );
-    if( val.psz_string ) free( val.psz_string );
+    free( val.psz_string );
 
     var_Create( p_this, "dshow-adev", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
     var_Get( p_this, "dshow-adev", &val );
     if( val.psz_string ) adevname = string( val.psz_string );
-    if( val.psz_string ) free( val.psz_string );
+    free( val.psz_string );
 
     static struct {char *psz_size; int  i_width; int  i_height;} size_table[] =
     { { "subqcif", 128, 96 }, { "qsif", 160, 120 }, { "qcif", 176, 144 },
@@ -368,7 +370,7 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys,
             msg_Dbg( p_this, "width x height %dx%d", i_width, i_height );
         }
     }
-    if( val.psz_string ) free( val.psz_string );
+    free( val.psz_string );
 
     p_sys->b_chroma = VLC_FALSE;
     var_Create( p_this, "dshow-chroma", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
@@ -379,7 +381,7 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys,
                                val.psz_string[2], val.psz_string[3] );
         p_sys->b_chroma = VLC_TRUE;
     }
-    if( val.psz_string ) free( val.psz_string );
+    free( val.psz_string );
 
     var_Create( p_this, "dshow-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
     var_Create( p_this, "dshow-tuner-channel",
@@ -890,6 +892,9 @@ static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys,
     {
         msg_Err( p_this, "can't use device: %s, unsupported device type",
                  devicename.c_str() );
+        intf_UserFatal( p_this, VLC_FALSE, _("Capturing failed"),
+                        _("VLC cannot use the device \"%s\", because its "
+                          "type is not supported.") );
         return VLC_EGENERIC;
     }
 
@@ -937,6 +942,9 @@ static int OpenDevice( vlc_object_t *p_this, access_sys_t *p_sys,
     else {
         /* capture device */
         msg_Err( p_this, "capture device '%s' does not support required parameters !", devicename.c_str() );
+        intf_UserFatal( p_this, VLC_FALSE, _("Capturing failed"),
+                        _("The capture device \"%s\" does not support the "
+                          "required parameters."), devicename.c_str() );
         p_device_filter->Release();
         return VLC_EGENERIC;
     }
@@ -1051,6 +1059,7 @@ FindCaptureDevice( vlc_object_t *p_this, string *p_devicename,
     IMoniker *p_moniker = NULL;
     ULONG i_fetched;
     HRESULT hr;
+    list<string> devicelist;
 
     /* Create the system device enumerator */
     ICreateDevEnum *p_dev_enum = NULL;
@@ -1114,9 +1123,29 @@ FindCaptureDevice( vlc_object_t *p_this, string *p_devicename,
                 SysFreeString(var.bstrVal);
                 p_buf[i_convert] = '\0';
 
-                if( p_listdevices ) p_listdevices->push_back( p_buf );
+        string devname = string(p_buf);
+
+        int dup = 0;
+        /* find out if this name is already used by a previously found device */
+        list<string>::const_iterator iter = devicelist.begin();
+        list<string>::const_iterator end = devicelist.end();
+        while ( iter != end )
+        {
+            if( 0 == (*iter).compare(0, devname.size(), devname) )
+            ++dup;
+            ++iter;
+        }
+        if( dup )
+        {
+            /* we have a duplicate device name, append a sequence number to name
+               to provive a unique list back to the user */
+            char seq[16];
+            sprintf(seq, " #%d", dup);
+            devname.append(seq);
+        }
+        devicelist.push_back( devname );
 
-                if( p_devicename && *p_devicename == string(p_buf) )
+                if( p_devicename && *p_devicename == devname )
                 {
                     /* Bind Moniker to a filter object */
                     hr = p_moniker->BindToObject( 0, 0, IID_IBaseFilter,
@@ -1140,6 +1169,11 @@ FindCaptureDevice( vlc_object_t *p_this, string *p_devicename,
     }
 
     p_class_enum->Release();
+
+    if( p_listdevices ) {
+    devicelist.sort();
+    *p_listdevices = devicelist;
+    }
     return NULL;
 }
 
@@ -1266,7 +1300,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
                                 if( i_height )
                                 {
                                     if( i_height % pVSCC->OutputGranularityY
-                                     || pVSCC->MinOutputSize.cy > i_height 
+                                     || pVSCC->MinOutputSize.cy > i_height
                                      || i_height > pVSCC->MaxOutputSize.cy )
                                     {
                                         // required height not compatible, try next media type
@@ -1279,7 +1313,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
 
                                 // Set the sample size and image size.
                                 // (Round the image width up to a DWORD boundary.)
-                                p_mt->lSampleSize = pVih->bmiHeader.biSizeImage = 
+                                p_mt->lSampleSize = pVih->bmiHeader.biSizeImage =
                                     ((pVih->bmiHeader.biWidth + 3) & ~3) *
                                     pVih->bmiHeader.biHeight * (pVih->bmiHeader.biBitCount>>3);
 
@@ -1292,7 +1326,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
                                 {
                                     i_priority = i_current_priority;
                                     if( i_fourcc )
-                                        // no need to check any more media types 
+                                        // no need to check any more media types
                                         i = piCount;
                                 }
                             }
@@ -1334,7 +1368,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
                                     }
                                     pWfx->nSamplesPerSec = val;
  
-                                    val = i_bitspersample; 
+                                    val = i_bitspersample;
                                     if( ! val )
                                     {
                                         if( VLC_FOURCC('f', 'l', '3', '2') == i_current_fourcc )
@@ -1397,7 +1431,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
                 LONGLONG i_current_atpf = ((VIDEOINFOHEADER *)p_mt->pbFormat)->AvgTimePerFrame;
 
                 if( i_current_height < 0 )
-                    i_current_height = -i_current_height; 
+                    i_current_height = -i_current_height;
 
                 msg_Dbg( p_this, "EnumDeviceCaps: input pin "
                          "accepts chroma: %4.4s, width:%i, height:%i, fps:%f",
@@ -1415,7 +1449,7 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
                 }
                 else FreeMediaType( *p_mt );
             }
-            else if( i_current_fourcc && p_mt->majortype == MEDIATYPE_Audio 
+            else if( i_current_fourcc && p_mt->majortype == MEDIATYPE_Audio
                     && p_mt->formattype == FORMAT_WaveFormatEx)
             {
                 int i_current_channels =
@@ -1512,33 +1546,33 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
                     i_current_fourcc = VLC_FOURCC('I','4','2','0');
                     if( !i_fourcc || i_fourcc == i_current_fourcc )
                     {
-                        // return alternative media type  
-                        AM_MEDIA_TYPE mtr;  
-                        VIDEOINFOHEADER vh;  
-             
-                        mtr.majortype            = MEDIATYPE_Video;  
-                        mtr.subtype              = MEDIASUBTYPE_I420;  
-                        mtr.bFixedSizeSamples    = TRUE;  
-                        mtr.bTemporalCompression = FALSE;  
-                        mtr.pUnk                 = NULL;  
-                        mtr.formattype           = FORMAT_VideoInfo;  
-                        mtr.cbFormat             = sizeof(vh);  
-                        mtr.pbFormat             = (BYTE *)&vh;  
-             
-                        memset(&vh, 0, sizeof(vh));  
-             
-                        vh.bmiHeader.biSize   = sizeof(vh.bmiHeader);  
+                        // return alternative media type
+                        AM_MEDIA_TYPE mtr;
+                        VIDEOINFOHEADER vh;
+                        mtr.majortype            = MEDIATYPE_Video;
+                        mtr.subtype              = MEDIASUBTYPE_I420;
+                        mtr.bFixedSizeSamples    = TRUE;
+                        mtr.bTemporalCompression = FALSE;
+                        mtr.pUnk                 = NULL;
+                        mtr.formattype           = FORMAT_VideoInfo;
+                        mtr.cbFormat             = sizeof(vh);
+                        mtr.pbFormat             = (BYTE *)&vh;
+                        memset(&vh, 0, sizeof(vh));
+                        vh.bmiHeader.biSize   = sizeof(vh.bmiHeader);
                         vh.bmiHeader.biWidth  = i_width > 0 ? i_width :
-                            ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biWidth;  
+                            ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biWidth;
                         vh.bmiHeader.biHeight = i_height > 0 ? i_height :
-                            ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biHeight;  
-                        vh.bmiHeader.biPlanes      = 3; 
-                        vh.bmiHeader.biBitCount    = 12;  
-                        vh.bmiHeader.biCompression = VLC_FOURCC('I','4','2','0');  
-                        vh.bmiHeader.biSizeImage   = vh.bmiHeader.biWidth * 12 *  
-                            vh.bmiHeader.biHeight / 8;  
-                        mtr.lSampleSize            = vh.bmiHeader.biSizeImage;  
-             
+                            ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biHeight;
+                        vh.bmiHeader.biPlanes      = 3;
+                        vh.bmiHeader.biBitCount    = 12;
+                        vh.bmiHeader.biCompression = VLC_FOURCC('I','4','2','0');
+                        vh.bmiHeader.biSizeImage   = vh.bmiHeader.biWidth * 12 *
+                            vh.bmiHeader.biHeight / 8;
+                        mtr.lSampleSize            = vh.bmiHeader.biSizeImage;
                         msg_Dbg( p_this, "EnumDeviceCaps: input pin media: using 'I420' in place of unsupported format 'HCW2'");
 
                         if( SUCCEEDED(CopyMediaType(mt+mt_count, &mtr)) )
@@ -1607,7 +1641,7 @@ static block_t *ReadCompressed( access_t *p_access )
         }
 
         sample.p_sample->GetPointer( &p_data );
-        p_access->p_vlc->pf_memcpy( p_block->p_buffer, p_data, i_data_size );
+        p_access->p_libvlc->pf_memcpy( p_block->p_buffer, p_data, i_data_size );
         sample.p_sample->Release();
 
         /* The caller got what he wanted */
@@ -1696,7 +1730,7 @@ static int Demux( demux_t *p_demux )
 #endif
 
     p_block = block_New( p_demux, i_data_size );
-    p_demux->p_vlc->pf_memcpy( p_block->p_buffer, p_data, i_data_size );
+    p_demux->p_libvlc->pf_memcpy( p_block->p_buffer, p_data, i_data_size );
     p_block->i_pts = p_block->i_dts = i_pts;
     sample.p_sample->Release();
 
@@ -1765,6 +1799,7 @@ static int DemuxControl( demux_t *p_demux, int i_query, va_list args )
     {
     /* Special for access_demux */
     case DEMUX_CAN_PAUSE:
+    case DEMUX_CAN_SEEK:
     case DEMUX_SET_PAUSE_STATE:
     case DEMUX_CAN_CONTROL_PACE:
         pb = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
@@ -1810,8 +1845,8 @@ static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
         /* Keep the 2 first entries */
         for( i = 2; i < p_item->i_list; i++ )
         {
-            free( p_item->ppsz_list[i] );
-            free( p_item->ppsz_list_text[i] );
+            free( const_cast<char *>(p_item->ppsz_list[i]) );
+            free( const_cast<char *>(p_item->ppsz_list_text[i]) );
         }
         /* TODO: Remove when no more needed */
         p_item->ppsz_list[i] = NULL;
@@ -1892,6 +1927,7 @@ static int ConfigDevicesCallback( vlc_object_t *p_this, char const *psz_name,
     if( p_device_filter )
     {
         ShowPropertyPage( p_device_filter );
+        p_device_filter->Release();
     }
     else
     {