2 * producer_decklink.c -- input from Blackmagic Design DeckLink
3 * Copyright (C) 2011 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 class DeckLinkProducer
30 : public IDeckLinkInputCallback
33 mlt_producer_s m_producer;
34 IDeckLink* m_decklink;
35 IDeckLinkInput* m_decklinkInput;
37 pthread_mutex_t m_mutex;
38 pthread_cond_t m_condition;
43 BMDDisplayMode getDisplayMode( mlt_profile profile )
45 IDeckLinkDisplayModeIterator* iter;
46 IDeckLinkDisplayMode* mode;
47 BMDDisplayMode result = bmdDisplayModeNotSupported;
49 if ( m_decklinkInput->GetDisplayModeIterator( &iter ) == S_OK )
51 while ( !result && iter->Next( &mode ) == S_OK )
53 int width = mode->GetWidth();
54 int height = mode->GetHeight();
55 BMDTimeValue duration;
56 BMDTimeScale timescale;
57 mode->GetFrameRate( &duration, ×cale );
58 double fps = (double) timescale / duration;
59 int p = mode->GetFieldDominance() == bmdProgressiveFrame;
60 mlt_log_verbose( getProducer(), "BMD mode %dx%d %.3f fps prog %d\n", width, height, fps, p );
62 if ( width == profile->width && height == profile->height && p == profile->progressive
63 && fps == mlt_profile_fps( profile ) )
64 result = mode->GetDisplayMode();
73 mlt_producer getProducer()
74 { return &m_producer; }
78 if ( m_decklinkInput )
79 m_decklinkInput->Release();
81 m_decklink->Release();
85 mlt_deque_close( m_queue );
86 pthread_mutex_destroy( &m_mutex );
87 pthread_cond_destroy( &m_condition );
91 bool open( mlt_profile profile, unsigned card = 0 )
93 IDeckLinkIterator* decklinkIterator = CreateDeckLinkIteratorInstance();
96 if ( !decklinkIterator )
97 throw "The DeckLink drivers are not installed.";
99 // Connect to the Nth DeckLink instance
102 if ( decklinkIterator->Next( &m_decklink ) != S_OK )
103 throw "DeckLink card not found.";
104 } while ( ++i <= card );
105 decklinkIterator->Release();
107 // Get the input interface
108 if ( m_decklink->QueryInterface( IID_IDeckLinkInput, (void**) &m_decklinkInput ) != S_OK )
109 throw "No DeckLink cards support input.";
111 // Provide this class as a delegate to the input callback
112 m_decklinkInput->SetCallback( this );
114 // Initialize other members
115 pthread_mutex_init( &m_mutex, NULL );
116 pthread_cond_init( &m_condition, NULL );
117 m_queue = mlt_deque_init();
120 m_isBuffering = true;
122 catch ( const char *error )
124 if ( decklinkIterator )
125 decklinkIterator->Release();
126 mlt_log_error( getProducer(), "%s\n", error );
132 bool start( mlt_profile profile = 0 )
139 profile = mlt_service_profile( MLT_PRODUCER_SERVICE( getProducer() ) );
141 // Get the display mode
142 BMDDisplayMode displayMode = getDisplayMode( profile );
143 if ( displayMode == bmdDisplayModeNotSupported )
144 throw "Profile is not compatible with decklink.";
146 // Enable video capture
147 BMDPixelFormat pixelFormat = bmdFormat8BitYUV;
148 BMDVideoInputFlags flags = bmdVideoInputFlagDefault;
149 if ( S_OK != m_decklinkInput->EnableVideoInput( displayMode, pixelFormat, flags ) )
150 throw "Failed to enable video capture.";
152 // Enable audio capture
153 BMDAudioSampleRate sampleRate = bmdAudioSampleRate48kHz;
154 BMDAudioSampleType sampleType = bmdAudioSampleType16bitInteger;
155 int channels = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "channels" );
156 if ( S_OK != m_decklinkInput->EnableAudioInput( sampleRate, sampleType, channels ) )
157 throw "Failed to enable audio capture.";
161 mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "dropped", m_dropped );
162 m_started = m_decklinkInput->StartStreams() == S_OK;
164 throw "Failed to start capture.";
166 catch ( const char *error )
168 m_decklinkInput->DisableVideoInput();
169 mlt_log_error( getProducer(), "%s\n", error );
180 // Release the wait in getFrame
181 pthread_mutex_lock( &m_mutex );
182 pthread_cond_broadcast( &m_condition );
183 pthread_mutex_unlock( &m_mutex );
185 m_decklinkInput->StopStreams();
188 pthread_mutex_lock( &m_mutex );
189 while ( mlt_frame frame = (mlt_frame) mlt_deque_pop_back( m_queue ) )
190 mlt_frame_close( frame );
191 pthread_mutex_unlock( &m_mutex );
198 mlt_frame frame = NULL;
201 double fps = mlt_producer_get_fps( getProducer() );
203 // Allow the buffer to fill to the requested initial buffer level.
206 int prefill = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "prefill" );
207 int buffer = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "buffer" );
209 m_isBuffering = false;
210 prefill = prefill > buffer ? buffer : prefill;
211 pthread_mutex_lock( &m_mutex );
212 while ( mlt_deque_count( m_queue ) < prefill )
214 // Wait up to buffer/fps seconds
215 gettimeofday( &now, NULL );
216 long usec = now.tv_sec * 1000000 + now.tv_usec;
217 usec += 1000000 * buffer / fps;
218 tm.tv_sec = usec / 1000000;
219 tm.tv_nsec = (usec % 1000000) * 1000;
220 if ( pthread_cond_timedwait( &m_condition, &m_mutex, &tm ) )
223 pthread_mutex_unlock( &m_mutex );
226 // Wait if queue is empty
227 pthread_mutex_lock( &m_mutex );
228 while ( mlt_deque_count( m_queue ) < 1 )
230 // Wait up to twice frame duration
231 gettimeofday( &now, NULL );
232 tm.tv_sec = now.tv_sec;
233 now.tv_usec += 2000000 / fps;
234 tm.tv_nsec = now.tv_usec * 1000;
235 if ( pthread_cond_timedwait( &m_condition, &m_mutex, &tm ) )
236 // Stop waiting if error (timed out)
240 // Get the first frame from the queue
241 frame = ( mlt_frame ) mlt_deque_pop_front( m_queue );
242 pthread_mutex_unlock( &m_mutex );
244 // Set frame timestamp and properties
247 mlt_profile profile = mlt_service_profile( MLT_PRODUCER_SERVICE( getProducer() ) );
248 mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
249 mlt_properties_set_int( properties, "progressive", profile->progressive );
250 mlt_properties_set_double( properties, "aspect_ratio", mlt_profile_sar( profile ) );
251 mlt_properties_set_int( properties, "width", profile->width );
252 mlt_properties_set_int( properties, "real_width", profile->width );
253 mlt_properties_set_int( properties, "height", profile->height );
254 mlt_properties_set_int( properties, "real_height", profile->height );
255 mlt_properties_set_int( properties, "format", mlt_image_yuv422 );
256 mlt_properties_set_int( properties, "audio_frequency", 48000 );
257 mlt_properties_set_int( properties, "audio_channels",
258 mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "channels" ) );
263 // *** DeckLink API implementation of IDeckLinkInputCallback *** //
265 // IUnknown needs only a dummy implementation
266 virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID iid, LPVOID *ppv )
267 { return E_NOINTERFACE; }
268 virtual ULONG STDMETHODCALLTYPE AddRef()
270 virtual ULONG STDMETHODCALLTYPE Release()
273 /************************* DeckLink API Delegate Methods *****************************/
275 virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(
276 IDeckLinkVideoInputFrame* video,
277 IDeckLinkAudioInputPacket* audio )
280 mlt_frame frame = mlt_frame_init( MLT_PRODUCER_SERVICE( getProducer() ) );
285 if ( !( video->GetFlags() & bmdFrameHasNoInputSource ) )
287 int size = video->GetRowBytes() * video->GetHeight();
288 void* image = mlt_pool_alloc( size );
291 video->GetBytes( &buffer );
292 if ( image && buffer )
294 swab( buffer, image, size );
295 mlt_frame_set_image( frame, (uint8_t*) image, size, mlt_pool_release );
299 mlt_log_verbose( getProducer(), "no video\n" );
300 mlt_pool_release( image );
305 mlt_log_verbose( getProducer(), "no signal\n" );
306 mlt_frame_close( frame );
312 mlt_log_verbose( getProducer(), "no video\n" );
313 mlt_frame_close( frame );
318 if ( frame && audio )
320 int channels = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "channels" );
321 int size = audio->GetSampleFrameCount() * channels * sizeof(int16_t);
322 mlt_audio_format format = mlt_audio_s16;
323 void* pcm = mlt_pool_alloc( size );
326 audio->GetBytes( &buffer );
329 memcpy( pcm, buffer, size );
330 mlt_frame_set_audio( frame, pcm, format, size, mlt_pool_release );
331 mlt_properties_set_int( MLT_FRAME_PROPERTIES(frame), "audio_samples", audio->GetSampleFrameCount() );
335 mlt_log_verbose( getProducer(), "no audio\n" );
336 mlt_pool_release( pcm );
341 mlt_log_verbose( getProducer(), "no audio\n" );
344 // Put frame in queue
347 int queueMax = mlt_properties_get_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "buffer" );
348 pthread_mutex_lock( &m_mutex );
349 if ( mlt_deque_count( m_queue ) < queueMax )
351 mlt_deque_push_back( m_queue, frame );
352 pthread_cond_broadcast( &m_condition );
356 mlt_frame_close( frame );
357 mlt_properties_set_int( MLT_PRODUCER_PROPERTIES( getProducer() ), "dropped", ++m_dropped );
358 mlt_log_warning( getProducer(), "frame dropped %d\n", m_dropped );
360 pthread_mutex_unlock( &m_mutex );
366 virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(
367 BMDVideoInputFormatChangedEvents events,
368 IDeckLinkDisplayMode* mode,
369 BMDDetectedVideoInputFormatFlags flags )
375 static int get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
377 return mlt_frame_get_audio( frame, (void**) buffer, format, frequency, channels, samples );
380 static int get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, int *width, int *height, int writable )
382 return mlt_frame_get_image( frame, buffer, format, width, height, writable );
385 static int get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
387 DeckLinkProducer* decklink = (DeckLinkProducer*) producer->child;
389 // Get the next frame from the decklink object
390 *frame = decklink->getFrame();
392 *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) );
394 // Calculate the next timecode
395 mlt_frame_set_position( *frame, mlt_producer_position( producer ) );
396 mlt_producer_prepare_next( producer );
398 // Add audio and video getters
399 mlt_frame_push_audio( *frame, (void*) get_audio );
400 mlt_frame_push_get_image( *frame, get_image );
405 static void producer_close( mlt_producer producer )
407 producer->close = NULL;
408 mlt_producer_close( producer );
409 delete (DeckLinkProducer*) producer->child;
414 /** Initialise the producer.
417 mlt_producer producer_decklink_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
419 // Allocate the producer
420 DeckLinkProducer* decklink = new DeckLinkProducer();
421 mlt_producer producer = NULL;
423 // If allocated and initializes
424 if ( decklink && !mlt_producer_init( decklink->getProducer(), decklink ) )
426 if ( decklink->open( profile, arg? atoi( arg ) : 0 ) )
428 producer = decklink->getProducer();
429 mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer );
432 producer->close = (mlt_destructor) producer_close;
433 producer->get_frame = get_frame;
436 mlt_properties_set( properties, "resource", arg? arg : "0" );
437 mlt_properties_set_int( properties, "channels", 2 );
438 mlt_properties_set_int( properties, "buffer", 25 );
439 mlt_properties_set_int( properties, "prefill", 25 );
441 // These properties effectively make it infinite.
442 mlt_properties_set_int( properties, "length", INT_MAX );
443 mlt_properties_set_int( properties, "out", INT_MAX - 1 );
444 mlt_properties_set( properties, "eof", "loop" );
447 if ( !decklink->start( profile ) )
449 producer_close( producer );