]> git.sesse.net Git - mlt/commitdiff
ppm ffmpeg
authorlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Sat, 27 Dec 2003 18:34:18 +0000 (18:34 +0000)
committerlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Sat, 27 Dec 2003 18:34:18 +0000 (18:34 +0000)
git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@26 d19143bc-622f-0410-bfdd-b5b2a6649095

34 files changed:
Makefile
README
configure
mlt/Makefile
mlt/README
mlt/configure
mlt/setenv [new file with mode: 0644]
mlt/src/framework/mlt_frame.c
mlt/src/framework/mlt_playlist.c
mlt/src/inigo/Makefile [new file with mode: 0644]
mlt/src/inigo/configure [new file with mode: 0755]
mlt/src/inigo/inigo.c [new file with mode: 0644]
mlt/src/inigo/io.c [new file with mode: 0644]
mlt/src/inigo/io.h [new file with mode: 0644]
mlt/src/modules/core/filter_resize.c
mlt/src/modules/core/filter_resize.h
mlt/src/modules/core/producer_ppm.c
mlt/src/modules/core/producer_ppm.h
mlt/src/modules/sdl/consumer_sdl.c
mlt/src/tests/charlie.c
setenv [new file with mode: 0644]
src/framework/mlt_frame.c
src/framework/mlt_playlist.c
src/inigo/Makefile [new file with mode: 0644]
src/inigo/configure [new file with mode: 0755]
src/inigo/inigo.c [new file with mode: 0644]
src/inigo/io.c [new file with mode: 0644]
src/inigo/io.h [new file with mode: 0644]
src/modules/core/filter_resize.c
src/modules/core/filter_resize.h
src/modules/core/producer_ppm.c
src/modules/core/producer_ppm.h
src/modules/sdl/consumer_sdl.c
src/tests/charlie.c

index a2754671db3ee6017299ef9ac16c545d8d3e012a..ef2180983bb68ddfeac7c414c28fd1d162d0ba8e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-SUBDIRS = src/framework src/valerie src/modules # src/miracle src/humperdink
+SUBDIRS = src/framework src/modules src/inigo src/valerie # src/miracle src/humperdink
 
 all clean dist-clean depend install:
        list='$(SUBDIRS)'; \
diff --git a/README b/README
index 6ed3c5f6d3000dad8975393e62f0de2603e73dae..fc7f3c5608c93d73639e1bd88528240b3f4019ce 100644 (file)
--- a/README
+++ b/README
@@ -14,21 +14,24 @@ Directories
        + docs                                  - Location of all text and source format 
                                                          documentation
        + src                                   - All project source is provided here
-               + framework                     - The media framework - this code is 100% posix
-                                                         and as such contain no implementations 
-                                                         requiring additional libraries
-               + modules                       - All components are defined here with a 
-                                                         subdirectory for each dependency
-                       + bluefish              - Bluefish dependent modules and test code
+               + framework                     - The media framework
+               + modules                       - All components are defined here
+                       + core                  - Non-dependent MLT service
+                       + dv                    - libdv services
                        + ffmpeg                - ffmpeg dependent modules and test code
-                       + mainconcept   - mainconcept dependent modules and test code
-                       + SDL                   - SDL dependent modules and test code
+                       + sdl                   - SDL dependent modules and test code
+                       + bluefish              - Bluefish dependent modules and test code (*)
+                       + mainconcept   - mainconcept dependent modules and test code (*)
+               + inigo                         - A media playing test application
                + valerie                       - Client API to access the server
                + miracle                       - The server implementation
+               + tests                         - Reserved for regression and unit tests
 
        Additional subdirectories may be nested below those shown and should be
        documented in their parent or here.
 
+       (*) Not posted to CVS due to licensing issues.
+
 Configuration
 -------------
 
@@ -49,6 +52,9 @@ Configuration
        ./configure --disable-[mod] - do not compile specified module(s)
        ./configure --[other]           - pass through to children
 
+       NB: This script must be run to register new services after a CVS checkout
+       or subsequent update.
+       
 Compilation
 -----------
 
@@ -73,9 +79,9 @@ Installation
        $prefix/bin/. This is linked against the framework shared object and
        posix libs but not against any of the modules.
 
-       The modules produce a shared object per module and a text file containing
-       a list of modules provided by this build. These are installed in
-       $prefix/share/mlt/. It is at the discretion of the module to install
+       The modules produce a shared object per module and update text files
+       containing a list of modules provided by this build. These are installed 
+       in $prefix/share/mlt/. It is at the discretion of the module to install
        additional support files. 
        
        To allow the development of external components, mlt-client-config and
@@ -102,8 +108,8 @@ Development
 
                #include <framework/file.h>
 
-       This allows migration of source between external and internal
-       modules. The configuration and Makefile template requirements will require
+       This allows migration of source between external and internal modules. 
+       The configuration and Makefile template requirements will require
        attention though.
 
 Summary
index 40b31a49225cf98bfb8e3b29afc135e31eb93733..4b39bfc32cb837bfce8937cb9d5bd5d7f63b4b47 100755 (executable)
--- a/configure
+++ b/configure
@@ -40,7 +40,7 @@ done
 [ $help = 1 ] && show_help
 
 # Iterate through each of the components
-for i in framework modules valerie miracle humperdink
+for i in framework modules inigo valerie miracle humperdink
 do
        if [ -x src/$i/configure ]
        then
index a2754671db3ee6017299ef9ac16c545d8d3e012a..ef2180983bb68ddfeac7c414c28fd1d162d0ba8e 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = src/framework src/valerie src/modules # src/miracle src/humperdink
+SUBDIRS = src/framework src/modules src/inigo src/valerie # src/miracle src/humperdink
 
 all clean dist-clean depend install:
        list='$(SUBDIRS)'; \
index 6ed3c5f6d3000dad8975393e62f0de2603e73dae..fc7f3c5608c93d73639e1bd88528240b3f4019ce 100644 (file)
@@ -14,21 +14,24 @@ Directories
        + docs                                  - Location of all text and source format 
                                                          documentation
        + src                                   - All project source is provided here
-               + framework                     - The media framework - this code is 100% posix
-                                                         and as such contain no implementations 
-                                                         requiring additional libraries
-               + modules                       - All components are defined here with a 
-                                                         subdirectory for each dependency
-                       + bluefish              - Bluefish dependent modules and test code
+               + framework                     - The media framework
+               + modules                       - All components are defined here
+                       + core                  - Non-dependent MLT service
+                       + dv                    - libdv services
                        + ffmpeg                - ffmpeg dependent modules and test code
-                       + mainconcept   - mainconcept dependent modules and test code
-                       + SDL                   - SDL dependent modules and test code
+                       + sdl                   - SDL dependent modules and test code
+                       + bluefish              - Bluefish dependent modules and test code (*)
+                       + mainconcept   - mainconcept dependent modules and test code (*)
+               + inigo                         - A media playing test application
                + valerie                       - Client API to access the server
                + miracle                       - The server implementation
+               + tests                         - Reserved for regression and unit tests
 
        Additional subdirectories may be nested below those shown and should be
        documented in their parent or here.
 
+       (*) Not posted to CVS due to licensing issues.
+
 Configuration
 -------------
 
@@ -49,6 +52,9 @@ Configuration
        ./configure --disable-[mod] - do not compile specified module(s)
        ./configure --[other]           - pass through to children
 
+       NB: This script must be run to register new services after a CVS checkout
+       or subsequent update.
+       
 Compilation
 -----------
 
@@ -73,9 +79,9 @@ Installation
        $prefix/bin/. This is linked against the framework shared object and
        posix libs but not against any of the modules.
 
-       The modules produce a shared object per module and a text file containing
-       a list of modules provided by this build. These are installed in
-       $prefix/share/mlt/. It is at the discretion of the module to install
+       The modules produce a shared object per module and update text files
+       containing a list of modules provided by this build. These are installed 
+       in $prefix/share/mlt/. It is at the discretion of the module to install
        additional support files. 
        
        To allow the development of external components, mlt-client-config and
