]> git.sesse.net Git - mlt/commitdiff
Convert producer_xml to use mlt_log rather than fprintf.
authorBrian Matherly <pez4brian@yahoo.com>
Thu, 26 Jan 2012 05:38:37 +0000 (23:38 -0600)
committerBrian Matherly <pez4brian@yahoo.com>
Thu, 26 Jan 2012 05:38:37 +0000 (23:38 -0600)
src/framework/mlt_types.h
src/modules/avformat/consumer_avformat.c
src/modules/core/filter_audiochannels.c
src/modules/core/filter_audioconvert.c
src/modules/core/filter_channelcopy.c
src/modules/core/filter_mono.c
src/modules/xml/producer_xml.c

index f30e94db8f3da75bfd392fc4108ccfd36a2b7c26..99fd4a3ed1ae64a75c1676a473f15ec2290ee035 100644 (file)
@@ -2,7 +2,7 @@
  * \file mlt_types.h
  * \brief Provides forward definitions of all public types
  *
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2012 Ushodaya Enterprises Limited
  * \author Charles Yates <charles.yates@pandora.be>
  *
  * This library is free software; you can redistribute it and/or
@@ -57,8 +57,8 @@ typedef enum
        mlt_audio_s16 = 1, /**< signed 16-bit interleaved PCM */
        mlt_audio_s32,     /**< signed 32-bit non-interleaved PCM */
        mlt_audio_float,   /**< 32-bit non-interleaved floating point */
-       mlt_audio_s32le,   /**< signed 32-bit interleaved PCM, may only used by producers */
-       mlt_audio_f32le    /**< 32-bit interleaved floating point, may only be used by producers */
+       mlt_audio_s32le,   /**< signed 32-bit interleaved PCM */
+       mlt_audio_f32le    /**< 32-bit interleaved floating point */
 }
 mlt_audio_format;
 
index 95b0a36e851e9cd552fff981048b202c68a6b2cd..5fdf9b3d700e43fe7188e628e75334f56579d4c1 100644 (file)
@@ -45,6 +45,9 @@
 #if LIBAVUTIL_VERSION_INT >= ((50<<16)+(8<<8)+0)
 #include <libavutil/pixdesc.h>
 #endif
+#if LIBAVUTIL_VERSION_INT >= ((50<<16)+(38<<8)+0)
+#include <libavutil/samplefmt.h>
+#endif
 #include <libavutil/mathematics.h>
 
 #if LIBAVUTIL_VERSION_INT < (50<<16)
@@ -72,7 +75,7 @@
 
 typedef struct
 {
-       int16_t *buffer;
+       uint8_t *buffer;
        int size;
        int used;
        double time;
@@ -89,42 +92,16 @@ sample_fifo sample_fifo_init( int frequency, int channels )
        return fifo;
 }
 
-// sample_fifo_clear and check are temporarily aborted (not working as intended)
-
-void sample_fifo_clear( sample_fifo fifo, double time )
-{
-       int words = ( float )( time - fifo->time ) * fifo->frequency * fifo->channels;
-       if ( ( int )( ( float )time * 100 ) < ( int )( ( float )fifo->time * 100 ) && fifo->used > words && words > 0 )
-       {
-               memmove( fifo->buffer, &fifo->buffer[ words ], ( fifo->used - words ) * sizeof( int16_t ) );
-               fifo->used -= words;
-               fifo->time = time;
-       }
-       else if ( ( int )( ( float )time * 100 ) != ( int )( ( float )fifo->time * 100 ) )
-       {
-               fifo->used = 0;
-               fifo->time = time;
-       }
-}
-
-void sample_fifo_check( sample_fifo fifo, double time )
-{
-       if ( fifo->used == 0 )
-       {
-               if ( ( int )( ( float )time * 100 ) < ( int )( ( float )fifo->time * 100 ) )
-                       fifo->time = time;
-       }
-}
-
-void sample_fifo_append( sample_fifo fifo, int16_t *samples, int count )
+// count is the number of samples multiplied by the number of bytes per sample
+void sample_fifo_append( sample_fifo fifo, uint8_t *samples, int count )
 {
        if ( ( fifo->size - fifo->used ) < count )
        {
                fifo->size += count * 5;
-               fifo->buffer = realloc( fifo->buffer, fifo->size * sizeof( int16_t ) );
+               fifo->buffer = realloc( fifo->buffer, fifo->size );
        }
 
-       memcpy( &fifo->buffer[ fifo->used ], samples, count * sizeof( int16_t ) );
+       memcpy( &fifo->buffer[ fifo->used ], samples, count );
        fifo->used += count;
 }
 
