]> git.sesse.net Git - mlt/blobdiff - src/modules/avformat/consumer_avformat.c
AVStream.r_frame_rate is still useful on FFmpeg (not libav).
[mlt] / src / modules / avformat / consumer_avformat.c
index 295e7fc65ce6411dcb07827aac8fdc37b89c17d8..b4753fa94c7b74c539c7f9ed4539472352264501 100644 (file)
@@ -196,6 +196,27 @@ mlt_consumer consumer_avformat_init( mlt_profile profile, char *arg )
        return consumer;
 }
 
+static void recompute_aspect_ratio( mlt_properties properties )
+{
+       double ar = mlt_properties_get_double( properties, "aspect" );
+       AVRational rational = av_d2q( ar, 255 );
+       int width = mlt_properties_get_int( properties, "width" );
+       int height = mlt_properties_get_int( properties, "height" );
+
+       // Update the profile and properties as well since this is an alias
+       // for mlt properties that correspond to profile settings
+       mlt_properties_set_int( properties, "display_aspect_num", rational.num );
+       mlt_properties_set_int( properties, "display_aspect_den", rational.den );
+
+       // Now compute the sample aspect ratio
+       rational = av_d2q( ar * height / FFMAX(width, 1), 255 );
+
+       // Update the profile and properties as well since this is an alias
+       // for mlt properties that correspond to profile settings
+       mlt_properties_set_int( properties, "sample_aspect_num", rational.num );
+       mlt_properties_set_int( properties, "sample_aspect_den", rational.den );
+}
+
 static void property_changed( mlt_properties owner, mlt_consumer self, char *name )
 {
        mlt_properties properties = MLT_CONSUMER_PROPERTIES( self );
@@ -223,27 +244,12 @@ static void property_changed( mlt_properties owner, mlt_consumer self, char *nam
                height = ( height / 2 ) * 2;
                mlt_properties_set_int( properties, "width", width );
                mlt_properties_set_int( properties, "height", height );
+               recompute_aspect_ratio( properties );
        }
        // "-aspect" on ffmpeg command line is display aspect ratio
-       else if ( !strcmp( name, "aspect" ) )
+       else if ( !strcmp( name, "aspect" ) || !strcmp( name, "width" ) || !strcmp( name, "height" ) )
        {
-               double ar = mlt_properties_get_double( properties, "aspect" );
-               AVRational rational = av_d2q( ar, 255 );
-               int width = mlt_properties_get_int( properties, "width" );
-               int height = mlt_properties_get_int( properties, "height" );
-
-               // Update the profile and properties as well since this is an alias
-               // for mlt properties that correspond to profile settings
-               mlt_properties_set_int( properties, "display_aspect_num", rational.num );
-               mlt_properties_set_int( properties, "display_aspect_den", rational.den );
-
-               // Now compute the sample aspect ratio
-               rational = av_d2q( ar * height / FFMAX(width, 1), 255 );
-
-               // Update the profile and properties as well since this is an alias
-               // for mlt properties that correspond to profile settings
-               mlt_properties_set_int( properties, "sample_aspect_num", rational.num );
-               mlt_properties_set_int( properties, "sample_aspect_den", rational.den );
+               recompute_aspect_ratio( properties );
        }
        // Handle the ffmpeg command line "-r" property for frame rate
        else if ( !strcmp( name, "r" ) )
@@ -703,6 +709,20 @@ static int open_audio( mlt_properties properties, AVFormatContext *oc, AVStream
                                case AV_CODEC_ID_PCM_U16BE:
                                        audio_input_frame_size >>= 1;
                                        break;
+#if LIBAVCODEC_VERSION_INT >= ((54<<16)+(59<<8)+0)
+                               case AV_CODEC_ID_PCM_S24LE:
+                               case AV_CODEC_ID_PCM_S24BE:
+                               case AV_CODEC_ID_PCM_U24LE:
+                               case AV_CODEC_ID_PCM_U24BE:
+                                       audio_input_frame_size /= 3;
+                                       break;
+                               case AV_CODEC_ID_PCM_S32LE:
+                               case AV_CODEC_ID_PCM_S32BE:
+                               case AV_CODEC_ID_PCM_U32LE:
+                               case AV_CODEC_ID_PCM_U32BE:
+                                       audio_input_frame_size >>= 2;
+                                       break;
+#endif
                                default:
                                        break;
                        }
@@ -1178,7 +1198,7 @@ static void *consumer_thread( void *arg )
        int count = 0;
 
        // Allocate the context
-       AVFormatContext *oc = avformat_alloc_context( );
+       AVFormatContext *oc = NULL;
 
        // Streams
        AVStream *video_st = NULL;
@@ -1232,6 +1252,22 @@ static void *consumer_thread( void *arg )
        if ( filename == NULL || !strcmp( filename, "" ) )
                filename = "pipe:";
 
+#if defined(FFUDIV) && LIBAVUTIL_VERSION_INT >= ((53<<16)+(2<<8)+0)
+       avformat_alloc_output_context2( &oc, fmt, format, filename );
+#else
+       oc = avformat_alloc_context( );
+       oc->oformat = fmt;
+       snprintf( oc->filename, sizeof(oc->filename), "%s", filename );
+
+       if ( oc->oformat && oc->oformat->priv_class && !oc->priv_data && oc->oformat->priv_data_size ) {
+               oc->priv_data = av_mallocz( oc->oformat->priv_data_size );
+               if ( oc->priv_data ) {
+                       *(const AVClass**)oc->priv_data = oc->oformat->priv_class;
+                       av_opt_set_defaults( oc->priv_data );
+               }
+       }
+#endif
+
        // Get the codec ids selected
        audio_codec_id = fmt->audio_codec;
        video_codec_id = fmt->video_codec;
@@ -1310,9 +1346,6 @@ static void *consumer_thread( void *arg )
                }
        }
 