@@ -102,8 +108,8 @@ Development
 
                #include <framework/file.h>
 
-       This allows migration of source between external and internal
-       modules. The configuration and Makefile template requirements will require
+       This allows migration of source between external and internal modules. 
+       The configuration and Makefile template requirements will require
        attention though.
 
 Summary
index 40b31a49225cf98bfb8e3b29afc135e31eb93733..4b39bfc32cb837bfce8937cb9d5bd5d7f63b4b47 100755 (executable)
@@ -40,7 +40,7 @@ done
 [ $help = 1 ] && show_help
 
 # Iterate through each of the components
-for i in framework modules valerie miracle humperdink
+for i in framework modules inigo valerie miracle humperdink
 do
        if [ -x src/$i/configure ]
        then
diff --git a/mlt/setenv b/mlt/setenv
new file mode 100644 (file)
index 0000000..01363eb
--- /dev/null
@@ -0,0 +1,10 @@
+export MLT_REPOSITORY=`pwd`/src/modules
+
+export LD_LIBRARY_PATH=`pwd`/src/framework:\
+`pwd`/src/modules/bluefish:\
+`pwd`/../bluefish/lib:\
+`pwd`/../mpeg_sdk_demo/bin:\
+`pwd`/../dv_sdk
+
+export PATH=$PATH:`pwd`/src/inigo:`pwd`/src/miracle
+
index f0b9351110cc89e27b2d0300c3de8f3c6a297eff..6b1558fc6a3c03e60e7e518ac7b681ffd091fb9f 100644 (file)
@@ -432,6 +432,14 @@ int mlt_frame_composite_yuv( mlt_frame this, mlt_frame that, int x, int y, float
        return ret;
 }
 
+void *memfill( void *dst, void *src, int l, int elements )
+{
+       int i = 0;
+       for ( i = 0; i < elements; i ++ )
+               dst = memcpy( dst, src, l ) + l;
+       return dst;
+}
+
 void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight )
 {
        // Calculate strides
@@ -439,22 +447,23 @@ void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input
        int ostride = owidth * 2;
 
        // Coordinates (0,0 is middle of output)
-       int y, x;
+       int y;
 
        // Calculate ranges
        int out_x_range = owidth / 2;
        int out_y_range = oheight / 2;
-       int in_x_range = iwidth / 2;
-       int in_y_range = iheight / 2;
+       int in_x_range = iwidth / 2 < out_x_range ? iwidth / 2 : out_x_range;
+       int in_y_range = iheight / 2 < out_y_range ? iheight / 2 : out_y_range;
 
        // Output pointers
        uint8_t *out_line = output;
        uint8_t *out_ptr;
 
        // Calculate a middle and possibly invalid pointer in the input
-       uint8_t *in_middle = input + istride * in_y_range + in_x_range * 2;
-       int in_line = - out_y_range * istride - out_x_range * 2;
-       int in_ptr;
+       uint8_t *in_middle = input + istride * ( iheight / 2 ) + ( iwidth / 2 ) * 2;
+       int in_line = - in_y_range * istride - in_x_range * 2;
+
+       uint8_t black[ 2 ] = { 16, 128 };
 
        // Loop for the entirety of our output height.
        for ( y = - out_y_range; y < out_y_range ; y ++ )
@@ -462,33 +471,29 @@ void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input
                // Start at the beginning of the line
                out_ptr = out_line;
 
-               // Point the start of the current input line (NB: can be out of range)
-               in_ptr = in_line;
-
-               // Loop for the entirety of our output row.
-               for ( x = - out_x_range; x < out_x_range; x ++ )
-               {
-               // Check if x and y are in the valid input range.
-               if ( abs( x ) < in_x_range && abs( y ) < in_y_range  )
-               {
-                       // We're in the input range for this row.
-                       *out_ptr ++ = *( in_middle + in_ptr ++ );
-                       *out_ptr ++ = *( in_middle + in_ptr ++ );
-               }
-               else
-               {
-                       // We're not in the input range for this row.
-                       *out_ptr ++ = 16;
-                       *out_ptr ++ = 128;
-                       in_ptr += 2;
-               }
-               }
+               if ( abs( y ) < iheight / 2 )
+               {
+                       // Fill the outer part with black
+                       out_ptr = memfill( out_ptr, black, 2, out_x_range - in_x_range );
+
+                       // We're in the input range for this row.
+                       memcpy( out_ptr, in_middle + in_line, 4 * in_x_range );
+                       out_ptr += 4 * in_x_range;
+
+                       // Fill the outer part with black
+                       out_ptr = memfill( out_ptr, black, 2, out_x_range - in_x_range );
+
+                       // Move to next input line
+                       in_line += istride;
+               }
+               else
+               {
+                       // Fill whole line with black
+                       out_ptr = memfill( out_ptr, black, 2, owidth );
+               }
 
                // Move to next output line
                out_line += ostride;
-
-               // Move to next input line
-               in_line += istride;
        }
 }
 
@@ -590,7 +595,7 @@ uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight )
                in_line = in_middle + dy * istride;
        
                // Loop for the entirety of our output row.
-               for ( x = - out_x_range; x < out_x_range; x += 2 )
+               for ( x = - out_x_range; x < out_x_range; x += 1 )
                {
                                // Calculated the derived x
                                dx = scale_width * x;
@@ -599,9 +604,7 @@ uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight )
                if ( abs( dx ) < in_x_range && abs( dy ) < in_y_range  )
                {
                        // We're in the input range for this row.
-                                       in_ptr = in_line + ( dx >> 1 ) * 4;
-                       *out_ptr ++ = *in_ptr ++;
-                       *out_ptr ++ = *in_ptr ++;
+                                       in_ptr = in_line + ( dx >> 1 ) * 4 - 2 * ( x & 1 );
                        *out_ptr ++ = *in_ptr ++;
                        *out_ptr ++ = *in_ptr ++;
                }
@@ -610,8 +613,6 @@ uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight )
                        // We're not in the input range for this row.
                        *out_ptr ++ = 16;
                        *out_ptr ++ = 128;
-                       *out_ptr ++ = 16;
-                       *out_ptr ++ = 128;
                }
                }
 
index b2f9bc863f9412250f7b689804d92c6e7fa74ef0..e79e43ca01325fe812b79a1407fbeaef6c12157f 100644 (file)
@@ -116,7 +116,7 @@ static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer
                // Inherit it from the producer
                fps = mlt_producer_get_fps( producer );
        }