@@ -133,14 +110,14 @@ int sample_fifo_used( sample_fifo fifo )
        return fifo->used;
 }
 
-int sample_fifo_fetch( sample_fifo fifo, int16_t *samples, int count )
+int sample_fifo_fetch( sample_fifo fifo, uint8_t *samples, int count )
 {
        if ( count > fifo->used )
                count = fifo->used;
 
-       memcpy( samples, fifo->buffer, count * sizeof( int16_t ) );
+       memcpy( samples, fifo->buffer, count );
        fifo->used -= count;
-       memmove( fifo->buffer, &fifo->buffer[ count ], fifo->used * sizeof( int16_t ) );
+       memmove( fifo->buffer, &fifo->buffer[ count ], fifo->used );
 
        fifo->time += ( double )count / fifo->channels / fifo->frequency;
 
@@ -195,6 +172,9 @@ mlt_consumer consumer_avformat_init( mlt_profile profile, char *arg )
                mlt_properties_set_double( properties, "muxdelay", 0.7 );
                mlt_properties_set_double( properties, "muxpreload", 0.5 );
 
+               // Some AVOption defaults we like
+               mlt_properties_set( properties, "strict", "experimental" );
+
                // Ensure termination at end of the stream
                mlt_properties_set_int( properties, "terminate_on_pause", 1 );
                
@@ -437,6 +417,73 @@ static void apply_properties( void *obj, mlt_properties properties, int flags )
        }
 }
 
+static int get_mlt_audio_format( int av_sample_fmt )
+{
+       switch ( av_sample_fmt )
+       {
+       case AV_SAMPLE_FMT_S32:
+               return mlt_audio_s32le;
+       case AV_SAMPLE_FMT_FLT:
+               return mlt_audio_f32le;
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+       case AV_SAMPLE_FMT_S32P:
+               return mlt_audio_s32;
+       case AV_SAMPLE_FMT_FLTP:
+               return mlt_audio_float;
+#endif
+       default:
+               return mlt_audio_s16;
+       }
+}
+
+static int pick_sample_fmt( mlt_properties properties, AVCodec *codec )
+{
+       int sample_fmt = AV_SAMPLE_FMT_S16;
+       const char *format = mlt_properties_get( properties, "mlt_audio_format" );
+       const int *p = codec->sample_fmts;
+
+       // get default av_sample_fmt from mlt_audio_format
+       if ( format )
+       {
+               if ( !strcmp( format, "s32le" ) )
+                       sample_fmt = AV_SAMPLE_FMT_S32;
+               else if ( !strcmp( format, "f32le" ) )
+                       sample_fmt = AV_SAMPLE_FMT_FLT;
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+               else if ( !strcmp( format, "s32" ) )
+                       sample_fmt = AV_SAMPLE_FMT_S32P;
+               else if ( !strcmp( format, "float" ) )
+                       sample_fmt = AV_SAMPLE_FMT_FLTP;
+#endif
+       }
+       // check if codec supports our mlt_audio_format
+       for ( ; *p != -1; p++ )
+       {
+               if ( *p == sample_fmt )
+                       return sample_fmt;
+       }
+       // no match - pick first one we support
+       for ( p = codec->sample_fmts; *p != -1; p++ )
+       {
+               switch (*p)
+               {
+               case AV_SAMPLE_FMT_S16:
+               case AV_SAMPLE_FMT_S32:
+               case AV_SAMPLE_FMT_FLT:
+#if LIBAVUTIL_VERSION_INT >= ((51<<16)+(17<<8)+0)
+               case AV_SAMPLE_FMT_S32P:
+               case AV_SAMPLE_FMT_FLTP:
+#endif
+                       return *p;
+               default:
+                       break;
+               }
+       }
+       mlt_log_error( properties, "audio codec sample_fmt not compatible" );
+
+       return AV_SAMPLE_FMT_NONE;
+}
+
 /** Add an audio output stream
 */
 
