X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmodules%2Fdecklink%2Fconsumer_decklink.cpp;h=e6d20e09998373ac179cb0251c4a345aacf30f4c;hb=307a2ef3af84a5dba60a5026a1a24f430a0e0bf2;hp=5fa468da937633815fb4126b31cdd84869830014;hpb=2762a88436a78e235bf0e11586c14a5fd3b4eec9;p=mlt diff --git a/src/modules/decklink/consumer_decklink.cpp b/src/modules/decklink/consumer_decklink.cpp index 5fa468da..e6d20e09 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,9 +73,9 @@ 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 ) + && (int) m_fps == (int) mlt_profile_fps( profile ) && ( m_height == profile->height || ( m_height == 486 && profile->height == 480 ) ) ) result = mode; else @@ -90,10 +83,10 @@ private: } SAFE_RELEASE( iter ); } - + return result; } - + public: mlt_consumer getConsumer() { return &m_consumer; } @@ -104,16 +97,17 @@ public: m_deckLinkKeyer = NULL; m_deckLinkOutput = NULL; m_deckLink = NULL; + m_decklinkFrame = NULL; } - ~DeckLinkConsumer() + virtual ~DeckLinkConsumer() { SAFE_RELEASE( m_displayMode ); SAFE_RELEASE( m_deckLinkKeyer ); SAFE_RELEASE( m_deckLinkOutput ); SAFE_RELEASE( m_deckLink ); } - + bool open( unsigned card = 0 ) { unsigned i = 0; @@ -133,7 +127,7 @@ public: } #else IDeckLinkIterator* deckLinkIterator = CreateDeckLinkIteratorInstance(); - + if ( !deckLinkIterator ) { mlt_log_error( getConsumer(), "The DeckLink drivers not installed.\n" ); @@ -163,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 ) @@ -188,19 +182,22 @@ public: // Provide this class as a delegate to the audio and video output interfaces m_deckLinkOutput->SetScheduledFrameCompletionCallback( this ); - + return true; } void* preroll_thread() { + mlt_properties properties = MLT_CONSUMER_PROPERTIES( getConsumer() ); + // preroll frames - for ( unsigned i = 0; i < m_preroll; i++ ) + for ( unsigned i = 0; i < m_preroll && mlt_properties_get_int( properties, "running" ); i++ ) ScheduleNextFrame( true ); // start scheduled playback - m_deckLinkOutput->StartScheduledPlayback( 0, m_timescale, 1.0 ); + if ( mlt_properties_get_int( properties, "running" ) ) + m_deckLinkOutput->StartScheduledPlayback( 0, m_timescale, 1.0 ); return 0; } @@ -231,7 +228,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" ) ) ) { @@ -272,15 +269,15 @@ public: m_preroll = preroll; m_reprio = false; - // Do preroll in thread to ensure asynchronicity of mlt_consumer_start(). - pthread_create( &m_prerollThread, NULL, preroll_thread_proxy, this ); - // Set the running state mlt_properties_set_int( properties, "running", 1 ); + // Do preroll in thread to ensure asynchronicity of mlt_consumer_start(). + pthread_create( &m_prerollThread, NULL, preroll_thread_proxy, this ); + return true; } - + bool stop() { mlt_properties properties = MLT_CONSUMER_PROPERTIES( getConsumer() ); @@ -288,7 +285,9 @@ public: // set running state is 0 mlt_properties_set_int( properties, "running", 0 ); - mlt_consumer_stopped( getConsumer() ); + + if ( wasRunning ) + pthread_join( m_prerollThread, NULL ); // Stop the audio and video output streams immediately if ( m_deckLinkOutput ) @@ -301,8 +300,7 @@ public: // release decklink frame SAFE_RELEASE( m_decklinkFrame ); - if ( wasRunning ) - pthread_join( m_prerollThread, NULL ); + mlt_consumer_stopped( getConsumer() ); return true; } @@ -317,15 +315,17 @@ public: if ( !mlt_frame_get_audio( frame, (void**) &pcm, &format, &frequency, &m_channels, &samples ) ) { #ifdef WIN32 +#define DECKLINK_UNSIGNED_FORMAT "%lu" unsigned long written = 0; #else +#define DECKLINK_UNSIGNED_FORMAT "%u" uint32_t written = 0; #endif BMDTimeValue streamTime = m_count * frequency * m_duration / m_timescale; m_deckLinkOutput->GetBufferedAudioSampleFrameCount( &written ); if ( written > (m_preroll + 1) * samples ) { - mlt_log_verbose( getConsumer(), "renderAudio: will flush %lu audiosamples\n", written ); + mlt_log_verbose( getConsumer(), "renderAudio: will flush " DECKLINK_UNSIGNED_FORMAT " audiosamples\n", written ); m_deckLinkOutput->FlushBufferedAudioSamples(); }; #ifdef WIN32 @@ -335,7 +335,7 @@ public: #endif if ( written != (uint32_t) samples ) - mlt_log_verbose( getConsumer(), "renderAudio: samples=%d, written=%lu\n", samples, written ); + mlt_log_verbose( getConsumer(), "renderAudio: samples=%d, written=" DECKLINK_UNSIGNED_FORMAT "\n", samples, written ); } } @@ -356,7 +356,7 @@ public: stop(); return false; } - + // Make the first line black for field order correction. if ( S_OK == frame->GetBytes( (void**) &buffer ) && buffer ) { @@ -416,9 +416,9 @@ public: // Normal non-keyer playout - needs byte swapping if ( !progressive && m_displayMode->GetFieldDominance() == bmdUpperFieldFirst ) // convert lower field first to top field first - swab( (char*) image, (char*) buffer + stride, stride * ( height - 1 ) ); + swab2( (char*) image, (char*) buffer + stride, stride * ( height - 1 ) ); else - swab( (char*) image, (char*) buffer, stride * height ); + swab2( (char*) image, (char*) buffer, stride * height ); } else if ( !mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "test_image" ) ) { @@ -475,7 +475,7 @@ public: return result; } - + // *** DeckLink API implementation of IDeckLinkVideoOutputCallback IDeckLinkAudioOutputCallback *** // // IUnknown needs only a dummy implementation @@ -485,9 +485,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 ) @@ -536,8 +536,8 @@ public: if ( cnt != m_acnt ) { mlt_log_debug( getConsumer(), - "ScheduledFrameCompleted: GetBufferedAudioSampleFrameCount %u -> %lu, m_count=%"PRIu64"\n", - m_acnt, cnt, m_count ); + "ScheduledFrameCompleted: GetBufferedAudioSampleFrameCount %u -> " DECKLINK_UNSIGNED_FORMAT + ", m_count=%"PRIu64"\n", m_acnt, cnt, m_count ); m_acnt = cnt; } @@ -569,7 +569,7 @@ public: { return mlt_consumer_is_stopped( getConsumer() ) ? S_FALSE : S_OK; } - + void ScheduleNextFrame( bool preroll ) { @@ -677,16 +677,18 @@ static void on_property_changed( void*, mlt_properties properties, const char *n { if ( decklink->QueryInterface( IID_IDeckLinkOutput, (void**) &decklinkOutput ) == S_OK ) { - char *name = NULL; - if ( decklink->GetModelName( (const char**) &name ) == 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 ); + mlt_properties_set( properties, key, name_cstr ); free( key ); - free( name ); + freeDLString( name ); + freeCString( name_cstr ); } SAFE_RELEASE( decklinkOutput ); }