From: Mike Brady Date: Wed, 1 Aug 2018 08:35:28 +0000 (+0100) Subject: Change calculation order to prevent overflow after about 26 hours at 44,100 fps in... X-Git-Tag: 3.3RC0~276 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3888125a24efa31e55aa1e05fd6b08c7e134a6a4;p=thirdparty%2Fshairport-sync.git Change calculation order to prevent overflow after about 26 hours at 44,100 fps in the frame rate calculations. Calculate frame rates whether statistcs are requested or not. Clean up some fps rate availability flags. --- diff --git a/audio_alsa.c b/audio_alsa.c index 27995d57..4ab704fe 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -894,14 +894,16 @@ int delay(long *the_delay) { } int get_rate_information(uint64_t *elapsed_time, uint64_t *frames_played) { + int response = 0; // zero means okay if (measurement_data_is_valid) { *elapsed_time = measurement_time - measurement_start_time; *frames_played = frames_played_at_measurement_time - frames_played_at_measurement_start_time; } else { *elapsed_time = 0; *frames_played = 0; + response = -1; } - return 0; + return response; } static int play(void *buf, int samples) { diff --git a/player.c b/player.c index 956a4dbd..3dd1ac4b 100644 --- a/player.c +++ b/player.c @@ -1445,7 +1445,7 @@ void player_thread_cleanup_handler(void *arg) { int elapsedHours = rawSeconds / 3600; int elapsedMin = (rawSeconds / 60) % 60; int elapsedSec = rawSeconds % 60; - if (conn->frame_rate_status == 0) + if (conn->frame_rate_status) inform("Playback Stopped. Total playing time %02d:%02d:%02d. Input: %0.2f, output: %0.2f frames per second.", elapsedHours, elapsedMin, elapsedSec, conn->input_frame_rate, conn->frame_rate); else @@ -1611,7 +1611,10 @@ void *player_thread_func(void *arg) { conn->playstart = time(NULL); conn->frame_rate = 0.0; - conn->frame_rate_status = -1; // zero means okay + conn->frame_rate_status = 0; + + conn->input_frame_rate = 0.0; + conn->input_frame_rate_status = 0; conn->buffer_occupancy = 0; @@ -2299,6 +2302,35 @@ void *player_thread_func(void *arg) { } } if (play_number % print_interval == 0) { + + // here, calculate the input and output frame rates, where possible, even if statistics have not been requested + // this is to calculate them in case they are needed by the D-Bus interface or elsewhere. + + if (conn->input_frame_rate_status) { + uint64_t elapsed_reception_time, frames_received; + elapsed_reception_time = conn->frames_inward_measurement_time - conn->frames_inward_measurement_start_time; + frames_received = conn->frames_inward_frames_received_at_measurement_time - conn->frames_inward_frames_received_at_measurement_start_time; + conn->input_frame_rate = (1.0 * frames_received) / elapsed_reception_time; // an IEEE double calculation with two 64-bit integers + conn->input_frame_rate = conn->input_frame_rate * (uint64_t)0x100000000; // this should just change the [binary] exponent in the IEEE FP representation; the mantissa should be unaffected. + } + + if ((config.output->delay) && (config.no_sync == 0) && (config.output->rate_info)) { + uint64_t elapsed_play_time, frames_played; + if (config.output->rate_info(&elapsed_play_time, &frames_played)==0) + conn->frame_rate_status = 1; + else + conn->frame_rate_status = 0; + if (conn->frame_rate_status) { + conn->frame_rate = + (1.0 * frames_played) / elapsed_play_time; // an IEEE double calculation with two 64-bit integers + conn->frame_rate = + conn->frame_rate * (uint64_t)0x100000000; // this should just change the [binary] exponent in the IEEE FP representation; the mantissa should be unaffected. + } else { + conn->frame_rate = 0.0; + } + } + + // we can now calculate running averages for sync error (frames), corrections (ppm), // insertions plus deletions (ppm), drift (ppm) double moving_average_sync_error = (1.0 * tsum_of_sync_errors) / number_of_statistics; @@ -2309,26 +2341,9 @@ void *player_thread_func(void *arg) { // if ((play_number/print_interval)%20==0) if (config.statistics_requested) { if (at_least_one_frame_seen) { - if (conn->input_frame_rate_status == 1) { - uint64_t elapsed_reception_time, frames_received; - elapsed_reception_time = conn->frames_inward_measurement_time - conn->frames_inward_measurement_start_time; - frames_received = conn->frames_inward_frames_received_at_measurement_time - conn->frames_inward_frames_received_at_measurement_start_time; - conn->input_frame_rate = 1.0 * (frames_received * (uint64_t)0x100000000) / elapsed_reception_time; - } else { - conn->input_frame_rate = 0.0; - } if ((config.output->delay)) { if (config.no_sync == 0) { - if (config.output->rate_info) { - uint64_t elapsed_play_time, frames_played; - conn->frame_rate_status = - config.output->rate_info(&elapsed_play_time, &frames_played); - if (conn->frame_rate_status == 0) { - conn->frame_rate = - 1.0 * (frames_played * (uint64_t)0x100000000) / elapsed_play_time; - } - } inform("%*.1f," /* Sync error in milliseconds */ "%*.1f," /* net correction in ppm */ "%*.1f," /* corrections in ppm */