@@ -466,7 +513,7 @@ static AVStream *add_audio_stream( mlt_consumer consumer, AVFormatContext *oc, A
 
                c->codec_id = codec->id;
                c->codec_type = CODEC_TYPE_AUDIO;
-               c->sample_fmt = SAMPLE_FMT_S16;
+               c->sample_fmt = pick_sample_fmt( properties, codec );
 
 #if 0 // disabled until some audio codecs are multi-threaded
                // Setup multi-threading
@@ -1041,11 +1088,10 @@ static void *consumer_thread( void *arg )
        int img_height = height;
 
        // Get default audio properties
-       mlt_audio_format aud_fmt = mlt_audio_s16;
        int channels = mlt_properties_get_int( properties, "channels" );
        int total_channels = channels;
        int frequency = mlt_properties_get_int( properties, "frequency" );
-       int16_t *pcm = NULL;
+       void *pcm = NULL;
        int samples = 0;
 
        // AVFormat audio buffer and frame size
@@ -1075,8 +1121,8 @@ static void *consumer_thread( void *arg )
        mlt_image_format img_fmt = mlt_image_yuv422;
 
        // For receiving audio samples back from the fifo
-       int16_t *audio_buf_1 = av_malloc( AUDIO_ENCODE_BUFFER_SIZE );
-       int16_t *audio_buf_2 = NULL;
+       uint8_t *audio_buf_1 = av_malloc( AUDIO_ENCODE_BUFFER_SIZE );
+       uint8_t *audio_buf_2 = NULL;
        int count = 0;
 
        // Allocate the context
@@ -1299,6 +1345,13 @@ static void *consumer_thread( void *arg )
        }
        mlt_properties_set_int( properties, "channels", total_channels );
 
+       // Audio format is determined when adding the audio stream
+       mlt_audio_format aud_fmt = mlt_audio_none;
+       if ( audio_st[0] )
+               aud_fmt = get_mlt_audio_format( audio_st[0]->codec->sample_fmt );
+       int sample_bytes = mlt_audio_format_size( aud_fmt, 1, 1 );
+       sample_bytes = sample_bytes ? sample_bytes : 1; // prevent divide by zero
+
        // Set the parameters (even though we have none...)
 #if LIBAVFORMAT_VERSION_INT < ((53<<16)+(2<<8)+0)
        if ( av_set_parameters(oc, NULL) >= 0 )
