Sundry consumer modifications; albino compile fix; minor mods to avformat producer
[melted] / src / modules / avformat / consumer_avformat.c
index a841339..52fe9da 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-
+#include <sys/time.h>
 #include <math.h>
 
 // avformat header files
-#include <ffmpeg/avformat.h>
+#include <avformat.h>
 
 typedef struct
 {
@@ -96,10 +96,10 @@ static void consumer_close( mlt_consumer this );
 mlt_consumer consumer_avformat_init( char *arg )
 {
        // Allocate the consumer
-       mlt_consumer this = calloc( 1, sizeof( struct mlt_consumer_s ) );
+       mlt_consumer this = mlt_consumer_new( );
 
        // If memory allocated and initialises without error
-       if ( this != NULL && mlt_consumer_init( this, NULL ) == 0 )
+       if ( this != NULL )
        {
                // Get properties from the consumer
                mlt_properties properties = mlt_consumer_properties( this );
@@ -134,12 +134,6 @@ mlt_consumer consumer_avformat_init( char *arg )
                this->stop = consumer_stop;
                this->is_stopped = consumer_is_stopped;
        }
-       else
-       {
-               // Clean up in case of init failure
-               free( this );
-               this = NULL;
-       }
 
        // Return this
        return this;
@@ -426,6 +420,13 @@ void close_video(AVFormatContext *oc, AVStream *st)
        avcodec_close(&st->codec);
 }
 
+static inline long time_difference( struct timeval *time1 )
+{
+       struct timeval time2;
+       gettimeofday( &time2, NULL );
+       return time2.tv_sec * 1000000 + time2.tv_usec - time1->tv_sec * 1000000 - time1->tv_usec;
+}
+
 /** The main thread - the argument is simply the consumer.
 */
 
@@ -440,6 +441,12 @@ static void *consumer_thread( void *arg )
        // Get the terminate on pause property
        int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" );
 
+       // Determine if feed is slow (for realtime stuff)
+       int real_time_output = mlt_properties_get_int( properties, "real_time" );
+
+       // Time structures
+       struct timeval ante;
+
        // Get the frame rate
        int fps = mlt_properties_get_double( properties, "fps" );
 
@@ -499,6 +506,10 @@ static void *consumer_thread( void *arg )
        // Loop variable
        int i;
 
+       // Frames despatched
+       long int frames = 0;
+       long int total_time = 0;
+
        // Determine the format
        AVOutputFormat *fmt = NULL;
        char *filename = mlt_properties_get( properties, "target" );
@@ -590,9 +601,6 @@ static void *consumer_thread( void *arg )
                        }
                }
        
-               if ( url_is_streamed( &oc->pb ) )
-                       fprintf( stderr, "FUCK!\n" );
-
                // Write the stream header, if any
                if ( mlt_properties_get_int( properties, "running" ) )
                        av_write_header( oc );
@@ -607,6 +615,9 @@ static void *consumer_thread( void *arg )
        if ( audio_st == NULL && video_st == NULL )
                mlt_properties_set_int( properties, "running", 0 );
 
+       // Get the starting time (can ignore the times above)
+       gettimeofday( &ante, NULL );
+
        // Loop while running
        while( mlt_properties_get_int( properties, "running" ) )
        {
@@ -616,6 +627,9 @@ static void *consumer_thread( void *arg )
                // Check that we have a frame to work with
                if ( frame != NULL )
                {
+                       // Increment frames despatched
+                       frames ++;
+
                        // Default audio args
                        frame_properties = mlt_frame_properties( frame );
 
@@ -625,6 +639,7 @@ static void *consumer_thread( void *arg )
                                samples = mlt_sample_calculator( fps, frequency, count );
                                mlt_frame_get_audio( frame, &pcm, &aud_fmt, &frequency, &channels, &samples );
                                sample_fifo_append( fifo, pcm, samples * channels );
+                               total_time += ( samples * 1000000 ) / frequency;
                        }
 
                        // Encode the image
@@ -741,6 +756,19 @@ static void *consumer_thread( void *arg )
                                }
                        }
                }
+
+               if ( real_time_output && frames % 25 == 0 )
+               {
+                       long passed = time_difference( &ante );
+                       long pending = ( ( ( long )sample_fifo_used( fifo ) * 1000 ) / frequency ) * 1000;
+                       passed -= pending;
+                       if ( passed < total_time )
+                       {
+                               long total = ( total_time - passed );
+                               struct timespec t = { total / 1000000, ( total % 1000000 ) * 1000 };
+                               nanosleep( &t, NULL );
+                       }
+               }
        }
 
        // close each codec