X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmodules%2Favformat%2Fproducer_avformat.c;h=c188b27cc481e184c2ddfc2bd3b63a7ca2281f82;hb=29bc1b715ce20f8202c60740707c39fd723c1c50;hp=aad08028d533393ef9dc3a93b313daa4e0d050e5;hpb=a07c3da76259d6ba479d800ffecc5617a9ad158f;p=melted diff --git a/src/modules/avformat/producer_avformat.c b/src/modules/avformat/producer_avformat.c index aad0802..c188b27 100644 --- a/src/modules/avformat/producer_avformat.c +++ b/src/modules/avformat/producer_avformat.c @@ -2,6 +2,7 @@ * producer_avformat.c -- avformat producer * Copyright (C) 2003-2004 Ushodaya Enterprises Limited * Author: Charles Yates + * Much code borrowed from ffmpeg.c: Copyright (c) 2000-2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,10 +19,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// Local header files -#include "producer_avformat.h" - // MLT Header files +#include #include // ffmpeg Header files @@ -40,13 +39,13 @@ void avformat_lock( ); void avformat_unlock( ); // Forward references. -static int producer_open( mlt_producer this, char *file ); +static int producer_open( mlt_producer this, mlt_profile profile, char *file ); static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index ); /** Constructor for libavformat. */ -mlt_producer producer_avformat_init( char *file ) +mlt_producer producer_avformat_init( mlt_profile profile, char *file ) { mlt_producer this = NULL; @@ -69,12 +68,17 @@ mlt_producer producer_avformat_init( char *file ) this->get_frame = producer_get_frame; // Open the file - if ( producer_open( this, file ) != 0 ) + if ( producer_open( this, profile, file ) != 0 ) { // Clean up mlt_producer_close( this ); this = NULL; } + + // Close the file to release resources for large playlists - reopen later as needed + mlt_properties_set_data( properties, "dummy_context", NULL, 0, NULL, NULL ); + mlt_properties_set_data( properties, "audio_context", NULL, 0, NULL, NULL ); + mlt_properties_set_data( properties, "video_context", NULL, 0, NULL, NULL ); } } @@ -92,13 +96,13 @@ static void find_default_streams( AVFormatContext *context, int *audio_index, in for( i = 0; i < context->nb_streams; i++ ) { // Get the codec context - AVCodecContext *codec_context = context->streams[ i ]->codec; + AVCodecContext *codec_context = context->streams[ i ]->codec; if ( avcodec_find_decoder( codec_context->codec_id ) == NULL ) continue; // Determine the type and obtain the first index of each type - switch( codec_context->codec_type ) + switch( codec_context->codec_type ) { case CODEC_TYPE_VIDEO: if ( *video_index < 0 ) @@ -107,9 +111,9 @@ static void find_default_streams( AVFormatContext *context, int *audio_index, in case CODEC_TYPE_AUDIO: if ( *audio_index < 0 ) *audio_index = i; - break; + break; default: - break; + break; } } } @@ -153,7 +157,7 @@ static void producer_codec_close( void *codec ) /** Open the file. */ -static int producer_open( mlt_producer this, char *file ) +static int producer_open( mlt_producer this, mlt_profile profile, char *file ) { // Return an error code (0 == no error) int error = 0; @@ -165,7 +169,7 @@ static int producer_open( mlt_producer this, char *file ) mlt_properties properties = MLT_PRODUCER_PROPERTIES( this ); // We will treat everything with the producer fps - double fps = mlt_producer_get_fps( this ); + double fps = mlt_profile_fps( profile ); // Lock the mutex now avformat_lock( ); @@ -282,8 +286,8 @@ static int producer_open( mlt_producer this, char *file ) // Find default audio and video streams find_default_streams( context, &audio_index, &video_index ); - if ( context->start_time != AV_NOPTS_VALUE ) - mlt_properties_set_double( properties, "_start_time", context->start_time ); + if ( context->start_time != AV_NOPTS_VALUE ) + mlt_properties_set_double( properties, "_start_time", context->start_time ); // Check if we're seekable (something funny about mpeg here :-/) if ( strcmp( file, "pipe:" ) && strncmp( file, "http://", 6 ) ) @@ -630,21 +634,23 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form got_picture = 0; } } + av_free_packet( &pkt ); + } + else if ( ret >= 0 ) + { + av_free_packet( &pkt ); } // Now handle the picture if we have one if ( got_picture ) { mlt_properties_set_int( frame_properties, "progressive", !av_frame->interlaced_frame ); - mlt_properties_set_int( frame_properties, "top_field_first", av_frame->top_field_first ); + mlt_properties_set_int( properties, "top_field_first", av_frame->top_field_first ); convert_image( av_frame, *buffer, codec_context->pix_fmt, *format, *width, *height ); mlt_properties_set_data( frame_properties, "image", *buffer, size, (mlt_destructor)mlt_pool_release, NULL ); mlt_properties_set_int( properties, "_current_position", int_position ); mlt_properties_set_int( properties, "_got_picture", 1 ); } - - // We're finished with this packet regardless - av_free_packet( &pkt ); } } @@ -672,6 +678,16 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) // Fetch the video_context AVFormatContext *context = mlt_properties_get_data( properties, "video_context", NULL ); + if ( !context ) + { + // Reopen the file + mlt_events_block( properties, this ); + producer_open( this, mlt_service_profile( MLT_PRODUCER_SERVICE(this) ), + mlt_properties_get( properties, "resource" ) ); + context = mlt_properties_get_data( properties, "video_context", NULL ); + mlt_properties_set_data( properties, "dummy_context", NULL, 0, NULL, NULL ); + mlt_events_unblock( properties, this ); + } // Get the video_index int index = mlt_properties_get_int( properties, "video_index" ); @@ -693,6 +709,16 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) // Initialise the codec if necessary if ( codec == NULL ) { + // Initialise multi-threading + int thread_count = mlt_properties_get_int( properties, "threads" ); + if ( thread_count == 0 && getenv( "MLT_AVFORMAT_THREADS" ) ) + thread_count = atoi( getenv( "MLT_AVFORMAT_THREADS" ) ); + if ( thread_count > 1 ) + { + avcodec_thread_init( codec_context, thread_count ); + codec_context->thread_count = thread_count; + } + // Find the codec codec = avcodec_find_decoder( codec_context->codec_id ); @@ -717,6 +743,28 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) double force_aspect_ratio = mlt_properties_get_double( properties, "force_aspect_ratio" ); double aspect_ratio; + if ( strcmp( codec_context->codec->name, "dvvideo" ) == 0 ) + { + // Override FFmpeg's notion of DV aspect ratios, which are + // based upon a width of 704. Since we do not have a normaliser + // that crops (nor is cropping 720 wide ITU-R 601 video always desirable) + // we just coerce the values to facilitate a passive behaviour through + // the rescale normaliser when using equivalent producers and consumers. + // = display_aspect / (width * height) + if ( codec_context->sample_aspect_ratio.num == 10 && + codec_context->sample_aspect_ratio.den == 11 ) + force_aspect_ratio = 8.0/9.0; // 4:3 NTSC + else if ( codec_context->sample_aspect_ratio.num == 59 && + codec_context->sample_aspect_ratio.den == 54 ) + force_aspect_ratio = 16.0/15.0; // 4:3 PAL + else if ( codec_context->sample_aspect_ratio.num == 40 && + codec_context->sample_aspect_ratio.den == 33 ) + force_aspect_ratio = 32.0/27.0; // 16:9 NTSC + else if ( codec_context->sample_aspect_ratio.num == 118 && + codec_context->sample_aspect_ratio.den == 81 ) + force_aspect_ratio = 64.0/45.0; // 16:9 PAL + } + // XXX: We won't know the real aspect ratio until an image is decoded // but we do need it now (to satisfy filter_resize) - take a guess based // on pal/ntsc @@ -730,8 +778,7 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame ) } else { - int is_pal = mlt_producer_get_fps( this ) == 25.0; - aspect_ratio = is_pal ? 59.0/54.0 : 10.0/11.0; + aspect_ratio = 1.0; } // Determine the fps @@ -1043,7 +1090,7 @@ static void producer_set_up_audio( mlt_producer this, mlt_frame frame ) static int producer_get_frame( mlt_producer this, mlt_frame_ptr frame, int index ) { // Create an empty frame - *frame = mlt_frame_init( ); + *frame = mlt_frame_init( MLT_PRODUCER_SERVICE( this ) ); // Update timecode on the frame we're creating mlt_frame_set_position( *frame, mlt_producer_position( this ) );