@@ -1431,7 +1484,7 @@ static void *consumer_thread( void *arg )
                        {
                                samples = mlt_sample_calculator( fps, frequency, count ++ );
                                channels = total_channels;
-                               mlt_frame_get_audio( frame, (void**) &pcm, &aud_fmt, &frequency, &channels, &samples );
+                               mlt_frame_get_audio( frame, &pcm, &aud_fmt, &frequency, &channels, &samples );
 
                                // Save the audio channel remap properties for later
                                mlt_properties_pass( frame_meta_properties, frame_properties, "meta.map.audio." );
@@ -1445,10 +1498,10 @@ static void *consumer_thread( void *arg )
 
                                // Silence if not normal forward speed
                                if ( mlt_properties_get_double( frame_properties, "_speed" ) != 1.0 )
-                                       memset( pcm, 0, samples * channels * 2 );
+                                       memset( pcm, 0, samples * channels * sample_bytes );
 
                                // Append the samples
-                               sample_fifo_append( fifo, pcm, samples * channels );
+                               sample_fifo_append( fifo, pcm, samples * channels * sample_bytes );
                                total_time += ( samples * 1000000 ) / frequency;
 
                                if ( !video_st )
@@ -1470,15 +1523,15 @@ static void *consumer_thread( void *arg )
                        if ( !video_st || ( video_st && audio_st[0] && audio_pts < video_pts ) )
                        {
                                // Write audio
-                               if ( ( video_st && terminated ) || ( channels * audio_input_frame_size ) < sample_fifo_used( fifo ) )
+                               if ( ( video_st && terminated ) || ( channels * audio_input_frame_size ) < sample_fifo_used( fifo ) / sample_bytes )
                                {
                                        int j = 0; // channel offset into interleaved source buffer
-                                       int n = FFMIN( FFMIN( channels * audio_input_frame_size, sample_fifo_used( fifo ) ), AUDIO_ENCODE_BUFFER_SIZE );
+                                       int n = FFMIN( FFMIN( channels * audio_input_frame_size, sample_fifo_used( fifo ) / sample_bytes ), AUDIO_ENCODE_BUFFER_SIZE );
 
                                        // Get the audio samples
                                        if ( n > 0 )
                                        {
-                                               sample_fifo_fetch( fifo, audio_buf_1, n );
+                                               sample_fifo_fetch( fifo, audio_buf_1, n * sample_bytes );
                                        }
                                        else if ( audio_codec_id == CODEC_ID_VORBIS && terminated )
                                        {
@@ -1505,7 +1558,7 @@ static void *consumer_thread( void *arg )
                                                // Optimized for single track and no channel remap
                                                if ( !audio_st[1] && !mlt_properties_count( frame_meta_properties ) )
                                                {
-                                                       pkt.size = avcodec_encode_audio( codec, audio_outbuf, audio_outbuf_size, audio_buf_1 );
+                                                       pkt.size = avcodec_encode_audio( codec, audio_outbuf, audio_outbuf_size, (short*) audio_buf_1 );
                                                }
                                                else
                                                {
@@ -1554,14 +1607,14 @@ static void *consumer_thread( void *arg )
                                                                        // Interleave the audio buffer with the # channels for this stream/mapping.
                                                                        for ( k = 0; k < map_channels; k++, j++, source_offset++, dest_offset++ )
                                                                        {
-                                                                               int16_t *src = audio_buf_1 + source_offset;
-                                                                               int16_t *dest = audio_buf_2 + dest_offset;
+                                                                               void *src = audio_buf_1 + source_offset * sample_bytes;
+                                                                               void *dest = audio_buf_2 + dest_offset * sample_bytes;
                                                                                int s = samples + 1;
 
                                                                                while ( --s ) {
-                                                                                       *dest = *src;
-                                                                                       dest += current_channels;
-                                                                                       src += channels;
+                                                                                       memcpy( dest, src, sample_bytes );
+                                                                                       dest += current_channels * sample_bytes;
+                                                                                       src += channels * sample_bytes;
                                                                                }
                                                                        }
                                                                }
@@ -1572,7 +1625,7 @@ static void *consumer_thread( void *arg )
                                                                        dest_offset += current_channels;
                                                                }
                                                        }
-                                                       pkt.size = avcodec_encode_audio( codec, audio_outbuf, audio_outbuf_size, audio_buf_2 );
+                                                       pkt.size = avcodec_encode_audio( codec, audio_outbuf, audio_outbuf_size, (short*) audio_buf_2 );
                                                }
 
                                                // Write the compressed frame in the media file
@@ -1770,7 +1823,7 @@ static void *consumer_thread( void *arg )
                        long passed = time_difference( &ante );
                        if ( fifo != NULL )
                        {
-                               long pending = ( ( ( long )sample_fifo_used( fifo ) * 1000 ) / frequency ) * 1000;
+                               long pending = ( ( ( long )sample_fifo_used( fifo ) / sample_bytes * 1000 ) / frequency ) * 1000;
                                passed -= pending;
                        }
                        if ( passed < total_time )
@@ -1795,10 +1848,10 @@ static void *consumer_thread( void *arg )
                        pkt.size = 0;
 
                        if ( /*( c->capabilities & CODEC_CAP_SMALL_LAST_FRAME ) &&*/
-                               ( channels * audio_input_frame_size < sample_fifo_used( fifo ) ) )
+                               ( channels * audio_input_frame_size < sample_fifo_used( fifo ) / sample_bytes ) )
                        {
-                               sample_fifo_fetch( fifo, audio_buf_1, channels * audio_input_frame_size );
-                               pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, audio_buf_1 );
+                               sample_fifo_fetch( fifo, audio_buf_1, channels * audio_input_frame_size * sample_bytes );
+                               pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, (short*) audio_buf_1 );
                        }
                        if ( pkt.size <= 0 )
                                pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, NULL );
