// 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 ".",
+ 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;
+ 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
if (conn->ab_write == seqno) { // expected 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)) {
+ 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->input_frame_rate_starting_point_is_valid = 1; // valid now
- debug(1,"input_frame_rate_starting_point_is_valid set");
+ debug(1, "input_frame_rate_starting_point_is_valid 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
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);
+ debug(2, "Dropping flushed packet in buffer_get_frame seqno %u, timestamp %" PRId64 ".",
+ curframe->sequence_number, curframe->timestamp);
curframe->ready = 0;
curframe->resend_level = 0;
flush_limit++;
// supposed to start playing this
have_sent_prefiller_silence = 0;
conn->packet_stream_established = 1;
-
+
// debug(1, "First packet timestamp is %" PRId64 ".", conn->first_packet_timestamp);
// say we have started playing here
// -4410 frames.
// debug(1, "Output sample ratio is %d", conn->output_sample_ratio);
-
-
- // what we are asking for here is "what is the local time at which time the calculated frame should be played"
+
+ // what we are asking for here is "what is the local time at which time the calculated
+ // frame should be played"
int64_t delta = (conn->first_packet_timestamp - reference_timestamp) +
conn->latency * conn->output_sample_ratio +
int64_t abs_delta = -delta;
int64_t delta_fp_sec =
(abs_delta << 32) / config.output_rate; // int64_t which is positive
- conn->first_packet_time_to_play = reference_timestamp_time - delta_fp_sec;
+ conn->first_packet_time_to_play = reference_timestamp_time - delta_fp_sec;
}
uint64_t should_be_time;
- frame_to_local_time(conn->first_packet_timestamp +conn->latency * conn->output_sample_ratio + (int64_t)(config.audio_backend_latency_offset * config.output_rate),&should_be_time,conn);
-
- if(should_be_time>=conn->first_packet_time_to_play) {
- if ((((should_be_time-conn->first_packet_time_to_play)*1000000)>>32)>10)
- debug(2,"New time for first packet timestamp %" PRId64 " is later than calculated time by %" PRId64 " microseconds.",curframe->timestamp,((should_be_time-conn->first_packet_time_to_play)*1000000)>>32);
+ frame_to_local_time(
+ conn->first_packet_timestamp + conn->latency * conn->output_sample_ratio +
+ (int64_t)(config.audio_backend_latency_offset * config.output_rate),
+ &should_be_time, conn);
+
+ if (should_be_time >= conn->first_packet_time_to_play) {
+ if ((((should_be_time - conn->first_packet_time_to_play) * 1000000) >> 32) > 10)
+ debug(2, "New time for first packet timestamp %" PRId64
+ " is later than calculated time by %" PRId64 " microseconds.",
+ curframe->timestamp,
+ ((should_be_time - conn->first_packet_time_to_play) * 1000000) >> 32);
} else {
- if ((((conn->first_packet_time_to_play-should_be_time)*1000000)>>32)>10)
- debug(2,"New time for first packet timestamp %" PRId64 " is earlier than calculated time by %" PRId64 " microseconds.",curframe->timestamp,((conn->first_packet_time_to_play-should_be_time)*1000000)>>32);
- }
-
+ if ((((conn->first_packet_time_to_play - should_be_time) * 1000000) >> 32) > 10)
+ debug(2, "New time for first packet timestamp %" PRId64
+ " is earlier than calculated time by %" PRId64 " microseconds.",
+ curframe->timestamp,
+ ((conn->first_packet_time_to_play - should_be_time) * 1000000) >> 32);
+ }
+
// cut over to new calculation scheme
- conn->first_packet_time_to_play = should_be_time;
+ conn->first_packet_time_to_play = should_be_time;
if (local_time_now >= conn->first_packet_time_to_play) {
debug(
(abs_delta << 32) / config.output_rate; // int64_t which is positive
conn->first_packet_time_to_play = reference_timestamp_time - delta_fp_sec;
}
-
+
uint64_t should_be_time;
- frame_to_local_time(conn->first_packet_timestamp +conn->latency * conn->output_sample_ratio + (int64_t)(config.audio_backend_latency_offset * config.output_rate),&should_be_time,conn);
-
- if(should_be_time>=conn->first_packet_time_to_play) {
- if ((((should_be_time-conn->first_packet_time_to_play)*1000000)>>32)>50)
- debug(2,"New time for recalculated first packet timestamp %" PRId64 " is later than calculated time by %" PRId64 " microseconds.",curframe->timestamp,((should_be_time-conn->first_packet_time_to_play)*1000000)>>32);
+ frame_to_local_time(
+ conn->first_packet_timestamp + conn->latency * conn->output_sample_ratio +
+ (int64_t)(config.audio_backend_latency_offset * config.output_rate),
+ &should_be_time, conn);
+
+ if (should_be_time >= conn->first_packet_time_to_play) {
+ if ((((should_be_time - conn->first_packet_time_to_play) * 1000000) >> 32) > 50)
+ debug(2, "New time for recalculated first packet timestamp %" PRId64
+ " is later than calculated time by %" PRId64 " microseconds.",
+ curframe->timestamp,
+ ((should_be_time - conn->first_packet_time_to_play) * 1000000) >> 32);
} else {
- if ((((conn->first_packet_time_to_play-should_be_time)*1000000)>>32)>50)
- debug(2,"New time for recalculated first packet timestamp %" PRId64 " is earlier than calculated time by %" PRId64 " microseconds.",curframe->timestamp,((conn->first_packet_time_to_play-should_be_time)*1000000)>>32);
- }
-
-
+ if ((((conn->first_packet_time_to_play - should_be_time) * 1000000) >> 32) > 50)
+ debug(2, "New time for recalculated first packet timestamp %" PRId64
+ " is earlier than calculated time by %" PRId64 " microseconds.",
+ curframe->timestamp,
+ ((conn->first_packet_time_to_play - should_be_time) * 1000000) >> 32);
+ }
// now, the size of the initial silence must be affected by the lead-in time.
// it must be somewhat less than the lead-in time so that dynamic adjustments can be
}
}
if (conn->ab_buffering == 0) {
- /*
- // note the time of the playing of the first frame
- uint64_t reference_timestamp_time; // don't need this...
- get_reference_timestamp_stuff(&conn->play_segment_reference_frame,
- &reference_timestamp_time,
- &conn->play_segment_reference_frame_remote_time, conn);
- conn->play_segment_reference_frame *= conn->output_sample_ratio;
- */
+/*
+ // note the time of the playing of the first frame
+ uint64_t reference_timestamp_time; // don't need this...
+ get_reference_timestamp_stuff(&conn->play_segment_reference_frame,
+ &reference_timestamp_time,
+ &conn->play_segment_reference_frame_remote_time, conn);
+ conn->play_segment_reference_frame *= conn->output_sample_ratio;
+*/
#ifdef CONFIG_METADATA
debug(2, "prsm");
send_ssnc_metadata('prsm', NULL, 0,
if ((conn->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...
-
+
// here, get the time to play the current frame.
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, conn); // all types okay
reference_timestamp *= conn->output_sample_ratio;
- if (have_timestamp_timing_information(conn)) { // if we have a reference time
+ if (have_timestamp_timing_information(conn)) { // if we have a reference time
int64_t packet_timestamp = curframe->timestamp; // types okay
int64_t delta = packet_timestamp - reference_timestamp;
int64_t offset =
(int64_t)(config.audio_backend_latency_offset * config.output_rate) -
config.audio_backend_buffer_desired_length *
config.output_rate; // all arguments are int32_t, so expression promotion okay
- int64_t net_offset = delta + offset; // okay
-
+ int64_t net_offset = delta + offset; // okay
+
uint64_t time_to_play = reference_timestamp_time; // type okay
if (net_offset >= 0) {
uint64_t net_offset_fp_sec =
time_to_play -= net_offset_fp_sec;
// debug(2,"Net Offset: %lld, adjusted: -%lld.",net_offset,net_offset_fp_sec);
}
-
+
uint64_t new_time_to_play = 0;
- frame_to_local_time(packet_timestamp+offset, &new_time_to_play, conn);
-
- if(new_time_to_play>=time_to_play) {
- if ((((new_time_to_play-time_to_play)*1000000)>>32)>100)
- debug(2,"New time for frame %" PRId64 " is later than calculated time by %" PRId64 " microseconds.",curframe->timestamp,((new_time_to_play-time_to_play)*1000000)>>32);
+ frame_to_local_time(packet_timestamp + offset, &new_time_to_play, conn);
+
+ if (new_time_to_play >= time_to_play) {
+ if ((((new_time_to_play - time_to_play) * 1000000) >> 32) > 100)
+ debug(2, "New time for frame %" PRId64 " is later than calculated time by %" PRId64
+ " microseconds.",
+ curframe->timestamp, ((new_time_to_play - time_to_play) * 1000000) >> 32);
} else {
- if ((((time_to_play-new_time_to_play)*1000000)>>32)>100)
- debug(2,"New time for frame %" PRId64 " is earlier than calculated time by %" PRId64 " microseconds.",curframe->timestamp,((time_to_play-new_time_to_play)*1000000)>>32);
- }
+ if ((((time_to_play - new_time_to_play) * 1000000) >> 32) > 100)
+ debug(2, "New time for frame %" PRId64 " is earlier than calculated time by %" PRId64
+ " microseconds.",
+ curframe->timestamp, ((time_to_play - new_time_to_play) * 1000000) >> 32);
+ }
// cut over to the new calculation system
- time_to_play = new_time_to_play;
-
+ time_to_play = new_time_to_play;
+
if (local_time_now >= time_to_play) {
do_wait = 0;
}
int elapsedMin = (rawSeconds / 60) % 60;
int elapsedSec = rawSeconds % 60;
if (conn->frame_rate_status)
- inform("Playback Stopped. Total playing time %02d:%02d:%02d. Input: %0.2f, output: %0.2f frames per second.",
+ 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. Input: %0.2f frames per second.", elapsedHours, elapsedMin,
- elapsedSec, conn->input_frame_rate);
+ 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
// uint64_t
// local_time_now=((uint64_t)tn.tv_sec<<32)+((uint64_t)tn.tv_nsec<<32)/1000000000;
- int64_t td = 0; // td is the time difference between the reference timestamp time and the present time. Only used to calculate td_in_frames
- int64_t td_in_frames = 0; // td_in_frames is the number of frames between between the reference timestamp time and the present time
-
+ int64_t td = 0; // td is the time difference between the reference timestamp time and the
+ // present time. Only used to calculate td_in_frames
+ int64_t td_in_frames = 0; // td_in_frames is the number of frames between between the
+ // reference timestamp time and the present time
+
if (local_time_now >= reference_timestamp_time) {
td = local_time_now - reference_timestamp_time; // this is the positive value.
// Conversion is positive uint64_t to
if (resp >= 0) {
- int64_t should_be_frame;
- local_time_to_frame(local_time_now,&should_be_frame,conn);
-
- if (abs(td_in_frames + rt-should_be_frame)>10*conn->output_sample_ratio)
- debug(1,"Difference between old and new frame number is %" PRId64 " frames.",td_in_frames + rt - should_be_frame);
+ int64_t should_be_frame;
+ local_time_to_frame(local_time_now, &should_be_frame, conn);
+
+ if (abs(td_in_frames + rt - should_be_frame) > 10 * conn->output_sample_ratio)
+ debug(1, "Difference between old and new frame number is %" PRId64 " frames.",
+ td_in_frames + rt - should_be_frame);
// this is the actual delay, including the latency we actually want, which will
// fluctuate a good bit about a potentially rising or falling trend.
-// int64_t delay = td_in_frames + rt - (nt - current_delay); // all int64_t
+ // int64_t delay = td_in_frames + rt - (nt - current_delay); // all int64_t
// cut over to the new calculation method
int64_t delay = should_be_frame - (nt - current_delay); // all int64_t
-
+
// td_in_frames + rt is the frame number that should be output at local_time_now.
-
// This is the timing error for the next audio frame in the DAC.
}
}
if (play_number % print_interval == 0) {
-
- // here, calculate the input and output frame rates, where possible, even if statistics have not been requested
+
+ // here, calculate the input and output frame rates, where possible, even if statistics
+ // have not been requested
// this is to calculate them in case they are needed by the D-Bus interface or elsewhere.
-
+
if (conn->input_frame_rate_starting_point_is_valid) {
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) / elapsed_reception_time; // an IEEE double calculation with two 64-bit integers
- conn->input_frame_rate = conn->input_frame_rate * (uint64_t)0x100000000; // this should just change the [binary] exponent in the IEEE FP representation; the mantissa should be unaffected.
+ 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) /
+ elapsed_reception_time; // an IEEE double calculation with two 64-bit integers
+ conn->input_frame_rate =
+ conn->input_frame_rate * (uint64_t)0x100000000; // this should just change the
+ // [binary] exponent in the IEEE FP
+ // representation; the mantissa
+ // should be unaffected.
} else {
conn->input_frame_rate = 0.0;
- }
-
+ }
+
if ((config.output->delay) && (config.no_sync == 0) && (config.output->rate_info)) {
uint64_t elapsed_play_time, frames_played;
- if (config.output->rate_info(&elapsed_play_time, &frames_played)==0)
+ if (config.output->rate_info(&elapsed_play_time, &frames_played) == 0)
conn->frame_rate_status = 1;
else
- conn->frame_rate_status = 0;
- if (conn->frame_rate_status) {
- conn->frame_rate =
- (1.0 * frames_played) / elapsed_play_time; // an IEEE double calculation with two 64-bit integers
+ conn->frame_rate_status = 0;
+ if (conn->frame_rate_status) {
conn->frame_rate =
- conn->frame_rate * (uint64_t)0x100000000; // this should just change the [binary] exponent in the IEEE FP representation; the mantissa should be unaffected.
+ (1.0 * frames_played) /
+ elapsed_play_time; // an IEEE double calculation with two 64-bit integers
+ conn->frame_rate = conn->frame_rate *
+ (uint64_t)0x100000000; // this should just change the [binary]
+ // exponent in the IEEE FP representation;
+ // the mantissa should be unaffected.
} else {
conn->frame_rate = 0.0;
}
- }
-
+ }
// we can now calculate running averages for sync error (frames), corrections (ppm),
// insertions plus deletions (ppm), drift (ppm)
// if ((play_number/print_interval)%20==0)
if (config.statistics_requested) {
if (at_least_one_frame_seen) {
-
+
if ((config.output->delay)) {
if (config.no_sync == 0) {
inform("%*.2f," /* Sync error in milliseconds */
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,
- 11, conn->remote_frame_rate,
- 11, conn->input_frame_rate,
- 11, conn->frame_rate ,
- 10, (1.0-conn->local_to_remote_time_gradient)*1000000,
- 6, conn->local_to_remote_time_gradient_sample_count);
+ maximum_buffer_occupancy, 11, conn->remote_frame_rate, 11,
+ conn->input_frame_rate, 11, conn->frame_rate, 10,
+ (1.0 - conn->local_to_remote_time_gradient) * 1000000, 6,
+ conn->local_to_remote_time_gradient_sample_count);
} else {
inform("%*.2f," /* Sync error in milliseconds */
"%*d," /* total packets */
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, 11, conn->input_frame_rate);
+ minimum_buffer_occupancy, 5, maximum_buffer_occupancy, 11,
+ conn->input_frame_rate);
}
} else {
inform("%*.2f," /* Sync error in milliseconds */
conn->input_frame_rate_starting_point_is_valid = 0;
conn->initial_reference_time = 0;
conn->initial_reference_timestamp = 0;
-
+
debug_mutex_unlock(&conn->flush_mutex, 3);
#ifdef CONFIG_METADATA
// so, if we have a non-zero clock drift, we will calculate the drift there would
// be from the time of the last time ping
uint64_t local_time_now_fp = get_absolute_time_in_fp();
- uint64_t time_since_last_local_to_remote_time_difference_measurement = local_time_now_fp - conn->local_to_remote_time_difference_measurement_time;
-
- uint64_t remote_time_since_last_local_to_remote_time_difference_measurement = (uint64_t)(conn->local_to_remote_time_gradient*time_since_last_local_to_remote_time_difference_measurement);
-
+ uint64_t time_since_last_local_to_remote_time_difference_measurement =
+ local_time_now_fp - conn->local_to_remote_time_difference_measurement_time;
+
+ uint64_t remote_time_since_last_local_to_remote_time_difference_measurement =
+ (uint64_t)(conn->local_to_remote_time_gradient *
+ time_since_last_local_to_remote_time_difference_measurement);
+
double drift;
- if (remote_time_since_last_local_to_remote_time_difference_measurement >= time_since_last_local_to_remote_time_difference_measurement)
- drift = (1.0*(remote_time_since_last_local_to_remote_time_difference_measurement - time_since_last_local_to_remote_time_difference_measurement))/(uint64_t)0x100000000;
+ if (remote_time_since_last_local_to_remote_time_difference_measurement >=
+ time_since_last_local_to_remote_time_difference_measurement)
+ drift = (1.0 * (remote_time_since_last_local_to_remote_time_difference_measurement -
+ time_since_last_local_to_remote_time_difference_measurement)) /
+ (uint64_t)0x100000000;
else
- drift = -((1.0*(time_since_last_local_to_remote_time_difference_measurement - remote_time_since_last_local_to_remote_time_difference_measurement))/(uint64_t)0x100000000);
-
-// double interval_ms = 1.0*(((time_since_last_local_to_remote_time_difference_measurement)*1000)>>32);
-// debug(1,"Measurement drift is %.2f microseconds (0x%" PRIx64 " in 64-bit fp) over %.2f milliseconds with drift of %.2f ppm.",drift*1000000,(uint64_t)(drift*(uint64_t)0x100000000),interval_ms,(1.0-conn->local_to_remote_time_gradient)*1000000);
-// return conn->local_to_remote_time_difference + (uint64_t)(drift*(uint64_t 0x100000000));
- return conn->local_to_remote_time_difference + (uint64_t)(drift*(uint64_t)0x100000000);
+ drift = -((1.0 * (time_since_last_local_to_remote_time_difference_measurement -
+ remote_time_since_last_local_to_remote_time_difference_measurement)) /
+ (uint64_t)0x100000000);
+
+ // double interval_ms =
+ // 1.0*(((time_since_last_local_to_remote_time_difference_measurement)*1000)>>32);
+ // debug(1,"Measurement drift is %.2f microseconds (0x%" PRIx64 " in 64-bit fp) over %.2f
+ // milliseconds with drift of %.2f
+ // ppm.",drift*1000000,(uint64_t)(drift*(uint64_t)0x100000000),interval_ms,(1.0-conn->local_to_remote_time_gradient)*1000000);
+ // return conn->local_to_remote_time_difference + (uint64_t)(drift*(uint64_t 0x100000000));
+ return conn->local_to_remote_time_difference + (uint64_t)(drift * (uint64_t)0x100000000);
}
void rtp_audio_receiver_cleanup_handler(void *arg) {
}
debug_mutex_lock(&conn->reference_time_mutex, 1000, 1);
-
+
if (conn->packet_stream_established) {
- if (conn->initial_reference_time==0) {
+ if (conn->initial_reference_time == 0) {
conn->initial_reference_time = remote_time_of_sync;
conn->initial_reference_timestamp = sync_rtp_timestamp;
} else {
- uint64_t remote_frame_time_interval = conn->remote_reference_timestamp_time - conn->initial_reference_time; // here, this should never be zero
+ uint64_t remote_frame_time_interval =
+ conn->remote_reference_timestamp_time -
+ conn->initial_reference_time; // here, this should never be zero
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 integers
- conn->remote_frame_rate = conn->remote_frame_rate * (uint64_t)0x100000000; // this should just change the [binary] exponent in the IEEE FP representation; the mantissa should be unaffected.
+ 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
+ // integers
+ conn->remote_frame_rate = conn->remote_frame_rate *
+ (uint64_t)0x100000000; // this should just change the
+ // [binary] exponent in the IEEE
+ // FP representation; the
+ // mantissa should be unaffected.
} else {
conn->remote_frame_rate = 0.0; // use as a flag.
- }
+ }
}
}
uint64_t old_remote_reference_time = conn->remote_reference_timestamp_time;
int64_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;
- //conn->reference_timestamp_time =
+ // conn->reference_timestamp_time =
// remote_time_of_sync - local_to_remote_time_difference_now(conn);
conn->reference_timestamp = sync_rtp_timestamp;
conn->latency_delayed_timestamp = rtp_timestamp_less_latency;
debug_mutex_unlock(&conn->reference_time_mutex, 3);
-
- conn->reference_to_previous_time_difference = remote_time_of_sync - old_remote_reference_time;
- if (old_reference_timestamp==0)
+
+ conn->reference_to_previous_time_difference =
+ remote_time_of_sync - old_remote_reference_time;
+ if (old_reference_timestamp == 0)
conn->reference_to_previous_frame_difference = 0;
else
- conn->reference_to_previous_frame_difference = sync_rtp_timestamp - old_reference_timestamp;
+ conn->reference_to_previous_frame_difference =
+ sync_rtp_timestamp - old_reference_timestamp;
+
+ // int64_t delayed_frame_difference = rtp_timestamp_less_latency -
+ // old_latency_delayed_timestamp;
- // int64_t delayed_frame_difference = rtp_timestamp_less_latency - old_latency_delayed_timestamp;
-
/*
if (old_remote_reference_time)
- debug(1,"Time difference: %" PRIu64 " reference and delayed frame differences: %" PRId64 " and %" PRId64 ", giving rates _at source!!_ of %f and %f respectively.",
+ debug(1,"Time difference: %" PRIu64 " reference and delayed frame differences: %"
+ PRId64 " and %" PRId64 ", giving rates _at source!!_ of %f and %f respectively.",
(conn->reference_to_previous_time_difference*1000000)>>32,conn->reference_to_previous_frame_difference,delayed_frame_difference,
(1.0*(conn->reference_to_previous_frame_difference*10000000))/((conn->reference_to_previous_time_difference*10000000)>>32),(1.0*(delayed_frame_difference*10000000))/((conn->reference_to_previous_time_difference*10000000)>>32));
else
// uint64_t first_local_to_remote_time_difference_time;
// uint64_t l2rtd = 0;
int sequence_number = 0;
-
+
// for getting mean and sd of return times
int32_t stat_n = 0;
double stat_mean = 0.0;
distant_transmit_time += nctohl(&packet[28]);
uint64_t remote_processing_time = distant_transmit_time - distant_receive_time;
-
- //debug(1,"Return trip time: %" PRIu64 " uS, remote processing time: %" PRIu64 " uS.",(return_time*1000000)>>32,(remote_processing_time*1000000)>>32);
-
+
+ // debug(1,"Return trip time: %" PRIu64 " uS, remote processing time: %" PRIu64 "
+ // uS.",(return_time*1000000)>>32,(remote_processing_time*1000000)>>32);
+
uint64_t local_time_by_remote_clock = distant_transmit_time + return_time / 2;
-
- // remove the remote processing time from the record of the return time, as long at the processing time looks sensible.
-
+
+ // remove the remote processing time from the record of the return time, as long at the
+ // processing time looks sensible.
+
if ((remote_processing_time > 0) && (remote_processing_time < return_time))
return_time -= remote_processing_time;
else
- debug(1,"Non-sensical remote processing time -- ignored.");
+ debug(1, "Non-sensical remote processing time -- ignored.");
int cc;
for (cc = time_ping_history - 1; cc > 0; cc--) {
conn->time_pings[cc] = conn->time_pings[cc - 1];
- //if ((conn->time_ping_count) && (conn->time_ping_count < 10))
-// conn->time_pings[cc].dispersion =
-// conn->time_pings[cc].dispersion * pow(2.14, 1.0/conn->time_ping_count);
+ // if ((conn->time_ping_count) && (conn->time_ping_count < 10))
+ // conn->time_pings[cc].dispersion =
+ // conn->time_pings[cc].dispersion * pow(2.14,
+ // 1.0/conn->time_ping_count);
conn->time_pings[cc].dispersion =
- (conn->time_pings[cc].dispersion * 110) / 100; // make the dispersions 'age' by this rational factor
+ (conn->time_pings[cc].dispersion * 110) /
+ 100; // make the dispersions 'age' by this rational factor
}
// these are used for doing a least squares calculation to get the drift
conn->time_pings[0].local_time = arrival_time;
- conn->time_pings[0].remote_time = distant_transmit_time;
- conn->time_pings[0].sequence_number = sequence_number++;
- conn->time_pings[0].chosen = 0;
-
-
+ conn->time_pings[0].remote_time = distant_transmit_time;
+ conn->time_pings[0].sequence_number = sequence_number++;
+ conn->time_pings[0].chosen = 0;
conn->time_pings[0].local_to_remote_difference =
local_time_by_remote_clock - arrival_time;
conn->time_pings[0].dispersion = return_time;
if (conn->time_ping_count < time_ping_history)
conn->time_ping_count++;
-
+
// here, calculate the mean and standard deviation of the return times
-
+
// mean and variance calculations from "online_variance" algorithm at
// https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
-
- double rtfus = 1.0*((return_time * 1000000) >> 32);
+
+ double rtfus = 1.0 * ((return_time * 1000000) >> 32);
stat_n += 1;
double stat_delta = rtfus - stat_mean;
stat_mean += stat_delta / stat_n;
stat_M2 += stat_delta * (rtfus - stat_mean);
- //debug(1, "Timing packet return time stats: current, mean and standard deviation over %d packets: %.1f, %.1f, %.1f (microseconds).",
+ // debug(1, "Timing packet return time stats: current, mean and standard deviation over
+ // %d packets: %.1f, %.1f, %.1f (microseconds).",
// stat_n,rtfus,stat_mean, sqrtf(stat_M2 / (stat_n - 1)));
-
+
// here, pick the record with the least dispersion, and record that it's been chosen
-
+
// uint64_t local_time_chosen = arrival_time;
// uint64_t remote_time_chosen = distant_transmit_time;
// now pick the timestamp with the lowest dispersion
// local_time_chosen = conn->time_pings[cc].local_time;
// remote_time_chosen = conn->time_pings[cc].remote_time;
}
- // debug(1,"Record %d has the lowest dispersion with %0.2f us dispersion.",chosen,1.0*((tld * 1000000) >> 32));
+ // debug(1,"Record %d has the lowest dispersion with %0.2f us
+ // dispersion.",chosen,1.0*((tld * 1000000) >> 32));
conn->time_pings[chosen].chosen = 1; // record the fact that it has been used for timing
/*
- // calculate the jitter -- the absolute time between the current local_to_remote_time_difference and the new one and add it to the total jitter count
+ // calculate the jitter -- the absolute time between the current
+ local_to_remote_time_difference and the new one and add it to the total jitter count
int64_t ji;
int64_t ltd =0; // local time difference for the jitter
-
+
if (conn->time_ping_count > 1) {
if (l2rtd > conn->local_to_remote_time_difference) {
local_to_remote_time_jitter =
local_to_remote_time_jitter + l2rtd - conn->local_to_remote_time_difference;
- ji = l2rtd - conn->local_to_remote_time_difference; // this is the difference between the present local-to-remote-time-difference and the new one, i.e. the jitter step
+ ji = l2rtd - conn->local_to_remote_time_difference; // this is the difference
+ between the present local-to-remote-time-difference and the new one, i.e. the jitter
+ step
} else {
local_to_remote_time_jitter =
local_to_remote_time_jitter + conn->local_to_remote_time_difference - l2rtd;
ltd = lt-conn->local_to_remote_time_difference_measurement_time;
else
ltd = -(conn->local_to_remote_time_difference_measurement_time-lt);
-
+
if (ltd) {
- debug(1,"Jitter: %" PRId64 " microseconds in %" PRId64 " microseconds.", (ji * (int64_t)1000000)>>32, (ltd * (int64_t)1000000)>>32);
+ debug(1,"Jitter: %" PRId64 " microseconds in %" PRId64 " microseconds.", (ji *
+ (int64_t)1000000)>>32, (ltd * (int64_t)1000000)>>32);
debug(1,"Source clock to local clock drift: %.2f ppm.",((1.0*ji)/ltd)*1000000.0);
- }
+ }
// uncomment below to print jitter between client's clock and our clock
if (ji) {
int64_t rtus = (tld*1000000)>>32;
- debug(1,"Choosing time difference[%d] with dispersion of %" PRId64 " us with an adjustment of %" PRId64 " us",chosen, rtus, (ji*1000000)>>32);
+ debug(1,"Choosing time difference[%d] with dispersion of %" PRId64 " us with an
+ adjustment of %" PRId64 " us",chosen, rtus, (ji*1000000)>>32);
}
*/
- conn->local_to_remote_time_difference = l2rtd; // make this the new local-to-remote-time-difference
+ conn->local_to_remote_time_difference =
+ l2rtd; // make this the new local-to-remote-time-difference
conn->local_to_remote_time_difference_measurement_time = lt; // done at this time.
-
+
if (first_local_to_remote_time_difference == 0) {
first_local_to_remote_time_difference = conn->local_to_remote_time_difference;
// first_local_to_remote_time_difference_time = get_absolute_time_in_fp();
}
- // here, let's try to use the timing pings that were selected because of their short return times to
+ // here, let's try to use the timing pings that were selected because of their short
+ // return times to
// estimate a figure for drift between the local clock (x) and the remote clock (y)
-
+
// if we plug in a local interval, we will get back what that is in remote time
-
+
// calculate the line of best fit for relating the local time and the remote time
// we will calculate the slope, which is the drift
// see https://www.varsitytutors.com/hotmath/hotmath_help/topics/line-of-best-fit
-
+
uint64_t y_bar = 0; // remote timestamp average
uint64_t x_bar = 0; // local timestamp average
int sample_count = 0;
-
+
// approximate time in seconds to let the system settle down
const int settling_time = 60;
// number of points to have for calculating a valid drift
const int sample_point_minimum = 8;
- for (cc = 0; cc < conn->time_ping_count; cc++)
- if ((conn->time_pings[cc].chosen) && (conn->time_pings[cc].sequence_number>(settling_time/3))) { // wait for a approximate settling time
- y_bar += (conn->time_pings[cc].remote_time>>12); //precision is down to 1/4th of a microsecond
- x_bar += (conn->time_pings[cc].local_time>>12);
+ for (cc = 0; cc < conn->time_ping_count; cc++)
+ if ((conn->time_pings[cc].chosen) &&
+ (conn->time_pings[cc].sequence_number >
+ (settling_time / 3))) { // wait for a approximate settling time
+ y_bar += (conn->time_pings[cc].remote_time >>
+ 12); // precision is down to 1/4th of a microsecond
+ x_bar += (conn->time_pings[cc].local_time >> 12);
sample_count++;
}
-
- y_bar = y_bar/sample_count;
- x_bar = x_bar/sample_count;
-
+
+ y_bar = y_bar / sample_count;
+ x_bar = x_bar / sample_count;
+
int64_t xid, yid;
int64_t mtl, mbl;
- mtl=0;mbl=0;
+ mtl = 0;
+ mbl = 0;
for (cc = 0; cc < conn->time_ping_count; cc++)
- if ((conn->time_pings[cc].chosen) && (conn->time_pings[cc].sequence_number>(settling_time/3))) {
-
- uint64_t slt = conn->time_pings[cc].local_time>>12;
+ if ((conn->time_pings[cc].chosen) &&
+ (conn->time_pings[cc].sequence_number > (settling_time / 3))) {
+
+ uint64_t slt = conn->time_pings[cc].local_time >> 12;
if (slt > x_bar)
xid = slt - x_bar;
else
xid = -(x_bar - slt);
-
- uint64_t srt = conn->time_pings[cc].remote_time>>12;
+
+ uint64_t srt = conn->time_pings[cc].remote_time >> 12;
if (srt > y_bar)
yid = srt - y_bar;
else
yid = -(y_bar - srt);
-
- mtl = mtl + xid*yid;
- mbl = mbl + xid*xid;
- }
- conn->local_to_remote_time_gradient_sample_count = sample_count;
- if (sample_count > sample_point_minimum) {
- conn->local_to_remote_time_gradient = (1.0*mtl)/mbl;
- // debug(1,"Drift is %12.2f ppm, based on %d samples.",(1.0-conn->local_to_remote_time_gradient)*1000000,sample_count);
+
+ mtl = mtl + xid * yid;
+ mbl = mbl + xid * xid;
+ }
+ conn->local_to_remote_time_gradient_sample_count = sample_count;
+ if (sample_count > sample_point_minimum) {
+ conn->local_to_remote_time_gradient = (1.0 * mtl) / mbl;
+ // debug(1,"Drift is %12.2f ppm, based on %d
+ // samples.",(1.0-conn->local_to_remote_time_gradient)*1000000,sample_count);
} else {
- conn->local_to_remote_time_gradient = 1.0;
+ conn->local_to_remote_time_gradient = 1.0;
}
} else {
debug(2, "Time ping turnaround time: %lld us -- it looks like a timing ping was lost.",
debug_mutex_lock(&conn->reference_time_mutex, 1000, 1);
*timestamp = conn->reference_timestamp;
*remote_timestamp_time = conn->remote_reference_timestamp_time;
- *timestamp_time = conn->remote_reference_timestamp_time - local_to_remote_time_difference_now(conn);
+ *timestamp_time =
+ conn->remote_reference_timestamp_time - local_to_remote_time_difference_now(conn);
// if ((*timestamp == 0) && (*timestamp_time == 0)) {
// debug(1,"Reference timestamp is invalid.");
//}
}
int have_timestamp_timing_information(rtsp_conn_info *conn) {
- if (conn->reference_timestamp==0)
+ if (conn->reference_timestamp == 0)
return 0;
else
return 1;
}
-// set this to zero to use the rates supplied by the sources, which might not always be completely right...
-const int use_nominal_rate = 0; // specify whether to use the nominal input rate, usually 44100 fps
+// set this to zero to use the rates supplied by the sources, which might not always be completely
+// right...
+const int use_nominal_rate = 0; // specify whether to use the nominal input rate, usually 44100 fps
int sanitised_source_rate_information(int64_t *frames, uint64_t *time, rtsp_conn_info *conn) {
int result = 1;
- *frames = conn->input_rate;
+ *frames = conn->input_rate;
*time = (uint64_t)(0x100000000); // one second in fp form
- if ((conn->packet_stream_established) && (conn->initial_reference_time) && (conn->initial_reference_timestamp)) {
+ if ((conn->packet_stream_established) && (conn->initial_reference_time) &&
+ (conn->initial_reference_timestamp)) {
int64_t local_frames = conn->reference_timestamp - conn->initial_reference_timestamp;
uint64_t local_time = conn->remote_reference_timestamp_time - conn->initial_reference_time;
if ((local_frames == 0) || (local_time == 0) || (use_nominal_rate)) {
result = 1;
} else {
- double calculated_frame_rate = ((1.0*local_frames)/local_time)*(uint64_t)0x100000000;
- if (((calculated_frame_rate/conn->input_rate) > 1.001) || ((calculated_frame_rate/conn->input_rate) < 0.999)) {
- debug(1,"input frame rate out of bounds at %.2f fps.",calculated_frame_rate);
+ double calculated_frame_rate = ((1.0 * local_frames) / local_time) * (uint64_t)0x100000000;
+ if (((calculated_frame_rate / conn->input_rate) > 1.001) ||
+ ((calculated_frame_rate / conn->input_rate) < 0.999)) {
+ debug(1, "input frame rate out of bounds at %.2f fps.", calculated_frame_rate);
result = 1;
} else {
*frames = local_frames;
return result;
}
-// we assume here that the timestamp is a timestamp calculated at the output rate, which could be an integer multiple of the input rate
+// we assume here that the timestamp is a timestamp calculated at the output rate, which could be an
+// integer multiple of the input rate
// the reference timestamps are denominated in terms of the input rate
int frame_to_local_time(int64_t timestamp, uint64_t *time, rtsp_conn_info *conn) {
int result = 0;
uint64_t time_difference;
int64_t frame_difference;
- result = sanitised_source_rate_information(&frame_difference,&time_difference,conn);
-
- int64_t timestamp_interval = timestamp - conn->reference_timestamp*conn->output_sample_ratio; // we could be dealing with multiples of 44100 (nominally)
- // debug(1, "Timestamp interval: %" PRId64 " frames with reference timestamp %" PRId64 ".",timestamp_interval,conn->reference_timestamp);
+ result = sanitised_source_rate_information(&frame_difference, &time_difference, conn);
+
+ int64_t timestamp_interval =
+ timestamp -
+ conn->reference_timestamp *
+ conn->output_sample_ratio; // we could be dealing with multiples of 44100 (nominally)
+ // debug(1, "Timestamp interval: %" PRId64 " frames with reference timestamp %" PRId64
+ // ".",timestamp_interval,conn->reference_timestamp);
uint64_t timestamp_interval_time;
uint64_t remote_time_of_timestamp;
- if (timestamp_interval>=0) {
- timestamp_interval_time = (timestamp_interval * time_difference)/(frame_difference*conn->output_sample_ratio); // this is the nominal time, based on the fps specified between current and previous sync frame.
- remote_time_of_timestamp = conn->remote_reference_timestamp_time + timestamp_interval_time; // based on the reference timestamp time plus the time interval calculated based on the specified fps.
+ if (timestamp_interval >= 0) {
+ timestamp_interval_time =
+ (timestamp_interval * time_difference) /
+ (frame_difference * conn->output_sample_ratio); // this is the nominal time, based on the
+ // fps specified between current and
+ // previous sync frame.
+ remote_time_of_timestamp = conn->remote_reference_timestamp_time +
+ timestamp_interval_time; // based on the reference timestamp time
+ // plus the time interval calculated based
+ // on the specified fps.
} else {
- timestamp_interval_time = ((-timestamp_interval) * time_difference)/(frame_difference*conn->output_sample_ratio); // this is the nominal time, based on the fps specified between current and previous sync frame.
- remote_time_of_timestamp = conn->remote_reference_timestamp_time - timestamp_interval_time; // based on the reference timestamp time plus the time interval calculated based on the specified fps.
+ timestamp_interval_time =
+ ((-timestamp_interval) * time_difference) /
+ (frame_difference * conn->output_sample_ratio); // this is the nominal time, based on the
+ // fps specified between current and
+ // previous sync frame.
+ remote_time_of_timestamp = conn->remote_reference_timestamp_time -
+ timestamp_interval_time; // based on the reference timestamp time
+ // plus the time interval calculated based
+ // on the specified fps.
}
*time = remote_time_of_timestamp - local_to_remote_time_difference_now(conn);
debug_mutex_unlock(&conn->reference_time_mutex, 3);
uint64_t time_difference;
int64_t frame_difference;
- result = sanitised_source_rate_information(&frame_difference,&time_difference,conn);
+ result = sanitised_source_rate_information(&frame_difference, &time_difference, conn);
// first, get from [local] time to remote time.
uint64_t remote_time = time + local_to_remote_time_difference_now(conn);
// next, get the remote time interval from the remote_time to the reference time
uint64_t time_interval;
-
+
// here, we calculate the time interval, in terms of remote time
if (remote_time >= conn->remote_reference_timestamp_time)
time_interval = remote_time - conn->remote_reference_timestamp_time;
else
time_interval = conn->remote_reference_timestamp_time - remote_time;
-
- // now, convert the remote time interval into frames using the frame rate we have observed or which has been nominated
- int64_t frame_interval = (time_interval * frame_difference)/time_difference;
+
+ // now, convert the remote time interval into frames using the frame rate we have observed or
+ // which has been nominated
+ int64_t frame_interval = (time_interval * frame_difference) / time_difference;
if (remote_time >= conn->remote_reference_timestamp_time) {
// debug(1,"Frame interval is %" PRId64 " frames.",frame_interval);
- *frame = (conn->reference_timestamp+frame_interval)*conn->output_sample_ratio;
+ *frame = (conn->reference_timestamp + frame_interval) * conn->output_sample_ratio;
} else {
// debug(1,"Frame interval is %" PRId64 " frames.",-frame_interval);
- *frame = (conn->reference_timestamp-frame_interval)*conn->output_sample_ratio;
+ *frame = (conn->reference_timestamp - frame_interval) * conn->output_sample_ratio;
}
debug_mutex_unlock(&conn->reference_time_mutex, 3);
return result;