]> git.sesse.net Git - mlt/commitdiff
Sundry consumer modifications; albino compile fix; minor mods to avformat producer
authorlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Fri, 30 Apr 2004 13:23:13 +0000 (13:23 +0000)
committerlilo_booter <lilo_booter@d19143bc-622f-0410-bfdd-b5b2a6649095>
Fri, 30 Apr 2004 13:23:13 +0000 (13:23 +0000)
git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@296 d19143bc-622f-0410-bfdd-b5b2a6649095

src/albino/Makefile
src/framework/mlt_consumer.c
src/modules/avformat/consumer_avformat.c
src/modules/avformat/producer_avformat.c
src/modules/core/filter_mirror.c
src/modules/fezzik.ini
src/modules/sdl/consumer_sdl.c

index 4947457172a25dc0d73f47f0172d841d583ed33b..05daf22ca669d88d44cd381280f170fcde7d5475 100644 (file)
@@ -6,7 +6,7 @@ OBJS = albino.o
 
 CFLAGS += -I.. -rdynamic
 
-LDFLAGS += -L../miracle -lmiracle -L../valerie -lvalerie -L../miracle -lmiracle
+LDFLAGS += -L../miracle -lmiracle -L../valerie -lvalerie -L../miracle -lmiracle -L../framework -lmlt
 
 SRCS := $(OBJS:.o=.c)
 
index 5f00b6ce7bb3e45923b4c0a3e4b90777b5ae210f..ef2760e95dd38bfa4d776d4ac93fe8316c8d549c 100644 (file)
@@ -234,6 +234,8 @@ static void *consumer_read_ahead_thread( void *arg )
        // Get the properties of the consumer
        mlt_properties properties = mlt_consumer_properties( this );
 
+       char *service = mlt_properties_get( properties, "mlt_service" );
+
        // Get the width and height
        int width = mlt_properties_get_int( properties, "width" );
        int height = mlt_properties_get_int( properties, "height" );
@@ -269,13 +271,14 @@ static void *consumer_read_ahead_thread( void *arg )
        while ( this->ahead )
        {
                // Put the current frame into the queue
+               time_difference( &ante );
                pthread_mutex_lock( &this->mutex );
                while( this->ahead && mlt_deque_count( this->queue ) >= buffer )
                        pthread_cond_wait( &this->cond, &this->mutex );
                mlt_deque_push_back( this->queue, frame );
                pthread_cond_broadcast( &this->cond );
                pthread_mutex_unlock( &this->mutex );
-               time_wait += time_difference( &ante );
+               time_wait = time_difference( &ante );
 
                // Get the next frame
                frame = mlt_consumer_get_frame( this );
@@ -294,8 +297,10 @@ static void *consumer_read_ahead_thread( void *arg )
                        count = 1;
                }
 
+               //fprintf( stderr, "%s: %d %d %lld %lld\n", service, mlt_deque_count( this->queue ), buffer, ( time_frame + time_image ) / count, ( time_wait / count ) );
+
                // Get the image
-               if ( ( time_frame + time_image ) / count < ( 40000 - ( time_wait / count ) ) )
+               if ( ( time_frame + time_image ) / count < 40000 )
                {
                        // Get the image, mark as rendered and time it
                        mlt_frame_get_image( frame, &image, &this->format, &width, &height, 0 );
@@ -307,16 +312,19 @@ static void *consumer_read_ahead_thread( void *arg )
                }
                else
                {
+                       fprintf( stderr, "Dropped a frame for %s\n", service );
+
                        // Increment the number of sequentially skipped frames
                        skipped ++;
 
+                       time_wait = 0;
+
                        // If we've reached an unacceptable level, reset everything
                        if ( skipped > 10 )
                        {
                                skipped = 0;
                                time_frame = 0;
                                time_image = 0;
-                               time_wait = 0;
                                count = 0;
                        }
                }
@@ -402,7 +410,7 @@ mlt_frame mlt_consumer_rt_frame( mlt_consumer this )
                        int buffer = mlt_properties_get_int( properties, "buffer" );
                        consumer_read_ahead_start( this );
                        if ( buffer > 1 )
-                               size = buffer / 2;
+                               size = buffer;
                }
        
                // Get frame from queue
index 77142e21151420e20c2c6ffd5ae8ee3223db9c59..52fe9da701873c23aaad78b2e5c60a64aae38363 100644 (file)
@@ -29,7 +29,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
-
+#include <sys/time.h>
 #include <math.h>
 
 // avformat header files