index 20e839bfebf9c6d176ccc2e6391bb136c153a15e..544d932b99b54f9dcd51f86222a573fb1273d1e7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * filter_audiochannels.c -- convert from one audio format to another
- * Copyright (C) 2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2009-2012 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -46,14 +46,27 @@ static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *f
                        {
                                for ( j = 0; j < *channels; j++ )
                                {
-                                       new_buffer[ ( i * *channels ) + j ]     = ((int16_t*)(*buffer))[ ( i * channels_avail ) + k ];
+                                       new_buffer[ ( i * *channels ) + j ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + k ];
+                                       k = ( k + 1 ) % channels_avail;
+                               }
+                       }
+               }
+               else if ( *format == mlt_audio_s32le || *format == mlt_audio_f32le )
+               {
+                       int32_t *p = (int32_t*) new_buffer;
+                       int i, j, k = 0;
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               for ( j = 0; j < *channels; j++ )
+                               {
+                                       p[ ( i * *channels ) + j ] = ((int32_t*)(*buffer))[ ( i * channels_avail ) + k ];
                                        k = ( k + 1 ) % channels_avail;
                                }
                        }
                }
                else
                {
-                       // non-interleaved
+                       // non-interleaved - s32 or float
                        int size_avail = mlt_audio_format_size( *format, *samples, channels_avail );
                        int32_t *p = (int32_t*) new_buffer;
                        int i = *channels / channels_avail;
index 6e930d7e0136ed6d8ae8d796de061765336ddd94..d1f7cb33bb416cfc4dbe5d903230b9ca366dca69 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * filter_audioconvert.c -- convert from one audio format to another
- * Copyright (C) 2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2009-2012 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -81,6 +81,34 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                error = 0;
                                break;
                        }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               int16_t *q = (int16_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = (int32_t) *q++ << 16;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int16_t *q = (int16_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = (float)( *q++ ) / 32768.0;
+                                       f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                       *p++ = f;
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
                        default:
                                break;
                        }
@@ -113,6 +141,36 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                error = 0;
                                break;
                        }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                               *p++ = *( q + c * samples + s );
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                       {
+                                               float f = (float)( *( q + c * samples + s ) ) / 2147483648.0;
+                                               f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                               *p++ = f;
+                                       }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
                        default:
                                break;
                        }
@@ -153,6 +211,36 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                error = 0;
                                break;
                        }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                       {
+                                               float f = *( q + c * samples + s );
+                                               f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                               *p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
+                                       }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               float *q = (float*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                               *p++ = *( q + c * samples + s );
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
                        default:
                                break;
                        }
@@ -210,6 +298,18 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                error = 0;
                                break;
                        }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = (float)( *q++ ) / 2147483648.0;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
                        default:
                                break;
                        }
@@ -273,6 +373,22 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                error = 0;
                                break;
                        }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = *q++;
+                                       f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                       *p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
                        default:
                                break;
                        }
index cbfb709b6005b2bf111d7719ce95aa3734cfec92..be206f89a61c4a840b7982bd42ac9bc390c53bff 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * filter_channelcopy.c -- copy one audio channel to another
- * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2012 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -86,6 +86,26 @@ static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *f
                        }
                        break;
                }
+               case mlt_audio_s32le:
+               case mlt_audio_f32le:
+               {
+                       int32_t *f = (int32_t*) *buffer + from;
+                       int32_t *t = (int32_t*) *buffer + to;
+                       int32_t x;
+                       int i;
+
+                       if ( swap )
+                               for ( i = 0; i < *samples; i++, f += *channels, t += *channels )
+                               {
+                                       x = *t;
+                                       *t = *f;
+                                       *f = x;
+                               }
+                       else
+                               for ( i = 0; i < *samples; i++, f += *channels, t += *channels )
+                                       *t = *f;
+                       break;
+               }
                case mlt_audio_float:
                {
                        float *f = (float*) *buffer + from * *samples;
index 01b6f462deda35c10d4a4e1edea60c4a13764be6..3d2eba71334d66b5576be9ee6be13962c4d4ee90 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * filter_mono.c -- mix all channels to a mono signal across n channels
- * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2003-2012 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
@@ -58,6 +58,34 @@ static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *f
                        *buffer = new_buffer;
                        break;
                }
