int mlt_sample_calculator( float fps, int frequency, int64_t position ) { /* 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. */ return mlt_sample_calculator_to_now( fps, frequency, position + 1 ) - mlt_sample_calculator_to_now( fps, frequency, position ); }
static void detect_blip( mlt_frame frame, mlt_position pos, double fps, avsync_stats* stats ) { int frequency = SAMPLE_FREQ; int channels = 1; int samples = mlt_sample_calculator( fps, frequency, pos ); mlt_audio_format format = mlt_audio_float; float* buffer = NULL; int error = mlt_frame_get_audio( frame, (void**) &buffer, &format, &frequency, &channels, &samples ); if ( !error && format == mlt_audio_float && buffer != NULL ) { int i = 0; for( i = 0; i < samples; i++ ) { if( !stats->blip_in_progress ) { if( buffer[i] > BLIP_THRESHOLD || buffer[i] < -BLIP_THRESHOLD ) { // This sample must start a blip stats->blip_in_progress = 1; stats->samples_since_blip = 0; stats->blip_history[1] = stats->blip_history[0]; stats->blip_history[0] = mlt_sample_calculator_to_now( fps, SAMPLE_FREQ, pos ); stats->blip_history[0] += i; if( stats->blip_history_count < 2 ) { stats->blip_history_count++; } stats->blip = 1; } } else { if( buffer[i] > -BLIP_THRESHOLD && buffer[i] < BLIP_THRESHOLD ) { if( ++stats->samples_since_blip > frequency / 1000 ) { // One ms of silence means the blip is over stats->blip_in_progress = 0; stats->samples_since_blip = 0; } } else { stats->samples_since_blip = 0; } } } } }
static void detect_flash( mlt_frame frame, mlt_position pos, double fps, avsync_stats* stats ) { int width = 0; int height = 0; mlt_image_format format = mlt_image_yuv422; uint8_t* image = NULL; int error = mlt_frame_get_image( frame, &image, &format, &width, &height, 0 ); if ( !error && format == mlt_image_yuv422 && image != NULL ) { int i, j = 0; int y_accumulator = 0; // Add up the luma values from 4 samples in 4 different quadrants. for( i = 1; i < 3; i++ ) { int x = ( width / 3 ) * i; x = x - x % 2; // Make sure this is a luma sample for( j = 1; j < 3; j++ ) { int y = ( height / 3 ) * j; y_accumulator += image[ y * height * 2 + x * 2 ]; } } // If the average luma value is > 150, assume it is a flash. stats->flash = ( y_accumulator / 4 ) > FLASH_LUMA_THRESHOLD; } if( stats->flash ) { stats->flash_history[1] = stats->flash_history[0]; stats->flash_history[0] = mlt_sample_calculator_to_now( fps, SAMPLE_FREQ, pos ); if( stats->flash_history_count < 2 ) { stats->flash_history_count++; } } }