Move the resend requests to outside the ab_mutex lock and put a send timeout on the resend requester.

This commit is contained in:
Mike Brady
2018-06-01 14:23:34 +01:00
parent 8e92da35b2
commit 497d49dda6
2 changed files with 58 additions and 44 deletions
+47 -43
View File
@@ -484,7 +484,7 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp
debug_mutex_unlock(&conn->flush_mutex, 3);
}
debug_mutex_lock(&conn->ab_mutex, 40000, 1);
debug_mutex_lock(&conn->ab_mutex, 20000, 1);
conn->packet_count++;
conn->time_of_last_audio_packet = get_absolute_time_in_fp();
if (conn->connection_state_to_output) { // if we are supposed to be processing these packets
@@ -526,37 +526,6 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp
conn->latency, resend_interval);
conn->resend_interval = resend_interval;
}
if (!conn->ab_buffering) {
int j;
for (j = 1; j <= number_of_resend_attempts; j++) {
// check j times, after a short period of has elapsed, assuming 352 frames per packet
int back_step = resend_interval * j;
int32_t sd = seq_diff(conn->ab_read, conn->ab_write, conn->ab_read);
int k;
for (k = -2; k <= 2; k++) {
if ((back_step + k) < sd) { // if it's within the range of frames in use...
int item_to_check = (conn->ab_write - (back_step + k)) & 0xffff;
seq_t next = item_to_check;
abuf_t *check_buf = conn->audio_buffer + BUFIDX(next);
if ((!check_buf->ready) &&
(check_buf->resend_level <
j)) { // prevent multiple requests from the same level of lookback
check_buf->resend_level = j;
if (config.disable_resend_requests == 0) {
rtp_request_resend(next, 1, conn);
if ((back_step + k + resend_interval) >= sd)
debug(2, "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);
conn->resend_requests++;
}
}
}
}
}
}
if (conn->ab_write == seqno) { // expected packet
abuf = conn->audio_buffer + BUFIDX(seqno);
@@ -621,16 +590,51 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp
}
// pthread_mutex_lock(&ab_mutex);
int rc = pthread_cond_signal(&conn->flowcontrol);
if (rc)
debug(1, "Error signalling flowcontrol.");
// if it's at the expected time, do a look back for missing packets
// but release the ab_mutex when doing a resend
if (!conn->ab_buffering) {
int j;
for (j = 1; j <= number_of_resend_attempts; j++) {
// check j times, after a short period of has elapsed, assuming 352 frames per packet
int back_step = resend_interval * j;
int k;
for (k = -2; k <= 2; k++) {
if ((back_step + k) <
seq_diff(conn->ab_read, conn->ab_write,
conn->ab_read)) { // if it's within the range of frames in use...
int item_to_check = (conn->ab_write - (back_step + k)) & 0xffff;
seq_t next = item_to_check;
abuf_t *check_buf = conn->audio_buffer + BUFIDX(next);
if ((!check_buf->ready) &&
(check_buf->resend_level <
j)) { // prevent multiple requests from the same level of lookback
check_buf->resend_level = j;
if (config.disable_resend_requests == 0) {
if ((back_step + k + resend_interval) >=
seq_diff(conn->ab_read, conn->ab_write, conn->ab_read))
debug(2, "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);
}
}
}
}
}
}
}
int rc = pthread_cond_signal(&conn->flowcontrol);
if (rc)
debug(1, "Error signalling flowcontrol.");
}
debug_mutex_unlock(&conn->ab_mutex, 3);
} else {
debug(
1,
"No player thread while adding a player_put_packet calle was made -- packet discarded.");
debug(1, "player_put_packet discarded packet %d because the player thread was gone.");
}
pthread_rwlock_unlock(&conn->player_thread_lock);
} else {
@@ -787,7 +791,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
abuf_t *curframe = 0;
int notified_buffer_empty = 0; // diagnostic only
debug_mutex_lock(&conn->ab_mutex, 40000, 1);
debug_mutex_lock(&conn->ab_mutex, 20000, 1);
int wait;
long dac_delay = 0; // long because alsa returns a long
do {
@@ -1215,10 +1219,10 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
struct timespec time_of_wakeup;
time_of_wakeup.tv_sec = sec;
time_of_wakeup.tv_nsec = nsec;
// pthread_cond_timedwait(&conn->flowcontrol, &conn->ab_mutex, &time_of_wakeup);
int rc = pthread_cond_timedwait(&conn->flowcontrol,&conn->ab_mutex,&time_of_wakeup);
if (rc!=0)
debug(3,"pthread_cond_timedwait returned error code %d.",rc);
// pthread_cond_timedwait(&conn->flowcontrol, &conn->ab_mutex, &time_of_wakeup);
int rc = pthread_cond_timedwait(&conn->flowcontrol, &conn->ab_mutex, &time_of_wakeup);
if (rc != 0)
debug(3, "pthread_cond_timedwait returned error code %d.", rc);
#endif
#ifdef COMPILE_FOR_OSX
uint64_t sec = time_to_wait_for_wakeup_fp >> 32;
+11 -1
View File
@@ -934,11 +934,21 @@ void rtp_request_resend(seq_t first, uint32_t count, rtsp_conn_info *conn) {
resend_error_backoff_time)) {
if ((config.diagnostic_drop_packet_fraction == 0.0) ||
(drand48() > config.diagnostic_drop_packet_fraction)) {
// put a time limit on the sendto
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
if (setsockopt(conn->control_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout,
sizeof(timeout)) < 0)
debug(1, "Can't set timeout on resend request socket.");
if (sendto(conn->control_socket, req, sizeof(req), 0,
(struct sockaddr *)&conn->rtp_client_control_socket, msgsize) == -1) {
char em[1024];
strerror_r(errno, em, sizeof(em));
debug(1, "Error %d using send-to to an audio socket: \"%s\". Backing off for 1/16th of a "
debug(1, "Error %d using sendto to an audio socket: \"%s\". Backing off for 1/16th of a "
"second.",
errno, em);
conn->rtp_time_of_last_resend_request_error_fp = time_of_sending_fp;