]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
If it's an AirPlay user agent up to and including version 363 (iOS 11.1.2) use the...
authorMike Brady <mikebrady@eircom.net>
Fri, 4 May 2018 17:25:52 +0000 (18:25 +0100)
committerMike Brady <mikebrady@eircom.net>
Fri, 4 May 2018 17:25:52 +0000 (18:25 +0100)
player.h
rtp.c
rtsp.c

index 031813a9ff8994fceee6b071c6ce1ece6d971354..7ede6e9f478cce05800927695f8e5e4cbaa14e6e 100644 (file)
--- a/player.h
+++ b/player.h
@@ -57,6 +57,7 @@ typedef struct {
 
 typedef struct {
   int connection_number;   // for debug ID purposes, nothing else...
+  int AirPlayVersion;      // zero if not an AirPlay session. Used to help calculate latency
   int64_t latency;         // the actual latency used for this play session
   int64_t minimum_latency; // set if an a=min-latency: line appears in the ANNOUNCE message; zero
                            // otherwise
diff --git a/rtp.c b/rtp.c
index a6cf22292d3447649c5a27e9eb33b3c421706fff..61a622629137a55fbecf106f5e1a7b37c88c9195 100644 (file)
--- a/rtp.c
+++ b/rtp.c
@@ -292,6 +292,8 @@ void *rtp_control_receiver(void *arg) {
               // delay of 11,025 frames should be added -- iTunes set this field to 7 and
               // AirPlay sets it to 4.
 
+              // However, on older versions of AirPlay, the 11,025 frames seem to be necessary too
+
               // The value of 11,025 (0.25 seconds) is a guess based on the "Audio-Latency"
               // parameter
               // returned by an AE.
@@ -300,9 +302,14 @@ void *rtp_control_receiver(void *arg) {
 
               uint16_t flags = nctohs(&packet[2]);
               int64_t la = sync_rtp_timestamp - rtp_timestamp_less_latency;
-              if (flags == 7)
+              debug(3, "Latency derived just from the sync packet is %" PRId64 " frames.", la);
+              if ((flags == 7) || ((conn->AirPlayVersion > 0) && (conn->AirPlayVersion <= 363))) {
                 la += config.fixedLatencyOffset;
-              // debug(1,"Latency calculated from the sync packet is %" PRId64 " frames.",la);
+                debug(3, "A fixed latency offset of %d frames has been added, giving a latency of "
+                         "%" PRId64
+                         " frames with flags: %d and AirPlay version %d (triggers if 363 or less).",
+                      config.fixedLatencyOffset, la, flags, conn->AirPlayVersion);
+              }
               if ((conn->maximum_latency) && (conn->maximum_latency < la))
                 la = conn->maximum_latency;
               if ((conn->minimum_latency) && (conn->minimum_latency > la))
@@ -969,8 +976,8 @@ void rtp_request_resend(seq_t first, uint32_t count, rtsp_conn_info *conn) {
     }
 #endif
     uint64_t time_of_sending_fp = get_absolute_time_in_fp();
-    uint64_t resend_error_backoff_time = (uint64_t)1 << (32-1); // half a second
-    if ((conn->rtp_time_of_last_resend_request_error_fp==0) ||
+    uint64_t resend_error_backoff_time = (uint64_t)1 << (32 - 1); // half a second
+    if ((conn->rtp_time_of_last_resend_request_error_fp == 0) ||
         ((time_of_sending_fp - conn->rtp_time_of_last_resend_request_error_fp) >
          resend_error_backoff_time)) {
       if ((config.diagnostic_drop_packet_fraction == 0.0) ||
@@ -979,17 +986,20 @@ void rtp_request_resend(seq_t first, uint32_t count, rtsp_conn_info *conn) {
                    (struct sockaddr *)&conn->rtp_client_control_socket, msgsize) == -1) {
           char em[1024];
           strerror_r(errno, em, sizeof(em));
-          debug(1, "Error %d using send-to to an audio socket: \"%s\". Backing off for 0.5 seconds.", errno, em);
+          debug(1,
+                "Error %d using send-to to an audio socket: \"%s\". Backing off for 0.5 seconds.",
+                errno, em);
           conn->rtp_time_of_last_resend_request_error_fp = time_of_sending_fp;
         } else {
           conn->rtp_time_of_last_resend_request_error_fp = 0;
         }
       } else {
-        debug(3, "Dropping resend request packet to simulate a bad network. Backing off for 0.5 seconds.");
+        debug(3, "Dropping resend request packet to simulate a bad network. Backing off for 0.5 "
+                 "seconds.");
         conn->rtp_time_of_last_resend_request_error_fp = time_of_sending_fp;
       }
     } else {
-       debug(3,"Backing off sending resend requests due to a previous send-to error");
+      debug(3, "Backing off sending resend requests due to a previous send-to error");
     }
   } else {
     // if (!request_sent) {
diff --git a/rtsp.c b/rtsp.c
index 3fb6ba39ed716def0f395197081f5b2649429a39..516e9968e8505b94ef070884b06d79353ff27030 100644 (file)
--- a/rtsp.c
+++ b/rtsp.c
@@ -1593,6 +1593,18 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
     if (hdr) {
       debug(2, "Play connection from user agent \"%s\" on RTSP conversation thread %d.", hdr,
             conn->connection_number);
+      // if the user agent is AirPlay and has a version number of 353 or less (from iOS 11.1)
+      // use the older way of calculating the latency
+
+      char *p = strstr(hdr, "AirPlay");
+      if (p) {
+        p = strchr(p, '/');
+        if (p) {
+          conn->AirPlayVersion = atoi(p + 1); // unsigned integer -- up to 2^32-1
+          debug(1, "AirPlay version %d detected.", conn->AirPlayVersion);
+        }
+      }
+
 #ifdef CONFIG_METADATA
       send_metadata('ssnc', 'snua', hdr, strlen(hdr), req, 1);
 #endif