]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Add input frame rate calculation.
authorMike Brady <mikebrady@eircom.net>
Mon, 30 Jul 2018 12:39:38 +0000 (13:39 +0100)
committerMike Brady <mikebrady@eircom.net>
Mon, 30 Jul 2018 12:39:38 +0000 (13:39 +0100)
player.c
player.h
shairport.c

index a143740ea8bf9a3fb9c659de2b36c96a23dda719..5e18c1e490ec887e67063bd37b690ad568de2562 100644 (file)
--- 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);
 }
index 42d75f9bc04239740df60fb017dcb73a96b73fc9..709eef341ab744ba02e835b615f3e74dbff98122 100644 (file)
--- 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;
index f07ad52ca4ee14f4064f256cf10b01a5d2509487..bd4025dc3efafbe11ad9728755ede9b3b8d7c447 100644 (file)
@@ -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.");
       }