]> git.sesse.net Git - mlt/blobdiff - src/modules/core/producer_consumer.c
Do not let consumer producer alter the profile when validating input.
[mlt] / src / modules / core / producer_consumer.c
index 280705d6097d41c83c8857a29f821c280eb68919..4803e96f9b5046c05ebbc455d5b50c28774edd2c 100644 (file)
@@ -46,32 +46,43 @@ static int get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format
        int result = mlt_frame_get_image( nested_frame, image, format, width, height, writable );
 
        // Allocate the image
-       int size = *width * *height * ( *format == mlt_image_yuv422 ? 2 : *format == mlt_image_rgb24 ? 3 : *format == mlt_image_rgb24a ? 4 : ( 3 / 2 ) );
+       int size = *width * *height * ( *format == mlt_image_yuv422 ? 2 : *format == mlt_image_rgb24 ? 3 :
+               ( *format == mlt_image_rgb24a || *format == mlt_image_opengl ) ? 4 : ( 3 / 2 ) );
        uint8_t *new_image = mlt_pool_alloc( size );
 
        // Update the frame
        mlt_properties properties = mlt_frame_properties( frame );
        mlt_properties_set_data( properties, "image", new_image, size, mlt_pool_release, NULL );
        memcpy( new_image, *image, size );
-       mlt_frame_close( nested_frame );
+       mlt_properties_set( properties, "progressive", mlt_properties_get( MLT_FRAME_PROPERTIES(nested_frame), "progressive" ) );
        *image = new_image;
 
-//     mlt_properties_debug( properties, "frame", stderr );
-//     mlt_properties_debug( mlt_frame_properties( nested_frame ), "nested_frame", stderr );
-
        return result;
 }
 
-static int get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+static int get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
 {
        mlt_frame nested_frame = mlt_frame_pop_audio( frame );
        int result = mlt_frame_get_audio( nested_frame, buffer, format, frequency, channels, samples );
-       int size = *channels * *samples * sizeof( int16_t );
+       int size = *channels * *samples;
+
+       switch ( *format )
+       {
+               case mlt_audio_s16:
+                       size *= sizeof( int16_t );
+                       break;
+               case mlt_audio_s32:
+                       size *= sizeof( int32_t );
+               case mlt_audio_float:
+                       size *= sizeof( float );
+               default:
+                       mlt_log_error( NULL, "[producer consumer] Invalid audio format\n" );
+       }
        int16_t *new_buffer = mlt_pool_alloc( size );
        mlt_properties_set_data( MLT_FRAME_PROPERTIES( frame ), "audio", new_buffer, size, mlt_pool_release, NULL );
        memcpy( new_buffer, *buffer, size );
        *buffer = new_buffer;
-       mlt_frame_close( nested_frame );
+
        return result;
 }
 
@@ -105,6 +116,15 @@ static int get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
                cx->profile->frame_rate_num = profile->frame_rate_num;
                cx->profile->frame_rate_den = profile->frame_rate_den;
 
+               // Encapsulate a real producer for the resource
+               cx->producer = mlt_factory_producer( cx->profile, NULL,
+                       mlt_properties_get( properties, "resource" ) );
+               mlt_properties_pass_list( properties, MLT_PRODUCER_PROPERTIES( cx->producer ),
+                       "out, length" );
+
+               // Since we control the seeking, prevent it from seeking on its own
+               mlt_producer_set_speed( cx->producer, 0 );
+
                // We will encapsulate a consumer
                cx->consumer = mlt_consumer_new( cx->profile );
                // Do not use _pass_list on real_time so that it defaults to 0 in the absence of
@@ -112,17 +132,8 @@ static int get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
                mlt_properties_set_int( MLT_CONSUMER_PROPERTIES( cx->consumer ), "real_time",
                        mlt_properties_get_int( properties, "real_time" ) );
                mlt_properties_pass_list( MLT_CONSUMER_PROPERTIES( cx->consumer ), properties,
-                       "buffer, prefill" );
+                       "buffer, prefill, deinterlace_method, rescale" );
        
-               // Encapsulate a real producer for the resource
-               cx->producer = mlt_factory_producer( cx->profile, mlt_environment( "MLT_PRODUCER" ),
-                       mlt_properties_get( properties, "resource" ) );
-               mlt_properties_pass_list( properties, MLT_PRODUCER_PROPERTIES( cx->producer ),
-                       "in, out, length, resource" );
-
-               // Since we control the seeking, prevent it from seeking on its own
-               mlt_producer_set_speed( cx->producer, 0 );
-
                // Connect it all together
                mlt_consumer_connect( cx->consumer, MLT_PRODUCER_SERVICE( cx->producer ) );
                mlt_consumer_start( cx->consumer );
@@ -133,7 +144,7 @@ static int get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
        if ( frame )
        {
                // Our "in" needs to be the same, keep it so
-               mlt_properties_pass_list( MLT_PRODUCER_PROPERTIES( cx->producer ), properties, "in" );
+               mlt_properties_pass_list( MLT_PRODUCER_PROPERTIES( cx->producer ), properties, "in, out" );
 
                // Seek the producer to the correct place
                // Calculate our positions
@@ -154,15 +165,17 @@ static int get_frame( mlt_producer this, mlt_frame_ptr frame, int index )
                // Give the returned frame temporal identity
                mlt_frame_set_position( *frame, mlt_producer_position( this ) );
                
-               // Put additional references on the frame so both get_image and get_audio
-               // methods can close it.
-               mlt_properties_inc_ref( MLT_FRAME_PROPERTIES( nested_frame ) );
+               // Store the nested frame on the produced frame for destruction
+               mlt_properties frame_props = MLT_FRAME_PROPERTIES( *frame );
+               mlt_properties_set_data( frame_props, "_producer_consumer.frame", nested_frame, 0, (mlt_destructor) mlt_frame_close, NULL );
 
                // Inform the normalizers about our video properties
-               mlt_properties frame_props = MLT_FRAME_PROPERTIES( *frame );
                mlt_properties_set_double( frame_props, "aspect_ratio", mlt_profile_sar( cx->profile ) );
-               mlt_properties_set_double( frame_props, "width", cx->profile->width );
-               mlt_properties_set_double( frame_props, "height", cx->profile->height );
+               mlt_properties_set_int( frame_props, "width", cx->profile->width );
+               mlt_properties_set_int( frame_props, "height", cx->profile->height );
+               mlt_properties_set_int( frame_props, "real_width", cx->profile->width );
+               mlt_properties_set_int( frame_props, "real_height", cx->profile->height );
+               mlt_properties_set_int( frame_props, "progressive", cx->profile->progressive );
        }
 
        // Calculate the next timecode
@@ -195,7 +208,8 @@ mlt_producer producer_consumer_init( mlt_profile profile, mlt_service_type type,
        mlt_producer this = mlt_producer_new( );
 
        // Encapsulate the real producer
-       mlt_producer real_producer = mlt_factory_producer( profile, mlt_environment( "MLT_PRODUCER" ), arg );
+       mlt_profile temp_profile = mlt_profile_init( NULL );
+       mlt_producer real_producer = mlt_factory_producer( temp_profile, NULL, arg );
 
        if ( this && real_producer )
        {
@@ -220,5 +234,6 @@ mlt_producer producer_consumer_init( mlt_profile profile, mlt_service_type type,
 
                this = NULL;
        }
+       mlt_profile_close( temp_profile );
        return this;
 }