@@ -420,6 +420,13 @@ void close_video(AVFormatContext *oc, AVStream *st)
        avcodec_close(&st->codec);
 }
 
+static inline long time_difference( struct timeval *time1 )
+{
+       struct timeval time2;
+       gettimeofday( &time2, NULL );
+       return time2.tv_sec * 1000000 + time2.tv_usec - time1->tv_sec * 1000000 - time1->tv_usec;
+}
+
 /** The main thread - the argument is simply the consumer.
 */
 
@@ -434,6 +441,12 @@ static void *consumer_thread( void *arg )
        // Get the terminate on pause property
        int terminate_on_pause = mlt_properties_get_int( properties, "terminate_on_pause" );
 
+       // Determine if feed is slow (for realtime stuff)
+       int real_time_output = mlt_properties_get_int( properties, "real_time" );
+
+       // Time structures
+       struct timeval ante;
+
        // Get the frame rate
        int fps = mlt_properties_get_double( properties, "fps" );
 
@@ -493,6 +506,10 @@ static void *consumer_thread( void *arg )
        // Loop variable
        int i;
 
+       // Frames despatched
+       long int frames = 0;
+       long int total_time = 0;
+
        // Determine the format
        AVOutputFormat *fmt = NULL;
        char *filename = mlt_properties_get( properties, "target" );
@@ -584,9 +601,6 @@ static void *consumer_thread( void *arg )
                        }
                }
        
-               if ( url_is_streamed( &oc->pb ) )
-                       fprintf( stderr, "FUCK!\n" );
-
                // Write the stream header, if any
                if ( mlt_properties_get_int( properties, "running" ) )
                        av_write_header( oc );
@@ -601,6 +615,9 @@ static void *consumer_thread( void *arg )
        if ( audio_st == NULL && video_st == NULL )
                mlt_properties_set_int( properties, "running", 0 );
 
+       // Get the starting time (can ignore the times above)
+       gettimeofday( &ante, NULL );
+
        // Loop while running
        while( mlt_properties_get_int( properties, "running" ) )
        {
@@ -610,6 +627,9 @@ static void *consumer_thread( void *arg )
                // Check that we have a frame to work with
                if ( frame != NULL )
                {
+                       // Increment frames despatched
+                       frames ++;
+
                        // Default audio args
                        frame_properties = mlt_frame_properties( frame );
 
@@ -619,6 +639,7 @@ static void *consumer_thread( void *arg )
                                samples = mlt_sample_calculator( fps, frequency, count );
                                mlt_frame_get_audio( frame, &pcm, &aud_fmt, &frequency, &channels, &samples );
                                sample_fifo_append( fifo, pcm, samples * channels );
+                               total_time += ( samples * 1000000 ) / frequency;
                        }
 
                        // Encode the image
@@ -735,6 +756,19 @@ static void *consumer_thread( void *arg )
                                }
                        }
                }
+
+               if ( real_time_output && frames % 25 == 0 )
+               {
+                       long passed = time_difference( &ante );
+                       long pending = ( ( ( long )sample_fifo_used( fifo ) * 1000 ) / frequency ) * 1000;
+                       passed -= pending;
+                       if ( passed < total_time )
+                       {
+                               long total = ( total_time - passed );
+                               struct timespec t = { total / 1000000, ( total % 1000000 ) * 1000 };
+                               nanosleep( &t, NULL );
+                       }
+               }
        }
 
        // close each codec 
index 9da63d480c0aedc1ed28178d0779fab7d1b805f6..e0c246d7095c4f819163a41be14eb19195a5648d 100644 (file)
@@ -267,6 +267,9 @@ static int producer_open( mlt_producer this, char *file )
                                mlt_properties_set_position( properties, "length", frames - 1 );
                        }
 
+                       // Check if we're seekable
+                       mlt_properties_set_int( properties, "seekable", av_seek_frame( context, -1, 0 ) == 0 );
+
                        // Find default audio and video streams
                        find_default_streams( context, &audio_index, &video_index );
 
@@ -700,6 +703,9 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
        // Get the audio_index
        int index = mlt_properties_get_int( properties, "audio_index" );
 
+       // Get the seekable status
+       int seekable = mlt_properties_get_int( properties, "seekable" );
+
        // Obtain the expected frame numer
        mlt_position expected = mlt_properties_get_position( properties, "audio_expected" );
 
