X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmodules%2Fdecklink%2Fconsumer_decklink.cpp;h=ee9ce7a8396b721517ce4acdc47e66178c336037;hb=b39198884603dd87583b21c840eb595dcaf3708c;hp=288e52f2a3ea8e0f4bec4b65f6c7027ca6b13cc5;hpb=edce14a421c21c1a190ade2d16d74753fa0c0511;p=mlt diff --git a/src/modules/decklink/consumer_decklink.cpp b/src/modules/decklink/consumer_decklink.cpp index 288e52f2..ee9ce7a8 100644 --- a/src/modules/decklink/consumer_decklink.cpp +++ b/src/modules/decklink/consumer_decklink.cpp @@ -26,14 +26,7 @@ #include #include #include -#ifdef WIN32 -#include -#include "DeckLinkAPI_h.h" -#else -#include "DeckLinkAPI.h" -#endif - -#define SAFE_RELEASE(V) if (V) { V->Release(); V = NULL; } +#include "common.h" static const unsigned PREROLL_MINIMUM = 3; @@ -69,7 +62,7 @@ private: IDeckLinkDisplayModeIterator* iter = NULL; IDeckLinkDisplayMode* mode = NULL; IDeckLinkDisplayMode* result = 0; - + if ( m_deckLinkOutput->GetDisplayModeIterator( &iter ) == S_OK ) { while ( !result && iter->Next( &mode ) == S_OK ) @@ -80,7 +73,7 @@ private: m_fps = (double) m_timescale / m_duration; int p = mode->GetFieldDominance() == bmdProgressiveFrame; mlt_log_verbose( getConsumer(), "BMD mode %dx%d %.3f fps prog %d\n", m_width, m_height, m_fps, p ); - + if ( m_width == profile->width && p == profile->progressive && m_fps == mlt_profile_fps( profile ) && ( m_height == profile->height || ( m_height == 486 && profile->height == 480 ) ) ) @@ -90,10 +83,10 @@ private: } SAFE_RELEASE( iter ); } - + return result; } - + public: mlt_consumer getConsumer() { return &m_consumer; } @@ -104,6 +97,7 @@ public: m_deckLinkKeyer = NULL; m_deckLinkOutput = NULL; m_deckLink = NULL; + m_decklinkFrame = NULL; } ~DeckLinkConsumer() @@ -113,58 +107,6 @@ public: SAFE_RELEASE( m_deckLinkOutput ); 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_IDeckLinkOutput, (void**) &m_deckLinkOutput ) == 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 ); - mlt_log_verbose( NULL, "[consumer decklink] %s = %s\n", key, name ); - free( key ); - free( name ); - } - SAFE_RELEASE( m_deckLinkOutput ); - } - SAFE_RELEASE( m_deckLink ); - } - SAFE_RELEASE( decklinkIterator ); - mlt_properties_set_int( properties, "devices", i ); - mlt_log_verbose( NULL, "[consumer decklink] devices = %d\n", i ); - - return true; - } - catch ( const char *error ) - { - SAFE_RELEASE( decklinkIterator ); - mlt_log_error( getConsumer(), "%s\n", error ); - return false; - } - } bool open( unsigned card = 0 ) { @@ -185,7 +127,7 @@ public: } #else IDeckLinkIterator* deckLinkIterator = CreateDeckLinkIteratorInstance(); - + if ( !deckLinkIterator ) { mlt_log_error( getConsumer(), "The DeckLink drivers not installed.\n" ); @@ -215,7 +157,7 @@ public: SAFE_RELEASE( m_deckLink ); return false; } - + // Get the keyer interface IDeckLinkAttributes *deckLinkAttributes = 0; if ( m_deckLink->QueryInterface( IID_IDeckLinkAttributes, (void**) &deckLinkAttributes ) == S_OK ) @@ -240,7 +182,7 @@ public: // Provide this class as a delegate to the audio and video output interfaces m_deckLinkOutput->SetScheduledFrameCompletionCallback( this ); - + return true; } @@ -283,7 +225,7 @@ public: mlt_log_error( getConsumer(), "Profile is not compatible with decklink.\n" ); return false; } - + // Set the keyer if ( m_deckLinkKeyer && ( m_isKeyer = mlt_properties_get_int( properties, "keyer" ) ) ) { @@ -332,7 +274,7 @@ public: return true; } - + bool stop() { mlt_properties properties = MLT_CONSUMER_PROPERTIES( getConsumer() ); @@ -408,7 +350,7 @@ public: stop(); return false; } - + // Make the first line black for field order correction. if ( S_OK == frame->GetBytes( (void**) &buffer ) && buffer ) { @@ -527,7 +469,7 @@ public: return result; } - + // *** DeckLink API implementation of IDeckLinkVideoOutputCallback IDeckLinkAudioOutputCallback *** // // IUnknown needs only a dummy implementation @@ -537,9 +479,9 @@ public: { return 1; } virtual ULONG STDMETHODCALLTYPE Release() { return 1; } - + /************************* DeckLink API Delegate Methods *****************************/ - + virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted( IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult completed ) { if( !m_reprio ) @@ -621,7 +563,7 @@ public: { return mlt_consumer_is_stopped( getConsumer() ) ? S_FALSE : S_OK; } - + void ScheduleNextFrame( bool preroll ) { @@ -703,6 +645,53 @@ static void close( mlt_consumer consumer ) extern "C" { +// Listen for the list_devices property to be set +static void on_property_changed( void*, mlt_properties properties, const char *name ) +{ + IDeckLinkIterator* decklinkIterator = NULL; + IDeckLink* decklink = NULL; + IDeckLinkInput* decklinkOutput = NULL; + int i = 0; + + if ( name && !strcmp( name, "list_devices" ) ) + mlt_event_block( (mlt_event) mlt_properties_get_data( properties, "list-devices-event", NULL ) ); + else + return; + +#ifdef WIN32 + if ( FAILED( CoInitialize( NULL ) ) ) + return; + if ( FAILED( CoCreateInstance( CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**) &decklinkIterator ) ) ) + return; +#else + if ( !( decklinkIterator = CreateDeckLinkIteratorInstance() ) ) + return; +#endif + for ( ; decklinkIterator->Next( &decklink ) == S_OK; i++ ) + { + if ( decklink->QueryInterface( IID_IDeckLinkOutput, (void**) &decklinkOutput ) == S_OK ) + { + DLString name = NULL; + if ( decklink->GetModelName( &name ) == S_OK ) + { + char *name_cstr = getCString( name ); + const char *format = "device.%d"; + char *key = (char*) calloc( 1, strlen( format ) + 1 ); + + sprintf( key, format, i ); + mlt_properties_set( properties, key, name_cstr ); + free( key ); + freeDLString( name ); + freeCString( name_cstr ); + } + SAFE_RELEASE( decklinkOutput ); + } + SAFE_RELEASE( decklink ); + } + SAFE_RELEASE( decklinkIterator ); + mlt_properties_set_int( properties, "devices", i ); +} + /** Initialise the consumer. */ @@ -716,17 +705,20 @@ mlt_consumer consumer_decklink_init( mlt_profile profile, mlt_service_type type, if ( decklink && !mlt_consumer_init( decklink->getConsumer(), decklink, profile ) ) { // If initialises without error - if ( decklink->listDevices( MLT_CONSUMER_PROPERTIES( decklink->getConsumer() ) ) && - decklink->open( arg? atoi(arg) : 0 ) ) + if ( decklink->open( arg? atoi(arg) : 0 ) ) { consumer = decklink->getConsumer(); - + mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer ); + // Setup callbacks consumer->close = close; consumer->start = start; consumer->stop = stop; consumer->is_stopped = is_stopped; - mlt_properties_set( MLT_CONSUMER_PROPERTIES(consumer), "deinterlace_method", "onefield" ); + mlt_properties_set( properties, "deinterlace_method", "onefield" ); + + mlt_event event = mlt_events_listen( properties, properties, "property-changed", (mlt_listener) on_property_changed ); + mlt_properties_set_data( properties, "list-devices-event", event, 0, NULL, NULL ); } }