filter_rescale.c, producer_avformat.c, producer_libdv.c, producer_consumer.c:
[melted] / src / modules / avformat / producer_avformat.c
index 4039d1e..df5b0b1 100644 (file)
@@ -25,6 +25,7 @@
 
 // ffmpeg Header files
 #include <avformat.h>
+#include <opt.h>
 #ifdef SWSCALE
 #  include <swscale.h>
 #endif
@@ -97,34 +98,73 @@ mlt_producer producer_avformat_init( mlt_profile profile, char *file )
 /** Find the default streams.
 */
 
-static void find_default_streams( AVFormatContext *context, int *audio_index, int *video_index )
+static mlt_properties find_default_streams( mlt_properties meta_media, AVFormatContext *context, int *audio_index, int *video_index )
 {
        int i;
+       char key[200];
+
+       mlt_properties_set_int( meta_media, "meta.media.nb_streams", context->nb_streams );
 
        // Allow for multiple audio and video streams in the file and select first of each (if available)
        for( i = 0; i < context->nb_streams; i++ ) 
        {
                // Get the codec context
-               AVCodecContext *codec_context = context->streams[ i ]->codec;
+               AVStream *stream = context->streams[ i ];
+               if ( ! stream ) continue;
+               AVCodecContext *codec_context = stream->codec;
+               if ( ! codec_context ) continue;
+               AVCodec *codec = avcodec_find_decoder( codec_context->codec_id );
+               if ( ! codec ) continue;
 
-               if ( avcodec_find_decoder( codec_context->codec_id ) == NULL )
-                       continue;
+               snprintf( key, sizeof(key), "meta.media.%d.stream.type", i );
 
                // 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 )
                                        *video_index = i;
+                               mlt_properties_set( meta_media, key, "video" );
+                               snprintf( key, sizeof(key), "meta.media.%d.stream.frame_rate", i );
+                               mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->r_frame_rate ) );
+                               snprintf( key, sizeof(key), "meta.media.%d.stream.sample_aspect_ratio", i );
+                               mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->sample_aspect_ratio ) );
+                               snprintf( key, sizeof(key), "meta.media.%d.codec.pix_fmt", i );
+                               mlt_properties_set( meta_media, key, avcodec_get_pix_fmt_name( codec_context->pix_fmt ) );
+                               snprintf( key, sizeof(key), "meta.media.%d.codec.sample_aspect_ratio", i );
+                               mlt_properties_set_double( meta_media, key, av_q2d( codec_context->sample_aspect_ratio ) );
                                break;
                        case CODEC_TYPE_AUDIO:
                                if ( *audio_index < 0 )
                                        *audio_index = i;
+                               mlt_properties_set( meta_media, key, "audio" );
+                               snprintf( key, sizeof(key), "meta.media.%d.codec.sample_fmt", i );
+                               mlt_properties_set( meta_media, key, avcodec_get_sample_fmt_name( codec_context->sample_fmt ) );
+                               snprintf( key, sizeof(key), "meta.media.%d.codec.sample_rate", i );
+                               mlt_properties_set_int( meta_media, key, codec_context->sample_rate );
+                               snprintf( key, sizeof(key), "meta.media.%d.codec.channels", i );
+                               mlt_properties_set_int( meta_media, key, codec_context->channels );
                                break;
                        default:
                                break;
                }
+//             snprintf( key, sizeof(key), "meta.media.%d.stream.time_base", i );
+//             mlt_properties_set_double( meta_media, key, av_q2d( context->streams[ i ]->time_base ) );
+               snprintf( key, sizeof(key), "meta.media.%d.codec.name", i );
+               mlt_properties_set( meta_media, key, codec->name );
+               snprintf( key, sizeof(key), "meta.media.%d.codec.long_name", i );
+               mlt_properties_set( meta_media, key, codec->long_name );
+               snprintf( key, sizeof(key), "meta.media.%d.codec.bit_rate", i );
+               mlt_properties_set_int( meta_media, key, codec_context->bit_rate );
+//             snprintf( key, sizeof(key), "meta.media.%d.codec.time_base", i );
+//             mlt_properties_set_double( meta_media, key, av_q2d( codec_context->time_base ) );
+               snprintf( key, sizeof(key), "meta.media.%d.codec.profile", i );
+               mlt_properties_set_int( meta_media, key, codec_context->profile );
+               snprintf( key, sizeof(key), "meta.media.%d.codec.level", i );
+               mlt_properties_set_int( meta_media, key, codec_context->level );
        }
