]> git.sesse.net Git - mlt/commitdiff
Fix a/v synch drift with some unhandled framerates (kdenlive-1034).
authorDan Dennedy <dan@dennedy.org>
Sat, 8 Aug 2009 03:02:51 +0000 (20:02 -0700)
committerDan Dennedy <dan@dennedy.org>
Sat, 8 Aug 2009 03:02:51 +0000 (20:02 -0700)
Previously only special handling provided for 32000, 44100, and 48000
sample rates on the strange NTSC frame rate. Patch provided by Mike
Adkins makes it generic including 24000/1001. Thanks!

Signed-off-by: Dan Dennedy <dan@dennedy.org>
src/framework/mlt_frame.c

index 804f9b5d90b8d274c9f268e81bbee93cecad35e4..85114624ecf8b73dc8376159ba9aa7c9f6bbf528 100644 (file)
@@ -589,43 +589,23 @@ int mlt_sample_calculator( float fps, int frequency, int64_t position )
 {
        int samples = 0;
 
-       if ( ( int )( fps * 100 ) == 2997 )
+       if ( fps )
        {
-               samples = frequency / 30;
-
-               switch ( frequency )
-               {
-                       case 48000:
-                               if ( position % 5 != 0 )
-                                       samples += 2;
-                               break;
-                       case 44100:
-                               if ( position % 300 == 0 )
-                                       samples = 1471;
-                               else if ( position % 30 == 0 )
-                                       samples = 1470;
-                               else if ( position % 2 == 0 )
-                                       samples = 1472;
-                               else
-                                       samples = 1471;
-                               break;
-                       case 32000:
-                               if ( position % 30 == 0 )
-                                       samples = 1068;
-                               else if ( position % 29 == 0 )
-                                       samples = 1067;
-                               else if ( position % 4 == 2 )
-                                       samples = 1067;
-                               else
-                                       samples = 1068;
-                               break;
-                       default:
-                               samples = 0;
-               }
-       }
-       else if ( fps != 0 )
-       {
-               samples = frequency / fps;
+               /* Compute the cumulative number of samples until the start of this frame and the
+               cumulative number of samples until the start of the next frame. Round each to the
+               nearest integer and take the difference to determine the number of samples in
+               this frame.
+
+               This approach should prevent rounding errors that can accumulate over a large number
+               of frames causing A/V sync problems. */
+
+               int64_t samples_at_this =
+                       (int64_t)( (double) position * (double) frequency / (double) fps +
+                       ( position < 0 ? -0.5 : 0.5 ) );
+               int64_t samples_at_next =
+                       (int64_t)( (double) (position + 1) * (double) frequency / (double) fps +
+                       ( position < 0 ? -0.5 : 0.5 ) );
+               samples = (int)( samples_at_next - samples_at_this );
        }
 
        return samples;
@@ -635,26 +615,10 @@ int64_t mlt_sample_calculator_to_now( float fps, int frequency, int64_t frame )
 {
        int64_t samples = 0;
 
-       // TODO: Correct rules for NTSC and drop the * 100 hack
-       if ( ( int )( fps * 100 ) == 2997 )
-       {
-               samples = ( ( double )( frame * frequency ) / 30 );
-               switch( frequency )
-               {
-                       case 48000:
-                               samples += 2 * ( frame / 5 );
-                               break;
-                       case 44100:
-                               samples += frame + ( frame / 2 ) - ( frame / 30 ) + ( frame / 300 );
-                               break;
-                       case 32000:
-                               samples += ( 2 * frame ) - ( frame / 4 ) - ( frame / 29 );
-                               break;
-               }
-       }
-       else if ( fps != 0 )
+       if ( fps )
        {
-               samples = ( ( frame * frequency ) / ( int )fps );
+               samples = (int64_t)( (double) frame * (double) frequency / (double) fps +
+                       ( frame < 0 ? -0.5 : 0.5 ) );
        }
 
        return samples;