Seems to work for higher rates
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user