2 * consumer_decklink.c -- output through Blackmagic Design DeckLink
3 * Copyright (C) 2010 Dan Dennedy <dan@dennedy.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with consumer library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <framework/mlt.h>
27 #include "DeckLinkAPI.h"
29 static const unsigned PREROLL_MINIMUM = 3;
36 pthread_mutex_t mutex;
39 static sample_fifo sample_fifo_init()
41 sample_fifo fifo = (sample_fifo) calloc( 1, sizeof( *fifo ) );
42 pthread_mutex_init( &fifo->mutex, NULL );
46 static void sample_fifo_append( sample_fifo fifo, int16_t *samples, int count )
48 pthread_mutex_lock( &fifo->mutex );
49 if ( ( fifo->size - fifo->used ) < count )
51 fifo->size += count * 5;
52 fifo->buffer = (int16_t*) realloc( fifo->buffer, fifo->size * sizeof( int16_t ) );
54 memcpy( fifo->buffer + fifo->used, samples, count * sizeof( int16_t ) );
56 pthread_mutex_unlock( &fifo->mutex );
59 static void sample_fifo_remove( sample_fifo fifo, int count )
61 pthread_mutex_lock( &fifo->mutex );
62 if ( count > fifo->used )
65 memmove( fifo->buffer, fifo->buffer + count, fifo->used * sizeof( int16_t ) );
66 pthread_mutex_unlock( &fifo->mutex );
69 static void sample_fifo_close( sample_fifo fifo )
72 pthread_mutex_destroy( &fifo->mutex );
77 class DeckLinkConsumer
78 : public IDeckLinkVideoOutputCallback
79 , public IDeckLinkAudioOutputCallback
82 mlt_consumer_s m_consumer;
83 IDeckLink* m_deckLink;
84 IDeckLinkOutput* m_deckLinkOutput;
85 IDeckLinkDisplayMode* m_displayMode;
86 pthread_mutex_t m_mutex;
87 pthread_cond_t m_condition;
90 BMDTimeValue m_duration;
91 BMDTimeScale m_timescale;
97 unsigned m_prerollCounter;
99 uint32_t m_maxAudioBuffer;
100 mlt_deque m_videoFrameQ;
105 IDeckLinkKeyer* m_deckLinkKeyer;
107 IDeckLinkDisplayMode* getDisplayMode()
109 mlt_profile profile = mlt_service_profile( MLT_CONSUMER_SERVICE( getConsumer() ) );
110 IDeckLinkDisplayModeIterator* iter;
111 IDeckLinkDisplayMode* mode;
112 IDeckLinkDisplayMode* result = 0;
114 if ( m_deckLinkOutput->GetDisplayModeIterator( &iter ) == S_OK )
116 while ( !result && iter->Next( &mode ) == S_OK )
118 m_width = mode->GetWidth();
119 m_height = mode->GetHeight();
120 mode->GetFrameRate( &m_duration, &m_timescale );
121 m_fps = (double) m_timescale / m_duration;
122 int p = mode->GetFieldDominance() == bmdProgressiveFrame;
123 mlt_log_verbose( getConsumer(), "BMD mode %dx%d %.3f fps prog %d\n", m_width, m_height, m_fps, p );
125 if ( m_width == profile->width && m_height == profile->height && p == profile->progressive
126 && m_fps == mlt_profile_fps( profile ) )
135 mlt_consumer getConsumer()
136 { return &m_consumer; }
137 uint64_t isBuffering() const
138 { return m_prerollCounter < m_preroll; }
142 if ( m_deckLinkKeyer )
143 m_deckLinkKeyer->Release();
144 if ( m_deckLinkOutput )
145 m_deckLinkOutput->Release();
147 m_deckLink->Release();
150 mlt_deque_close( m_videoFrameQ );
151 pthread_mutex_destroy( &m_mutex );
152 pthread_cond_destroy( &m_condition );
156 bool open( unsigned card = 0 )
158 IDeckLinkIterator* deckLinkIterator = CreateDeckLinkIteratorInstance();
161 if ( !deckLinkIterator )
163 mlt_log_error( getConsumer(), "The DeckLink drivers not installed.\n" );
167 // Connect to the Nth DeckLink instance
169 if ( deckLinkIterator->Next( &m_deckLink ) != S_OK )
171 mlt_log_error( getConsumer(), "DeckLink card not found\n" );
172 deckLinkIterator->Release();
175 } while ( ++i <= card );
176 deckLinkIterator->Release();
178 // Obtain the audio/video output interface (IDeckLinkOutput)
179 if ( m_deckLink->QueryInterface( IID_IDeckLinkOutput, (void**)&m_deckLinkOutput ) != S_OK )
181 mlt_log_error( getConsumer(), "No DeckLink cards support output\n" );
182 m_deckLink->Release();
187 // Get the keyer interface
188 IDeckLinkAttributes *deckLinkAttributes = 0;
190 if ( m_deckLink->QueryInterface( IID_IDeckLinkAttributes, (void**) &deckLinkAttributes ) == S_OK )
193 if ( deckLinkAttributes->GetFlag( BMDDeckLinkSupportsInternalKeying, &flag ) == S_OK && flag )
195 if ( m_deckLink->QueryInterface( IID_IDeckLinkKeyer, (void**) &m_deckLinkKeyer ) != S_OK )
197 mlt_log_error( getConsumer(), "Failed to get keyer\n" );
198 m_deckLinkOutput->Release();
199 m_deckLinkOutput = 0;
200 m_deckLink->Release();
205 deckLinkAttributes->Release();
208 // Provide this class as a delegate to the audio and video output interfaces
209 m_deckLinkOutput->SetScheduledFrameCompletionCallback( this );
210 m_deckLinkOutput->SetAudioCallback( this );
212 pthread_mutex_init( &m_mutex, NULL );
213 pthread_cond_init( &m_condition, NULL );
214 m_maxAudioBuffer = bmdAudioSampleRate48kHz;
215 m_videoFrameQ = mlt_deque_init();
220 bool start( unsigned preroll )
222 mlt_properties properties = MLT_CONSUMER_PROPERTIES( getConsumer() );
224 // Initialize members
228 m_isPrerolling = true;
229 m_prerollCounter = 0;
230 m_preroll = preroll < PREROLL_MINIMUM ? PREROLL_MINIMUM : preroll;
231 m_channels = mlt_properties_get_int( properties, "channels" );
232 m_isAudio = !mlt_properties_get_int( properties, "audio_off" );
234 m_displayMode = getDisplayMode();
235 if ( !m_displayMode )
237 mlt_log_error( getConsumer(), "Profile is not compatible with decklink.\n" );
242 if ( m_deckLinkKeyer && ( m_isKeyer = mlt_properties_get_int( properties, "keyer" ) ) )
244 bool external = (m_isKeyer == 2);
245 double level = mlt_properties_get_double( properties, "keyer_level" );
247 if ( m_deckLinkKeyer->Enable( external ) != S_OK )
248 mlt_log_error( getConsumer(), "Failed to enable %s keyer\n",
249 external ? "external" : "internal" );
250 m_deckLinkKeyer->SetLevel( level <= 1 ? ( level > 0 ? 255 * level : 255 ) : 255 );
254 else if ( m_deckLinkKeyer )
256 m_deckLinkKeyer->Disable();
259 // Set the video output mode
260 if ( S_OK != m_deckLinkOutput->EnableVideoOutput( m_displayMode->GetDisplayMode(), bmdVideoOutputFlagDefault) )
262 mlt_log_error( getConsumer(), "Failed to enable video output\n" );
266 // Set the audio output mode
269 m_deckLinkOutput->DisableAudioOutput();
272 if ( S_OK != m_deckLinkOutput->EnableAudioOutput( bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger,
273 m_channels, bmdAudioOutputStreamContinuous ) )
275 mlt_log_error( getConsumer(), "Failed to enable audio output\n" );
279 m_fifo = sample_fifo_init();
280 m_deckLinkOutput->BeginAudioPreroll();
287 pthread_mutex_lock( &m_mutex );
288 pthread_cond_broadcast( &m_condition );
289 pthread_mutex_unlock( &m_mutex );
297 gettimeofday( &tv, NULL );
298 ts.tv_sec = tv.tv_sec + 1;
299 ts.tv_nsec = tv.tv_usec * 1000;
300 pthread_mutex_lock( &m_mutex );
301 pthread_cond_timedwait( &m_condition, &m_mutex, &ts );
302 pthread_mutex_unlock( &m_mutex );
307 // Stop the audio and video output streams immediately
308 if ( m_deckLinkOutput )
310 m_deckLinkOutput->StopScheduledPlayback( 0, 0, 0 );
311 m_deckLinkOutput->DisableAudioOutput();
312 m_deckLinkOutput->DisableVideoOutput();
314 while ( mlt_deque_count( m_videoFrameQ ) )
316 IDeckLinkMutableVideoFrame* frame = (IDeckLinkMutableVideoFrame*) mlt_deque_pop_back( m_videoFrameQ );
319 if ( m_fifo ) sample_fifo_close( m_fifo );
320 mlt_frame_close( m_frame );
323 void renderAudio( mlt_frame frame )
325 mlt_audio_format format = mlt_audio_s16;
326 int frequency = bmdAudioSampleRate48kHz;
327 int samples = mlt_sample_calculator( m_fps, frequency, m_count );
330 if ( !mlt_frame_get_audio( frame, (void**) &pcm, &format, &frequency, &m_channels, &samples ) )
334 if ( !m_isPrerolling )
336 uint32_t audioCount = 0;
337 uint32_t videoCount = 0;
340 m_deckLinkOutput->GetBufferedAudioSampleFrameCount( &audioCount );
341 m_deckLinkOutput->GetBufferedVideoFrameCount( &videoCount );
343 // Underflow typically occurs during non-normal speed playback.
344 if ( audioCount < 1 || videoCount < 1 )
346 // Upon switching to normal playback, buffer some frames faster than realtime.
347 mlt_log_info( getConsumer(), "buffer underrun: audio buf %u video buf %u frames\n", audioCount, videoCount );
348 m_prerollCounter = 0;
352 if ( videoCount == 0 && isBuffering() )
354 // Only append audio to reach the ideal level and not overbuffer.
355 int ideal = ( m_preroll - 1 ) * bmdAudioSampleRate48kHz / m_fps;
356 int actual = m_fifo->used / m_channels + audioCount;
357 int diff = ideal / 2 - actual;
358 count = diff < 0 ? 0 : diff < count ? diff : count;
362 sample_fifo_append( m_fifo, pcm, count * m_channels );
368 BMDPixelFormat format = m_isKeyer? bmdFormat8BitARGB : bmdFormat8BitYUV;
369 IDeckLinkMutableVideoFrame* frame = 0;
371 int stride = m_width * ( m_isKeyer? 4 : 2 );
373 // Generate a DeckLink video frame
374 if ( S_OK != m_deckLinkOutput->CreateVideoFrame( m_width, m_height,
375 stride, format, bmdFrameFlagDefault, &frame ) )
377 mlt_log_verbose( getConsumer(), "Failed to create video frame\n" );
382 // Make the first line black for field order correction.
383 if ( S_OK == frame->GetBytes( (void**) &buffer ) && buffer )
387 memset( buffer, 0, stride );
389 else for ( int i = 0; i < m_width; i++ )
395 mlt_log_debug( getConsumer(), "created video frame\n" );
396 mlt_deque_push_back( m_videoFrameQ, frame );
403 mlt_image_format format = m_isKeyer? mlt_image_rgb24a : mlt_image_yuv422;
406 if ( !mlt_frame_get_image( m_frame, &image, &format, &m_width, &m_height, 0 ) )
408 IDeckLinkMutableVideoFrame* decklinkFrame = (IDeckLinkMutableVideoFrame*) mlt_deque_pop_back( m_videoFrameQ );
410 int stride = m_width * ( m_isKeyer? 4 : 2 );
412 decklinkFrame->GetBytes( (void**) &buffer );
415 int progressive = mlt_properties_get_int( MLT_FRAME_PROPERTIES( m_frame ), "progressive" );
419 // Normal non-keyer playout - needs byte swapping
420 if ( !progressive && m_displayMode->GetFieldDominance() == bmdUpperFieldFirst )
421 // convert lower field first to top field first
422 swab( image, buffer + stride, stride * ( m_height - 1 ) );
424 swab( image, buffer, stride * m_height );
426 else if ( !mlt_properties_get_int( MLT_FRAME_PROPERTIES( m_frame ), "test_image" ) )
428 // Normal keyer output
429 int y = m_height + 1;
430 uint32_t* s = (uint32_t*) image;
431 uint32_t* d = (uint32_t*) buffer;
433 if ( !progressive && m_displayMode->GetFieldDominance() == bmdUpperFieldFirst )
435 // Correct field order
441 // Need to relocate alpha channel RGBA => ARGB
447 *d++ = ( *s << 8 ) | ( *s >> 24 );
454 // Keying blank frames - nullify alpha
455 memset( buffer, 0, stride * m_height );
457 m_deckLinkOutput->ScheduleVideoFrame( decklinkFrame, m_count * m_duration, m_duration, m_timescale );
459 mlt_deque_push_front( m_videoFrameQ, decklinkFrame );
463 HRESULT render( mlt_frame frame )
465 HRESULT result = S_OK;
468 double speed = mlt_properties_get_double( MLT_FRAME_PROPERTIES(frame), "_speed" );
469 if ( m_isAudio && speed == 1.0 )
470 renderAudio( frame );
472 // Create video frames while pre-rolling
473 if ( m_isPrerolling )
475 if ( !createFrame() )
477 mlt_log_error( getConsumer(), "failed to create video frame\n" );
482 if ( mlt_properties_get_int( MLT_FRAME_PROPERTIES( frame ), "rendered") )
484 // Close the previous frame and use the new one
485 mlt_frame_close( m_frame );
492 // Reuse the last frame
493 mlt_log_verbose( getConsumer(), "dropped video frame %u\n", ++m_dropped );
500 // Check for end of pre-roll
501 if ( ++m_prerollCounter > m_preroll && m_isPrerolling )
503 // Start audio and video output
505 m_deckLinkOutput->EndAudioPreroll();
506 m_deckLinkOutput->StartScheduledPlayback( 0, m_timescale, 1.0 );
507 m_isPrerolling = false;
513 // *** DeckLink API implementation of IDeckLinkVideoOutputCallback IDeckLinkAudioOutputCallback *** //
515 // IUnknown needs only a dummy implementation
516 virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID iid, LPVOID *ppv )
517 { return E_NOINTERFACE; }
518 virtual ULONG STDMETHODCALLTYPE AddRef()
520 virtual ULONG STDMETHODCALLTYPE Release()
523 /************************* DeckLink API Delegate Methods *****************************/
525 virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted( IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult completed )
527 // When a video frame has been released by the API, schedule another video frame to be output
533 virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped()
535 return mlt_consumer_is_stopped( getConsumer() ) ? S_FALSE : S_OK;
538 virtual HRESULT STDMETHODCALLTYPE RenderAudioSamples( bool preroll )
540 // Provide more audio samples to the DeckLink API
541 HRESULT result = S_OK;
543 uint32_t count = m_fifo->used / m_channels;
544 uint32_t buffered = count;
547 // Stay under preferred buffer level
548 && ( S_OK == m_deckLinkOutput->GetBufferedAudioSampleFrameCount( &buffered ) )
549 && buffered < m_maxAudioBuffer )
551 uint32_t written = 0;
553 buffered = m_maxAudioBuffer - buffered;
554 count = buffered > count ? count : buffered;
555 result = m_deckLinkOutput->ScheduleAudioSamples( m_fifo->buffer, count, 0, 0, &written );
557 sample_fifo_remove( m_fifo, written * m_channels );
567 static void *run( void *arg )
569 // Map the argument to the object
570 DeckLinkConsumer* decklink = (DeckLinkConsumer*) arg;
571 mlt_consumer consumer = decklink->getConsumer();
573 // Get the properties
574 mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
576 // Convenience functionality
577 int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" );
581 mlt_frame frame = NULL;
583 // Loop while running
584 while ( !terminated && mlt_properties_get_int( properties, "running" ) )
587 if ( ( frame = mlt_consumer_rt_frame( consumer ) ) )
589 // Check for termination
590 if ( terminate_on_pause )
591 terminated = mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame ), "_speed" ) == 0.0;
593 decklink->render( frame );
594 if ( !decklink->isBuffering() )
596 mlt_events_fire( properties, "consumer-frame-show", frame, NULL );
600 // Indicate that the consumer is stopped
602 mlt_properties_set_int( properties, "running", 0 );
603 mlt_consumer_stopped( consumer );
608 /** Start the consumer.
611 static int start( mlt_consumer consumer )
613 // Get the properties
614 mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
615 DeckLinkConsumer* decklink = (DeckLinkConsumer*) consumer->child;
616 int result = decklink->start( mlt_properties_get_int( properties, "preroll" ) ) ? 0 : 1;
618 // Check that we're not already running
619 if ( !result && !mlt_properties_get_int( properties, "running" ) )
622 pthread_t *pthread = (pthread_t*) calloc( 1, sizeof( pthread_t ) );
624 // Assign the thread to properties
625 mlt_properties_set_data( properties, "pthread", pthread, sizeof( pthread_t ), free, NULL );
627 // Set the running state
628 mlt_properties_set_int( properties, "running", 1 );
629 mlt_properties_set_int( properties, "joined", 0 );
632 pthread_create( pthread, NULL, run, consumer->child );
637 /** Stop the consumer.
640 static int stop( mlt_consumer consumer )
642 // Get the properties
643 mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
645 // Check that we're running
646 if ( !mlt_properties_get_int( properties, "joined" ) )
649 pthread_t *pthread = (pthread_t*) mlt_properties_get_data( properties, "pthread", NULL );
654 mlt_properties_set_int( properties, "running", 0 );
655 mlt_properties_set_int( properties, "joined", 1 );
657 // Wait for termination
658 pthread_join( *pthread, NULL );
665 /** Determine if the consumer is stopped.
668 static int is_stopped( mlt_consumer consumer )
670 // Get the properties
671 mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
672 return !mlt_properties_get_int( properties, "running" );
675 /** Close the consumer.
678 static void close( mlt_consumer consumer )
681 mlt_consumer_stop( consumer );
684 consumer->close = NULL;
685 mlt_consumer_close( consumer );
688 delete (DeckLinkConsumer*) consumer->child;
693 /** Initialise the consumer.
696 mlt_consumer consumer_decklink_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
698 // Allocate the consumer
699 DeckLinkConsumer* decklink = new DeckLinkConsumer();
700 mlt_consumer consumer = NULL;
703 if ( decklink && !mlt_consumer_init( decklink->getConsumer(), decklink, profile ) )
705 // If initialises without error
706 if ( decklink->open( arg? atoi(arg) : 0 ) )
708 consumer = decklink->getConsumer();
711 consumer->close = close;
712 consumer->start = start;
713 consumer->stop = stop;
714 consumer->is_stopped = is_stopped;
722 extern mlt_producer producer_decklink_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg );
724 static mlt_properties metadata( mlt_service_type type, const char *id, void *data )
726 char file[ PATH_MAX ];
727 const char *service_type = NULL;
731 service_type = "consumer";
734 service_type = "producer";
739 snprintf( file, PATH_MAX, "%s/decklink/%s_%s.yml", mlt_environment( "MLT_DATA" ), service_type, id );
740 return mlt_properties_parse_yaml( file );
745 MLT_REGISTER( consumer_type, "decklink", consumer_decklink_init );
746 MLT_REGISTER( producer_type, "decklink", producer_decklink_init );
747 MLT_REGISTER_METADATA( consumer_type, "decklink", metadata, NULL );
748 MLT_REGISTER_METADATA( producer_type, "decklink", metadata, NULL );