@@ -729,7 +735,6 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
 
        // Flag for paused (silence) 
        int paused = 0;
-       int locked = 0;
 
        // Lock the mutex now
        avformat_lock( );
@@ -775,12 +780,11 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
                else
                {
                        // Set to the real timecode
-                       av_seek_frame( context, -1, real_timecode * 1000000.0 );
+                       if ( !seekable || av_seek_frame( context, -1, real_timecode * 1000000.0 ) != 0 )
+                               paused = 1;
 
                        // Clear the usage in the audio buffer
                        audio_used = 0;
-
-                       locked = 1;
                }
        }
 
@@ -865,7 +869,7 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
                                        mlt_properties_set_double( properties, "discrepancy", discrepancy );
                                }
 
-                               if ( !ignore && discrepancy * current_pts <= ( real_timecode - 0.02 ) )
+                               if ( seekable && ( !ignore && discrepancy * current_pts <= ( real_timecode - 0.02 ) ) )
                                        ignore = 1;
                        }
 
@@ -901,8 +905,9 @@ static int producer_get_audio( mlt_frame frame, int16_t **buffer, mlt_audio_form
                mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
        }
 
-       // Regardless of speed, we expect to get the next frame (cos we ain't too bright)
-       mlt_properties_set_position( properties, "audio_expected", position + 1 );
+       // Regardless of speed (other than paused), we expect to get the next frame
+       if ( !paused )
+               mlt_properties_set_position( properties, "audio_expected", position + 1 );
 
        // Unlock the mutex now
        avformat_unlock( );
index bc8927aae7b0b611b9958586c4645911cc162260..e007ac2a06818758c152b3a0e97ece1afafe5eb9 100644 (file)
@@ -145,6 +145,42 @@ static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format
                                }
                        }
                }
+               else if ( !strcmp( mirror, "xdiagonal" ) )
+               {
+                       uint8_t *end = ( uint8_t *)*image + *width * *height * 2;
+                       uint8_t *p = NULL;
+                       uint8_t *q = NULL;
+                       int i;
+                       int j;
+                       for ( i = 0; i < *height; i ++ )
+                       {
+                               p = ( uint8_t * )*image + ( i + 1 ) * *width * 2;
+                               q = end - ( i + 1 ) * *width * 2;
+                               j = ( ( *width * ( *height - i ) ) / *height ) / 2;
+                               if ( !reverse )
+                               {
+                                       while ( j -- )
+                                       {
+                                               *q ++ = *( p - 2 );
+                                               *q ++ = *( p - 3 );
+                                               *q ++ = *( p - 4 );
+                                               *q ++ = *( p - 1 );
+                                               p -= 4;
+                                       }
+                               }
+                               else
+                               {
+                                       while ( j -- )
+                                       {
+                                               *( p - 2 ) = *q ++;
+                                               *( p - 3 ) = *q ++;
+                                               *( p - 4 ) = *q ++;
+                                               *( p - 1 ) = *q ++;
+                                               p -= 4;
+                                       }
+                               }
+                       }
+               }
                else if ( !strcmp( mirror, "flip" ) )
                {
                        uint8_t t[ 4 ];
index 9e7caaaf8d0863d5acf84a1bb52651ee6c428ab0..153f60d15d3559dde1d7d5193714efadc7f9cb31 100644 (file)
@@ -6,7 +6,7 @@
 # The names of the services on the right dictate the preference used (if unavailable
 # the second and third are applied as applicable).
 
-deinterlace=deinterlace,avdeinterlace
+deinterlace=avdeinterlace
 rescaler=mcrescale,gtkrescale,rescale
 resizer=resize
-resampler=resample,soxresample,avresample
+resampler=soxresample,avresample
index 6b9ad0ce20549a61b7ad58bed1a28388d1b9819a..b2dcd900df8c098dfa132ca079b95527dbe8b388 100644 (file)
@@ -489,9 +489,6 @@ static int consumer_play_video( consumer_sdl this, mlt_frame frame )
                }
        }
 
-       // Close the frame
-       mlt_frame_close( frame );
-
        return 0;
 }
 
@@ -518,6 +515,7 @@ static void *consumer_thread( void *arg )
        struct timespec tm;
        mlt_frame next = NULL;
        mlt_frame frame = NULL;
