X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmodules%2Fdecklink%2Fproducer_decklink.cpp;h=877c0eacc400742e3ea686e92eb3b2613b74f94e;hb=307a2ef3af84a5dba60a5026a1a24f430a0e0bf2;hp=93489091d8dc46955eceaf8ed8e727b3f4150e85;hpb=edce14a421c21c1a190ade2d16d74753fa0c0511;p=mlt diff --git a/src/modules/decklink/producer_decklink.cpp b/src/modules/decklink/producer_decklink.cpp index 93489091..877c0eac 100644 --- a/src/modules/decklink/producer_decklink.cpp +++ b/src/modules/decklink/producer_decklink.cpp @@ -24,14 +24,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" class DeckLinkProducer : public IDeckLinkInputCallback @@ -50,6 +43,7 @@ private: int m_colorspace; int m_vancLines; mlt_cache m_cache; + bool m_reprio; BMDDisplayMode getDisplayMode( mlt_profile profile, int vancLines ) { @@ -74,7 +68,7 @@ private: if ( width == profile->width && p == profile->progressive && ( height + vancLines == profile->height || ( height == 486 && profile->height == 480 + vancLines ) ) - && fps == mlt_profile_fps( profile ) ) + && (int) fps == (int) mlt_profile_fps( profile ) ) result = mode->GetDisplayMode(); SAFE_RELEASE( mode ); } @@ -94,11 +88,12 @@ public: DeckLinkProducer() { + m_producer = NULL; m_decklink = NULL; m_decklinkInput = NULL; } - ~DeckLinkProducer() + virtual ~DeckLinkProducer() { if ( m_queue ) { @@ -112,55 +107,6 @@ public: 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 ) { IDeckLinkIterator* decklinkIterator = NULL; @@ -178,7 +124,6 @@ public: if ( !decklinkIterator ) throw "The DeckLink drivers are not installed."; #endif - // Connect to the Nth DeckLink instance for ( unsigned i = 0; decklinkIterator->Next( &m_decklink ) == S_OK ; i++) { @@ -299,6 +244,8 @@ public: pthread_mutex_unlock( &m_mutex ); m_decklinkInput->StopStreams(); + m_decklinkInput->DisableVideoInput(); + m_decklinkInput->DisableAudioInput(); // Cleanup queue pthread_mutex_lock( &m_mutex ); @@ -309,12 +256,11 @@ public: mlt_frame getFrame() { - mlt_frame frame = NULL; struct timeval now; struct timespec tm; double fps = mlt_producer_get_fps( getProducer() ); mlt_position position = mlt_producer_position( getProducer() ); - mlt_cache_item cached = mlt_cache_get( m_cache, (void*) position ); + mlt_frame frame = mlt_cache_get_frame( m_cache, position ); // Allow the buffer to fill to the requested initial buffer level. if ( m_isBuffering ) @@ -339,13 +285,7 @@ public: pthread_mutex_unlock( &m_mutex ); } - if ( cached ) - { - // Copy cached frame instead of pulling from queue - frame = mlt_frame_clone( (mlt_frame) mlt_cache_item_data( cached, NULL ), 0 ); - mlt_cache_item_close( cached ); - } - else + if ( !frame ) { // Wait if queue is empty pthread_mutex_lock( &m_mutex ); @@ -366,8 +306,10 @@ public: // add to cache if ( frame ) - mlt_cache_put( m_cache, (void*) position, mlt_frame_clone( frame, 1 ), 0, - (mlt_destructor) mlt_frame_close ); + { + mlt_frame_set_position( frame, position ); + mlt_cache_put_frame( m_cache, frame ); + } } // Set frame timestamp and properties @@ -416,6 +358,43 @@ public: IDeckLinkVideoInputFrame* video, IDeckLinkAudioInputPacket* audio ) { + if( !m_reprio ) + { + mlt_properties properties = MLT_PRODUCER_PROPERTIES( getProducer() ); + + if ( mlt_properties_get( properties, "priority" ) ) + { + int r; + pthread_t thread; + pthread_attr_t tattr; + struct sched_param param; + + pthread_attr_init(&tattr); + pthread_attr_setschedpolicy(&tattr, SCHED_FIFO); + + if ( !strcmp( "max", mlt_properties_get( properties, "priority" ) ) ) + param.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1; + else if ( !strcmp( "min", mlt_properties_get( properties, "priority" ) ) ) + param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 1; + else + param.sched_priority = mlt_properties_get_int( properties, "priority" ); + + pthread_attr_setschedparam(&tattr, ¶m); + + thread = pthread_self(); + + r = pthread_setschedparam(thread, SCHED_FIFO, ¶m); + if( r ) + mlt_log_verbose( getProducer(), + "VideoInputFrameArrived: pthread_setschedparam returned %d\n", r); + else + mlt_log_verbose( getProducer(), + "VideoInputFrameArrived: param.sched_priority=%d\n", param.sched_priority); + }; + + m_reprio = true; + }; + if ( mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "preview" ) && mlt_producer_get_speed( getProducer() ) == 0.0 && !mlt_deque_count( m_queue )) { @@ -453,7 +432,7 @@ public: for ( int i = 1; i < m_vancLines + 1; i++ ) { if ( vanc->GetBufferForVerticalBlankingLine( i, &buffer ) == S_OK ) - swab( (char*) buffer, (char*) image + ( i - 1 ) * video->GetRowBytes(), video->GetRowBytes() ); + swab2( (char*) buffer, (char*) image + ( i - 1 ) * video->GetRowBytes(), video->GetRowBytes() ); else mlt_log_debug( getProducer(), "failed capture vanc line %d\n", i ); } @@ -466,7 +445,7 @@ public: if ( image && buffer ) { size = video->GetRowBytes() * video->GetHeight(); - swab( (char*) buffer, (char*) image + m_vancLines * video->GetRowBytes(), size ); + swab2( (char*) buffer, (char*) image + m_vancLines * video->GetRowBytes(), size ); mlt_frame_set_image( frame, (uint8_t*) image, size, mlt_pool_release ); } else if ( image ) @@ -486,19 +465,16 @@ public: IDeckLinkTimecode* timecode = 0; if ( video->GetTimecode( bmdTimecodeVITC, &timecode ) == S_OK && timecode ) { - const char* timecodeString = 0; + DLString timecodeString = 0; -#ifdef WIN32 - if ( timecode->GetString( (BSTR*) &timecodeString ) == S_OK ) -#else if ( timecode->GetString( &timecodeString ) == S_OK ) -#endif { - mlt_properties_set( MLT_FRAME_PROPERTIES( frame ), "meta.attr.vitc.markup", timecodeString ); - mlt_log_debug( getProducer(), "timecode %s\n", timecodeString ); + char* s = getCString( timecodeString ); + mlt_properties_set( MLT_FRAME_PROPERTIES( frame ), "meta.attr.vitc.markup", s ); + mlt_log_debug( getProducer(), "timecode %s\n", s ); + freeCString( s ); } - if ( timecodeString ) - free( (void*) timecodeString ); + freeDLString( timecodeString ); SAFE_RELEASE( timecode ); } } @@ -550,7 +526,7 @@ public: { mlt_frame_close( frame ); mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "dropped", ++m_dropped ); - mlt_log_warning( getProducer(), "frame dropped %d\n", m_dropped ); + mlt_log_warning( getProducer(), "buffer overrun, frame dropped %d\n", m_dropped ); } pthread_mutex_unlock( &m_mutex ); } @@ -659,7 +635,6 @@ static int get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) *frame = mlt_frame_init( MLT_PRODUCER_SERVICE(producer) ); // Calculate the next timecode - mlt_frame_set_position( *frame, mlt_producer_position( producer ) ); mlt_producer_prepare_next( producer ); // Close DeckLink if at end @@ -682,6 +657,53 @@ static void producer_close( mlt_producer producer ) 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* decklinkInput = 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_IDeckLinkInput, (void**) &decklinkInput ) == 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( decklinkInput ); + } + SAFE_RELEASE( decklink ); + } + SAFE_RELEASE( decklinkIterator ); + mlt_properties_set_int( properties, "devices", i ); +} + /** Initialise the producer. */ @@ -694,8 +716,7 @@ 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->listDevices( MLT_PRODUCER_PROPERTIES( producer ) ) && - decklink->open( arg? atoi( arg ) : 0 ) ) + if ( decklink->open( arg? atoi( arg ) : 0 ) ) { mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); @@ -717,6 +738,9 @@ mlt_producer producer_decklink_init( mlt_profile profile, mlt_service_type type, mlt_properties_set_int( properties, "length", INT_MAX ); mlt_properties_set_int( properties, "out", INT_MAX - 1 ); mlt_properties_set( properties, "eof", "loop" ); + + 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 ); } }