]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Try to fix modulo calculations
authorMike Brady <mikebrady@eircom.net>
Thu, 18 Oct 2018 16:44:50 +0000 (17:44 +0100)
committerMike Brady <mikebrady@eircom.net>
Thu, 18 Oct 2018 16:44:50 +0000 (17:44 +0100)
common.h
player.c
player.h
rtp.c
rtp.h

index c5d03aa3ddf21c91b82de144d94f22b2109206e7..0042d2c4d59efc406829bbee835de19fdebe2a90 100644 (file)
--- a/common.h
+++ b/common.h
@@ -134,8 +134,8 @@ typedef struct {
   char *mdns_name;
   mdns_backend *mdns;
   int buffer_start_fill;
-  int64_t userSuppliedLatency; // overrides all other latencies -- use with caution
-  int64_t fixedLatencyOffset;  // add this to all automatic latencies supplied to get the actual
+  uint32_t userSuppliedLatency; // overrides all other latencies -- use with caution
+  uint32_t fixedLatencyOffset;  // add this to all automatic latencies supplied to get the actual
                                // total latency
   // the total latency will be limited to the min and max-latency values, if supplied
   int daemonise;
index 457cd702b2aba332685296727e59c0ee69ab998a..235b03ab563ec93e676c0c628bc90e1d4101dc15 100644 (file)
--- a/player.c
+++ b/player.c
 // static abuf_t audio_buffer[BUFFER_FRAMES];
 #define BUFIDX(seqno) ((seq_t)(seqno) % BUFFER_FRAMES)
 
-void do_flush(int64_t timestamp, rtsp_conn_info *conn);
-
-// make timestamps and seqnos definitely monotonic
-
-// add an epoch to the timestamp. The monotonic timestamp guaranteed to start between 2^32 and 2^33
-// frames and continue up to 2^63-1 frames
-// if should never get into the negative range
-// which is about 2*10^8 * 1,000 seconds at 384,000 frames per second -- about 2 trillion seconds or
-// over 50,000 years.
-// also, it won't reach zero until then, if ever, so we can safely say that a null monotonic
-// timestamp can mean something special
-int64_t monotonic_timestamp(uint32_t timestamp, rtsp_conn_info *conn) {
-  int64_t previous_value;
-  int64_t return_value;
-  if (conn->timestamp_epoch == 0) {
-    if (timestamp > conn->maximum_timestamp_interval)
-      conn->timestamp_epoch = 1;
-    else
-      conn->timestamp_epoch = 2;
-    previous_value = conn->timestamp_epoch;
-    previous_value <<= 32;
-    previous_value += timestamp;
-  } else {
-    previous_value = conn->timestamp_epoch;
-    previous_value <<= 32;
-    previous_value += conn->last_timestamp;
-    if (timestamp < conn->last_timestamp) {
-      // the incoming timestamp is less than the last one.
-      // if the difference is more than a minute, assume it's really from the next epoch
-      if ((conn->last_timestamp - timestamp) > conn->maximum_timestamp_interval)
-        conn->timestamp_epoch++;
-    } else {
-      // the incoming timestamp is greater than the last one.
-      // if the difference is more than a minute, assume it's really from the previous epoch
-      if ((timestamp - conn->last_timestamp) > conn->maximum_timestamp_interval)
-        conn->timestamp_epoch--;
-    }
-  }
-  return_value = conn->timestamp_epoch;
-  return_value <<= 32;
-  return_value += timestamp;
-  if (previous_value > return_value) {
-    if ((previous_value - return_value) > conn->maximum_timestamp_interval)
-      debug(2, "interval between successive rtptimes greater than allowed!");
-  } else {
-    if ((return_value - previous_value) > conn->maximum_timestamp_interval)
-      debug(2, "interval between successive rtptimes greater than allowed!");
-  }
-  if (return_value < 0)
-    debug(1, "monotonic rtptime is negative!");
-  conn->last_timestamp = timestamp;
-  return return_value;
+uint32_t rtp_frame_offset(uint32_t base, uint32_t frame_in_question) {
+       if (base <= frame_in_question)
+               return frame_in_question - base;
+       else
+               return UINT32_MAX - base + frame_in_question + 1;
 }
 
+void do_flush(uint32_t timestamp, rtsp_conn_info *conn);
+
 static void ab_resync(rtsp_conn_info *conn) {
   int i;
   for (i = 0; i < BUFFER_FRAMES; i++) {
@@ -165,11 +120,36 @@ static void ab_resync(rtsp_conn_info *conn) {
   conn->ab_buffering = 1;
 }
 
-// the sequence number is a 16-bit unsigned number which wraps pretty often
-// to work out if one seqno is 'after' another therefore depends whether wrap has occurred
-// this function works out the actual ordinate of the seqno, i.e. the distance up from
-// the zeroth element, at ab_read, taking due account of wrap.
+// given starting and ending points as unsigned 32-bit integers running modulo 2^32, returns the position of x in the interval in *pos
+// returns true if x is actually within the buffer
+
+int position_in_modulo_uint32_t_buffer(uint32_t x, uint32_t start, uint32_t end, uint32_t *pos ) {
+       int response = 0; // not in the buffer
+       if (start <= end ) {
+               if (x < start) {
+                       if (pos)
+                               *pos = UINT32_MAX - start + 1 + x;
+               } else {
+                       if (pos)
+                               *pos = x - start;
+                       if (x < end) 
+                               response = 1;
+               }
+       } else if ((x >= start) && (x <= UINT32_MAX)) {
+               response = 1;
+               if (pos)
+                       *pos = x - start;
+       } else {
+               if (pos)
+                       *pos = UINT32_MAX - start + 1 + x;
+               if (x < end) {
+                       response = 1;
+               }
+       }
+       return response;
+}
 
+// this is used.
 static inline seq_t SUCCESSOR(seq_t x) {
   uint32_t p = x & 0xffff;
   p += 1;
@@ -177,6 +157,7 @@ static inline seq_t SUCCESSOR(seq_t x) {
   return p;
 }
 
+// this is not used
 static inline seq_t PREDECESSOR(seq_t x) {
   uint32_t p = (x & 0xffff) + 0x10000;
   p -= 1;
@@ -184,6 +165,8 @@ static inline seq_t PREDECESSOR(seq_t x) {
   return p;
 }
 
+// used in seq_diff and seq_order
+
 // anything with ORDINATE in it must be proctected by the ab_mutex
 static inline int32_t ORDINATE(seq_t x, seq_t base) {
   int32_t p = x;    // int32_t from seq_t, i.e. uint16_t, so okay
@@ -458,14 +441,8 @@ static void free_audio_buffers(rtsp_conn_info *conn) {
     free(conn->audio_buffer[i].data);
 }
 
-void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp, uint8_t *data,
+void player_put_packet(seq_t seqno, uint32_t actual_timestamp, uint8_t *data,
                        int len, rtsp_conn_info *conn) {
-  // all timestamps are done at the output rate
-  // the "actual_timestamp" is the one that comes in the packet, and is carried over for
-  // debugging
-  // and checking only.
-
-  int64_t ltimestamp = timestamp * conn->output_sample_ratio;
 
   // ignore a request to flush that has been made before the first packet...
   if (conn->packet_count == 0) {
@@ -483,22 +460,26 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp
 
     //    if (flush_rtp_timestamp != 0)
     //         debug(1,"Flush_rtp_timestamp is %u",flush_rtp_timestamp);
-
-    if ((conn->flush_rtp_timestamp != 0) && (ltimestamp <= conn->flush_rtp_timestamp)) {
-      debug(3, "Dropping flushed packet in player_put_packet, seqno %u, timestamp %" PRId64
-               ", flushing to "
-               "timestamp: %" PRId64 ".",
-            seqno, ltimestamp, conn->flush_rtp_timestamp);
-      conn->initial_reference_time = 0;
-      conn->initial_reference_timestamp = 0;
+    
+    // now, if a flush_rtp_timestamp has been defined and the incoming timestamp is "before" it, drop it…
+    
+    if ((conn->flush_rtp_timestamp != 0) && (rtp_frame_offset(actual_timestamp,conn->flush_rtp_timestamp) < 8820)) {// if it's less than 0.2 seconds
+                               debug(2, "Dropping flushed packet in player_put_packet, seqno %u, timestamp %" PRIu32
+                                        ", flushing to "
+                                        "timestamp: %" PRIu32 ".",
+                               seqno, actual_timestamp, conn->flush_rtp_timestamp);
+                               conn->initial_reference_time = 0;
+                               conn->initial_reference_timestamp = 0;
     } else {
-      if ((conn->flush_rtp_timestamp != 0x0) &&
-          (ltimestamp > conn->flush_rtp_timestamp)) // if we have gone past the flush boundary time
-        conn->flush_rtp_timestamp = 0x0;
+      if ((conn->flush_rtp_timestamp != 0) && (rtp_frame_offset(conn->flush_rtp_timestamp,actual_timestamp) > 8820) && (rtp_frame_offset(conn->flush_rtp_timestamp,actual_timestamp) < 44100)) {
+       debug(2,"Dropping flush request");
+        conn->flush_rtp_timestamp = 0;
+      }
 
       abuf_t *abuf = 0;
 
       if (!conn->ab_synced) {
+       // if this is the first packet…
         debug(3, "syncing to seqno %u.", seqno);
         conn->ab_write = seqno;
         conn->ab_read = seqno;
@@ -519,21 +500,21 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp
         conn->resend_interval = resend_interval;
       }
 
-      if (conn->ab_write == seqno) { // expected packet
+      if (conn->ab_write == seqno) { // if this is the expected packet (which could be the first packet…)
         uint64_t reception_time = get_absolute_time_in_fp();
         if (conn->input_frame_rate_starting_point_is_valid == 0) {
           if ((conn->packet_count_since_flush >= 500) && (conn->packet_count_since_flush <= 510)) {
             conn->frames_inward_measurement_start_time = reception_time;
-            conn->frames_inward_frames_received_at_measurement_start_time = timestamp;
+            conn->frames_inward_frames_received_at_measurement_start_time = actual_timestamp;
             conn->input_frame_rate_starting_point_is_valid = 1; // valid now
           }
         }
 
         conn->frames_inward_measurement_time = reception_time;
-        conn->frames_inward_frames_received_at_measurement_time = timestamp;
+        conn->frames_inward_frames_received_at_measurement_time = actual_timestamp;
 
         abuf = conn->audio_buffer + BUFIDX(seqno);
-        conn->ab_write = SUCCESSOR(seqno);
+        conn->ab_write = SUCCESSOR(seqno); // move the write pointer to the next free space
       } else if (seq_order(conn->ab_write, seqno, conn->ab_read)) { // newer than expected
         // if (ORDINATE(seqno)>(BUFFER_FRAMES*7)/8)
         // debug(1,"An interval of %u frames has opened, with ab_read: %u, ab_write: %u and
@@ -547,7 +528,7 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp
           abuf = conn->audio_buffer + BUFIDX(seq_sum(conn->ab_write, i));
           abuf->ready = 0; // to be sure, to be sure
           abuf->resend_level = 0;
-          abuf->timestamp = 0;
+          // abuf->timestamp = 0;
           abuf->given_timestamp = 0;
           abuf->sequence_number = 0;
         }
@@ -580,14 +561,14 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp
         if (alac_decode(abuf->data, &datalen, data, len, conn) == 0) {
           abuf->ready = 1;
           abuf->length = datalen;
-          abuf->timestamp = ltimestamp;
+          // abuf->timestamp = ltimestamp;
           abuf->given_timestamp = actual_timestamp;
           abuf->sequence_number = seqno;
         } else {
           debug(1, "Bad audio packet detected and discarded.");
           abuf->ready = 0;
           abuf->resend_level = 0;
-          abuf->timestamp = 0;
+          // abuf->timestamp = 0;
           abuf->given_timestamp = 0;
           abuf->sequence_number = 0;
         }
@@ -621,12 +602,6 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp
                    j)) { // prevent multiple requests from the same level of lookback
                 check_buf->resend_level = j;
                 if (config.disable_resend_requests == 0) {
-                  if (((int)(resend_interval * pow(j + 1, step_exponent)) + k) >=
-                      seq_diff(conn->ab_read, conn->ab_write, conn->ab_read))
-                    debug(3, "Last-ditch (#%d) resend request for packet %u in range %u to %u. "
-                             "Looking back %d packets.",
-                          j, next, conn->ab_read, conn->ab_write, back_step + k);
-                  debug_mutex_unlock(&conn->ab_mutex, 3);
                   rtp_request_resend(next, 1, conn);
                   conn->resend_requests++;
                   debug_mutex_lock(&conn->ab_mutex, 20000, 1);
@@ -877,20 +852,23 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
               debug(1, "Inconsistent sequence numbers detected");
             }
           }
-
-          if ((conn->flush_rtp_timestamp != 0) &&
-              (curframe->timestamp <= conn->flush_rtp_timestamp)) {
-            debug(2, "Dropping flushed packet in buffer_get_frame seqno %u, timestamp %" PRId64 ".",
-                  curframe->sequence_number, curframe->timestamp);
+          
+                                       if ((conn->flush_rtp_timestamp != 0) && (rtp_frame_offset(curframe->given_timestamp,conn->flush_rtp_timestamp) < 8820)) {// if it's less than 0.2 seconds
+                                               debug(2, "Dropping flushed packet in buffer_get_frame, seqno %u, timestamp %" PRIu32
+                                                        ", flushing to "
+                                                        "timestamp: %" PRIu32 ".",
+                                               curframe->sequence_number, curframe->given_timestamp, conn->flush_rtp_timestamp);
             curframe->ready = 0;
             curframe->resend_level = 0;
-            flush_limit++;
+            flush_limit += curframe->length;
             conn->ab_read = SUCCESSOR(conn->ab_read);
             conn->initial_reference_time = 0;
             conn->initial_reference_timestamp = 0;
           }
-          if (curframe->timestamp > conn->flush_rtp_timestamp)
-            conn->flush_rtp_timestamp = 0;
+                                       if ((conn->flush_rtp_timestamp != 0) && (rtp_frame_offset(conn->flush_rtp_timestamp,curframe->given_timestamp) > 8820) && (rtp_frame_offset(conn->flush_rtp_timestamp,curframe->given_timestamp) < 44100)) {
+                                               debug(2,"Dropping flush request");
+                                               conn->flush_rtp_timestamp = 0;
+                                       }
         }
       } while ((conn->flush_rtp_timestamp != 0) && (flush_limit <= 8820) && (curframe->ready == 0));
 
@@ -921,7 +899,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
             if (have_timestamp_timing_information(conn)) { // if we have a reference time
               // debug(1,"First frame seen with timestamp...");
               conn->first_packet_timestamp =
-                  curframe->timestamp; // we will keep buffering until we are
+                  curframe->given_timestamp; // we will keep buffering until we are
                                        // supposed to start playing this
               have_sent_prefiller_silence = 0;
               conn->packet_stream_established = 1;
@@ -1174,7 +1152,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
     // Note: the last three items are expressed in frames and must be converted to time.
 
     int do_wait = 0; // don't wait unless we can really prove we must
-    if ((conn->ab_synced) && (curframe) && (curframe->ready) && (curframe->timestamp)) {
+    if ((conn->ab_synced) && (curframe) && (curframe->ready) && (curframe->given_timestamp)) {
       do_wait =
           1; // if the current frame exists and is ready, then wait unless it's time to let it go...
 
@@ -1184,7 +1162,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
 
         uint64_t time_to_play;
         frame_to_local_time(
-            curframe->timestamp + conn->latency * conn->output_sample_ratio +
+            (curframe->given_timestamp + conn->latency) * conn->output_sample_ratio +
                 (int64_t)(config.audio_backend_latency_offset * config.output_rate) -
                 config.audio_backend_buffer_desired_length * config.output_rate,
             &time_to_play, conn);
@@ -1242,7 +1220,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
   if (!curframe->ready) {
     // debug(1, "Supplying a silent frame for frame %u", read);
     conn->missing_packets++;
-    curframe->timestamp = 0; // indicate a silent frame should be substituted
+    curframe->given_timestamp = 0; // indicate a silent frame should be substituted
   }
   curframe->ready = 0;
   curframe->resend_level = 0;
@@ -1791,7 +1769,7 @@ void *player_thread_func(void *arg) {
         //        if (play_number % 100 == 0)
         //          debug(3, "Play frame %d.", play_number);
         conn->play_number_after_flush++;
-        if (inframe->timestamp == 0) {
+        if (inframe->given_timestamp == 0) {
           debug(3, "Player has supplied a silent frame, (possibly frame %u) for play number %d.",
                 SUCCESSOR(conn->last_seqno_read), play_number);
           conn->last_seqno_read = (SUCCESSOR(conn->last_seqno_read) &
@@ -1925,14 +1903,16 @@ void *player_thread_func(void *arg) {
           // now, go back as far as the total latency less, say, 100 ms, and check the presence of
           // frames from then onwards
 
-          int64_t reference_timestamp;
+          uint32_t reference_timestamp;
           uint64_t reference_timestamp_time, remote_reference_timestamp_time;
           get_reference_timestamp_stuff(&reference_timestamp, &reference_timestamp_time,
                                         &remote_reference_timestamp_time, conn); // types okay
           reference_timestamp *= conn->output_sample_ratio;
           int64_t rt, nt;
           rt = reference_timestamp; // uint32_t to int64_t
-          nt = inframe->timestamp;  // uint32_t to int64_t
+          nt = inframe->given_timestamp;  // uint32_t to int64_t
+          rt *= conn->output_sample_ratio;
+          nt *= conn->output_sample_ratio;
 
           uint64_t local_time_now = get_absolute_time_in_fp(); // types okay
           // struct timespec tn;
@@ -2056,7 +2036,7 @@ void *player_thread_func(void *arg) {
             if (abs_sync_error < 0)
               abs_sync_error = -abs_sync_error;
 
-            if ((config.no_sync == 0) && (inframe->timestamp != 0) &&
+            if ((config.no_sync == 0) && (inframe->given_timestamp != 0) &&
                 (config.resyncthreshold > 0.0) &&
                 (abs_sync_error > config.resyncthreshold * config.output_rate)) {
               if (abs_sync_error > 3 * config.output_rate) {
@@ -2282,7 +2262,7 @@ void *player_thread_func(void *arg) {
           }
 
           // mark the frame as finished
-          inframe->timestamp = 0;
+          inframe->given_timestamp = 0;
           inframe->sequence_number = 0;
 
           // debug(1,"Sync error %lld frames. Amount to stuff %d." ,sync_error,amount_to_stuff);
@@ -2726,7 +2706,7 @@ void player_volume(double airplay_volume, rtsp_conn_info *conn) {
   player_volume_without_notification(airplay_volume, conn);
 }
 
-void do_flush(int64_t timestamp, rtsp_conn_info *conn) {
+void do_flush(uint32_t timestamp, rtsp_conn_info *conn) {
 
   debug(3, "Flush requested up to %u. It seems as if 0 is special.", timestamp);
   debug_mutex_lock(&conn->flush_mutex, 1000, 1);
@@ -2755,7 +2735,7 @@ void do_flush(int64_t timestamp, rtsp_conn_info *conn) {
   debug(3, "Flush request made.");
 }
 
-void player_flush(int64_t timestamp, rtsp_conn_info *conn) {
+void player_flush(uint32_t timestamp, rtsp_conn_info *conn) {
   debug(3, "player_flush");
   do_flush(timestamp, conn);
 }
index fe7077b1a4d85aaf9c49f94f01131c96852d9d97..6c10d34d025edd708b7592bdd06a7717412d041d 100644 (file)
--- a/player.h
+++ b/player.h
@@ -40,7 +40,7 @@ typedef uint16_t seq_t;
 typedef struct audio_buffer_entry { // decoded audio packets
   int ready;
   int resend_level;
-  int64_t timestamp;
+  // int64_t timestamp;
   seq_t sequence_number;
   uint32_t given_timestamp; // for debugging and checking
   signed short *data;
@@ -71,10 +71,10 @@ typedef struct {
   int connection_number;   // for debug ID purposes, nothing else...
   int resend_interval;     // this is really just for debugging
   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
+  uint32_t latency;         // the actual latency used for this play session
+  uint32_t minimum_latency; // set if an a=min-latency: line appears in the ANNOUNCE message; zero
                            // otherwise
-  int64_t maximum_latency; // set if an a=max-latency: line appears in the ANNOUNCE message; zero
+  uint32_t maximum_latency; // set if an a=max-latency: line appears in the ANNOUNCE message; zero
                            // otherwise
 
   int fd;
@@ -103,10 +103,10 @@ typedef struct {
   int input_frame_rate_starting_point_is_valid;
 
   uint64_t frames_inward_measurement_start_time;
-  uint64_t frames_inward_frames_received_at_measurement_start_time;
+  uint32_t frames_inward_frames_received_at_measurement_start_time;
 
   uint64_t frames_inward_measurement_time;
-  uint64_t frames_inward_frames_received_at_measurement_time;
+  uint32_t frames_inward_frames_received_at_measurement_time;
 
   // other stuff...
   pthread_t *player_thread;
@@ -136,7 +136,7 @@ typedef struct {
   int ab_buffering, ab_synced;
   int64_t first_packet_timestamp;
   int flush_requested;
-  int64_t flush_rtp_timestamp;
+  uint32_t flush_rtp_timestamp;
   uint64_t time_of_last_audio_packet;
   seq_t ab_read, ab_write;
 
@@ -187,7 +187,7 @@ typedef struct {
 
   // this is what connects an rtp timestamp to the remote time
 
-  int64_t reference_timestamp;
+  uint32_t reference_timestamp;
   uint64_t remote_reference_timestamp_time;
 
   int packet_stream_established; // true if a stream of packets is flowing, made true by a first
@@ -195,7 +195,7 @@ typedef struct {
 
   // used as the initials values for calculating the rate at which the source thinks it's sending
   // frames
-  int64_t initial_reference_timestamp;
+  uint32_t initial_reference_timestamp;
   uint64_t initial_reference_time;
   double remote_frame_rate;
 
@@ -247,8 +247,8 @@ int player_stop(rtsp_conn_info *conn);
 
 void player_volume(double f, rtsp_conn_info *conn);
 void player_volume_without_notification(double f, rtsp_conn_info *conn);
-void player_flush(int64_t timestamp, rtsp_conn_info *conn);
-void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp, uint8_t *data,
+void player_flush(uint32_t timestamp, rtsp_conn_info *conn);
+void player_put_packet(seq_t seqno, uint32_t actual_timestamp, uint8_t *data,
                        int len, rtsp_conn_info *conn);
 int64_t monotonic_timestamp(uint32_t timestamp,
                             rtsp_conn_info *conn); // add an epoch to the timestamp. The monotonic
diff --git a/rtp.c b/rtp.c
index b8c8ee526d8a866f36a72ac86b5b26ba65cd7425..4cd96aba755ab56bac450cb581d1d7e53a274ee8 100644 (file)
--- a/rtp.c
+++ b/rtp.c
@@ -179,7 +179,6 @@ void *rtp_audio_receiver(void *arg) {
         }
 
         uint32_t actual_timestamp = ntohl(*(uint32_t *)(pktp + 4));
-        int64_t timestamp = monotonic_timestamp(actual_timestamp, conn);
 
         // if (packet[1]&0x10)
         //     debug(1,"Audio packet Extension bit set.");
@@ -191,7 +190,7 @@ void *rtp_audio_receiver(void *arg) {
         if (plen >= 16) {
           if ((config.diagnostic_drop_packet_fraction == 0.0) ||
               (drand48() > config.diagnostic_drop_packet_fraction))
-            player_put_packet(seqno, actual_timestamp, timestamp, pktp, plen, conn);
+            player_put_packet(seqno, actual_timestamp, pktp, plen, conn);
           else
             debug(3, "Dropping audio packet %u to simulate a bad connection.", seqno);
           continue;
@@ -238,7 +237,7 @@ void *rtp_control_receiver(void *arg) {
   uint8_t packet[2048], *pktp;
   // struct timespec tn;
   uint64_t remote_time_of_sync;
-  int64_t sync_rtp_timestamp;
+  uint32_t sync_rtp_timestamp;
   ssize_t nread;
   while (1) {
     nread = recv(conn->control_socket, packet, sizeof(packet), 0);
@@ -304,14 +303,14 @@ void *rtp_control_receiver(void *arg) {
 
             // debug(1,"Remote Sync Time: %0llx.",remote_time_of_sync);
 
-            sync_rtp_timestamp = monotonic_timestamp(nctohl(&packet[16]), conn);
-            int64_t rtp_timestamp_less_latency = monotonic_timestamp(nctohl(&packet[4]), conn);
+            sync_rtp_timestamp = nctohl(&packet[16]);
+            uint32_t rtp_timestamp_less_latency = nctohl(&packet[4]);
 
             // debug(1,"Sync timestamp is %u.",ntohl(*((uint32_t *)&packet[16])));
 
             if (config.userSuppliedLatency) {
               if (config.userSuppliedLatency != conn->latency) {
-                debug(1, "Using the user-supplied latency: %" PRId64 ".",
+                debug(1, "Using the user-supplied latency: %" PRIu32 ".",
                       config.userSuppliedLatency);
               }
               conn->latency = config.userSuppliedLatency;
@@ -330,8 +329,8 @@ void *rtp_control_receiver(void *arg) {
               // Sigh, it would be nice to have a published protocol...
 
               uint16_t flags = nctohs(&packet[2]);
-              int64_t la = sync_rtp_timestamp - rtp_timestamp_less_latency;
-              // debug(3, "Latency derived just from the sync packet is %" PRId64 " frames.", la);
+              uint32_t la = sync_rtp_timestamp - rtp_timestamp_less_latency; // note, this might loop around in modulo. Not sure if you'll get an error!
+              // debug(3, "Latency derived just from the sync packet is %" PRIu32 " frames.", la);
               
               if ((flags == 7) || ((conn->AirPlayVersion > 0) && (conn->AirPlayVersion <= 353)) || ((conn->AirPlayVersion > 0) && (conn->AirPlayVersion >= 371))) {
                 la += config.fixedLatencyOffset;
@@ -347,20 +346,20 @@ void *rtp_control_receiver(void *arg) {
               if ((conn->minimum_latency) && (conn->minimum_latency > la))
                 la = conn->minimum_latency;
 
-              const int max_frames = ((3 * BUFFER_FRAMES * 352) / 4) - 11025;
+              const uint32_t max_frames = ((3 * BUFFER_FRAMES * 352) / 4) - 11025;
 
-              if ((la < 0) || (la > max_frames)) {
-                warn("An out-of-range latency request of %" PRId64
-                     " frames was ignored. Must be %d frames or less (44,100 frames per second). "
-                     "Latency remains at %" PRId64 " frames.",
+              if (la > max_frames) {
+                warn("An out-of-range latency request of %" PRIu32
+                     " frames was ignored. Must be %" PRIu32 " frames or less (44,100 frames per second). "
+                     "Latency remains at %" PRIu32 " frames.",
                      la, max_frames, conn->latency);
               } else {
 
                 if (la != conn->latency) {
                   conn->latency = la;
-                  debug(3, "New latency detected: %" PRId64 ", sync latency: %" PRId64
-                           ", minimum latency: %" PRId64 ", maximum "
-                           "latency: %" PRId64 ", fixed offset: %" PRId64 ".",
+                  debug(3, "New latency detected: %" PRIu32 ", sync latency: %" PRIu32
+                           ", minimum latency: %" PRIu32 ", maximum "
+                           "latency: %" PRIu32 ", fixed offset: %" PRIu32 ".",
                         la, sync_rtp_timestamp - rtp_timestamp_less_latency, conn->minimum_latency,
                         conn->maximum_latency, config.fixedLatencyOffset);
                 }
@@ -380,7 +379,7 @@ void *rtp_control_receiver(void *arg) {
                 if (remote_frame_time_interval) {
                   conn->remote_frame_rate =
                       (1.0 * (conn->reference_timestamp - conn->initial_reference_timestamp)) /
-                      remote_frame_time_interval; // an IEEE double calculation with two 64-bit
+                      remote_frame_time_interval; // an IEEE double calculation with a 32-bit numerator and 64-bit denominator
                                                   // integers
                   conn->remote_frame_rate = conn->remote_frame_rate *
                                             (uint64_t)0x100000000; // this should just change the
@@ -395,7 +394,7 @@ void *rtp_control_receiver(void *arg) {
 
             // this is for debugging
             uint64_t old_remote_reference_time = conn->remote_reference_timestamp_time;
-            int64_t old_reference_timestamp = conn->reference_timestamp;
+            uint32_t old_reference_timestamp = conn->reference_timestamp;
             // int64_t old_latency_delayed_timestamp = conn->latency_delayed_timestamp;
 
             conn->remote_reference_timestamp_time = remote_time_of_sync;
@@ -444,14 +443,13 @@ void *rtp_control_receiver(void *arg) {
           debug(3, "Control Receiver -- Retransmitted Audio Data Packet %u received.", seqno);
 
           uint32_t actual_timestamp = ntohl(*(uint32_t *)(pktp + 4));
-          int64_t timestamp = monotonic_timestamp(actual_timestamp, conn);
 
           pktp += 12;
           plen -= 12;
 
           // check if packet contains enough content to be reasonable
           if (plen >= 16) {
-            player_put_packet(seqno, actual_timestamp, timestamp, pktp, plen, conn);
+            player_put_packet(seqno, actual_timestamp, pktp, plen, conn);
             continue;
           } else {
             debug(3, "Too-short retransmitted audio packet received in control port, ignored.");
@@ -1004,7 +1002,7 @@ void rtp_setup(SOCKADDR *local, SOCKADDR *remote, uint16_t cport, uint16_t tport
   }
 }
 
-void get_reference_timestamp_stuff(int64_t *timestamp, uint64_t *timestamp_time,
+void get_reference_timestamp_stuff(uint32_t *timestamp, uint64_t *timestamp_time,
                                    uint64_t *remote_timestamp_time, rtsp_conn_info *conn) {
   // types okay
   debug_mutex_lock(&conn->reference_time_mutex, 1000, 1);
diff --git a/rtp.h b/rtp.h
index 13bf2b3fdada84c9c1fb4fa7476ec7c9254e8558..9bf5c696545e0d0a207b779b487f101964c0b8e4 100644 (file)
--- a/rtp.h
+++ b/rtp.h
@@ -17,7 +17,7 @@ void rtp_setup(SOCKADDR *local, SOCKADDR *remote, uint16_t controlport, uint16_t
 void rtp_request_resend(seq_t first, uint32_t count, rtsp_conn_info *conn);
 void rtp_request_client_pause(rtsp_conn_info *conn); // ask the client to pause
 
-void get_reference_timestamp_stuff(int64_t *timestamp, uint64_t *timestamp_time,
+void get_reference_timestamp_stuff(uint32_t *timestamp, uint64_t *timestamp_time,
                                    uint64_t *remote_timestamp_time, rtsp_conn_info *conn);
 void clear_reference_timestamp(rtsp_conn_info *conn);