+       mlt_properties properties = NULL;
 
        if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE ) < 0 )
        {
@@ -537,23 +535,24 @@ static void *consumer_thread( void *arg )
                // Ensure that we have a frame
                if ( frame != NULL )
                {
+                       // Get the frame properties
+                       properties =  mlt_frame_properties( frame );
+
                        // Play audio
                        init_audio = consumer_play_audio( this, frame, init_audio, &duration );
 
-                       if ( this->playing )
+                       // Determine the start time now
+                       if ( this->playing && start == 0 )
                        {
                                // Get the current time
                                gettimeofday( &now, NULL );
 
-                               // Determine elapsed time
-                               if ( start == 0 )
-                                       start = ( int64_t )now.tv_sec * 1000000 + now.tv_usec;
-                               else
-                                       elapsed = ( ( int64_t )now.tv_sec * 1000000 + now.tv_usec) - start;
+                               // Determine start time
+                               start = ( int64_t )now.tv_sec * 1000000 + now.tv_usec;
                        }
 
                        // Set playtime for this frame
-                       mlt_properties_set_position( mlt_frame_properties( frame ), "playtime", playtime );
+                       mlt_properties_set_position( properties, "playtime", playtime );
 
                        // Push this frame to the back of the queue
                        mlt_deque_push_back( this->queue, frame );
@@ -562,41 +561,57 @@ static void *consumer_thread( void *arg )
                        playtime += ( duration * 1000 );
                }
 
-               if ( this->playing )
+               // Pop the next frame
+               next = mlt_deque_pop_front( this->queue );
+
+               while ( next != NULL && this->playing )
                {
-                       // Pop the next frame
-                       next = mlt_deque_pop_front( this->queue );
+                       // Get the properties
+                       properties =  mlt_frame_properties( next );
+
+                       // Get the current time
+                       gettimeofday( &now, NULL );
+
+                       // Get the elapsed time
+                       elapsed = ( ( int64_t )now.tv_sec * 1000000 + now.tv_usec ) - start;
 
                        // See if we have to delay the display of the current frame
-                       if ( next != NULL && mlt_properties_get_int( mlt_frame_properties( next ), "rendered" ) == 1 )
+                       if ( mlt_properties_get_int( properties, "rendered" ) == 1 )
                        {
-                               mlt_position scheduled = mlt_properties_get_position( mlt_frame_properties( next ), "playtime" ) + 5000;
-                               if ( scheduled > elapsed && mlt_deque_count( this->queue ) > 25 )
+                               // Obtain the scheduled playout time
+                               mlt_position scheduled = mlt_properties_get_position( properties, "playtime" );
+
+                               // Determine the difference between the elapsed time and the scheduled playout time
+                               mlt_position difference = scheduled - elapsed;
+
+                               // If the frame is quite some way in the future, go get another
+                               if ( difference > 80000 && mlt_deque_count( this->queue ) < 6 )
+                                       break;
+
+                               // Smooth playback a bit
+                               if ( difference > 20000 && mlt_properties_get_double( properties, "_speed" ) == 1.0 )
                                {
-                                       tm.tv_sec = ( scheduled - elapsed ) / 1000000;
-                                       tm.tv_nsec = ( ( scheduled - elapsed ) % 1000000 ) * 1000;
+                                       tm.tv_sec = difference / 1000000;
+                                       tm.tv_nsec = ( difference % 1000000 ) * 1000;
                                        nanosleep( &tm, NULL );
+                               }
 
-                                       // Show current frame
+                               // Show current frame if not too old
+                               if ( difference > -10000 || mlt_properties_get_double( properties, "_speed" ) != 1.0 )
                                        consumer_play_video( this, next );
-                               }
-                               else if ( scheduled > elapsed )
-                               {
-                                       // More time to kill
-                                       mlt_deque_push_front( this->queue, next );
-                               }
                                else
-                               {
-                                       // Show current frame
-                                       consumer_play_video( this, next );
-                               }
-                       }
-                       else
-                       {
-                               // This is an unrendered frame - just close it
-                               mlt_frame_close( next );
+                                       start = start - difference;
                        }
+
+                       // This is an unrendered frame - just close it
+                       mlt_frame_close( next );
+
+                       // Pop the next frame
+                       next = mlt_deque_pop_front( this->queue );
                }
+
+               if ( next != NULL )
+                       mlt_deque_push_front( this->queue, next );
        }
 
        // internal cleanup