Enable 64-bit monotonic rtptime calculations

This commit is contained in:
Mike Brady
2016-09-02 16:53:52 +01:00
parent 1185a2aaa9
commit ef851a927b
5 changed files with 51 additions and 53 deletions
+6 -6
View File
@@ -107,11 +107,11 @@ typedef struct {
char *mdns_name;
mdns_backend *mdns;
int buffer_start_fill;
int32_t latency;
int32_t userSuppliedLatency; // overrides all other latencies -- use with caution
int32_t iTunesLatency; // supplied with --iTunesLatency option
int32_t AirPlayLatency; // supplied with --AirPlayLatency option
int32_t ForkedDaapdLatency; // supplied with --ForkedDaapdLatency option
int64_t latency;
int64_t userSuppliedLatency; // overrides all other latencies -- use with caution
int64_t iTunesLatency; // supplied with --iTunesLatency option
int64_t AirPlayLatency; // supplied with --AirPlayLatency option
int64_t ForkedDaapdLatency; // supplied with --ForkedDaapdLatency option
int daemonise;
int statistics_requested,use_negotiated_latencies;
enum playback_mode_type playback_mode;
@@ -176,7 +176,7 @@ config_t config_file_stuff;
int32_t buffer_occupancy; // allow it to be negative because seq_diff may be negative
int64_t session_corrections;
uint32_t play_segment_reference_frame;
int64_t play_segment_reference_frame;
uint64_t play_segment_reference_frame_remote_time;
void command_start(void);
+31 -33
View File
@@ -122,7 +122,7 @@ static pthread_mutex_t vol_mutex = PTHREAD_MUTEX_INITIALIZER;
typedef struct audio_buffer_entry { // decoded audio packets
int ready;
uint32_t timestamp;
int64_t timestamp;
seq_t sequence_number;
signed short *data;
int length; // the length of the decoded data
@@ -133,9 +133,9 @@ static abuf_t audio_buffer[BUFFER_FRAMES];
// mutex-protected variables
static seq_t ab_read, ab_write;
static int ab_buffering = 1, ab_synced = 0;
static uint32_t first_packet_timestamp = 0;
static int64_t first_packet_timestamp = 0;
static int flush_requested = 0;
static uint32_t flush_rtp_timestamp;
static int64_t flush_rtp_timestamp;
static uint64_t time_of_last_audio_packet;
static int shutdown_requested;
@@ -153,12 +153,13 @@ static uint64_t missing_packets, late_packets, too_late_packets, resend_requests
// 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^64 frames
// which is about 4*10^8 * 1,000 seconds at 384,000 frames per second -- about 4 trillion seconds or over 100,000 years.
// 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
uint64_t monotonic_timestamp(uint32_t timestamp) {
uint64_t previous_value;
uint64_t return_value;
int64_t monotonic_timestamp(uint32_t timestamp) {
int64_t previous_value;
int64_t return_value;
if (timestamp_epoch==0) {
if (timestamp>maximum_timestamp_interval)
timestamp_epoch=1;
@@ -194,6 +195,8 @@ uint64_t monotonic_timestamp(uint32_t timestamp) {
if ((return_value-previous_value)>maximum_timestamp_interval)
debug(1,"interval between successive rtptimes greater than allowed!");
}
if (return_value<0)
debug(1,"monotonic rtptime is negative!");
return return_value;
}
@@ -466,7 +469,7 @@ static void free_buffer(void) {
free(audio_buffer[i].data);
}
void player_put_packet(seq_t seqno, uint32_t timestamp, uint8_t *data, int len) {
void player_put_packet(seq_t seqno, int64_t timestamp, uint8_t *data, int len) {
// ignore a request to flush that has been made before the first packet...
if (packet_count==0) {
@@ -485,14 +488,13 @@ void player_put_packet(seq_t seqno, uint32_t timestamp, uint8_t *data, int len)
// debug(1,"Flush_rtp_timestamp is %u",flush_rtp_timestamp);
if ((flush_rtp_timestamp != 0) &&
((timestamp == flush_rtp_timestamp) || seq32_order(timestamp, flush_rtp_timestamp))) {
debug(3, "Dropping flushed packet in player_put_packet, seqno %u, timestamp %u, flushing to "
"timestamp: %u.",
(timestamp <= flush_rtp_timestamp)) {
debug(3, "Dropping flushed packet in player_put_packet, seqno %u, timestamp %lld, flushing to "
"timestamp: %lld.",
seqno, timestamp, flush_rtp_timestamp);
} else {
if ((flush_rtp_timestamp != 0x0) &&
(!seq32_order(timestamp,
flush_rtp_timestamp))) // if we have gone past the flush boundary time
(timestamp>flush_rtp_timestamp)) // if we have gone past the flush boundary time
flush_rtp_timestamp = 0x0;
abuf_t *abuf = 0;
@@ -699,17 +701,14 @@ static abuf_t *buffer_get_frame(void) {
}
if ((flush_rtp_timestamp != 0) &&
((curframe->timestamp == flush_rtp_timestamp) ||
seq32_order(curframe->timestamp, flush_rtp_timestamp))) {
debug(1, "Dropping flushed packet seqno %u, timestamp %u", curframe->sequence_number,
(curframe->timestamp <= flush_rtp_timestamp)) {
debug(1, "Dropping flushed packet seqno %u, timestamp %lld", curframe->sequence_number,
curframe->timestamp);
curframe->ready = 0;
flush_limit++;
ab_read = SUCCESSOR(ab_read);
}
if ((flush_rtp_timestamp != 0) &&
(!seq32_order(curframe->timestamp,
flush_rtp_timestamp))) // if we have gone past the flush boundary time
if (curframe->timestamp>flush_rtp_timestamp)
flush_rtp_timestamp = 0;
}
} while ((flush_rtp_timestamp != 0) && (flush_limit <= 8820) && (curframe->ready == 0));
@@ -725,7 +724,7 @@ static abuf_t *buffer_get_frame(void) {
notified_buffer_empty=0; // at least one buffer now -- diagnostic only.
if (ab_buffering) { // if we are getting packets but not yet forwarding them to the player
int have_sent_prefiller_silence; // set true when we have sent some silent frames to the DAC
uint32_t reference_timestamp;
int64_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);
if (first_packet_timestamp == 0) { // if this is the very first packet
@@ -760,14 +759,14 @@ static abuf_t *buffer_get_frame(void) {
// if would be in sync. To do this, we would give it a latency offset of -100 ms, i.e.
// -4410 frames.
int64_t delta = ((int64_t)first_packet_timestamp - (int64_t)reference_timestamp)+config.latency+config.audio_backend_latency_offset; // uint32_t to int64_t is okay and int32t to int64t promotion is okay.
int64_t delta = (first_packet_timestamp - reference_timestamp)+config.latency+config.audio_backend_latency_offset;
if (delta>=0) {
uint64_t delta_fp_sec = (delta << 32) / 44100; // int64_t which is positive
int64_t delta_fp_sec = (delta << 32) / 44100; // int64_t which is positive
first_packet_time_to_play=reference_timestamp_time+delta_fp_sec;
} else {
int64_t abs_delta = -delta;
uint64_t delta_fp_sec = (abs_delta << 32) / 44100; // int64_t which is positive
int64_t delta_fp_sec = (abs_delta << 32) / 44100; // int64_t which is positive
first_packet_time_to_play=reference_timestamp_time-delta_fp_sec;
}
@@ -782,14 +781,14 @@ static abuf_t *buffer_get_frame(void) {
if (first_packet_time_to_play != 0) {
// recalculate first_packet_time_to_play -- the latency might change
int64_t delta = ((int64_t)first_packet_timestamp - (int64_t)reference_timestamp)+config.latency+config.audio_backend_latency_offset; // uint32_t to int64_t is okay and int32t to int64t promotion is okay.
int64_t delta = (first_packet_timestamp - reference_timestamp)+config.latency+config.audio_backend_latency_offset;
if (delta>=0) {
uint64_t delta_fp_sec = (delta << 32) / 44100; // int64_t which is positive
int64_t delta_fp_sec = (delta << 32) / 44100; // int64_t which is positive
first_packet_time_to_play=reference_timestamp_time+delta_fp_sec;
} else {
int64_t abs_delta = -delta;
uint64_t delta_fp_sec = (abs_delta << 32) / 44100; // int64_t which is positive
int64_t delta_fp_sec = (abs_delta << 32) / 44100; // int64_t which is positive
first_packet_time_to_play=reference_timestamp_time-delta_fp_sec;
}
@@ -896,12 +895,12 @@ static abuf_t *buffer_get_frame(void) {
int do_wait = 0; // don't wait unless we can really prove we must
if ((ab_synced) && (curframe) && (curframe->ready) && (curframe->timestamp)) {
do_wait = 1; // if the current frame exists and is ready, then wait unless it's time to let it go...
uint32_t reference_timestamp;
int64_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); // all types okay
if (reference_timestamp) { // if we have a reference time
uint32_t packet_timestamp = curframe->timestamp; // types okay
int64_t delta = (int64_t)packet_timestamp - (int64_t)reference_timestamp; // uint32_t to int64_t is okay.
int64_t packet_timestamp = curframe->timestamp; // types okay
int64_t delta = packet_timestamp - reference_timestamp;
int64_t offset = config.latency + config.audio_backend_latency_offset -
config.audio_backend_buffer_desired_length; // all arguments are int32_t, so expression promotion okay
int64_t net_offset = delta + offset; // okay
@@ -954,7 +953,6 @@ static abuf_t *buffer_get_frame(void) {
#endif
#ifdef COMPILE_FOR_OSX
uint64_t sec = time_to_wait_for_wakeup_fp >> 32;
;
uint64_t nsec = ((time_to_wait_for_wakeup_fp & 0xffffffff) * 1000000000) >> 32;
struct timespec time_to_wait;
time_to_wait.tv_sec = sec;
@@ -1288,7 +1286,7 @@ static void *player_thread_func(void *arg) {
at_least_one_frame_seen = 1;
uint32_t reference_timestamp;
int64_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); // types okay
@@ -1840,7 +1838,7 @@ void player_volume(double airplay_volume) {
#endif
}
void player_flush(uint32_t timestamp) {
void player_flush(int64_t timestamp) {
debug(3,"Flush requested up to %u. It seems as if 0 is special.",timestamp);
pthread_mutex_lock(&flush_mutex);
flush_requested = 1;
+4 -4
View File
@@ -18,12 +18,12 @@ int player_play(stream_cfg *cfg, pthread_t *thread);
void player_stop(pthread_t *thread);
void player_volume(double f);
void player_flush(uint32_t timestamp);
void player_flush(int64_t timestamp);
void player_put_packet(seq_t seqno, uint32_t timestamp, uint8_t *data, int len);
void player_put_packet(seq_t seqno, int64_t timestamp, uint8_t *data, int len);
uint64_t monotonic_timestamp(uint32_t timestamp); // add an epoch to the timestamp. The monotonic timestamp guaranteed to start between 2^32 2^33 frames and continue up to 2^64 frames
// which is about 4*10^8 * 1,000 seconds at 384,000 frames per second -- about 4 trillion seconds.
int64_t monotonic_timestamp(uint32_t timestamp); // add an epoch to the timestamp. The monotonic timestamp guaranteed to start between 2^32 2^33 frames and continue up to 2^64 frames
// which is about 2*10^8 * 1,000 seconds at 384,000 frames per second -- about 2 trillion seconds.
// assumes, without checking, that successive timestamps in a series always span an interval of less than one minute.
uint64_t monotonic_seqno(uint16_t seq_no); // add an epoch to the seq_no. Uses the accompanying timstamp to detemine the correct epoch
+9 -9
View File
@@ -71,7 +71,7 @@ static int control_socket; // our local [server] control socket
static int timing_socket; // local timing socket
//static pthread_t rtp_audio_thread, rtp_control_thread, rtp_timing_thread;
static uint32_t reference_timestamp;
static int64_t reference_timestamp;
static uint64_t reference_timestamp_time;
static uint64_t remote_reference_timestamp_time;
@@ -159,7 +159,7 @@ void *rtp_audio_receiver(void *arg) {
// debug(3, "RTP: Packets out of sequence: expected: %d, got %d.", last_seqno, seqno);
last_seqno = seqno; // reset warning...
}
uint32_t timestamp = ntohl(*(unsigned long *)(pktp + 4));
int64_t timestamp = monotonic_timestamp(ntohl(*(unsigned long *)(pktp + 4)));
// if (packet[1]&0x10)
// debug(1,"Audio packet Extension bit set.");
@@ -198,7 +198,7 @@ void *rtp_control_receiver(void *arg) {
uint8_t packet[2048], *pktp;
struct timespec tn;
uint64_t remote_time_of_sync, local_time_now, remote_time_now;
uint32_t sync_rtp_timestamp, rtp_timestamp_less_latency;
int64_t sync_rtp_timestamp, rtp_timestamp_less_latency;
ssize_t nread;
while (itr->please_stop==0) {
nread = recv(control_socket, packet, sizeof(packet), 0);
@@ -229,11 +229,11 @@ void *rtp_control_receiver(void *arg) {
// debug(1,"Remote Sync Time: %0llx.",remote_time_of_sync);
rtp_timestamp_less_latency = ntohl(*((uint32_t *)&packet[4]));
sync_rtp_timestamp = ntohl(*((uint32_t *)&packet[16]));
rtp_timestamp_less_latency = monotonic_timestamp(ntohl(*((uint32_t *)&packet[4])));
sync_rtp_timestamp = monotonic_timestamp(ntohl(*((uint32_t *)&packet[16])));
if (config.use_negotiated_latencies) {
uint32_t la = sync_rtp_timestamp-rtp_timestamp_less_latency+11025;
int64_t la = sync_rtp_timestamp-rtp_timestamp_less_latency+11025;
if (la!=config.latency) {
config.latency = la;
// debug(1,"Using negotiated latency of %u frames.",config.latency);
@@ -269,7 +269,7 @@ void *rtp_control_receiver(void *arg) {
plen -= 4;
seq_t seqno = ntohs(*(unsigned short *)(pktp + 2));
uint32_t timestamp = ntohl(*(unsigned long *)(pktp + 4));
int64_t timestamp = monotonic_timestamp(ntohl(*(unsigned long *)(pktp + 4)));
pktp += 12;
plen -= 12;
@@ -494,7 +494,7 @@ void *rtp_timing_receiver(void *arg) {
int64_t source_drift_usec;
if (play_segment_reference_frame!=0) {
uint32_t reference_timestamp;
int64_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);
uint64_t frame_difference = 0;
@@ -708,7 +708,7 @@ void rtp_setup(SOCKADDR *local, SOCKADDR *remote, int cport, int tport, uint32_t
request_sent = 0;
}
void get_reference_timestamp_stuff(uint32_t *timestamp, uint64_t *timestamp_time, uint64_t *remote_timestamp_time) {
void get_reference_timestamp_stuff(int64_t *timestamp, uint64_t *timestamp_time, uint64_t *remote_timestamp_time) {
// types okay
pthread_mutex_lock(&reference_time_mutex);
*timestamp = reference_timestamp;
+1 -1
View File
@@ -19,7 +19,7 @@ void rtp_shutdown(void);
void rtp_request_resend(seq_t first, uint32_t count);
void rtp_request_client_pause(void); // ask the client to pause
void get_reference_timestamp_stuff(uint32_t *timestamp, uint64_t *timestamp_time, uint64_t *remote_timestamp_time);
void get_reference_timestamp_stuff(int64_t *timestamp, uint64_t *timestamp_time, uint64_t *remote_timestamp_time);
void clear_reference_timestamp(void);
uint64_t static local_to_remote_time_jitters;