+
+       return meta_media;
 }
 
 /** Producer file destructor.
@@ -375,7 +415,7 @@ static int producer_open( mlt_producer this, mlt_profile profile, char *file )
                        }
 
                        // Find default audio and video streams
-                       find_default_streams( context, &audio_index, &video_index );
+                       find_default_streams( properties, context, &audio_index, &video_index );
 
                        if ( context->start_time != AV_NOPTS_VALUE )
                                mlt_properties_set_double( properties, "_start_time", context->start_time );
@@ -714,10 +754,7 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
 
                // Construct an AVFrame for YUV422 conversion
                if ( av_frame == NULL )
-               {
                        av_frame = avcodec_alloc_frame( );
-                       mlt_properties_set_data( properties, "av_frame", av_frame, 0, av_free, NULL );
-               }
 
                while( ret >= 0 && !got_picture )
                {
@@ -774,6 +811,7 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
                                        mlt_properties_set_int( properties, "top_field_first", av_frame->top_field_first );
                                        mlt_properties_set_int( properties, "_current_position", int_position );
                                        mlt_properties_set_int( properties, "_got_picture", 1 );
+                                       mlt_properties_set_data( properties, "av_frame", av_frame, 0, av_free, NULL );
                                }
                                else
                                {
@@ -799,6 +837,28 @@ static int producer_get_image( mlt_frame frame, uint8_t **buffer, mlt_image_form
        return 0;
 }
 
+/** Process properties as AVOptions and apply to AV context obj
+*/
+
+static void apply_properties( void *obj, mlt_properties properties, int flags )
+{
+       int i;
+       int count = mlt_properties_count( properties ); 
+       for ( i = 0; i < count; i++ )
+       {
+               const char *opt_name = mlt_properties_get_name( properties, i );
+               const AVOption *opt = av_find_opt( obj, opt_name, NULL, flags, flags );
+               if ( opt != NULL )
+#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(7<<8)+0)
+                       av_set_string3( obj, opt_name, mlt_properties_get( properties, opt_name), 0, NULL );
+#elif LIBAVCODEC_VERSION_INT >= ((51<<16)+(59<<8)+0)
+                       av_set_string2( obj, opt_name, mlt_properties_get( properties, opt_name), 0 );
+#else
+                       av_set_string( obj, opt_name, mlt_properties_get( properties, opt_name) );
+#endif
+       }
+}
+
 /** Set up video handling.
 */
 
@@ -822,6 +882,9 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame )
                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 );
+
+               // Process properties as AVOptions
+               apply_properties( context, properties, AV_OPT_FLAG_DECODING_PARAM );
        }
 
        // Exception handling for video_index
@@ -896,6 +959,9 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame )
                                index = -1;
                        }
                        avformat_unlock( );
+
+                       // Process properties as AVOptions
+                       apply_properties( codec_context, properties, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM );
                }
 
                // No codec, no show...
@@ -919,6 +985,8 @@ static void producer_set_up_video( mlt_producer this, mlt_frame frame )
                        // Set the width and height
                        mlt_properties_set_int( frame_properties, "width", codec_context->width );
                        mlt_properties_set_int( frame_properties, "height", codec_context->height );
+                       mlt_properties_set_int( frame_properties, "real_width", codec_context->width );
+                       mlt_properties_set_int( frame_properties, "real_height", codec_context->height );
                        mlt_properties_set_double( frame_properties, "aspect_ratio", aspect_ratio );
 
                        mlt_frame_push_get_image( frame, producer_get_image );
@@ -999,7 +1067,7 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
        int paused = 0;
 
        // Check for resample and create if necessary
-       if ( resample == NULL && ( *frequency != codec_context->sample_rate || codec_context->channels <= 2 ) )
+       if ( resample == NULL && codec_context->channels <= 2 )
        {
                // Create the resampler
                resample = audio_resample_init( *channels, codec_context->channels, *frequency, codec_context->sample_rate );
@@ -1038,12 +1106,13 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
        if ( decode_buffer == NULL )
        {
                // Allocate the audio buffer
-               decode_buffer = mlt_pool_alloc( AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof( int16_t ) );
+               decode_buffer = av_malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof( int16_t ) );
 
                // And store it on properties for reuse
-               mlt_properties_set_data( properties, "decode_buffer", decode_buffer, 0, ( mlt_destructor )mlt_pool_release, NULL );
+               mlt_properties_set_data( properties, "decode_buffer", decode_buffer, 0, ( mlt_destructor )av_free, NULL );
        }
 
+#if (LIBAVCODEC_VERSION_INT >= ((51<<16)+(71<<8)+0))
        // Check for format converter buffer and create if necessary
        if ( resample && convert && convert_buffer == NULL )
        {
@@ -1053,6 +1122,7 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
                // And store it on properties for reuse
                mlt_properties_set_data( properties, "convert_buffer", convert_buffer, 0, ( mlt_destructor )mlt_pool_release, NULL );
        }
+#endif
 
        // Seek if necessary
        if ( position != expected )
@@ -1293,6 +1363,9 @@ static void producer_set_up_audio( mlt_producer this, mlt_frame frame )
                                index = -1;
                        }
                        avformat_unlock( );
+
+                       // Process properties as AVOptions
+                       apply_properties( codec_context, properties, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM );
                }
 
                // No codec, no show...