+               case mlt_audio_s32le:
+               {
+                       int32_t *new_buffer = mlt_pool_alloc( size );
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               int32_t mixdown = 0;
+                               for ( j = 0; j < *channels; j++ )
+                                       mixdown += ((int32_t*) *buffer)[ ( i * *channels ) + j ] / *channels;
+                               for ( j = 0; j < channels_out; j++ )
+                                       new_buffer[ ( i * channels_out ) + j ] = mixdown;
+                       }
+                       *buffer = new_buffer;
+                       break;
+               }
+               case mlt_audio_f32le:
+               {
+                       float *new_buffer = mlt_pool_alloc( size );
+                       for ( i = 0; i < *samples; i++ )
+                       {
+                               float mixdown = 0;
+                               for ( j = 0; j < *channels; j++ )
+                                       mixdown += ((float*) *buffer)[ ( i * *channels ) + j ] / *channels;
+                               for ( j = 0; j < channels_out; j++ )
+                                       new_buffer[ ( i * channels_out ) + j ] = mixdown;
+                       }
+                       *buffer = new_buffer;
+                       break;
+               }
                case mlt_audio_s32:
                {
                        int32_t *new_buffer = mlt_pool_alloc( size );
index 516d54950aaf1573117fe220e691084a29fa0a3f..f38c96c882ac48887b71fdac46bd0aa0641bfd04 100644 (file)
@@ -274,7 +274,7 @@ static int add_producer( deserialise_context context, mlt_service service, mlt_p
                                break;
                        default:
                                result = 0;
-                               mlt_log_warning( container, "Producer defined inside something that isn't a container\n" );
+                               mlt_log_warning( NULL, "[producer_xml] Producer defined inside something that isn't a container\n" );
                                break;
                };
 
@@ -403,7 +403,7 @@ static void on_end_tractor( deserialise_context context, const xmlChar *name )
        }
        else
        {
-               mlt_log_warning( tractor, "Invalid state for tractor\n" );
+               mlt_log_error( NULL, "[producer_xml] Invalid state for tractor\n" );
        }
 }
 
@@ -446,7 +446,7 @@ static void on_start_multitrack( deserialise_context context, const xmlChar *nam
        }
        else
        {
-               mlt_log_warning( parent, "Invalid multitrack position\n" );
+               mlt_log_error( NULL, "[producer_xml] Invalid multitrack position\n" );
        }
 }
 
@@ -457,7 +457,7 @@ static void on_end_multitrack( deserialise_context context, const xmlChar *name
        mlt_service service = context_pop_service( context, &type );
 
        if ( service == NULL || type != mlt_multitrack_type )
-               mlt_log_warning( service, "End multitrack in the wrong state...\n" );
+               mlt_log_error( NULL, "[producer_xml] End multitrack in the wrong state...\n" );
 }
 
 static void on_start_playlist( deserialise_context context, const xmlChar *name, const xmlChar **atts)
@@ -506,7 +506,7 @@ static void on_end_playlist( deserialise_context context, const xmlChar *name )
        }
        else
        {
-               mlt_log_warning( service, "Invalid state of playlist end %d\n", type );
+               mlt_log_error( NULL, "[producer_xml] Invalid state of playlist end %d\n", type );
        }
 }
 
@@ -605,7 +605,7 @@ static void on_end_producer( deserialise_context context, const xmlChar *name )
                if ( !producer && resource )
                        producer = MLT_SERVICE( mlt_factory_producer( context->profile, NULL, resource ) );
                if ( !producer )
-                       mlt_log_warning( service, "failed to load producer \"%s\"\n", resource );
+                       mlt_log_error( NULL, "[producer_xml] failed to load producer \"%s\"\n", resource );
                if ( !producer )
                        producer = MLT_SERVICE( mlt_factory_producer( context->profile, NULL, "+INVALID.txt" ) );
                if ( !producer )
@@ -746,7 +746,7 @@ static void on_start_blank( deserialise_context context, const xmlChar *name, co
        }
        else
        {
-               mlt_log_warning( service, "blank without a playlist - a definite no no\n" );
+               mlt_log_error( NULL, "[producer_xml] blank without a playlist - a definite no no\n" );
        }
 }
 
@@ -800,7 +800,7 @@ static void on_start_entry( deserialise_context context, const xmlChar *name, co
                }
                else
                {
-                       mlt_log_warning( parent, "Entry not part of a playlist...\n" );
+                       mlt_log_error( NULL, "[producer_xml] Entry not part of a playlist...\n" );
                }
 
                context_push_service( context, parent, parent_type );
@@ -820,7 +820,7 @@ static void on_end_entry( deserialise_context context, const xmlChar *name )
 
        if ( entry == NULL && entry_type != mlt_entry_type )
        {
-               mlt_log_warning( entry, "Invalid state at end of entry\n" );
+               mlt_log_error( NULL, "[producer_xml] Invalid state at end of entry\n" );
        }
 }
 