-       else
+       else if ( fps != mlt_properties_get_double( mlt_producer_properties( producer ), "fps" ) )
        {
                // Generate a warning for now - the following attempt to fix may fail
                fprintf( stderr, "Warning: fps mismatch on playlist producer %d\n", this->count );
diff --git a/mlt/src/inigo/Makefile b/mlt/src/inigo/Makefile
new file mode 100644 (file)
index 0000000..78e7cfa
--- /dev/null
@@ -0,0 +1,28 @@
+TARGET = inigo
+
+OBJS = inigo.o \
+          io.o
+
+CFLAGS = -I .. -Wall -g -D_FILE_OFFSET_BITS=64 -pthread -rdynamic
+
+LDFLAGS = -L ../framework -lmlt 
+
+SRCS := $(OBJS:.o=.c)
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+               $(CC) -o $@ $(OBJS) $(LDFLAGS)
+
+depend:        $(SRCS)
+               $(CC) -MM $(CFLAGS) $^ 1>.depend
+
+dist-clean:    clean
+               rm -f .depend
+
+clean: 
+               rm -f $(OBJS) $(TARGET)
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/mlt/src/inigo/configure b/mlt/src/inigo/configure
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/mlt/src/inigo/inigo.c b/mlt/src/inigo/inigo.c
new file mode 100644 (file)
index 0000000..ec6000e
--- /dev/null
@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <framework/mlt.h>
+
+#include "io.h"
+
+mlt_producer create_producer( char *file )
+{
+       mlt_producer result = NULL;
+
+       // 1st Line preferences
+       if ( strstr( file, ".mpg" ) )
+               result = mlt_factory_producer( "mcmpeg", file );
+       else if ( strstr( file, ".mpeg" ) )
+               result = mlt_factory_producer( "mcmpeg", file );
+       else if ( strstr( file, ".dv" ) )
+               result = mlt_factory_producer( "mcdv", file );
+       else if ( strstr( file, ".dif" ) )
+               result = mlt_factory_producer( "mcdv", file );
+       else if ( strstr( file, ".jpg" ) )
+               result = mlt_factory_producer( "pixbuf", file );
+       else if ( strstr( file, ".JPG" ) )
+               result = mlt_factory_producer( "pixbuf", file );
+       else if ( strstr( file, ".jpeg" ) )
+               result = mlt_factory_producer( "pixbuf", file );
+       else if ( strstr( file, ".png" ) )
+               result = mlt_factory_producer( "pixbuf", file );
+
+       // 2nd Line fallbacks
+       if ( result == NULL && strstr( file, ".dv" ) )
+               result = mlt_factory_producer( "libdv", file );
+       else if ( result == NULL && strstr( file, ".dif" ) )
+               result = mlt_factory_producer( "libdv", file );
+
+       // 3rd line fallbacks 
+       if ( result == NULL )
+               result = mlt_factory_producer( "ppm", file );
+
+       return result;
+}
+
+void transport_action( mlt_producer producer, char *value )
+{
+       mlt_properties properties = mlt_producer_properties( producer );
+
+       switch( value[ 0 ] )
+       {
+               case 'q':
+                       mlt_properties_set_int( properties, "done", 1 );
+                       break;
+               case '0':
+                       mlt_producer_set_speed( producer, 1 );
+                       mlt_producer_seek( producer, 0 );
+                       break;
+               case '1':
+                       mlt_producer_set_speed( producer, -5 );
+                       break;
+               case '2':
+                       mlt_producer_set_speed( producer, -2.5 );
+                       break;
+               case '3':
+                       mlt_producer_set_speed( producer, -1 );
+                       break;
+               case '4':
+                       mlt_producer_set_speed( producer, -0.5 );
+                       break;
+               case '5':
+                       mlt_producer_set_speed( producer, 0 );
+                       break;
+               case '6':
+                       mlt_producer_set_speed( producer, 0.5 );
+                       break;
+               case '7':
+                       mlt_producer_set_speed( producer, 1 );
+                       break;
+               case '8':
+                       mlt_producer_set_speed( producer, 2.5 );
+                       break;
+               case '9':
+                       mlt_producer_set_speed( producer, 5 );
+                       break;
+       }
+}
+
+mlt_consumer create_consumer( char *id, mlt_producer producer )
+{
+       char *arg = strchr( id, ':' );
+       if ( arg != NULL )
+               *arg ++ = '\0';
+       mlt_consumer consumer = mlt_factory_consumer( id, arg );
+       if ( consumer != NULL )
+       {
+               mlt_properties properties = mlt_consumer_properties( consumer );
+               mlt_properties_set_data( properties, "transport_callback", transport_action, 0, NULL, NULL );
+               mlt_properties_set_data( properties, "transport_producer", producer, 0, NULL, NULL );
+       }
+       return consumer;
+}
+
+void track_service( mlt_field field, void *service, mlt_destructor destructor )
+{
+       mlt_properties properties = mlt_field_properties( field );
+       int registered = mlt_properties_get_int( properties, "registered" );
+       char *key = mlt_properties_get( properties, "registered" );
+       mlt_properties_set_data( properties, key, service, 0, destructor, NULL );
+       mlt_properties_set_int( properties, "registered", ++ registered );
+}
+
+mlt_filter create_filter( mlt_field field, char *id, int track )
+{
+       char *arg = strchr( id, ':' );
+       if ( arg != NULL )
+               *arg ++ = '\0';
+       mlt_filter filter = mlt_factory_filter( id, arg );
+       if ( filter != NULL )
+       {
+               mlt_field_plant_filter( field, filter, track );
+               track_service( field, filter, ( mlt_destructor )mlt_filter_close );
+       }
+       return filter;
+}
+
+void set_properties( mlt_service service, char *namevalue )
+{
+       mlt_properties properties = mlt_service_properties( service );
+       mlt_properties_parse( properties, namevalue );
+}
+
+void transport( mlt_producer producer )
+{
+       mlt_properties properties = mlt_producer_properties( producer );
+
+       term_init( );
+       fprintf( stderr, "Press 'q' to continue\n" );
+       while( mlt_properties_get_int( properties, "done" ) == 0 )
+       {
+               int value = term_read( );
+               if ( value != -1 )
+                       transport_action( producer, ( char * )&value );
+       }
+}
+
+int main( int argc, char **argv )
+{
+       int i;
+       mlt_service  service = NULL;
+       mlt_consumer consumer = NULL;
+       mlt_multitrack multitrack = NULL;
+       mlt_producer producer = NULL;
+       mlt_playlist playlist = NULL;
+       mlt_field field = NULL;
+
+       // Construct the factory
+       mlt_factory_init( getenv( "MLT_REPOSITORY" ) );
+
+       // Set up containers
+       playlist = mlt_playlist_init( );
+
+       // Construct the field
+       field = mlt_field_init( );
+
+       // We need to track the number of registered filters
+       mlt_properties properties = mlt_field_properties( field );
+       mlt_properties_set_int( properties, "registered", 0 );
+
+       // Get the multitrack from the field
+       multitrack = mlt_field_multitrack( field );
+
+       // Parse the arguments
+       for ( i = 1; i < argc; i ++ )
+       {
+               if ( !strcmp( argv[ i ], "-consumer" ) )
+               {
+                       consumer = create_consumer( argv[ ++ i ], mlt_multitrack_producer( multitrack ) );
+                       if ( consumer != NULL )
+                               service = mlt_consumer_service( consumer );
+               }
+               else if ( !strcmp( argv[ i ], "-filter" ) )
+               {
+                       mlt_filter filter = create_filter( field, argv[ ++ i ], 0 );
+                       if ( filter != NULL )
+                               service = mlt_filter_service( filter );
+               }
+               else if ( !strstr( argv[ i ], "=" ) )
+               {
+                       if ( producer != NULL )
+                               mlt_playlist_append( playlist, producer );
+                       producer = create_producer( argv[ i ] );
+                       if ( producer != NULL )
+                               service = mlt_producer_service( producer );
+               }
+               else
+               {
+                       set_properties( service, argv[ i ] );
+               }
+       }
+
+       // If we have no consumer, default to sdl
+       if ( consumer == NULL )
+               consumer = create_consumer( "sdl", mlt_multitrack_producer( multitrack ) );
+
+       // Connect producer to playlist
+       if ( producer != NULL )
+               mlt_playlist_append( playlist, producer );
+
+       // Connect multitrack to producer
+       mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist ), 0 );
+
+       // Connect consumer to tractor
+       mlt_consumer_connect( consumer, mlt_field_service( field ) );
+
+       // Transport functionality
+       transport( mlt_multitrack_producer( multitrack ) );
+
+       // Close the services
+       mlt_consumer_close( consumer );
+       mlt_field_close( field );
+       mlt_producer_close( producer );
+
+       // Close the factory
+       mlt_factory_close( );
+
+       return 0;
+}
diff --git a/mlt/src/inigo/io.c b/mlt/src/inigo/io.c
new file mode 100644 (file)
index 0000000..431003d
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * io.c -- dv1394d client demo input/output
+ * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* System header files */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <termios.h>
+#include <unistd.h>
+
+/* Application header files */
+#include "io.h"
+
+char *chomp( char *input )
+{
+       if ( input != NULL )
+       {
+               int length = strlen( input );
+               if ( length && input[ length - 1 ] == '\n' )
+                       input[ length - 1 ] = '\0';
+               if ( length > 1 && input[ length - 2 ] == '\r' )
+                       input[ length - 2 ] = '\0';
+       }
+       return input;
+}
+
+char *trim( char *input )
+{
+       if ( input != NULL )
+       {
+               int length = strlen( input );
+               int first = 0;
+               while( first < length && isspace( input[ first ] ) )
+                       first ++;
+               memmove( input, input + first, length - first + 1 );
+               length = length - first;
+               while ( length > 0 && isspace( input[ length - 1 ] ) )
+                       input[ -- length ] = '\0';
+       }
+       return input;
+}
+
+char *strip_quotes( char *input )
+{
+       if ( input != NULL )
+       {
+               char *ptr = strrchr( input, '\"' );
+               if ( ptr != NULL )
+                       *ptr = '\0';
+               if ( input[ 0 ] == '\"' )
+                       strcpy( input, input + 1 );
+       }
+       return input;
+}
+
+char *get_string( char *output, int maxlength, char *use )
+{
+       char *value = NULL;
+       strcpy( output, use );
+       if ( trim( chomp( fgets( output, maxlength, stdin ) ) ) != NULL )
+       {
+               if ( !strcmp( output, "" ) )
+                       strcpy( output, use );
+               value = output;
+       }
+       return value;
+}
+
+int *get_int( int *output, int use )
+{
+       int *value = NULL;
+       char temp[ 132 ];
+       *output = use;
+       if ( trim( chomp( fgets( temp, 132, stdin ) ) ) != NULL )
+       {
+               if ( strcmp( temp, "" ) )
+                       *output = atoi( temp );
+               value = output;
+       }
+       return value;
+}
+
+/** This stores the previous settings
+*/
+
+static struct termios oldtty;
+static int mode = 0;
+
+/** This is called automatically on application exit to restore the 
+       previous tty settings.
+*/
+
+void term_exit(void)
+{
+       if ( mode == 1 )
+       {
+               tcsetattr( 0, TCSANOW, &oldtty );
+               mode = 0;
+       }
+}
+
+/** Init terminal so that we can grab keys without blocking.
+*/
+
+void term_init( )
+{
+       struct termios tty;
+
+       tcgetattr( 0, &tty );
+       oldtty = tty;
+
+       tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+       tty.c_oflag |= OPOST;
+       tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+       tty.c_cflag &= ~(CSIZE|PARENB);
+       tty.c_cflag |= CS8;
+       tty.c_cc[ VMIN ] = 1;
+       tty.c_cc[ VTIME ] = 0;
+    
+       tcsetattr( 0, TCSANOW, &tty );
+
+       mode = 1;
+
+       atexit( term_exit );
+}
+
+/** Check for a keypress without blocking infinitely.
+       Returns: ASCII value of keypress or -1 if no keypress detected.
+*/
+
+int term_read( )
+{
+    int n = 1;
+    unsigned char ch;
+    struct timeval tv;
+    fd_set rfds;
+
+    FD_ZERO( &rfds );
+    FD_SET( 0, &rfds );
+    tv.tv_sec = 0;
+    tv.tv_usec = 250;
+    n = select( 1, &rfds, NULL, NULL, &tv );
+    if (n > 0) 
+       {
+        n = read( 0, &ch, 1 );
+               tcflush( 0, TCIFLUSH );
+        if (n == 1)
+            return ch;
+        return n;
+    }
+    return -1;
+}
+
+char get_keypress( )
+{
+       char value = '\0';
+       int pressed = 0;
+
+       fflush( stdout );
+
+       term_init( );
+       while ( ( pressed = term_read( ) ) == -1 ) ;
+       term_exit( );
+
+       value = (char)pressed;
+
+       return value;
+}
+
+void wait_for_any_key( char *message )
+{
+       if ( message == NULL )
+               printf( "Press any key to continue: " );
+       else
+               printf( "%s", message );
+
+       get_keypress( );
+
+       printf( "\n\n" );
+}
+
+void beep( )
+{
+       printf( "%c", 7 );
+       fflush( stdout );
+}
diff --git a/mlt/src/inigo/io.h b/mlt/src/inigo/io.h
new file mode 100644 (file)
index 0000000..f97e69e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * io.h -- dv1394d client demo input/output
+ * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEMO_IO_H_
+#define _DEMO_IO_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern char *chomp( char * );
+extern char *trim( char * );
+extern char *strip_quotes( char * );
+extern char *get_string( char *, int, char * );
+extern int *get_int( int *, int );
+extern void term_init( );
+extern int term_read( );
+extern void term_exit( );
+extern char get_keypress( );
+extern void wait_for_any_key( char * );
+extern void beep( );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index dab7fdfc04d0141f91dbe017ecf2f60c304a820b..537ce505aedfb64e9604b43e5017f04152cbe227 100644 (file)
@@ -58,13 +58,16 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 /** Constructor for the filter.
 */
 
