diff --git a/daemon/codec.c b/daemon/codec.c index 480c627e1..6c76c819e 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -1371,7 +1371,7 @@ static void __rtcp_timer_run(struct codec_timer *ct) { for (GList *l = ssrc_out.head; l; l = l->next) { struct ssrc_entry_call *se = l->data; - rtcp_send_report(media, se); + rtcp_send_report(media, se, NULL); } rwlock_unlock_r(&rt->call->master_lock); diff --git a/daemon/media_player.c b/daemon/media_player.c index adb7f9e58..ef369f1ee 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -306,12 +306,13 @@ struct send_timer *send_timer_new(struct packet_stream *ps) { // call is locked in R // ssrc_out is locked +// st->sink is locked static void send_timer_rtcp(struct send_timer *st, struct ssrc_entry_call *ssrc_out) { struct call_media *media = st->sink ? st->sink->media : NULL; if (!media) return; - rtcp_send_report(media, ssrc_out); + rtcp_send_report(media, ssrc_out, st->sink); ssrc_out->next_rtcp = rtpe_now; ssrc_out->next_rtcp += 5000000 + (ssl_random() % 2000000); @@ -408,6 +409,7 @@ out: log_info_pop(); } +// sink->lock is held static void __send_timer_rtcp(struct send_timer *st, struct ssrc_entry_call *ssrc_out) { // do we send RTCP? if (!ssrc_out) @@ -436,9 +438,10 @@ static void send_timer_send_lock(struct send_timer *st, struct codec_packet *cp) __send_timer_send_common(st, cp); + __send_timer_rtcp(st, ssrc_out); + mutex_unlock(&st->sink->lock); - __send_timer_rtcp(st, ssrc_out); ssrc_entry_release(ssrc_out); rwlock_unlock_r(&call->master_lock); diff --git a/daemon/rtcp.c b/daemon/rtcp.c index 67d4a9a7f..173ce7ff1 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -1550,8 +1550,10 @@ static void rtcp_receiver_reports(ssrc_q *out, struct ssrc_hash *hash) { // call must be locked in R -// no in_lock or out_lock must be held -void rtcp_send_report(struct call_media *media, struct ssrc_entry_call *ssrc_out) { +// if a `ps` is locked, it must be passed as argument +void rtcp_send_report(struct call_media *media, struct ssrc_entry_call *ssrc_out, + const struct packet_stream *locked) +{ // figure out where to send it struct packet_stream *ps = media->streams.head->data; // crypto context is held separately @@ -1562,16 +1564,15 @@ void rtcp_send_report(struct call_media *media, struct ssrc_entry_call *ssrc_out else { if (PS_ISSET(rtcp_ps, RTCP)) ps = rtcp_ps; - else - rtcp_ps = ps; } - LOCK(&ps->lock); + if (ps != locked) + mutex_lock(&ps->lock); - if (!ps->selected_sfd || !rtcp_ps->selected_sfd) - return; + if (!ps->selected_sfd) + goto out; if (ps->selected_sfd->socket.fd == -1 || ps->endpoint.address.family == NULL) - return; + goto out; log_info_stream_fd(ps->selected_sfd); @@ -1623,6 +1624,11 @@ void rtcp_send_report(struct call_media *media, struct ssrc_entry_call *ssrc_out struct ssrc_receiver_report *srr = t_queue_pop_head(&srrs); g_free(srr); } + +out: + if (ps != locked) + mutex_unlock(&ps->lock); + } diff --git a/include/rtcp.h b/include/rtcp.h index aa6a0995f..e38c45d29 100644 --- a/include/rtcp.h +++ b/include/rtcp.h @@ -30,6 +30,7 @@ rtcp_filter_func rtcp_avpf2avp_filter; void rtcp_init(void); -void rtcp_send_report(struct call_media *media, struct ssrc_entry_call *ssrc_out); +void rtcp_send_report(struct call_media *media, struct ssrc_entry_call *ssrc_out, + const struct packet_stream *locked); #endif