@@ -870,7 +870,7 @@ static void on_end_track( deserialise_context context, const xmlChar *name )
                else if ( parent_type == mlt_multitrack_type )
                        multitrack = MLT_MULTITRACK( parent );
                else
-                       mlt_log_warning( track, "track contained in an invalid container\n" );
+                       mlt_log_error( NULL, "[producer_xml] track contained in an invalid container\n" );
 
                if ( multitrack != NULL )
                {
@@ -915,7 +915,7 @@ static void on_end_track( deserialise_context context, const xmlChar *name )
        }
        else
        {
-               mlt_log_warning( track, "Invalid state at end of track\n" );
+               mlt_log_error( NULL, "[producer_xml] Invalid state at end of track\n" );
        }
 }
 
@@ -951,7 +951,7 @@ static void on_end_filter( deserialise_context context, const xmlChar *name )
 
                if ( !filter )
                {
-                       mlt_log_warning( service, "failed to load filter \"%s\"\n", id );
+                       mlt_log_error( NULL, "[producer_xml] failed to load filter \"%s\"\n", id );
                        if ( parent )
                                context_push_service( context, parent, parent_type );
                        mlt_service_close( service );
@@ -993,7 +993,7 @@ static void on_end_filter( deserialise_context context, const xmlChar *name )
                }
                else
                {
-                       mlt_log_warning( service, "filter closed with invalid parent...\n" );
+                       mlt_log_error( NULL, "[producer_xml] filter closed with invalid parent...\n" );
                }
 
                // Close the dummy filter service
@@ -1001,7 +1001,7 @@ static void on_end_filter( deserialise_context context, const xmlChar *name )
        }
        else
        {
-               mlt_log_warning( service, "Invalid top of stack on filter close\n" );
+               mlt_log_error( NULL, "[producer_xml] Invalid top of stack on filter close\n" );
        }
 }
 
@@ -1037,7 +1037,7 @@ static void on_end_transition( deserialise_context context, const xmlChar *name
 
                if ( !effect )
                {
-                       mlt_log_warning( service, "failed to load transition \"%s\"\n", id );
+                       mlt_log_error( NULL, "[producer_xml] failed to load transition \"%s\"\n", id );
                        if ( parent )
                                context_push_service( context, parent, parent_type );
                        mlt_service_close( service );
@@ -1074,7 +1074,7 @@ static void on_end_transition( deserialise_context context, const xmlChar *name
                        }
                        else
                        {
-                               mlt_log_warning( service, "Misplaced transition - ignoring\n" );
+                               mlt_log_warning( NULL, "[producer_xml] Misplaced transition - ignoring\n" );
                        }
 
                        // Put the parent back on the stack
@@ -1082,7 +1082,7 @@ static void on_end_transition( deserialise_context context, const xmlChar *name
                }
                else
                {
-                       mlt_log_warning( service, "transition closed with invalid parent...\n" );
+                       mlt_log_error( NULL, "[producer_xml] transition closed with invalid parent...\n" );
                }
 
                // Close the dummy filter service
@@ -1090,7 +1090,7 @@ static void on_end_transition( deserialise_context context, const xmlChar *name
        }
        else
        {
-               mlt_log_warning( service, "Invalid top of stack on transition close\n" );
+               mlt_log_error( NULL, "[producer_xml] Invalid top of stack on transition close\n" );
        }
 }
 
@@ -1196,7 +1196,7 @@ static void on_start_property( deserialise_context context, const xmlChar *name,
        }
        else
        {
-               mlt_log_warning( service, "Property without a service '%s'?\n", ( const char * )name );
+               mlt_log_error( NULL, "[producer_xml] Property without a service '%s'?\n", ( const char * )name );
        }
 }
 
@@ -1237,7 +1237,7 @@ static void on_end_property( deserialise_context context, const xmlChar *name )
        }
        else
        {
-               mlt_log_warning( service, "Property without a service '%s'??\n", (const char *)name );
+               mlt_log_error( NULL, "[producer_xml] Property without a service '%s'??\n", (const char *)name );
        }
 }
 