-mlt_filter filter_resize_init( void *arg )
+mlt_filter filter_resize_init( char *arg )
 {
        mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
        if ( mlt_filter_init( this, this ) == 0 )
        {
                this->process = filter_process;
-               mlt_properties_set( mlt_filter_properties( this ), "scale", "off" );
+               if ( arg != NULL )
+                       mlt_properties_set( mlt_filter_properties( this ), "scale", arg );
+               else
+                       mlt_properties_set( mlt_filter_properties( this ), "scale", "off" );
        }
        return this;
 }
index 0d175292d1d4a0207fabb875917e382eed47fbdb..17c9c192a5cce9a1f4670cfb7734a07c8d798700 100644 (file)
@@ -23,6 +23,6 @@
 
 #include <framework/mlt_filter.h>
 
-extern mlt_filter filter_resize_init( void *arg );
+extern mlt_filter filter_resize_init( char *arg );
 
 #endif
index e1357c8fb34374a0c18740c172de0800908abe91..ca1947172c319fbb86e4ab144ecf32c2bdff5029 100644 (file)
@@ -36,13 +36,9 @@ mlt_producer producer_ppm_init( void *command )
                producer->get_frame = producer_get_frame;
                producer->close = producer_close;
 
-               if ( command == NULL )
-                       this->command = strdup( "image2raw -n -a -r 3 -ppm /usr/share/pixmaps/*.png" );
-               else
+               if ( command != NULL )
                        this->command = strdup( command );
 
-               this->pipe = popen( this->command, "r" );
-
                return producer;
        }
        free( this );
@@ -77,6 +73,84 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma
        return 0;
 }
 
