]> git.sesse.net Git - mlt/commitdiff
Add re-open capability to decklink producer.
authorDan Dennedy <dan@dennedy.org>
Thu, 29 Sep 2011 03:26:00 +0000 (20:26 -0700)
committerDan Dennedy <dan@dennedy.org>
Thu, 29 Sep 2011 03:26:00 +0000 (20:26 -0700)
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.

src/modules/decklink/producer_decklink.cpp

index 5c81d9f83fd616651093b4c91cff039b8e347ece..8c763a1a4089e9e01ccdbd997c90029ddba26cbc 100644 (file)
@@ -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 );