-       oc->oformat = fmt;
-       snprintf( oc->filename, sizeof(oc->filename), "%s", filename );
-
        // Get a frame now, so we can set some AVOptions from properties.
        frame = mlt_consumer_rt_frame( consumer );
 
@@ -1455,10 +1488,15 @@ static void *consumer_thread( void *arg )
                // Write the stream header.
                if ( mlt_properties_get_int( properties, "running" ) )
 #if LIBAVFORMAT_VERSION_INT >= ((53<<16)+(2<<8)+0)
-                       avformat_write_header( oc, NULL );
+                       if ( avformat_write_header( oc, NULL ) < 0 )
 #else
-                       av_write_header( oc );
+                       if ( av_write_header( oc ) < 0 )
 #endif
+                       {
+                               mlt_log_error( MLT_CONSUMER_SERVICE( consumer ), "Could not write header '%s'\n", filename );
+                               mlt_events_fire( properties, "consumer-fatal-error", NULL );
+                               goto on_fatal_error;
+                       }
        }
 #if LIBAVFORMAT_VERSION_INT < ((53<<16)+(2<<8)+0)
        else
@@ -1480,7 +1518,7 @@ static void *consumer_thread( void *arg )
        if ( video_st )
                converted_avframe = alloc_picture( video_st->codec->pix_fmt, width, height );
 
-#if LIBAVCODEC_VERSION_MAJOR >= 55
+#if LIBAVCODEC_VERSION_MAJOR >= 54
        // Allocate audio AVFrame
        if ( audio_st[0] )
        {
@@ -1613,11 +1651,13 @@ static void *consumer_thread( void *arg )
                                                        else if ( codec->sample_fmt == AV_SAMPLE_FMT_U8P )
                                                                p = interleaved_to_planar( samples, channels, p, sizeof( uint8_t ) );
 #endif
-#if LIBAVCODEC_VERSION_MAJOR >= 55
+#if LIBAVCODEC_VERSION_MAJOR >= 54
                                                        audio_avframe->nb_samples = FFMAX( samples, audio_input_nb_samples );
+#if LIBAVCODEC_VERSION_MAJOR >= 55
                                                        if ( audio_codec_id == AV_CODEC_ID_VORBIS )
                                                                audio_avframe->pts = synth_audio_pts;
                                                        synth_audio_pts += audio_avframe->nb_samples;
+#endif
                                                        avcodec_fill_audio_frame( audio_avframe, codec->channels, codec->sample_fmt,
                                                                (const uint8_t*) p, AUDIO_ENCODE_BUFFER_SIZE, 0 );
                                                        int got_packet = 0;
@@ -1703,11 +1743,13 @@ static void *consumer_thread( void *arg )
                                                                        dest_offset += current_channels;
                                                                }
                                                        }