+static void producer_ppm_position( producer_ppm this, uint64_t requested )
+{
+       if ( requested != this->expected )
+       {
+               if ( this->video != NULL )
+                       pclose( this->video );
+               this->video = NULL;
+               if ( this->audio != NULL )
+                       pclose( this->audio );
+               this->audio = NULL;
+       }
+
+       // This is the next frame we expect
+       this->expected = mlt_producer_frame( &this->parent ) + 1;
+}
+
+FILE *producer_ppm_run_video( producer_ppm this )
+{
+       if ( this->video == NULL )
+       {
+               if ( this->command == NULL )
+               {
+                       this->video = popen( "image2raw -n -a -r 3 -ppm /usr/share/pixmaps/*.png", "r" );
+               }
+               else
+               {
+                       char command[ 1024 ];
+                       float fps = mlt_producer_get_fps( &this->parent );
+                       float position = mlt_producer_position( &this->parent );
+                       sprintf( command, "ffmpeg -i \"%s\" -ss %f -f imagepipe -r %f -img ppm -", this->command, position, fps );
+                       this->video = popen( command, "r" );
+               }
+       }
+       return this->video;
+}
+
+FILE *producer_ppm_run_audio( producer_ppm this )
+{
+       if ( this->audio == NULL )
+       {
+               if ( this->command != NULL )
+               {
+                       char command[ 1024 ];
+                       float position = mlt_producer_position( &this->parent );
+                       sprintf( command, "ffmpeg -i \"%s\" -ss %f -f s16le -ar 48000 -ac 2 -", this->command, position );
+                       this->audio = popen( command, "r" );
+               }
+       }
+       return this->audio;
+}
+
+
+static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+{
+       // Get the frames properties
+       mlt_properties properties = mlt_frame_properties( this );
+
+       FILE *pipe = mlt_properties_get_data( properties, "audio.pipe", NULL );
+
+       *frequency = 48000;
+       *channels = 2;
+       *samples = 1920;
+
+       // Size
+       int size = *samples * *channels * 2;
+
+       // Allocate an image
+       *buffer = malloc( size );
+               
+       // Read it
+       fread( *buffer, size, 1, pipe );
+
+       // Pass the data on the frame properties
+       mlt_properties_set_data( properties, "audio", *buffer, size, free, NULL );
+
+       return 0;
+}
+
 static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
 {
        producer_ppm this = producer->child;
@@ -86,17 +160,26 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
        // Construct a test frame
        *frame = mlt_frame_init( );
 
-       // Scan the header
-       if ( fscanf( this->pipe, "P6\n%d %d\n255\n", &width, &height ) == 2 )
-       {
-               // Get the frames properties
-               mlt_properties properties = mlt_frame_properties( *frame );
+       // Are we at the position expected?
+       producer_ppm_position( this, mlt_producer_frame( producer ) );
+
+       // Open the pipe
+       FILE *video = producer_ppm_run_video( this );
+
+       // Open the audio pipe
+       FILE *audio = producer_ppm_run_audio( this );
+
+       // Get the frames properties
+       mlt_properties properties = mlt_frame_properties( *frame );
 
+       // Read the video
+       if ( video != NULL && fscanf( video, "P6\n%d %d\n255\n", &width, &height ) == 2 )
+       {
                // Allocate an image
                uint8_t *image = malloc( width * height * 3 );
                
                // Read it
-               fread( image, width * height * 3, 1, this->pipe );
+               fread( image, width * height * 3, 1, video );
 
                // Pass the data on the frame properties
                mlt_properties_set_data( properties, "image", image, width * height * 3, free, NULL );
@@ -107,6 +190,16 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
                mlt_frame_push_get_image( *frame, producer_get_image );
        }
 
+       // Read the audio
+       if ( audio != NULL )
+       {
+               // Set the audio pipe
+               mlt_properties_set_data( properties, "audio.pipe", audio, 0, NULL, NULL );
+
+               // Hmm - register audio callback
+               ( *frame )->get_audio = producer_get_audio;
+       }
+
        // Update timecode on the frame we're creating
        mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
 
@@ -119,7 +212,10 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 static void producer_close( mlt_producer parent )
 {
        producer_ppm this = parent->child;
-       pclose( this->pipe );
+       if ( this->video )
+               pclose( this->video );
+       if ( this->audio )
+               pclose( this->audio );
        free( this->command );
        parent->close = NULL;
        mlt_producer_close( parent );
index 4787b8f6e6d8d4f5fa396f6b2849f850be9e43b1..69a253a245da79d4c00c97e8a573cba79554678f 100644 (file)
@@ -30,7 +30,9 @@ struct producer_ppm_s
 {
        struct mlt_producer_s parent;
        char *command;
-       FILE *pipe;
+       FILE *video;
+       FILE *audio;
+       uint64_t expected;
 };
 
 extern mlt_producer producer_ppm_init( void *command );
index a4d6b30aac024097abec05d35578420d1337d227..cf02c737e7c00317e71e2a0fca31e20f0d6fbcc4 100644 (file)
@@ -234,7 +234,7 @@ static void *consumer_thread( void *arg )
                                request.freq = frequency;
                                request.format = AUDIO_S16;
                                request.channels = channels;
-                               request.samples = 1024;
+                               request.samples = 512;
                                request.callback = sdl_fill_audio;
                                request.userdata = (void *)this;
                                if ( SDL_OpenAudio( &request, NULL ) < 0 )
index d6dc995ccfe334ff169a6ce2b6c37ae37ba3153d..bcd4dae68008873c0658b41483ce6a35d20bf05b 100644 (file)
@@ -156,6 +156,8 @@ int main( int argc, char **argv )
 
        // Construct the field
        field = mlt_field_init( );
+
+       // We need to track the number of registered filters
        mlt_properties properties = mlt_field_properties( field );
        mlt_properties_set_int( properties, "registered", 0 );
 
diff --git a/setenv b/setenv
new file mode 100644 (file)
index 0000000..01363eb
--- /dev/null
+++ b/setenv
@@ -0,0 +1,10 @@
+export MLT_REPOSITORY=`pwd`/src/modules
+
+export LD_LIBRARY_PATH=`pwd`/src/framework:\
+`pwd`/src/modules/bluefish:\
+`pwd`/../bluefish/lib:\
+`pwd`/../mpeg_sdk_demo/bin:\
+`pwd`/../dv_sdk
+
+export PATH=$PATH:`pwd`/src/inigo:`pwd`/src/miracle
+
index f0b9351110cc89e27b2d0300c3de8f3c6a297eff..6b1558fc6a3c03e60e7e518ac7b681ffd091fb9f 100644 (file)
@@ -432,6 +432,14 @@ int mlt_frame_composite_yuv( mlt_frame this, mlt_frame that, int x, int y, float
        return ret;
 }
 
+void *memfill( void *dst, void *src, int l, int elements )
+{
+       int i = 0;
+       for ( i = 0; i < elements; i ++ )
+               dst = memcpy( dst, src, l ) + l;
+       return dst;
+}
+
 void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input, int iwidth, int iheight )
 {
        // Calculate strides
@@ -439,22 +447,23 @@ void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input
        int ostride = owidth * 2;
 
        // Coordinates (0,0 is middle of output)
-       int y, x;
+       int y;
 
        // Calculate ranges
        int out_x_range = owidth / 2;
        int out_y_range = oheight / 2;
-       int in_x_range = iwidth / 2;
-       int in_y_range = iheight / 2;
+       int in_x_range = iwidth / 2 < out_x_range ? iwidth / 2 : out_x_range;
+       int in_y_range = iheight / 2 < out_y_range ? iheight / 2 : out_y_range;
 
        // Output pointers
        uint8_t *out_line = output;
        uint8_t *out_ptr;
 
        // Calculate a middle and possibly invalid pointer in the input
-       uint8_t *in_middle = input + istride * in_y_range + in_x_range * 2;
-       int in_line = - out_y_range * istride - out_x_range * 2;
-       int in_ptr;
+       uint8_t *in_middle = input + istride * ( iheight / 2 ) + ( iwidth / 2 ) * 2;
+       int in_line = - in_y_range * istride - in_x_range * 2;
+
+       uint8_t black[ 2 ] = { 16, 128 };
 
        // Loop for the entirety of our output height.
        for ( y = - out_y_range; y < out_y_range ; y ++ )
@@ -462,33 +471,29 @@ void mlt_resize_yuv422( uint8_t *output, int owidth, int oheight, uint8_t *input
                // Start at the beginning of the line
                out_ptr = out_line;
 
-               // Point the start of the current input line (NB: can be out of range)
-               in_ptr = in_line;
-
-               // Loop for the entirety of our output row.
-               for ( x = - out_x_range; x < out_x_range; x ++ )
-               {
-               // Check if x and y are in the valid input range.
-               if ( abs( x ) < in_x_range && abs( y ) < in_y_range  )
-               {
-                       // We're in the input range for this row.
-                       *out_ptr ++ = *( in_middle + in_ptr ++ );
-                       *out_ptr ++ = *( in_middle + in_ptr ++ );
-               }
-               else
-               {
-                       // We're not in the input range for this row.
-                       *out_ptr ++ = 16;
-                       *out_ptr ++ = 128;
-                       in_ptr += 2;
-               }
-               }
+               if ( abs( y ) < iheight / 2 )
+               {
+                       // Fill the outer part with black
+                       out_ptr = memfill( out_ptr, black, 2, out_x_range - in_x_range );
+
+                       // We're in the input range for this row.
+                       memcpy( out_ptr, in_middle + in_line, 4 * in_x_range );
+                       out_ptr += 4 * in_x_range;
+
+                       // Fill the outer part with black
+                       out_ptr = memfill( out_ptr, black, 2, out_x_range - in_x_range );
+
+                       // Move to next input line
+                       in_line += istride;
+               }
+               else
+               {
+                       // Fill whole line with black
+                       out_ptr = memfill( out_ptr, black, 2, owidth );
+               }
 
                // Move to next output line
                out_line += ostride;
-
-               // Move to next input line
-               in_line += istride;
        }
 }
 
@@ -590,7 +595,7 @@ uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight )
                in_line = in_middle + dy * istride;
        
                // Loop for the entirety of our output row.
-               for ( x = - out_x_range; x < out_x_range; x += 2 )
+               for ( x = - out_x_range; x < out_x_range; x += 1 )
                {
                                // Calculated the derived x
                                dx = scale_width * x;
@@ -599,9 +604,7 @@ uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight )
                if ( abs( dx ) < in_x_range && abs( dy ) < in_y_range  )
                {
                        // We're in the input range for this row.
-                                       in_ptr = in_line + ( dx >> 1 ) * 4;
-                       *out_ptr ++ = *in_ptr ++;
-                       *out_ptr ++ = *in_ptr ++;
+                                       in_ptr = in_line + ( dx >> 1 ) * 4 - 2 * ( x & 1 );
                        *out_ptr ++ = *in_ptr ++;
                        *out_ptr ++ = *in_ptr ++;
                }
@@ -610,8 +613,6 @@ uint8_t *mlt_frame_rescale_yuv422( mlt_frame this, int owidth, int oheight )
                        // We're not in the input range for this row.
                        *out_ptr ++ = 16;
                        *out_ptr ++ = 128;
-                       *out_ptr ++ = 16;
-                       *out_ptr ++ = 128;
                }
                }
 
