]> git.sesse.net Git - mlt/blobdiff - src/modules/decklink/producer_decklink.cpp
Initialize all decklink interface pointers and reset them upon release.
[mlt] / src / modules / decklink / producer_decklink.cpp
index be3406683401e6849496b20f794279708f458f38..93489091d8dc46955eceaf8ed8e727b3f4150e85 100644 (file)
@@ -31,6 +31,8 @@
 #include "DeckLinkAPI.h"
 #endif
 
+#define SAFE_RELEASE(V) if (V) { V->Release(); V = NULL; }
+
 class DeckLinkProducer
        : public IDeckLinkInputCallback
 {
@@ -51,8 +53,8 @@ private:
 
        BMDDisplayMode getDisplayMode( mlt_profile profile, int vancLines )
        {
-               IDeckLinkDisplayModeIterator* iter;
-               IDeckLinkDisplayMode* mode;
+               IDeckLinkDisplayModeIterator* iter = NULL;
+               IDeckLinkDisplayMode* mode = NULL;
                BMDDisplayMode result = (BMDDisplayMode) bmdDisplayModeNotSupported;
 
                if ( m_decklinkInput->GetDisplayModeIterator( &iter ) == S_OK )
@@ -74,7 +76,9 @@ private:
                                         && ( height + vancLines == profile->height || ( height == 486 && profile->height == 480 + vancLines ) )
                                         && fps == mlt_profile_fps( profile ) )
                                        result = mode->GetDisplayMode();
+                               SAFE_RELEASE( mode );
                        }
+                       SAFE_RELEASE( iter );
                }
 
                return result;
@@ -88,6 +92,12 @@ public:
        mlt_producer getProducer() const
                { return m_producer; }
 
+       DeckLinkProducer()
+       {
+               m_decklink = NULL;
+               m_decklinkInput = NULL;
+       }
+
        ~DeckLinkProducer()
        {
                if ( m_queue )
@@ -98,10 +108,57 @@ public:
                        pthread_cond_destroy( &m_condition );
                        mlt_cache_close( m_cache );
                }
-               if ( m_decklinkInput )
-                       m_decklinkInput->Release();
-               if ( m_decklink )
-                       m_decklink->Release();
+               SAFE_RELEASE( m_decklinkInput );
+               SAFE_RELEASE( m_decklink );
+       }
+
+       bool listDevices( mlt_properties properties )
+       {
+               IDeckLinkIterator* decklinkIterator = NULL;
+               try
+               {
+                       int i = 0;
+#ifdef WIN32
+                       HRESULT result =  CoInitialize( NULL );
+                       if ( FAILED( result ) )
+                               throw "COM initialization failed";
+                       result = CoCreateInstance( CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**) &decklinkIterator );
+                       if ( FAILED( result ) )
+                               throw "The DeckLink drivers are not installed.";
+#else
+                       decklinkIterator = CreateDeckLinkIteratorInstance();
+                       if ( !decklinkIterator )
+                               throw "The DeckLink drivers are not installed.";
+#endif
+                       for ( ; decklinkIterator->Next( &m_decklink ) == S_OK; i++ )
+                       {
+                               if ( m_decklink->QueryInterface( IID_IDeckLinkInput, (void**) &m_decklinkInput ) == S_OK )
+                               {
+                                       char *name = NULL;
+                                       if ( m_decklink->GetModelName( (const char**) &name ) == S_OK )
+                                       {
+                                               const char *format = "device.%d";
+                                               char *key = (char*) calloc( 1, strlen( format ) + 1 );
+
+                                               sprintf( key, format, i );
+                                               mlt_properties_set( properties, key, name );
+                                               free( key );
+                                               free( name );
+                                       }
+                                       SAFE_RELEASE( m_decklinkInput );
+                               }
+                               SAFE_RELEASE( m_decklink );
+                       }
+                       SAFE_RELEASE( decklinkIterator );
+                       mlt_properties_set_int( properties, "devices", i );
+                       return true;
+               }
+               catch ( const char *error )
+               {
+                       SAFE_RELEASE( decklinkIterator );
+                       mlt_log_error( getProducer(), "%s\n", error );
+                       return false;
+               }
        }
 
        bool open( unsigned card =  0 )
