From: Mike Brady Date: Fri, 19 Oct 2018 21:14:23 +0000 (+0100) Subject: Seems to work for higher rates X-Git-Tag: 3.3RC0~190^2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d2dba7cdba6ddbe433563db6c9aa2bd493f7ad4b;p=thirdparty%2Fshairport-sync.git Seems to work for higher rates --- diff --git a/player.c b/player.c index a96fc845..7c055a5c 100644 --- a/player.c +++ b/player.c @@ -99,11 +99,11 @@ // static abuf_t audio_buffer[BUFFER_FRAMES]; #define BUFIDX(seqno) ((seq_t)(seqno) % BUFFER_FRAMES) -uint32_t rtp_frame_offset(uint32_t base, uint32_t frame_in_question) { - if (base <= frame_in_question) - return frame_in_question - base; +uint32_t rtp_frame_offset(uint32_t from, uint32_t to) { + if (from <= to) + return to - from; else - return UINT32_MAX - base + frame_in_question + 1; + return UINT32_MAX - from + to + 1; } void do_flush(uint32_t timestamp, rtsp_conn_info *conn); @@ -944,8 +944,8 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) { 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), + conn->first_packet_timestamp + conn->latency + + (uint32_t)(config.audio_backend_latency_offset * conn->input_rate), // this will go modulo 2^32 &should_be_time, conn); conn->first_packet_time_to_play = should_be_time; @@ -965,8 +965,8 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) { 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), + conn->first_packet_timestamp + conn->latency + + (uint32_t)(config.audio_backend_latency_offset * conn->input_rate), // this should go modulo 2^32 &should_be_time, conn); conn->first_packet_time_to_play = should_be_time; @@ -1163,9 +1163,9 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) { uint64_t time_to_play; frame_to_local_time( - (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, + curframe->given_timestamp + conn->latency + + (uint32_t)(config.audio_backend_latency_offset * conn->input_rate) - + (uint32_t)(config.audio_backend_buffer_desired_length * conn->input_rate), // this will go modulo 2^32 &time_to_play, conn); if (local_time_now >= time_to_play) { @@ -1908,7 +1908,6 @@ void *player_thread_func(void *arg) { 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->given_timestamp; // uint32_t to int64_t @@ -2000,8 +1999,9 @@ void *player_thread_func(void *arg) { if (resp >= 0) { - int64_t should_be_frame; - local_time_to_frame(local_time_now, &should_be_frame, conn); + uint32_t should_be_frame_32; + local_time_to_frame(local_time_now, &should_be_frame_32, conn); + int64_t should_be_frame = ((int64_t)should_be_frame_32) * conn->output_sample_ratio; // int64_t absolute_difference_in_frames = td_in_frames + rt - should_be_frame; // if (absolute_difference_in_frames < 0) @@ -2041,11 +2041,11 @@ void *player_thread_func(void *arg) { (config.resyncthreshold > 0.0) && (abs_sync_error > config.resyncthreshold * config.output_rate)) { if (abs_sync_error > 3 * config.output_rate) { - warn("Very large sync error: %" PRId64 " frames, with delay: %" PRId64 - ", td_in_frames: %" PRId64 ", rt: %" PRId64 ", nt: %" PRId64 - ", current_delay: %" PRId64 ", seqno: %u, given timestamp: %" PRIu32 ".", - sync_error, delay, td_in_frames, rt, nt, current_delay, - inframe->sequence_number, inframe->given_timestamp); + + warn("Very large sync error: %" PRId64 " frames, with should_be_frame: %" PRId64 + ", nt: %" PRId64 + ", current_delay: %" PRId64 ", given timestamp %" PRIX32 ", reference timestamp %" PRIX32 ", should_be_frame %" PRIX32 ".", + sync_error, should_be_frame, nt, current_delay, inframe->given_timestamp, reference_timestamp, should_be_frame_32); } sync_error_out_of_bounds++; } else { diff --git a/player.h b/player.h index 6c10d34d..43d93c05 100644 --- a/player.h +++ b/player.h @@ -242,6 +242,8 @@ typedef struct { void *dapo_private_storage; // this is used for compatibility, if dacp stuff isn't enabled. } rtsp_conn_info; +uint32_t rtp_frame_offset(uint32_t from, uint32_t to); + int player_play(rtsp_conn_info *conn); int player_stop(rtsp_conn_info *conn); diff --git a/rtp.c b/rtp.c index 4cd96aba..599d5a48 100644 --- a/rtp.c +++ b/rtp.c @@ -1034,13 +1034,14 @@ int have_timestamp_timing_information(rtsp_conn_info *conn) { // 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 sanitised_source_rate_information(uint32_t *frames, uint64_t *time, rtsp_conn_info *conn) { int result = 1; *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)) { - int64_t local_frames = conn->reference_timestamp - conn->initial_reference_timestamp; +// uint32_t local_frames = conn->reference_timestamp - conn->initial_reference_timestamp; + uint32_t local_frames = rtp_frame_offset(conn->initial_reference_timestamp, conn->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; @@ -1060,39 +1061,34 @@ int sanitised_source_rate_information(int64_t *frames, uint64_t *time, rtsp_conn 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 +// the timestamp is a timestamp calculated at 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 frame_to_local_time(uint32_t timestamp, uint64_t *time, rtsp_conn_info *conn) { debug_mutex_lock(&conn->reference_time_mutex, 1000, 1); int result = 0; uint64_t time_difference; - int64_t frame_difference; + uint32_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); uint64_t timestamp_interval_time; uint64_t remote_time_of_timestamp; - if (timestamp_interval >= 0) { + uint32_t timestamp_interval = rtp_frame_offset(conn->reference_timestamp,timestamp); + if (timestamp_interval <= 44100*10) { // i.e. timestamp was really after the reference timestamp timestamp_interval_time = (timestamp_interval * time_difference) / - (frame_difference * conn->output_sample_ratio); // this is the nominal time, based on the + (frame_difference); // 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 { + } else { // i.e. timestamp was actually after the reference timestamp + timestamp_interval = rtp_frame_offset(timestamp,conn->reference_timestamp); // fix the calculation timestamp_interval_time = - ((-timestamp_interval) * time_difference) / - (frame_difference * conn->output_sample_ratio); // this is the nominal time, based on the + (timestamp_interval * time_difference) / + (frame_difference); // 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 - @@ -1105,12 +1101,12 @@ int frame_to_local_time(int64_t timestamp, uint64_t *time, rtsp_conn_info *conn) return result; } -int local_time_to_frame(uint64_t time, int64_t *frame, rtsp_conn_info *conn) { +int local_time_to_frame(uint64_t time, uint32_t *frame, rtsp_conn_info *conn) { debug_mutex_lock(&conn->reference_time_mutex, 1000, 1); int result = 0; uint64_t time_difference; - int64_t frame_difference; + uint32_t frame_difference; result = sanitised_source_rate_information(&frame_difference, &time_difference, conn); // first, get from [local] time to remote time. @@ -1129,10 +1125,10 @@ int local_time_to_frame(uint64_t time, int64_t *frame, rtsp_conn_info *conn) { 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); } 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); } debug_mutex_unlock(&conn->reference_time_mutex, 3); return result; diff --git a/rtp.h b/rtp.h index 9bf5c696..171bd651 100644 --- a/rtp.h +++ b/rtp.h @@ -25,9 +25,9 @@ int have_timestamp_timing_information(rtsp_conn_info *conn); int get_frame_play_time(int64_t timestamp, int sample_ratio, uint64_t *time_to_play); -int frame_to_local_time(int64_t timestamp, uint64_t *time, rtsp_conn_info *conn); -int local_time_to_frame(uint64_t time, int64_t *frame, rtsp_conn_info *conn); +int frame_to_local_time(uint32_t timestamp, uint64_t *time, rtsp_conn_info *conn); +int local_time_to_frame(uint64_t time, uint32_t *frame, rtsp_conn_info *conn); -int sanitised_source_rate_information(int64_t *frames, uint64_t *time, rtsp_conn_info *conn); +int sanitised_source_rate_information(uint32_t *frames, uint64_t *time, rtsp_conn_info *conn); #endif // _RTP_H