index b2f9bc863f9412250f7b689804d92c6e7fa74ef0..e79e43ca01325fe812b79a1407fbeaef6c12157f 100644 (file)
@@ -116,7 +116,7 @@ static int mlt_playlist_virtual_append( mlt_playlist this, mlt_producer producer
                // Inherit it from the producer
                fps = mlt_producer_get_fps( producer );
        }
-       else
+       else if ( fps != mlt_properties_get_double( mlt_producer_properties( producer ), "fps" ) )
        {
                // Generate a warning for now - the following attempt to fix may fail
                fprintf( stderr, "Warning: fps mismatch on playlist producer %d\n", this->count );
diff --git a/src/inigo/Makefile b/src/inigo/Makefile
new file mode 100644 (file)
index 0000000..78e7cfa
--- /dev/null
@@ -0,0 +1,28 @@
+TARGET = inigo
+
+OBJS = inigo.o \
+          io.o
+
+CFLAGS = -I .. -Wall -g -D_FILE_OFFSET_BITS=64 -pthread -rdynamic
+
+LDFLAGS = -L ../framework -lmlt 
+
+SRCS := $(OBJS:.o=.c)
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+               $(CC) -o $@ $(OBJS) $(LDFLAGS)
+
+depend:        $(SRCS)
+               $(CC) -MM $(CFLAGS) $^ 1>.depend
+
+dist-clean:    clean
+               rm -f .depend
+
+clean: 
+               rm -f $(OBJS) $(TARGET)
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/src/inigo/configure b/src/inigo/configure
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/src/inigo/inigo.c b/src/inigo/inigo.c
new file mode 100644 (file)
index 0000000..ec6000e
--- /dev/null
@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <framework/mlt.h>
+
+#include "io.h"
+
+mlt_producer create_producer( char *file )
+{
+       mlt_producer result = NULL;
+
+       // 1st Line preferences
+       if ( strstr( file, ".mpg" ) )
+               result = mlt_factory_producer( "mcmpeg", file );
+       else if ( strstr( file, ".mpeg" ) )
+               result = mlt_factory_producer( "mcmpeg", file );
+       else if ( strstr( file, ".dv" ) )
+               result = mlt_factory_producer( "mcdv", file );
+       else if ( strstr( file, ".dif" ) )
+               result = mlt_factory_producer( "mcdv", file );
+       else if ( strstr( file, ".jpg" ) )
+               result = mlt_factory_producer( "pixbuf", file );
+       else if ( strstr( file, ".JPG" ) )
+               result = mlt_factory_producer( "pixbuf", file );
+       else if ( strstr( file, ".jpeg" ) )
+               result = mlt_factory_producer( "pixbuf", file );
+       else if ( strstr( file, ".png" ) )
+               result = mlt_factory_producer( "pixbuf", file );
+
+       // 2nd Line fallbacks
+       if ( result == NULL && strstr( file, ".dv" ) )
+               result = mlt_factory_producer( "libdv", file );
+       else if ( result == NULL && strstr( file, ".dif" ) )
+               result = mlt_factory_producer( "libdv", file );
+
+       // 3rd line fallbacks 
+       if ( result == NULL )
+               result = mlt_factory_producer( "ppm", file );
+
+       return result;
+}
+
+void transport_action( mlt_producer producer, char *value )
+{
+       mlt_properties properties = mlt_producer_properties( producer );
+
+       switch( value[ 0 ] )
+       {
+               case 'q':
+                       mlt_properties_set_int( properties, "done", 1 );
+                       break;
+               case '0':
+                       mlt_producer_set_speed( producer, 1 );
+                       mlt_producer_seek( producer, 0 );
+                       break;
+               case '1':
+                       mlt_producer_set_speed( producer, -5 );
+                       break;
+               case '2':
+                       mlt_producer_set_speed( producer, -2.5 );
+                       break;
+               case '3':
+                       mlt_producer_set_speed( producer, -1 );
+                       break;
+               case '4':
+                       mlt_producer_set_speed( producer, -0.5 );
+                       break;
+               case '5':
+                       mlt_producer_set_speed( producer, 0 );
+                       break;
+               case '6':
+                       mlt_producer_set_speed( producer, 0.5 );
+                       break;
+               case '7':
+                       mlt_producer_set_speed( producer, 1 );
+                       break;
+               case '8':
+                       mlt_producer_set_speed( producer, 2.5 );
+                       break;
+               case '9':
+                       mlt_producer_set_speed( producer, 5 );
+                       break;
+       }
+}
+
+mlt_consumer create_consumer( char *id, mlt_producer producer )
+{
+       char *arg = strchr( id, ':' );
+       if ( arg != NULL )
+               *arg ++ = '\0';
+       mlt_consumer consumer = mlt_factory_consumer( id, arg );
+       if ( consumer != NULL )
+       {
+               mlt_properties properties = mlt_consumer_properties( consumer );
+               mlt_properties_set_data( properties, "transport_callback", transport_action, 0, NULL, NULL );
+               mlt_properties_set_data( properties, "transport_producer", producer, 0, NULL, NULL );
+       }
+       return consumer;
+}
+
+void track_service( mlt_field field, void *service, mlt_destructor destructor )
+{
+       mlt_properties properties = mlt_field_properties( field );
+       int registered = mlt_properties_get_int( properties, "registered" );
+       char *key = mlt_properties_get( properties, "registered" );
+       mlt_properties_set_data( properties, key, service, 0, destructor, NULL );
+       mlt_properties_set_int( properties, "registered", ++ registered );
+}
+
+mlt_filter create_filter( mlt_field field, char *id, int track )
+{
+       char *arg = strchr( id, ':' );
+       if ( arg != NULL )
+               *arg ++ = '\0';
+       mlt_filter filter = mlt_factory_filter( id, arg );
+       if ( filter != NULL )
+       {
+               mlt_field_plant_filter( field, filter, track );
+               track_service( field, filter, ( mlt_destructor )mlt_filter_close );
+       }
+       return filter;
+}
+
+void set_properties( mlt_service service, char *namevalue )
+{
+       mlt_properties properties = mlt_service_properties( service );
+       mlt_properties_parse( properties, namevalue );
+}
+
+void transport( mlt_producer producer )
+{
+       mlt_properties properties = mlt_producer_properties( producer );
+
+       term_init( );
+       fprintf( stderr, "Press 'q' to continue\n" );
+       while( mlt_properties_get_int( properties, "done" ) == 0 )
+       {
+               int value = term_read( );
+               if ( value != -1 )
+                       transport_action( producer, ( char * )&value );
+       }
+}
+
+int main( int argc, char **argv )
+{
+       int i;
+       mlt_service  service = NULL;
+       mlt_consumer consumer = NULL;
+       mlt_multitrack multitrack = NULL;
+       mlt_producer producer = NULL;
+       mlt_playlist playlist = NULL;
+       mlt_field field = NULL;
+
+       // Construct the factory
+       mlt_factory_init( getenv( "MLT_REPOSITORY" ) );
+
+       // Set up containers
+       playlist = mlt_playlist_init( );
+
+       // Construct the field
+       field = mlt_field_init( );
+
+       // We need to track the number of registered filters
+       mlt_properties properties = mlt_field_properties( field );
+       mlt_properties_set_int( properties, "registered", 0 );
+
+       // Get the multitrack from the field
+       multitrack = mlt_field_multitrack( field );
+
+       // Parse the arguments
+       for ( i = 1; i < argc; i ++ )
+       {
+               if ( !strcmp( argv[ i ], "-consumer" ) )
+               {
+                       consumer = create_consumer( argv[ ++ i ], mlt_multitrack_producer( multitrack ) );
+                       if ( consumer != NULL )
+                               service = mlt_consumer_service( consumer );
+               }
+               else if ( !strcmp( argv[ i ], "-filter" ) )
+               {
+                       mlt_filter filter = create_filter( field, argv[ ++ i ], 0 );
+                       if ( filter != NULL )
+                               service = mlt_filter_service( filter );
+               }
+               else if ( !strstr( argv[ i ], "=" ) )
+               {
+                       if ( producer != NULL )
+                               mlt_playlist_append( playlist, producer );
+                       producer = create_producer( argv[ i ] );
+                       if ( producer != NULL )
+                               service = mlt_producer_service( producer );
+               }
+               else
+               {
+                       set_properties( service, argv[ i ] );
+               }
+       }
+
+       // If we have no consumer, default to sdl
+       if ( consumer == NULL )
+               consumer = create_consumer( "sdl", mlt_multitrack_producer( multitrack ) );
+
+       // Connect producer to playlist
+       if ( producer != NULL )
+               mlt_playlist_append( playlist, producer );
+
+       // Connect multitrack to producer
+       mlt_multitrack_connect( multitrack, mlt_playlist_producer( playlist ), 0 );
+
+       // Connect consumer to tractor
+       mlt_consumer_connect( consumer, mlt_field_service( field ) );
+
+       // Transport functionality
+       transport( mlt_multitrack_producer( multitrack ) );
+
+       // Close the services
+       mlt_consumer_close( consumer );
+       mlt_field_close( field );
+       mlt_producer_close( producer );
+
+       // Close the factory
+       mlt_factory_close( );
+
+       return 0;
+}
diff --git a/src/inigo/io.c b/src/inigo/io.c
new file mode 100644 (file)
index 0000000..431003d
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * io.c -- dv1394d client demo input/output
+ * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* System header files */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <termios.h>
+#include <unistd.h>
+
+/* Application header files */
+#include "io.h"
+
+char *chomp( char *input )
+{
+       if ( input != NULL )
+       {
+               int length = strlen( input );
+               if ( length && input[ length - 1 ] == '\n' )
+                       input[ length - 1 ] = '\0';
+               if ( length > 1 && input[ length - 2 ] == '\r' )
+                       input[ length - 2 ] = '\0';
+       }
+       return input;
+}
+
+char *trim( char *input )
+{
+       if ( input != NULL )
+       {
+               int length = strlen( input );
+               int first = 0;
+               while( first < length && isspace( input[ first ] ) )
+                       first ++;
+               memmove( input, input + first, length - first + 1 );
+               length = length - first;
+               while ( length > 0 && isspace( input[ length - 1 ] ) )
+                       input[ -- length ] = '\0';
+       }
+       return input;
+}
+
+char *strip_quotes( char *input )
+{
+       if ( input != NULL )
+       {
+               char *ptr = strrchr( input, '\"' );
+               if ( ptr != NULL )
+                       *ptr = '\0';
+               if ( input[ 0 ] == '\"' )
+                       strcpy( input, input + 1 );
+       }
+       return input;
+}
+
+char *get_string( char *output, int maxlength, char *use )
+{
+       char *value = NULL;
+       strcpy( output, use );
+       if ( trim( chomp( fgets( output, maxlength, stdin ) ) ) != NULL )
+       {
+               if ( !strcmp( output, "" ) )
+                       strcpy( output, use );
+               value = output;
+       }
+       return value;
+}
+
+int *get_int( int *output, int use )
+{
+       int *value = NULL;
+       char temp[ 132 ];
+       *output = use;
+       if ( trim( chomp( fgets( temp, 132, stdin ) ) ) != NULL )
+       {
+               if ( strcmp( temp, "" ) )
+                       *output = atoi( temp );
+               value = output;
+       }
+       return value;
+}
+
+/** This stores the previous settings
+*/
+
+static struct termios oldtty;
+static int mode = 0;
+
+/** This is called automatically on application exit to restore the 
+       previous tty settings.
+*/
+
+void term_exit(void)
+{
+       if ( mode == 1 )
+       {
+               tcsetattr( 0, TCSANOW, &oldtty );
+               mode = 0;
+       }
+}
+
+/** Init terminal so that we can grab keys without blocking.
+*/
+
+void term_init( )
+{
+       struct termios tty;
+
+       tcgetattr( 0, &tty );
+       oldtty = tty;
+
+       tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+       tty.c_oflag |= OPOST;
+       tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+       tty.c_cflag &= ~(CSIZE|PARENB);
+       tty.c_cflag |= CS8;
+       tty.c_cc[ VMIN ] = 1;
+       tty.c_cc[ VTIME ] = 0;
+    
+       tcsetattr( 0, TCSANOW, &tty );
+
+       mode = 1;
+
+       atexit( term_exit );
+}
+
+/** Check for a keypress without blocking infinitely.
+       Returns: ASCII value of keypress or -1 if no keypress detected.
+*/
+
+int term_read( )
+{
+    int n = 1;
+    unsigned char ch;
+    struct timeval tv;
+    fd_set rfds;
+
+    FD_ZERO( &rfds );
+    FD_SET( 0, &rfds );
+    tv.tv_sec = 0;
+    tv.tv_usec = 250;
+    n = select( 1, &rfds, NULL, NULL, &tv );
+    if (n > 0) 
+       {
+        n = read( 0, &ch, 1 );
+               tcflush( 0, TCIFLUSH );
+        if (n == 1)
+            return ch;
+        return n;
+    }
+    return -1;
+}
+
+char get_keypress( )
+{
+       char value = '\0';
+       int pressed = 0;
+
+       fflush( stdout );
+
+       term_init( );
+       while ( ( pressed = term_read( ) ) == -1 ) ;
+       term_exit( );
+
+       value = (char)pressed;
+
+       return value;
+}
+
+void wait_for_any_key( char *message )
+{
+       if ( message == NULL )
+               printf( "Press any key to continue: " );
+       else
+               printf( "%s", message );
+
+       get_keypress( );
+
+       printf( "\n\n" );
+}
+
+void beep( )
+{
+       printf( "%c", 7 );
+       fflush( stdout );
+}
diff --git a/src/inigo/io.h b/src/inigo/io.h
new file mode 100644 (file)
index 0000000..f97e69e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * io.h -- dv1394d client demo input/output
+ * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEMO_IO_H_
+#define _DEMO_IO_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern char *chomp( char * );
+extern char *trim( char * );
+extern char *strip_quotes( char * );
+extern char *get_string( char *, int, char * );
+extern int *get_int( int *, int );
+extern void term_init( );
+extern int term_read( );
+extern void term_exit( );
+extern char get_keypress( );
+extern void wait_for_any_key( char * );
+extern void beep( );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index dab7fdfc04d0141f91dbe017ecf2f60c304a820b..537ce505aedfb64e9604b43e5017f04152cbe227 100644 (file)
@@ -58,13 +58,16 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 /** Constructor for the filter.
 */
 
-mlt_filter filter_resize_init( void *arg )
+mlt_filter filter_resize_init( char *arg )
 {
        mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
        if ( mlt_filter_init( this, this ) == 0 )
        {
                this->process = filter_process;
-               mlt_properties_set( mlt_filter_properties( this ), "scale", "off" );
+               if ( arg != NULL )
+                       mlt_properties_set( mlt_filter_properties( this ), "scale", arg );
+               else
+                       mlt_properties_set( mlt_filter_properties( this ), "scale", "off" );
        }
        return this;
 }
index 0d175292d1d4a0207fabb875917e382eed47fbdb..17c9c192a5cce9a1f4670cfb7734a07c8d798700 100644 (file)
@@ -23,6 +23,6 @@
 
 #include <framework/mlt_filter.h>
 
-extern mlt_filter filter_resize_init( void *arg );
+extern mlt_filter filter_resize_init( char *arg );
 
 #endif
index e1357c8fb34374a0c18740c172de0800908abe91..ca1947172c319fbb86e4ab144ecf32c2bdff5029 100644 (file)
@@ -36,13 +36,9 @@ mlt_producer producer_ppm_init( void *command )
                producer->get_frame = producer_get_frame;
                producer->close = producer_close;
 
-               if ( command == NULL )
-                       this->command = strdup( "image2raw -n -a -r 3 -ppm /usr/share/pixmaps/*.png" );
-               else
+               if ( command != NULL )
                        this->command = strdup( command );
 
-               this->pipe = popen( this->command, "r" );
-
                return producer;
        }
        free( this );
