From: Dan Dennedy Date: Thu, 29 Sep 2011 03:26:00 +0000 (-0700) Subject: Add re-open capability to decklink producer. X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=034daac171e90da9e79e6d4bb735267a9f17cd6f;p=mlt Add re-open capability to decklink producer. This causes the producer to automatically close itself when it reaches the "end" as defined by an out or length property. Then, the same producer can be re-opened if reused elsewhere in a playlist or another instance of the decklink producer can use the same card. This requires that the decklink producer be permitted to play out to its duration. --- diff --git a/src/modules/decklink/producer_decklink.cpp b/src/modules/decklink/producer_decklink.cpp index 5c81d9f8..8c763a1a 100644 --- a/src/modules/decklink/producer_decklink.cpp +++ b/src/modules/decklink/producer_decklink.cpp @@ -35,7 +35,7 @@ class DeckLinkProducer : public IDeckLinkInputCallback { private: - mlt_producer_s m_producer; + mlt_producer m_producer; IDeckLink* m_decklink; IDeckLinkInput* m_decklinkInput; mlt_deque m_queue; @@ -81,8 +81,11 @@ private: public: - mlt_producer getProducer() - { return &m_producer; } + void setProducer( mlt_producer producer ) + { m_producer = producer; } + + mlt_producer getProducer() const + { return m_producer; } ~DeckLinkProducer() { @@ -99,7 +102,7 @@ public: } } - bool open( mlt_profile profile, unsigned card = 0 ) + bool open( unsigned card = 0 ) { IDeckLinkIterator* decklinkIterator = NULL; try @@ -534,31 +537,54 @@ static int get_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *forma static int get_frame( mlt_producer producer, mlt_frame_ptr frame, int index ) { DeckLinkProducer* decklink = (DeckLinkProducer*) producer->child; + mlt_position pos = mlt_producer_position( producer ); + mlt_position end = mlt_producer_get_playtime( producer ); + end = ( mlt_producer_get_length( producer ) < end ? mlt_producer_get_length( producer ) : end ) - 1; + + // Re-open if needed + if ( !decklink && pos < end ) + { + producer->child = decklink = new DeckLinkProducer(); + decklink->setProducer( producer ); + decklink->open( mlt_properties_get_int( MLT_PRODUCER_PROPERTIES(producer), "resource" ) ); + } // Start if needed - decklink->start( mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) ) ); + if ( decklink ) + { + decklink->start( mlt_service_profile( MLT_PRODUCER_SERVICE( producer ) ) ); - // Get the next frame from the decklink object - *frame = decklink->getFrame(); + // Get the next frame from the decklink object + if ( ( *frame = decklink->getFrame() )) + { + // Add audio and video getters + mlt_frame_push_audio( *frame, (void*) get_audio ); + mlt_frame_push_get_image( *frame, get_image ); + } + } if ( !*frame ) - *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( producer ) ); + *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 ); - // Add audio and video getters - mlt_frame_push_audio( *frame, (void*) get_audio ); - mlt_frame_push_get_image( *frame, get_image ); + // Close DeckLink if at end + if ( pos >= end && decklink ) + { + decklink->stop(); + delete decklink; + producer->child = NULL; + } return 0; } static void producer_close( mlt_producer producer ) { + delete (DeckLinkProducer*) producer->child; producer->close = NULL; mlt_producer_close( producer ); - delete (DeckLinkProducer*) producer->child; } extern "C" { @@ -570,22 +596,25 @@ mlt_producer producer_decklink_init( mlt_profile profile, mlt_service_type type, { // Allocate the producer DeckLinkProducer* decklink = new DeckLinkProducer(); - mlt_producer producer = NULL; + mlt_producer producer = (mlt_producer) calloc( 1, sizeof( *producer ) ); // If allocated and initializes - if ( decklink && !mlt_producer_init( decklink->getProducer(), decklink ) ) + if ( decklink && !mlt_producer_init( producer, decklink ) ) { - if ( decklink->open( profile, arg? atoi( arg ) : 0 ) ) + if ( decklink->open( arg? atoi( arg ) : 0 ) ) { - producer = decklink->getProducer(); mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); + // Close DeckLink and defer re-open to get_frame + delete decklink; + producer->child = NULL; + // Set callbacks producer->close = (mlt_destructor) producer_close; producer->get_frame = get_frame; // Set properties - mlt_properties_set( properties, "resource", arg? arg : "0" ); + mlt_properties_set( properties, "resource", (arg && strcmp( arg, ""))? arg : "0" ); mlt_properties_set_int( properties, "channels", 2 ); mlt_properties_set_int( properties, "buffer", 25 ); mlt_properties_set_int( properties, "prefill", 25 );