@@ -1246,7 +1246,6 @@ static void on_start_element( void *ctx, const xmlChar *name, const xmlChar **at
        struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
        deserialise_context context = ( deserialise_context )( xmlcontext->_private );
        
-//printf("on_start_element: %s\n", name );
        if ( context->pass == 0 )
        {
                if ( xmlStrcmp( name, _x("mlt") ) == 0 ||
@@ -1321,7 +1320,6 @@ static void on_end_element( void *ctx, const xmlChar *name )
        struct _xmlParserCtxt *xmlcontext = ( struct _xmlParserCtxt* )ctx;
        deserialise_context context = ( deserialise_context )( xmlcontext->_private );
        
-//printf("on_end_element: %s\n", name );
        if ( context->is_value == 1 && context->pass == 1 && xmlStrcmp( name, _x("property") ) != 0 )
                context_pop_node( context );
        else if ( xmlStrcmp( name, _x("multitrack") ) == 0 )
@@ -1469,13 +1467,26 @@ static xmlEntityPtr on_get_entity( void *ctx, const xmlChar* name )
        return e;
 }
 
-/** Handle error messages from the parser.
-*/
-static void    on_error( void * ctx, const char * msg, ...)
+static void    on_error( void * ctx, const char * msg, ... )
 {
-       struct _xmlError* err_ptr = xmlCtxtGetLastError(ctx);
-       mlt_log_error( NULL, "XML producer parse error: %s\trow: %d\tcol: %d\n",
-                              err_ptr->message, err_ptr->line, err_ptr->int2 );
+       struct _xmlError* err_ptr = xmlCtxtGetLastError( ctx );
+
+       switch( err_ptr->level )
+       {
+       case XML_ERR_WARNING:
+               mlt_log_warning( NULL, "[producer_xml] parse warning: %s\trow: %d\tcol: %d\n",
+                                        err_ptr->message, err_ptr->line, err_ptr->int2 );
+               break;
+       case XML_ERR_ERROR:
+               mlt_log_error( NULL, "[producer_xml] parse error: %s\trow: %d\tcol: %d\n",
+                                      err_ptr->message, err_ptr->line, err_ptr->int2 );
+               break;
+       default:
+       case XML_ERR_FATAL:
+               mlt_log_fatal( NULL, "[producer_xml] parse fatal: %s\trow: %d\tcol: %d\n",
+                                      err_ptr->message, err_ptr->line, err_ptr->int2 );
+               break;
+       }
 }
 
 /** Convert a hexadecimal character to its value.
@@ -1616,6 +1627,12 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
        // We need to track the number of registered filters
        mlt_properties_set_int( context->destructors, "registered", 0 );
 
+       // Setup SAX callbacks for first pass
+       sax->startElement = on_start_element;
+       sax->warning = on_error;
+       sax->error = on_error;
+       sax->fatalError = on_error;
+
        // Setup libxml2 SAX parsing
        xmlInitParser(); 
        xmlSubstituteEntitiesDefault( 1 );
@@ -1642,6 +1659,7 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
        xmlcontext->sax = sax;
        xmlcontext->_private = ( void* )context;        
        xmlParseDocument( xmlcontext );
+       well_formed = xmlcontext->wellFormed;
        
        // Cleanup after parsing
        xmlcontext->sax = NULL;
@@ -1650,6 +1668,19 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
        context->stack_node_size = 0;
        context->stack_service_size = 0;
 
+       // Bad xml - clean up and return NULL
+       if ( !well_formed )
+       {
+               mlt_properties_close( context->producer_map );
+               mlt_properties_close( context->destructors );
+               mlt_properties_close( context->params );
+               xmlFreeDoc( context->entity_doc );
+               free( context );
+               free( sax );
+               free( filename );
+               return NULL;
+       }
+
        // Setup the second pass
        context->pass ++;
        if ( info == 0 )
@@ -1670,16 +1701,13 @@ mlt_producer producer_xml_init( mlt_profile profile, mlt_service_type servtype,
                return NULL;
        }
 
-       // Setup SAX callbacks
-       sax->startElement = on_start_element;
+       // Setup SAX callbacks for second pass
        sax->endElement = on_end_element;
        sax->characters = on_characters;
        sax->cdataBlock = on_characters;
        sax->internalSubset = on_internal_subset;
        sax->entityDecl = on_entity_declaration;
        sax->getEntity = on_get_entity;
-       sax->error = on_error;
-       sax->fatalError = on_error;
 
        // Parse
        xmlcontext->sax = sax;