]> git.sesse.net Git - vlc/blobdiff - modules/access/dshow/dshow.cpp
Trailing ;
[vlc] / modules / access / dshow / dshow.cpp
index 7d9b59ed4360574310d26f94bed38b32d6bba6d7..2ae738d20f70ada1795d6ded57736d1132838920 100644 (file)
@@ -98,7 +98,7 @@ static const char *const ppsz_amtuner_mode_text[] = { N_("Default"),
 #define CACHING_TEXT N_("Caching value in ms")
 #define CACHING_LONGTEXT N_( \
     "Caching value for DirectShow streams. " \
-    "This value should be set in millisecondss." )
+    "This value should be set in milliseconds." )
 #define VDEV_TEXT N_("Video device name")
 #define VDEV_LONGTEXT N_( \
     "Name of the video device that will be used by the " \
@@ -182,37 +182,37 @@ static void AccessClose( vlc_object_t * );
 static int  DemuxOpen  ( vlc_object_t * );
 static void DemuxClose ( vlc_object_t * );
 
-vlc_module_begin();
-    set_shortname( N_("DirectShow") );
-    set_description( N_("DirectShow input") );
-    set_category( CAT_INPUT );
-    set_subcategory( SUBCAT_INPUT_ACCESS );
+vlc_module_begin ()
+    set_shortname( N_("DirectShow") )
+    set_description( N_("DirectShow input") )
+    set_category( CAT_INPUT )
+    set_subcategory( SUBCAT_INPUT_ACCESS )
     add_integer( "dshow-caching", (mtime_t)(0.2*CLOCK_FREQ) / 1000, NULL,
                  CACHING_TEXT, CACHING_LONGTEXT, true );
 
-    add_string( "dshow-vdev", NULL, NULL, VDEV_TEXT, VDEV_LONGTEXT, false);
+    add_string( "dshow-vdev", NULL, NULL, VDEV_TEXT, VDEV_LONGTEXT, false)
         change_string_list( ppsz_vdev, ppsz_vdev_text, FindDevicesCallback );
-        change_action_add( FindDevicesCallback, N_("Refresh list") );
-        change_action_add( ConfigDevicesCallback, N_("Configure") );
+        change_action_add( FindDevicesCallback, N_("Refresh list") )
+        change_action_add( ConfigDevicesCallback, N_("Configure") )
 
-    add_string( "dshow-adev", NULL, NULL, ADEV_TEXT, ADEV_LONGTEXT, false);
+    add_string( "dshow-adev", NULL, NULL, ADEV_TEXT, ADEV_LONGTEXT, false)
         change_string_list( ppsz_adev, ppsz_adev_text, FindDevicesCallback );
-        change_action_add( FindDevicesCallback, N_("Refresh list") );
-        change_action_add( ConfigDevicesCallback, N_("Configure") );
+        change_action_add( FindDevicesCallback, N_("Refresh list") )
+        change_action_add( ConfigDevicesCallback, N_("Configure") )
 
-    add_string( "dshow-size", NULL, NULL, SIZE_TEXT, SIZE_LONGTEXT, false);
+    add_string( "dshow-size", NULL, NULL, SIZE_TEXT, SIZE_LONGTEXT, false)
 
     add_string( "dshow-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT,
-                true );
+                true )
 
     add_float( "dshow-fps", 0.0f, NULL, FPS_TEXT, FPS_LONGTEXT,
-                true );
+                true )
 
     add_bool( "dshow-config", false, NULL, CONFIG_TEXT, CONFIG_LONGTEXT,
-              true );
+              true )
 
     add_bool( "dshow-tuner", false, NULL, TUNER_TEXT, TUNER_LONGTEXT,
-              true );
+              true )
 
     add_integer( "dshow-tuner-channel", 0, NULL, CHANNEL_TEXT,
                  CHANNEL_LONGTEXT, true );
@@ -247,16 +247,16 @@ vlc_module_begin();
     add_integer( "dshow-audio-bitspersample", 0, NULL, AUDIO_BITSPERSAMPLE_TEXT,
                  AUDIO_BITSPERSAMPLE_LONGTEXT, true );
 
-    add_shortcut( "dshow" );
-    set_capability( "access_demux", 0 );
-    set_callbacks( DemuxOpen, DemuxClose );
+    add_shortcut( "dshow" )
+    set_capability( "access_demux", 0 )
+    set_callbacks( DemuxOpen, DemuxClose )
 