-#if LIBAVCODEC_VERSION_MAJOR >= 55
+#if LIBAVCODEC_VERSION_MAJOR >= 54
                                                        audio_avframe->nb_samples = FFMAX( samples, audio_input_nb_samples );
+#if LIBAVCODEC_VERSION_MAJOR >= 55
                                                        if ( audio_codec_id == AV_CODEC_ID_VORBIS )
                                                                audio_avframe->pts = synth_audio_pts;
                                                        synth_audio_pts += audio_avframe->nb_samples;
+#endif
                                                        avcodec_fill_audio_frame( audio_avframe, codec->channels, codec->sample_fmt,
                                                                (const uint8_t*) audio_buf_2, AUDIO_ENCODE_BUFFER_SIZE, 0 );
                                                        int got_packet = 0;
@@ -2013,12 +2055,14 @@ static void *consumer_thread( void *arg )
                                else if ( c->sample_fmt == AV_SAMPLE_FMT_U8P )
                                        p = interleaved_to_planar( audio_input_nb_samples, channels, p, sizeof( uint8_t ) );
 #endif
-#if LIBAVCODEC_VERSION_MAJOR >= 55
+#if LIBAVCODEC_VERSION_MAJOR >= 54
                                pkt.size = audio_outbuf_size;
                                audio_avframe->nb_samples = FFMAX( samples / channels, audio_input_nb_samples );
+#if LIBAVCODEC_VERSION_MAJOR >= 55
                                if ( audio_codec_id == AV_CODEC_ID_VORBIS )
                                        audio_avframe->pts = synth_audio_pts;
                                synth_audio_pts += audio_avframe->nb_samples;
+#endif
                                avcodec_fill_audio_frame( audio_avframe, c->channels, c->sample_fmt,
                                        (const uint8_t*) p, AUDIO_ENCODE_BUFFER_SIZE, 0 );
                                int got_packet = 0;
@@ -2041,7 +2085,7 @@ static void *consumer_thread( void *arg )
                        {
                                // Drain the codec
                                if ( pkt.size <= 0 ) {
-#if LIBAVCODEC_VERSION_MAJOR >= 55
+#if LIBAVCODEC_VERSION_MAJOR >= 54
                                        pkt.size = audio_outbuf_size;
                                        int got_packet = 0;
                                        int ret = avcodec_encode_audio2( c, &pkt, NULL, &got_packet );
@@ -2131,7 +2175,10 @@ static void *consumer_thread( void *arg )
        }
 
 on_fatal_error:
-       
+
+       if ( frame )
+               mlt_frame_close( frame );
+
        // Write the trailer, if any
        if ( frames )
                av_write_trailer( oc );
@@ -2200,6 +2247,18 @@ on_fatal_error:
                free( full );
                free( cwd );
                remove( "x264_2pass.log.temp" );
+
+               // Recent versions of libavcodec/x264 support passlogfile and need cleanup if specified.
+               if ( !mlt_properties_get( properties, "_logfilename" ) &&
+                     mlt_properties_get( properties, "passlogfile" ) )
+               {
+                       file = mlt_properties_get( properties, "passlogfile" );
+                       remove( file );
+                       full = malloc( strlen( file ) + strlen( ".mbtree" ) + 1 );
+                       sprintf( full, "%s.mbtree", file );
+                       remove( full );
+                       free( full );
+               }
        }
 
        while ( ( frame = mlt_deque_pop_back( queue ) ) )