From 33098e52cecf267d3dadb6836f03da8b59eac126 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Fri, 7 Aug 2009 20:02:51 -0700 Subject: [PATCH] Fix a/v synch drift with some unhandled framerates (kdenlive-1034). 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 --- src/framework/mlt_frame.c | 74 ++++++++++----------------------------- 1 file changed, 19 insertions(+), 55 deletions(-) diff --git a/src/framework/mlt_frame.c b/src/framework/mlt_frame.c index 804f9b5d..85114624 100644 --- a/src/framework/mlt_frame.c +++ b/src/framework/mlt_frame.c @@ -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; -- 2.39.2