@@ -123,12 +180,16 @@ public:
 #endif
 
                        // Connect to the Nth DeckLink instance
-                       unsigned i = 0;
-                       do {
-                               if ( decklinkIterator->Next( &m_decklink ) != S_OK )
-                                       throw "DeckLink card not found.";
-                       } while ( ++i <= card );
-                       decklinkIterator->Release();
+                       for ( unsigned i = 0; decklinkIterator->Next( &m_decklink ) == S_OK ; i++)
+                       {
+                               if ( i == card )
+                                       break;
+                               else
+                                       SAFE_RELEASE( m_decklink );
+                       }
+                       SAFE_RELEASE( decklinkIterator );
+                       if ( !m_decklink )
+                               throw "DeckLink card not found.";
 
                        // Get the input interface
                        if ( m_decklink->QueryInterface( IID_IDeckLinkInput, (void**) &m_decklinkInput ) != S_OK )
@@ -151,8 +212,8 @@ public:
                }
                catch ( const char *error )
                {
-                       if ( decklinkIterator )
-                               decklinkIterator->Release();
+                       SAFE_RELEASE( m_decklinkInput );
+                       SAFE_RELEASE( m_decklink );
                        mlt_log_error( getProducer(), "%s\n", error );
                        return false;
                }
@@ -193,7 +254,7 @@ public:
                        {
                                if ( decklinkAttributes->GetFlag( BMDDeckLinkSupportsInputFormatDetection, &doesDetectFormat ) != S_OK )
                                        doesDetectFormat = false;
-                               decklinkAttributes->Release();
+                               SAFE_RELEASE( decklinkAttributes );
                        }
                        mlt_log_verbose( getProducer(), "%s format detection\n", doesDetectFormat ? "supports" : "does not support" );
 
@@ -323,10 +384,8 @@ public:
                        mlt_properties_set_int( properties, "meta.media.frame_rate_num", profile->frame_rate_num );
                        mlt_properties_set_int( properties, "meta.media.frame_rate_den", profile->frame_rate_den );
                        mlt_properties_set_int( properties, "width", profile->width );
-                       mlt_properties_set_int( properties, "real_width", profile->width );
                        mlt_properties_set_int( properties, "meta.media.width", profile->width );
                        mlt_properties_set_int( properties, "height", profile->height );
-                       mlt_properties_set_int( properties, "real_height", profile->height );
                        mlt_properties_set_int( properties, "meta.media.height", profile->height );
                        mlt_properties_set_int( properties, "format", mlt_image_yuv422 );
                        mlt_properties_set_int( properties, "colorspace", m_colorspace );
@@ -357,7 +416,8 @@ public:
                        IDeckLinkVideoInputFrame* video,
                        IDeckLinkAudioInputPacket* audio )
        {
-               if ( mlt_producer_get_speed( getProducer() ) == 0.0 && !mlt_deque_count( m_queue ))
+               if ( mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "preview" ) &&
+                       mlt_producer_get_speed( getProducer() ) == 0.0 && !mlt_deque_count( m_queue ))
                {
                        pthread_cond_broadcast( &m_condition );
                        return S_OK;
@@ -397,7 +457,7 @@ public:
                                                        else
                                                                mlt_log_debug( getProducer(), "failed capture vanc line %d\n", i );
                                                }
-                                               vanc->Release();
+                                               SAFE_RELEASE(vanc);
                                        }
                                }
 
@@ -439,7 +499,7 @@ public:
                                }
                                if ( timecodeString )
                                        free( (void*) timecodeString );
-                               timecode->Release();
+                               SAFE_RELEASE( timecode );
                        }
                }
                else
@@ -634,7 +694,8 @@ mlt_producer producer_decklink_init( mlt_profile profile, mlt_service_type type,
        // If allocated and initializes
        if ( decklink && !mlt_producer_init( producer, decklink ) )
        {
-               if ( decklink->open( arg? atoi( arg ) : 0 ) )
+               if ( decklink->listDevices( MLT_PRODUCER_PROPERTIES( producer ) ) &&
+                        decklink->open( arg? atoi( arg ) : 0 ) )
                {
                        mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );