From: Mike Brady Date: Thu, 18 Oct 2018 16:44:50 +0000 (+0100) Subject: Try to fix modulo calculations X-Git-Tag: 3.3RC0~190^2~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de071aeffc16d0d94b5c70741d55dfd9ff54edfb;p=thirdparty%2Fshairport-sync.git Try to fix modulo calculations --- diff --git a/common.h b/common.h index c5d03aa3..0042d2c4 100644 --- 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; diff --git a/player.c b/player.c index 457cd702..235b03ab 100644 --- a/player.c +++ b/player.c @@ -99,60 +99,15 @@ // 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); } diff --git a/player.h b/player.h index fe7077b1..6c10d34d 100644 --- 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 b8c8ee52..4cd96aba 100644 --- 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 13bf2b3f..9bf5c696 100644 --- 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);