-    add_submodule();
-    set_description( N_("DirectShow input") );
-    set_capability( "access", 0 );
-    set_callbacks( AccessOpen, AccessClose );
+    add_submodule ()
+    set_description( N_("DirectShow input") )
+    set_capability( "access", 0 )
+    set_callbacks( AccessOpen, AccessClose )
 
-vlc_module_end();
+vlc_module_end ()
 
 /*****************************************************************************
  * DirectShow elementary stream descriptor
@@ -279,6 +279,8 @@ typedef struct dshow_stream_t
     es_out_id_t     *p_es;
 
     bool      b_pts;
+
+    deque<VLCMediaSample> samples_queue;
 } dshow_stream_t;
 
 /*****************************************************************************
@@ -430,7 +432,7 @@ static int CommonOpen( vlc_object_t *p_this, access_sys_t *p_sys,
 
     /* Initialize some data */
     p_sys->i_streams = 0;
-    p_sys->pp_streams = 0;
+    p_sys->pp_streams = NULL;
     p_sys->i_width = i_width;
     p_sys->i_height = i_height;
     p_sys->i_chroma = i_chroma;
@@ -577,10 +579,9 @@ static int DemuxOpen( vlc_object_t *p_this )
     access_sys_t *p_sys;
     int i;
 
-    p_sys = (access_sys_t *)malloc( sizeof( access_sys_t ) );
+    p_sys = (access_sys_t*)calloc( 1, sizeof( access_sys_t ) );
     if( !p_sys )
         return VLC_ENOMEM;
-    memset( p_sys, 0, sizeof( access_sys_t ) );
     p_demux->p_sys = (demux_sys_t *)p_sys;
 
     if( CommonOpen( p_this, p_sys, true ) != VLC_SUCCESS )
@@ -661,10 +662,9 @@ static int AccessOpen( vlc_object_t *p_this )
     access_t     *p_access = (access_t*)p_this;
     access_sys_t *p_sys;
 
-    p_access->p_sys = p_sys = (access_sys_t *)malloc( sizeof( access_sys_t ) );
+    p_access->p_sys = p_sys = (access_sys_t*)calloc( 1, sizeof( access_sys_t ) );
     if( !p_sys )
         return VLC_ENOMEM;
