From: Mike Brady Date: Mon, 30 Jul 2018 12:39:38 +0000 (+0100) Subject: Add input frame rate calculation. X-Git-Tag: 3.3RC0~281 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b75c82d14a544b072fd30f181e9de16a15095fb9;p=thirdparty%2Fshairport-sync.git Add input frame rate calculation. --- diff --git a/player.c b/player.c index a143740e..5e18c1e4 100644 --- a/player.c +++ b/player.c @@ -523,6 +523,18 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp } if (conn->ab_write == seqno) { // expected packet + uint64_t reception_time = get_absolute_time_in_fp(); + + if ((conn->packet_count >= 145) && (conn->packet_count <= 155)) { + conn->frames_inward_measurement_start_time = reception_time; + conn->frames_inward_frames_received_at_measurement_start_time = timestamp; + conn->input_frame_rate_status = 1; // valid now + debug(1, "frames_inward_measurement_start_time set"); + } + + conn->frames_inward_measurement_time = reception_time; + conn->frames_inward_frames_received_at_measurement_time = timestamp; + abuf = conn->audio_buffer + BUFIDX(seqno); conn->ab_write = SUCCESSOR(seqno); } else if (seq_order(conn->ab_write, seqno, conn->ab_read)) { // newer than expected @@ -1432,11 +1444,12 @@ void player_thread_cleanup_handler(void *arg) { int elapsedMin = (rawSeconds / 60) % 60; int elapsedSec = rawSeconds % 60; if (conn->frame_rate_status == 0) - inform("Playback Stopped. Total playing time %02d:%02d:%02d at %0.2f frames per second.", - elapsedHours, elapsedMin, elapsedSec, conn->frame_rate); + 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 - inform("Playback Stopped. Total playing time %02d:%02d:%02d.", elapsedHours, elapsedMin, - elapsedSec); + inform("Playback Stopped. Total playing time %02d:%02d:%02d. Input: %0.2f frames per second.", + elapsedHours, elapsedMin, elapsedSec, conn->input_frame_rate); } #ifdef HAVE_DACP_CLIENT @@ -1720,7 +1733,8 @@ void *player_thread_func(void *arg) { "min DAC queue size, " "min buffer occupancy, " "max buffer occupancy, " - "frames per second"); + "input frames per second, " + "output frames per second."); } else { inform("sync error in milliseconds, " "total packets, " @@ -1730,7 +1744,8 @@ void *player_thread_func(void *arg) { "resend requests, " "min DAC queue size, " "min buffer occupancy, " - "max buffer occupancy"); + "max buffer occupancy, " + "input frames per second."); } } else { inform("sync error in milliseconds, " @@ -1740,7 +1755,8 @@ void *player_thread_func(void *arg) { "too late packets, " "resend requests, " "min buffer occupancy, " - "max buffer occupancy"); + "max buffer occupancy, " + "input frames per second."); } } @@ -2291,6 +2307,18 @@ 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) { @@ -2313,7 +2341,8 @@ void *player_thread_func(void *arg) { "%*lli," /* min DAC queue size */ "%*d," /* min buffer occupancy */ "%*d," /* max buffer occupancy */ - "%*.2f", /* frame rate */ + "%*.2f," /* input frame rate */ + "%*.2f", /* output frame rate */ 10, 1000 * moving_average_sync_error / config.output_rate, 10, moving_average_correction * 1000000 / (352 * conn->output_sample_ratio), @@ -2322,7 +2351,8 @@ void *player_thread_func(void *arg) { 12, play_number, 7, conn->missing_packets, 7, conn->late_packets, 7, conn->too_late_packets, 7, conn->resend_requests, 7, minimum_dac_queue_size, 5, minimum_buffer_occupancy, 5, - maximum_buffer_occupancy, 10, conn->frame_rate); + maximum_buffer_occupancy, 11, conn->input_frame_rate, 11, + conn->frame_rate); } else { inform("%*.1f," /* Sync error in milliseconds */ "%*d," /* total packets */ @@ -2332,12 +2362,14 @@ void *player_thread_func(void *arg) { "%*llu," /* resend requests */ "%*lli," /* min DAC queue size */ "%*d," /* min buffer occupancy */ - "%*d", /* max buffer occupancy */ + "%*d," /* max buffer occupancy */ + "%*.2f", /* input frame rate */ 10, 1000 * moving_average_sync_error / config.output_rate, 12, play_number, 7, conn->missing_packets, 7, conn->late_packets, 7, conn->too_late_packets, 7, conn->resend_requests, 7, minimum_dac_queue_size, 5, - minimum_buffer_occupancy, 5, maximum_buffer_occupancy); + minimum_buffer_occupancy, 5, maximum_buffer_occupancy, 11, + conn->input_frame_rate); } } else { inform("%*.1f," /* Sync error in milliseconds */ @@ -2347,12 +2379,13 @@ void *player_thread_func(void *arg) { "%*llu," /* too late packets */ "%*llu," /* resend requests */ "%*d," /* min buffer occupancy */ - "%*d", /* max buffer occupancy */ + "%*d," /* max buffer occupancy */ + "%*.2f", /* input frame rate */ 10, 1000 * moving_average_sync_error / config.output_rate, 12, play_number, 7, conn->missing_packets, 7, conn->late_packets, 7, conn->too_late_packets, 7, conn->resend_requests, 5, minimum_buffer_occupancy, 5, - maximum_buffer_occupancy); + maximum_buffer_occupancy, 11, conn->input_frame_rate); } } else { inform("No frames received in the last sampling interval."); @@ -2368,72 +2401,6 @@ void *player_thread_func(void *arg) { } debug(1, "This should never be called."); - - /* all done in the cleanup... - - debug(3, "Connection %d: player thread main loop exit.", conn->connection_number); - - if (config.statistics_requested) { - int rawSeconds = (int)difftime(time(NULL), conn->playstart); - int elapsedHours = rawSeconds / 3600; - int elapsedMin = (rawSeconds / 60) % 60; - int elapsedSec = rawSeconds % 60; - inform("Playback Stopped. Total playing time %02d:%02d:%02d.", elapsedHours, elapsedMin, - elapsedSec); - } - - #ifdef HAVE_DACP_CLIENT - - relinquish_dacp_server_information(conn); // say it doesn't belong to this conversation thread - any more... - - #else - // stop watching for DACP port number stuff - // this is only used for compatability, if dacp stuff isn't enabled. - if (conn->dapo_private_storage) { - mdns_dacp_dont_monitor(conn->dapo_private_storage); - conn->dapo_private_storage = NULL; - } else { - debug(2, "DACP Monitor already stopped"); - } - #endif - - debug(2, "Cancelling timing, control and audio threads..."); - debug(2, "Cancel timing thread."); - pthread_cancel(rtp_timing_thread); - debug(2, "Join timing thread."); - pthread_join(rtp_timing_thread, NULL); - debug(2, "Timing thread terminated."); - debug(2, "Cancel control thread."); - pthread_cancel(rtp_control_thread); - debug(2, "Join control thread."); - pthread_join(rtp_control_thread, NULL); - debug(2, "Control thread terminated."); - debug(2, "Cancel audio thread."); - pthread_cancel(rtp_audio_thread); - debug(2, "Join audio thread."); - pthread_join(rtp_audio_thread, NULL); - debug(2, "Audio thread terminated."); - clear_reference_timestamp(conn); - conn->rtp_running = 0; - - debug(3, "Connection %d: stopping output device.", conn->connection_number); - - if (config.output->stop) - config.output->stop(); - - debug(2, "Freeing audio buffers and decoders."); - - free_audio_buffers(conn); - terminate_decoders(conn); - debug(2, "Connection %d: player thread terminated.", conn->connection_number); - if (outbuf) - free(outbuf); - if (tbuf) - free(tbuf); - if (sbuf) - free(sbuf); - */ pthread_cleanup_pop(1); pthread_exit(NULL); } diff --git a/player.h b/player.h index 42d75f9b..709eef34 100644 --- a/player.h +++ b/player.h @@ -91,10 +91,22 @@ typedef struct { int32_t *sbuf; char *outbuf; - // for holding the rate information until printed out at the end of a session + // for holding the output rate information until printed out at the end of a session double frame_rate; int frame_rate_status; + // for holding input rate information until printed out at the end of a session + + double input_frame_rate; + int input_frame_rate_status; + + uint64_t frames_inward_measurement_start_time; + uint64_t frames_inward_frames_received_at_measurement_start_time; + + uint64_t frames_inward_measurement_time; + uint64_t frames_inward_frames_received_at_measurement_time; + + // other stuff... pthread_t *player_thread; abuf_t audio_buffer[BUFFER_FRAMES]; int max_frames_per_packet, input_num_channels, input_bit_depth, input_rate; diff --git a/shairport.c b/shairport.c index f07ad52c..bd4025dc 100644 --- a/shairport.c +++ b/shairport.c @@ -465,7 +465,7 @@ int parse_options(int argc, char **argv) { /* Get the statistics setting. */ if (config_set_lookup_bool(config.cfg, "general.statistics", - &(config.statistics_requested))) { + &(config.statistics_requested))) { warn("The \"general\" \"statistics\" setting is deprecated. Please use the \"diagnostics\" " "\"statistics\" setting instead."); }