]> git.sesse.net Git - mlt/blobdiff - mlt/src/modules/core/producer_ppm.c
ppm ffmpeg
[mlt] / mlt / src / modules / core / producer_ppm.c
index e1357c8fb34374a0c18740c172de0800908abe91..ca1947172c319fbb86e4ab144ecf32c2bdff5029 100644 (file)
@@ -36,13 +36,9 @@ mlt_producer producer_ppm_init( void *command )
                producer->get_frame = producer_get_frame;
                producer->close = producer_close;
 
-               if ( command == NULL )
-                       this->command = strdup( "image2raw -n -a -r 3 -ppm /usr/share/pixmaps/*.png" );
-               else
+               if ( command != NULL )
                        this->command = strdup( command );
 
-               this->pipe = popen( this->command, "r" );
-
                return producer;
        }
        free( this );
@@ -77,6 +73,84 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma
        return 0;
 }
 
+static void producer_ppm_position( producer_ppm this, uint64_t requested )
+{
+       if ( requested != this->expected )
+       {
+               if ( this->video != NULL )
+                       pclose( this->video );
+               this->video = NULL;
+               if ( this->audio != NULL )
+                       pclose( this->audio );
+               this->audio = NULL;
+       }
+
+       // This is the next frame we expect
+       this->expected = mlt_producer_frame( &this->parent ) + 1;
+}
+
+FILE *producer_ppm_run_video( producer_ppm this )
+{
+       if ( this->video == NULL )
+       {
+               if ( this->command == NULL )
+               {
+                       this->video = popen( "image2raw -n -a -r 3 -ppm /usr/share/pixmaps/*.png", "r" );
+               }
+               else
+               {
+                       char command[ 1024 ];
+                       float fps = mlt_producer_get_fps( &this->parent );
+                       float position = mlt_producer_position( &this->parent );
+                       sprintf( command, "ffmpeg -i \"%s\" -ss %f -f imagepipe -r %f -img ppm -", this->command, position, fps );
+                       this->video = popen( command, "r" );
+               }
+       }
+       return this->video;
+}
+
+FILE *producer_ppm_run_audio( producer_ppm this )
+{
+       if ( this->audio == NULL )
+       {
+               if ( this->command != NULL )
+               {
+                       char command[ 1024 ];
+                       float position = mlt_producer_position( &this->parent );
+                       sprintf( command, "ffmpeg -i \"%s\" -ss %f -f s16le -ar 48000 -ac 2 -", this->command, position );
+                       this->audio = popen( command, "r" );
+               }
+       }
+       return this->audio;
+}
+
+
+static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+{
+       // Get the frames properties
+       mlt_properties properties = mlt_frame_properties( this );
+
+       FILE *pipe = mlt_properties_get_data( properties, "audio.pipe", NULL );
+
+       *frequency = 48000;
+       *channels = 2;
+       *samples = 1920;
+
+       // Size
+       int size = *samples * *channels * 2;
+
+       // Allocate an image
+       *buffer = malloc( size );
+               
+       // Read it
+       fread( *buffer, size, 1, pipe );
+
+       // Pass the data on the frame properties
+       mlt_properties_set_data( properties, "audio", *buffer, size, free, NULL );
+
+       return 0;
+}
+
 static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
 {
        producer_ppm this = producer->child;
@@ -86,17 +160,26 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
        // Construct a test frame
        *frame = mlt_frame_init( );
 
-       // Scan the header
-       if ( fscanf( this->pipe, "P6\n%d %d\n255\n", &width, &height ) == 2 )
-       {
-               // Get the frames properties
-               mlt_properties properties = mlt_frame_properties( *frame );
+       // Are we at the position expected?
+       producer_ppm_position( this, mlt_producer_frame( producer ) );
+
+       // Open the pipe
+       FILE *video = producer_ppm_run_video( this );
+
+       // Open the audio pipe
+       FILE *audio = producer_ppm_run_audio( this );
+
+       // Get the frames properties
+       mlt_properties properties = mlt_frame_properties( *frame );
 
+       // Read the video
+       if ( video != NULL && fscanf( video, "P6\n%d %d\n255\n", &width, &height ) == 2 )
+       {
                // Allocate an image
                uint8_t *image = malloc( width * height * 3 );
                
                // Read it
-               fread( image, width * height * 3, 1, this->pipe );
+               fread( image, width * height * 3, 1, video );
 
                // Pass the data on the frame properties
                mlt_properties_set_data( properties, "image", image, width * height * 3, free, NULL );
@@ -107,6 +190,16 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
                mlt_frame_push_get_image( *frame, producer_get_image );
        }
 
+       // Read the audio
+       if ( audio != NULL )
+       {
+               // Set the audio pipe
+               mlt_properties_set_data( properties, "audio.pipe", audio, 0, NULL, NULL );
+
+               // Hmm - register audio callback
+               ( *frame )->get_audio = producer_get_audio;
+       }
+
        // Update timecode on the frame we're creating
        mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
 
@@ -119,7 +212,10 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 static void producer_close( mlt_producer parent )
 {
        producer_ppm this = parent->child;
-       pclose( this->pipe );
+       if ( this->video )
+               pclose( this->video );
+       if ( this->audio )
+               pclose( this->audio );
        free( this->command );
        parent->close = NULL;
        mlt_producer_close( parent );