-    memset( p_sys, 0, sizeof( access_sys_t ) );
 
     if( CommonOpen( p_this, p_sys, false ) != VLC_SUCCESS )
     {
@@ -782,16 +782,16 @@ static bool ConnectFilters( vlc_object_t *p_this, access_sys_t *p_sys,
 
         // Sort out all the possible video inputs
         // The class needs to be given the capture filters ANALOGVIDEO input pin
-        IEnumPins *pins = 0;
+        IEnumPins *pins = NULL;
         if( ( mediaType.majortype == MEDIATYPE_Video ||
               mediaType.majortype == MEDIATYPE_Stream ) &&
             SUCCEEDED(p_filter->EnumPins(&pins)) )
         {
-            IPin        *pP = 0;
+            IPin        *pP = NULL;
             ULONG        n;
             PIN_INFO     pinInfo;
             BOOL         Found = FALSE;
-            IKsPropertySet *pKs=0;
+            IKsPropertySet *pKs = NULL;
             GUID guid;
             DWORD dw;
 
@@ -1318,9 +1318,14 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
 
                                 if( i_width )
                                 {
-                                    if( i_width % pVSCC->OutputGranularityX
-                                     || pVSCC->MinOutputSize.cx > i_width
-                                     || i_width > pVSCC->MaxOutputSize.cx )
+                                    if((   !pVSCC->OutputGranularityX
+                                           && i_width != pVSCC->MinOutputSize.cx
+                                           && i_width != pVSCC->MaxOutputSize.cx)
+                                       ||
+                                       (   pVSCC->OutputGranularityX
+                                           && ((i_width % pVSCC->OutputGranularityX)
+                                               || pVSCC->MinOutputSize.cx > i_width
+                                               || i_width > pVSCC->MaxOutputSize.cx )))
                                     {
                                         // required width not compatible, try next media type
                                         FreeMediaType( *p_mt );
@@ -1332,9 +1337,14 @@ 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
-                                     || i_height > pVSCC->MaxOutputSize.cy )
+                                    if((   !pVSCC->OutputGranularityY
+                                           && i_height != pVSCC->MinOutputSize.cy
+                                           && i_height != pVSCC->MaxOutputSize.cy)
+                                       ||
+                                       (   pVSCC->OutputGranularityY
+                                           && ((i_height % pVSCC->OutputGranularityY)
+                                               || pVSCC->MinOutputSize.cy > i_height
+                                               || i_height > pVSCC->MaxOutputSize.cy )))
                                     {
                                         // required height not compatible, try next media type
                                         FreeMediaType( *p_mt );
@@ -1375,9 +1385,14 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
                                     if( ! val )
                                         val = 2;
 
-                                    if( val % pASCC->ChannelsGranularity
-                                     || (unsigned int)val < pASCC->MinimumChannels
-                                     || (unsigned int)val > pASCC->MaximumChannels )
+                                    if( (   !pASCC->ChannelsGranularity
+                                            && (unsigned int)val != pASCC->MinimumChannels
+                                            && (unsigned int)val != pASCC->MaximumChannels)
+                                        ||
+                                        (   pASCC->ChannelsGranularity
+                                            && ((val % pASCC->ChannelsGranularity)
+                                                || (unsigned int)val < pASCC->MinimumChannels
+                                                || (unsigned int)val > pASCC->MaximumChannels)))
                                     {
                                         // required number channels not available, try next media type
                                         FreeMediaType( *p_mt );
@@ -1390,9 +1405,14 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
                                     if( ! val )
                                         val = 44100;
 
-                                    if( val % pASCC->SampleFrequencyGranularity
-                                     || (unsigned int)val < pASCC->MinimumSampleFrequency
-                                     || (unsigned int)val > pASCC->MaximumSampleFrequency )
+                                    if( (   !pASCC->SampleFrequencyGranularity
+                                            && (unsigned int)val != pASCC->MinimumSampleFrequency
+                                            && (unsigned int)val != pASCC->MaximumSampleFrequency)
+                                        ||
+                                        (   pASCC->SampleFrequencyGranularity
+                                            && ((val % pASCC->SampleFrequencyGranularity)
+                                                || (unsigned int)val < pASCC->MinimumSampleFrequency
+                                                || (unsigned int)val > pASCC->MaximumSampleFrequency )))
                                     {
                                         // required sampling rate not available, try next media type
                                         FreeMediaType( *p_mt );
@@ -1410,9 +1430,14 @@ static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter,
                                             val = 16;
                                     }
 
-                                    if( val % pASCC->BitsPerSampleGranularity
-                                     || (unsigned int)val < pASCC->MinimumBitsPerSample
-                                     || (unsigned int)val > pASCC->MaximumBitsPerSample )
+                                    if( (   !pASCC->BitsPerSampleGranularity
+                                            && (unsigned int)val != pASCC->MinimumBitsPerSample
+                                            && (unsigned int)val != pASCC->MaximumBitsPerSample )
+                                        ||
+                                        (   pASCC->BitsPerSampleGranularity
+                                            && ((val % pASCC->BitsPerSampleGranularity)
+                                                || (unsigned int)val < pASCC->MinimumBitsPerSample
+                                                || (unsigned int)val > pASCC->MaximumBitsPerSample )))
                                     {
                                         // required sample size not available, try next media type
                                         FreeMediaType( *p_mt );
@@ -1681,7 +1706,7 @@ static block_t *ReadCompressed( access_t *p_access )
         return p_block;
     }
 
-    return 0; /* never reached */
+    return NULL; /* never reached */
 }
 
 /****************************************************************************
@@ -1690,85 +1715,90 @@ static block_t *ReadCompressed( access_t *p_access )
 static int Demux( demux_t *p_demux )
 {
     access_sys_t *p_sys = (access_sys_t *)p_demux->p_sys;
-    dshow_stream_t *p_stream = NULL;
-    VLCMediaSample sample;
-    int i_data_size, i_stream;
-    uint8_t *p_data;
-    block_t *p_block;
+    int i_stream;
+    int i_found_samples;
 
+    i_found_samples = 0;
     vlc_mutex_lock( &p_sys->lock );
 
-    /* Try to grab an audio sample (audio has a higher priority) */
-    for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
-    {
-        p_stream = p_sys->pp_streams[i_stream];
-        if( p_stream->mt.majortype == MEDIATYPE_Audio &&
-            p_stream->p_capture_filter &&
-            p_stream->p_capture_filter->CustomGetPin()
-              ->CustomGetSample( &sample ) == S_OK )
-        {
-            break;
-        }
-    }
-    /* Try to grab a video sample */
-    if( i_stream == p_sys->i_streams )
+    while ( !i_found_samples )
     {
+        /* Try to grab samples from all streams */
         for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
         {
-            p_stream = p_sys->pp_streams[i_stream];
+            dshow_stream_t *p_stream = p_sys->pp_streams[i_stream];
             if( p_stream->p_capture_filter &&
                 p_stream->p_capture_filter->CustomGetPin()
-                    ->CustomGetSample( &sample ) == S_OK )
+                ->CustomGetSamples( p_stream->samples_queue ) == S_OK )
             {
-                break;
+                i_found_samples = 1;
             }
         }
+
+        if ( !i_found_samples)
+        {
+            /* Didn't find any audio nor video sample, just wait till the
+             * dshow thread pushes some samples */
+            vlc_cond_wait( &p_sys->wait, &p_sys->lock );
+            /* Some DShow thread pushed data, or the OS broke the wait all
+             * by itself. In all cases, it's *strongly* advised to test the
+             * condition again, so let the loop do the test again */
+        }
     }
 
     vlc_mutex_unlock( &p_sys->lock );
 
-    if( i_stream == p_sys->i_streams )
+    for ( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
     {
-        /* Sleep so we do not consume all the cpu, 10ms seems
-         * like a good value (100fps) */
-        msleep( 10000 );
-        return 1;
-    }
+        int i_samples;
+        dshow_stream_t *p_stream = p_sys->pp_streams[i_stream];
 
-    /*
-     * We got our sample
-     */
-    i_data_size = sample.p_sample->GetActualDataLength();
-    sample.p_sample->GetPointer( &p_data );
+        i_samples = p_stream->samples_queue.size();
+        while ( i_samples > 0 )
+        {
+            int i_data_size;
+            uint8_t *p_data;
+            block_t *p_block;
+            VLCMediaSample sample;
 
-    REFERENCE_TIME i_pts, i_end_date;
-    HRESULT hr = sample.p_sample->GetTime( &i_pts, &i_end_date );
-    if( hr != VFW_S_NO_STOP_TIME && hr != S_OK ) i_pts = 0;
+            sample = p_stream->samples_queue.front();
+            p_stream->samples_queue.pop_front();
 
-    if( !i_pts )
-    {
-        if( p_stream->mt.majortype == MEDIATYPE_Video || !p_stream->b_pts )
-        {
-            /* Use our data timestamp */
-            i_pts = sample.i_timestamp;
-            p_stream->b_pts = true;
-        }
-    }
+            i_data_size = sample.p_sample->GetActualDataLength();
+            sample.p_sample->GetPointer( &p_data );
+
+            REFERENCE_TIME i_pts, i_end_date;
+            HRESULT hr = sample.p_sample->GetTime( &i_pts, &i_end_date );
+            if( hr != VFW_S_NO_STOP_TIME && hr != S_OK ) i_pts = 0;
+
+            if( !i_pts )
+            {
+                if( p_stream->mt.majortype == MEDIATYPE_Video || !p_stream->b_pts )
+                {
+                    /* Use our data timestamp */
+                    i_pts = sample.i_timestamp;
+                    p_stream->b_pts = true;
+                }
+            }
 
-    i_pts /= 10; /* Dshow works with 100 nano-seconds resolution */
+            i_pts /= 10; /* Dshow works with 100 nano-seconds resolution */
 
 #if 0
-    msg_Dbg( p_demux, "Read() stream: %i, size: %i, PTS: %"PRId64,
-             i_stream, i_data_size, i_pts );
+            msg_Dbg( p_demux, "Read() stream: %i, size: %i, PTS: %"PRId64,
+                     i_stream, i_data_size, i_pts );
 #endif
 
-    p_block = block_New( p_demux, i_data_size );
-    vlc_memcpy( p_block->p_buffer, p_data, i_data_size );
-    p_block->i_pts = p_block->i_dts = i_pts;
-    sample.p_sample->Release();
+            p_block = block_New( p_demux, i_data_size );
+            vlc_memcpy( p_block->p_buffer, p_data, i_data_size );
+            p_block->i_pts = p_block->i_dts = i_pts;
+            sample.p_sample->Release();
+
+            es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_pts > 0 ? i_pts : 0 );
+            es_out_Send( p_demux->out, p_stream->p_es, p_block );
 
-    es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_pts > 0 ? i_pts : 0 );
-    es_out_Send( p_demux->out, p_stream->p_es, p_block );
+            i_samples--;
+        }
+    }
 
     return 1;
 }
@@ -1794,11 +1824,6 @@ static int AccessControl( access_t *p_access, int i_query, va_list args )
         break;
 
     /* */
-    case ACCESS_GET_MTU:
-        pi_int = (int*)va_arg( args, int * );
-        *pi_int = 0;
-        break;
-
     case ACCESS_GET_PTS_DELAY:
         pi_64 = (int64_t*)va_arg( args, int64_t * );
         *pi_64 = (int64_t)var_GetInteger( p_access, "dshow-caching" ) * 1000;