X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmodules%2Favformat%2Fproducer_avformat.c;h=3186007c86e03ca56874014e30309d760d9777e8;hb=6159bd78fa8e72c784747776a2c4c63d9c461ff5;hp=1b609f8ba96a731c7dd92e4b4f0f6f9d750c9e56;hpb=16c5c516008b9debec7765e34f4756f8063dee7e;p=melted diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index 1b609f8..3186007 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -30,6 +30,7 @@ // System header files #include #include +#include // Forward references. static int producer_open( mlt_producer this, char *file ); @@ -37,6 +38,7 @@ static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index // A static flag used to determine if avformat has been initialised static int avformat_initialised = 0; +static pthread_mutex_t avformat_mutex; /** Constructor for libavformat. */ @@ -69,6 +71,7 @@ mlt_producer producer_avformat_init( char *file ) // Initialise avformat if necessary if ( avformat_initialised == 0 ) { + pthread_mutex_init( &avformat_mutex, NULL ); avformat_initialised = 1; av_register_all( ); } @@ -89,7 +92,7 @@ mlt_producer producer_avformat_init( char *file ) /** Find the default streams. */ -void find_default_streams( AVFormatContext *context, int *audio_index, int *video_index ) +static void find_default_streams( AVFormatContext *context, int *audio_index, int *video_index ) { int i; @@ -116,6 +119,42 @@ void find_default_streams( AVFormatContext *context, int *audio_index, int *vide } } +/** Producer file destructor. +*/ + +static void producer_file_close( void *context ) +{ + if ( context != NULL ) + { + // Lock the mutex now + pthread_mutex_lock( &avformat_mutex ); + + // Close the file + av_close_input_file( context ); + + // Unlock the mutex now + pthread_mutex_unlock( &avformat_mutex ); + } +} + +/** Producer file destructor. +*/ + +static void producer_codec_close( void *codec ) +{ + if ( codec != NULL ) + { + // Lock the mutex now + pthread_mutex_lock( &avformat_mutex ); + + // Close the file + avcodec_close( codec ); + + // Unlock the mutex now + pthread_mutex_unlock( &avformat_mutex ); + } +} + /** Open the file. NOTE: We need to have a valid [PAL or NTSC] frame rate before we can determine the @@ -141,6 +180,9 @@ static int producer_open( mlt_producer this, char *file ) // We will treat everything with the producer fps double fps = mlt_properties_get_double( properties, "fps" ); + // Lock the mutex now + pthread_mutex_lock( &avformat_mutex ); + // Now attempt to open the file error = av_open_input_file( &context, file, NULL, 0, NULL ) < 0; @@ -162,8 +204,8 @@ static int producer_open( mlt_producer this, char *file ) { // This isn't going to be accurate for all formats mlt_position frames = ( mlt_position )( ( ( double )context->duration / ( double )AV_TIME_BASE ) * fps ); - mlt_properties_set_position( properties, "out", frames - 1 ); - mlt_properties_set_position( properties, "length", frames ); + mlt_properties_set_position( properties, "out", frames - 2 ); + mlt_properties_set_position( properties, "length", frames - 1 ); } // Find default audio and video streams @@ -177,24 +219,24 @@ static int producer_open( mlt_producer this, char *file ) if ( audio_index != -1 && video_index != -1 ) { // We'll use the open one as our video_context - mlt_properties_set_data( properties, "video_context", context, 0, ( mlt_destructor )av_close_input_file, NULL ); + mlt_properties_set_data( properties, "video_context", context, 0, producer_file_close, NULL ); // And open again for our audio context av_open_input_file( &context, file, NULL, 0, NULL ); av_find_stream_info( context ); // Audio context - mlt_properties_set_data( properties, "audio_context", context, 0, ( mlt_destructor )av_close_input_file, NULL ); + mlt_properties_set_data( properties, "audio_context", context, 0, producer_file_close, NULL ); } else if ( video_index != -1 ) { // We only have a video context - mlt_properties_set_data( properties, "video_context", context, 0, ( mlt_destructor )av_close_input_file, NULL ); + mlt_properties_set_data( properties, "video_context", context, 0, producer_file_close, NULL ); } else if ( audio_index != -1 ) { // We only have an audio context - mlt_properties_set_data( properties, "audio_context", context, 0, ( mlt_destructor )av_close_input_file, NULL ); + mlt_properties_set_data( properties, "audio_context", context, 0, producer_file_close, NULL ); } else { @@ -204,6 +246,9 @@ static int producer_open( mlt_producer this, char *file ) } } + // Unlock the mutex now + pthread_mutex_unlock( &avformat_mutex ); + return error; } @@ -281,6 +326,9 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form mlt_properties_set_int( frame_properties, "width", *width ); mlt_properties_set_int( frame_properties, "height", *height ); + // Lock the mutex now + pthread_mutex_lock( &avformat_mutex ); + // Construct an AVFrame for YUV422 conversion if ( output == NULL ) { @@ -401,6 +449,9 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form // Regardless of speed, we expect to get the next frame (cos we ain't too bright) mlt_properties_set_position( properties, "video_expected", position + 1 ); + // Unlock the mutex now + pthread_mutex_unlock( &avformat_mutex ); + return 0; } @@ -418,11 +469,14 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) // Get the video_index int index = mlt_properties_get_int( properties, "video_index" ); + // Get the frame properties + mlt_properties frame_properties = mlt_frame_properties( frame ); + + // Lock the mutex now + pthread_mutex_lock( &avformat_mutex ); + if ( context != NULL && index != -1 ) { - // Get the frame properties - mlt_properties frame_properties = mlt_frame_properties( frame ); - // Get the video stream AVStream *stream = context->streams[ index ]; @@ -455,7 +509,7 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) mlt_properties_set_double( properties, "aspect_ratio", aspect_ratio ); // Now store the codec with its destructor - mlt_properties_set_data( properties, "video_codec", codec, 0, ( mlt_destructor )avcodec_close, NULL ); + mlt_properties_set_data( properties, "video_codec", codec_context, 0, producer_codec_close, NULL ); // Set to the real timecode av_seek_frame( context, -1, 0 ); @@ -473,7 +527,18 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) mlt_frame_push_get_image( frame, producer_get_image ); mlt_properties_set_data( frame_properties, "avformat_producer", this, 0, NULL, NULL ); } + else + { + mlt_properties_set_int( frame_properties, "test_image", 1 ); + } } + else + { + mlt_properties_set_int( frame_properties, "test_image", 1 ); + } + + // Unlock the mutex now + pthread_mutex_unlock( &avformat_mutex ); } /** Get the audio from a frame. @@ -529,6 +594,9 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form // Flag for paused (silence) int paused = 0; + // Lock the mutex now + pthread_mutex_lock( &avformat_mutex ); + // Check for resample and create if necessary if ( resample == NULL ) { @@ -536,7 +604,7 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form resample = audio_resample_init( *channels, codec_context->channels, *frequency, codec_context->sample_rate ); // And store it on properties - mlt_properties_set_data( properties, "audio_resample", resample, 0, ( mlt_destructor ) audio_resample_close, NULL ); + mlt_properties_set_data( properties, "audio_resample", resample, 0, ( mlt_destructor )audio_resample_close, NULL ); } // Check for audio buffer and create if necessary @@ -630,8 +698,6 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form // If we're behind, ignore this packet float current_pts = (float)pkt.pts / 1000000.0; double discrepancy = mlt_properties_get_double( properties, "discrepancy" ); - - fprintf( stderr, "%f < %f\n", discrepancy * current_pts, (float) real_timecode ); if ( discrepancy * current_pts < real_timecode ) ignore = 1; } @@ -641,6 +707,7 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form } // Now handle the audio if we have enough + if ( audio_used >= *samples ) { *buffer = malloc( *samples * *channels * sizeof( int16_t ) ); @@ -669,6 +736,9 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form // Regardless of speed, we expect to get the next frame (cos we ain't too bright) mlt_properties_set_position( properties, "audio_expected", position + 1 ); + // Unlock the mutex now + pthread_mutex_unlock( &avformat_mutex ); + return 0; } @@ -686,6 +756,9 @@ static void producer_set_up_audio( mlt_producer this, mlt_frame frame ) // Get the audio_index int index = mlt_properties_get_int( properties, "audio_index" ); + // Lock the mutex now + pthread_mutex_lock( &avformat_mutex ); + // Deal with audio context if ( context != NULL && index != -1 ) { @@ -711,7 +784,7 @@ static void producer_set_up_audio( mlt_producer this, mlt_frame frame ) if ( codec != NULL && avcodec_open( codec_context, codec ) >= 0 ) { // Now store the codec with its destructor - mlt_properties_set_data( properties, "audio_codec", codec, 0, ( mlt_destructor )avcodec_close, NULL ); + mlt_properties_set_data( properties, "audio_codec", codec_context, 0, producer_codec_close, NULL ); } else { @@ -727,6 +800,9 @@ static void producer_set_up_audio( mlt_producer this, mlt_frame frame ) mlt_properties_set_data( frame_properties, "avformat_producer", this, 0, NULL, NULL ); } } + + // Unlock the mutex now + pthread_mutex_unlock( &avformat_mutex ); } /** Our get frame implementation.