@@ -77,6 +73,84 @@ static int producer_get_image( mlt_frame this, uint8_t **buffer, mlt_image_forma
        return 0;
 }
 
+static void producer_ppm_position( producer_ppm this, uint64_t requested )
+{
+       if ( requested != this->expected )
+       {
+               if ( this->video != NULL )
+                       pclose( this->video );
+               this->video = NULL;
+               if ( this->audio != NULL )
+                       pclose( this->audio );
+               this->audio = NULL;
+       }
+
+       // This is the next frame we expect
+       this->expected = mlt_producer_frame( &this->parent ) + 1;
+}
+
+FILE *producer_ppm_run_video( producer_ppm this )
+{
+       if ( this->video == NULL )
+       {
+               if ( this->command == NULL )
+               {
+                       this->video = popen( "image2raw -n -a -r 3 -ppm /usr/share/pixmaps/*.png", "r" );
+               }
+               else
+               {
+                       char command[ 1024 ];
+                       float fps = mlt_producer_get_fps( &this->parent );
+                       float position = mlt_producer_position( &this->parent );
+                       sprintf( command, "ffmpeg -i \"%s\" -ss %f -f imagepipe -r %f -img ppm -", this->command, position, fps );
+                       this->video = popen( command, "r" );
+               }
+       }
+       return this->video;
+}
+
+FILE *producer_ppm_run_audio( producer_ppm this )
+{
+       if ( this->audio == NULL )
+       {
+               if ( this->command != NULL )
+               {
+                       char command[ 1024 ];
+                       float position = mlt_producer_position( &this->parent );
+                       sprintf( command, "ffmpeg -i \"%s\" -ss %f -f s16le -ar 48000 -ac 2 -", this->command, position );
+                       this->audio = popen( command, "r" );
+               }
+       }
+       return this->audio;
+}
+
+
+static int producer_get_audio( mlt_frame this, int16_t **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
+{
+       // Get the frames properties
+       mlt_properties properties = mlt_frame_properties( this );
+
+       FILE *pipe = mlt_properties_get_data( properties, "audio.pipe", NULL );
+
+       *frequency = 48000;
+       *channels = 2;
+       *samples = 1920;
+
+       // Size
+       int size = *samples * *channels * 2;
+
+       // Allocate an image
+       *buffer = malloc( size );
+               
+       // Read it
+       fread( *buffer, size, 1, pipe );
+
+       // Pass the data on the frame properties
+       mlt_properties_set_data( properties, "audio", *buffer, size, free, NULL );
+
+       return 0;
+}
+
 static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int index )
 {
        producer_ppm this = producer->child;
@@ -86,17 +160,26 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
        // Construct a test frame
        *frame = mlt_frame_init( );
 
-       // Scan the header
-       if ( fscanf( this->pipe, "P6\n%d %d\n255\n", &width, &height ) == 2 )
-       {
-               // Get the frames properties
-               mlt_properties properties = mlt_frame_properties( *frame );
+       // Are we at the position expected?
+       producer_ppm_position( this, mlt_producer_frame( producer ) );
+
+       // Open the pipe
+       FILE *video = producer_ppm_run_video( this );
+
+       // Open the audio pipe
+       FILE *audio = producer_ppm_run_audio( this );
+
+       // Get the frames properties
+       mlt_properties properties = mlt_frame_properties( *frame );
 
+       // Read the video
+       if ( video != NULL && fscanf( video, "P6\n%d %d\n255\n", &width, &height ) == 2 )
+       {
                // Allocate an image
                uint8_t *image = malloc( width * height * 3 );
                
                // Read it
-               fread( image, width * height * 3, 1, this->pipe );
+               fread( image, width * height * 3, 1, video );
 
                // Pass the data on the frame properties
                mlt_properties_set_data( properties, "image", image, width * height * 3, free, NULL );
@@ -107,6 +190,16 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
                mlt_frame_push_get_image( *frame, producer_get_image );
        }
 
+       // Read the audio
+       if ( audio != NULL )
+       {
+               // Set the audio pipe
+               mlt_properties_set_data( properties, "audio.pipe", audio, 0, NULL, NULL );
+
+               // Hmm - register audio callback
+               ( *frame )->get_audio = producer_get_audio;
+       }
+
        // Update timecode on the frame we're creating
        mlt_frame_set_timecode( *frame, mlt_producer_position( producer ) );
 
@@ -119,7 +212,10 @@ static int producer_get_frame( mlt_producer producer, mlt_frame_ptr frame, int i
 static void producer_close( mlt_producer parent )
 {
        producer_ppm this = parent->child;
-       pclose( this->pipe );
+       if ( this->video )
+               pclose( this->video );
+       if ( this->audio )
+               pclose( this->audio );
        free( this->command );
        parent->close = NULL;
        mlt_producer_close( parent );
index 4787b8f6e6d8d4f5fa396f6b2849f850be9e43b1..69a253a245da79d4c00c97e8a573cba79554678f 100644 (file)
@@ -30,7 +30,9 @@ struct producer_ppm_s
 {
        struct mlt_producer_s parent;
        char *command;
-       FILE *pipe;
+       FILE *video;
+       FILE *audio;
+       uint64_t expected;
 };
 
 extern mlt_producer producer_ppm_init( void *command );
index a4d6b30aac024097abec05d35578420d1337d227..cf02c737e7c00317e71e2a0fca31e20f0d6fbcc4 100644 (file)
@@ -234,7 +234,7 @@ static void *consumer_thread( void *arg )
                                request.freq = frequency;
                                request.format = AUDIO_S16;
                                request.channels = channels;
-                               request.samples = 1024;
+                               request.samples = 512;
                                request.callback = sdl_fill_audio;
                                request.userdata = (void *)this;
                                if ( SDL_OpenAudio( &request, NULL ) < 0 )
index d6dc995ccfe334ff169a6ce2b6c37ae37ba3153d..bcd4dae68008873c0658b41483ce6a35d20bf05b 100644 (file)
@@ -156,6 +156,8 @@ int main( int argc, char **argv )
 
        // Construct the field
        field = mlt_field_init( );
+
+       // We need to track the number of registered filters
        mlt_properties properties = mlt_field_properties( field );
        mlt_properties_set_int( properties, "registered", 0 );