#include "DeckLinkAPI.h"
#endif
+#define SAFE_RELEASE(V) if (V) { V->Release(); V = NULL; }
+
class DeckLinkProducer
: public IDeckLinkInputCallback
{
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 )
&& ( 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;
mlt_producer getProducer() const
{ return m_producer; }
+ DeckLinkProducer()
+ {
+ m_decklink = NULL;
+ m_decklinkInput = NULL;
+ }
+
~DeckLinkProducer()
{
if ( m_queue )
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 )
#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 )
}
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;
}
{
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" );
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 );
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;
else
mlt_log_debug( getProducer(), "failed capture vanc line %d\n", i );
}
- vanc->Release();
+ SAFE_RELEASE(vanc);
}
}
}
if ( timecodeString )
free( (void*) timecodeString );
- timecode->Release();
+ SAFE_RELEASE( timecode );
}
}
else
// 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 );