mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-18 03:28:07 +00:00
Handle and add test for AVPF generic NACK.
This commit is contained in:
parent
f3a4fc6b4a
commit
53ccb2c564
8 changed files with 103 additions and 6 deletions
|
|
@ -128,6 +128,12 @@ static void add_rtcp_fb_attributes(belle_sdp_media_description_t *media_desc, co
|
|||
if (general_trr_int == TRUE) {
|
||||
add_rtcp_fb_trr_int_attribute(media_desc, -1, trr_int);
|
||||
}
|
||||
if (stream->rtcp_fb.generic_nack_enabled == TRUE) {
|
||||
add_rtcp_fb_nack_attribute(media_desc, -1, BELLE_SDP_RTCP_FB_NONE);
|
||||
}
|
||||
if (stream->rtcp_fb.tmmbr_enabled == TRUE) {
|
||||
add_rtcp_fb_ccm_attribute(media_desc, -1, BELLE_SDP_RTCP_FB_TMMBR);
|
||||
}
|
||||
|
||||
for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) {
|
||||
pt = (PayloadType *)pt_it->data;
|
||||
|
|
@ -550,7 +556,7 @@ static void enable_avpf_for_stream(SalStreamDescription *stream) {
|
|||
}
|
||||
}
|
||||
|
||||
static void apply_rtcp_fb_attribute_to_payload(belle_sdp_rtcp_fb_attribute_t *fb_attribute, PayloadType *pt) {
|
||||
static void apply_rtcp_fb_attribute_to_payload(belle_sdp_rtcp_fb_attribute_t *fb_attribute, SalStreamDescription *stream, PayloadType *pt) {
|
||||
PayloadTypeAvpfParams avpf_params = payload_type_get_avpf_params(pt);
|
||||
switch (belle_sdp_rtcp_fb_attribute_get_type(fb_attribute)) {
|
||||
case BELLE_SDP_RTCP_FB_ACK:
|
||||
|
|
@ -574,6 +580,8 @@ static void apply_rtcp_fb_attribute_to_payload(belle_sdp_rtcp_fb_attribute_t *fb
|
|||
avpf_params.rpsi_compatibility = TRUE;
|
||||
break;
|
||||
case BELLE_SDP_RTCP_FB_NONE:
|
||||
stream->rtcp_fb.generic_nack_enabled = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -586,6 +594,9 @@ static void apply_rtcp_fb_attribute_to_payload(belle_sdp_rtcp_fb_attribute_t *fb
|
|||
case BELLE_SDP_RTCP_FB_FIR:
|
||||
avpf_params.features |= PAYLOAD_TYPE_AVPF_FIR;
|
||||
break;
|
||||
case BELLE_SDP_RTCP_FB_TMMBR:
|
||||
stream->rtcp_fb.tmmbr_enabled = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -612,7 +623,7 @@ static void sdp_parse_rtcp_fb_parameters(belle_sdp_media_description_t *media_de
|
|||
if (belle_sdp_rtcp_fb_attribute_get_id(fb_attribute) == -1) {
|
||||
for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) {
|
||||
pt = (PayloadType *)pt_it->data;
|
||||
apply_rtcp_fb_attribute_to_payload(fb_attribute, pt);
|
||||
apply_rtcp_fb_attribute_to_payload(fb_attribute, stream, pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -627,7 +638,7 @@ static void sdp_parse_rtcp_fb_parameters(belle_sdp_media_description_t *media_de
|
|||
for (pt_it = stream->payloads; pt_it != NULL; pt_it = pt_it->next) {
|
||||
pt = (PayloadType *)pt_it->data;
|
||||
if (payload_type_get_number(pt) == (int)pt_num) {
|
||||
apply_rtcp_fb_attribute_to_payload(fb_attribute, pt);
|
||||
apply_rtcp_fb_attribute_to_payload(fb_attribute, stream, pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -485,10 +485,13 @@ static void setup_rtcp_fb(LinphoneCall *call, SalMediaDescription *md) {
|
|||
MSList *pt_it;
|
||||
PayloadType *pt;
|
||||
PayloadTypeAvpfParams avpf_params;
|
||||
LinphoneCore *lc = call->core;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < md->nb_streams; i++) {
|
||||
if (!sal_stream_description_active(&md->streams[i])) continue;
|
||||
md->streams[i].rtcp_fb.generic_nack_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_fb_generic_nack_enabled", 0);
|
||||
md->streams[i].rtcp_fb.tmmbr_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_fb_tmmbr_enabled", 0);
|
||||
for (pt_it = md->streams[i].payloads; pt_it != NULL; pt_it = pt_it->next) {
|
||||
pt = (PayloadType *)pt_it->data;
|
||||
if (call->params->avpf_enabled == TRUE) {
|
||||
|
|
@ -2392,6 +2395,27 @@ static int find_crypto_index_from_tag(const SalSrtpCryptoAlgo crypto[],unsigned
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void configure_rtp_session_for_rtcp_fb(LinphoneCall *call, SalStreamDescription *stream) {
|
||||
RtpSession *session = NULL;
|
||||
|
||||
if (stream->type == SalAudio) {
|
||||
session = call->audiostream->ms.sessions.rtp_session;
|
||||
} else if (stream->type == SalVideo) {
|
||||
session = call->videostream->ms.sessions.rtp_session;
|
||||
} else {
|
||||
// Do nothing for streams that are not audio or video
|
||||
return;
|
||||
}
|
||||
if (stream->rtcp_fb.generic_nack_enabled)
|
||||
rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_GENERIC_NACK, TRUE);
|
||||
else
|
||||
rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_GENERIC_NACK, FALSE);
|
||||
if (stream->rtcp_fb.tmmbr_enabled)
|
||||
rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_TMMBR, TRUE);
|
||||
else
|
||||
rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_TMMBR, FALSE);
|
||||
}
|
||||
|
||||
static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *call, SalStreamType type) {
|
||||
RtpSession *session;
|
||||
const OrtpRtcpXrConfiguration *localconfig;
|
||||
|
|
@ -2622,6 +2646,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b
|
|||
ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag);
|
||||
}
|
||||
}
|
||||
configure_rtp_session_for_rtcp_fb(call, stream);
|
||||
configure_rtp_session_for_rtcp_xr(lc, call, SalAudio);
|
||||
if (is_multicast)
|
||||
rtp_session_set_multicast_ttl(call->audiostream->ms.sessions.rtp_session,stream->ttl);
|
||||
|
|
@ -2789,6 +2814,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu
|
|||
media_stream_set_srtp_send_key_b64(&(call->videostream->ms.sessions),vstream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
|
||||
}
|
||||
}
|
||||
configure_rtp_session_for_rtcp_fb(call, vstream);
|
||||
configure_rtp_session_for_rtcp_xr(lc, call, SalVideo);
|
||||
|
||||
call->log->video_enabled = TRUE;
|
||||
|
|
|
|||
|
|
@ -503,6 +503,8 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
|
|||
if ((ls->rtcp_xr.enabled == TRUE) && (rs->rtcp_xr.enabled == FALSE)) {
|
||||
result->streams[i].rtcp_xr.enabled = FALSE;
|
||||
}
|
||||
result->streams[i].rtcp_fb.generic_nack_enabled = ls->rtcp_fb.generic_nack_enabled & rs->rtcp_fb.generic_nack_enabled;
|
||||
result->streams[i].rtcp_fb.tmmbr_enabled = ls->rtcp_fb.tmmbr_enabled & rs->rtcp_fb.tmmbr_enabled;
|
||||
++j;
|
||||
}
|
||||
else ms_warning("No matching stream for %i",i);
|
||||
|
|
@ -569,6 +571,9 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
|
|||
}else ms_warning("Unknown protocol for mline %i, declining",i);
|
||||
if (ls){
|
||||
initiate_incoming(ls,rs,&result->streams[i],one_matching_codec);
|
||||
// Handle global RTCP FB attributes
|
||||
result->streams[i].rtcp_fb.generic_nack_enabled = rs->rtcp_fb.generic_nack_enabled;
|
||||
result->streams[i].rtcp_fb.tmmbr_enabled = rs->rtcp_fb.tmmbr_enabled;
|
||||
// Handle media RTCP XR attribute
|
||||
memset(&result->streams[i].rtcp_xr, 0, sizeof(result->streams[i].rtcp_xr));
|
||||
if (rs->rtcp_xr.enabled == TRUE) {
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ typedef struct SalStreamDescription{
|
|||
SalSrtpCryptoAlgo crypto[SAL_CRYPTO_ALGO_MAX];
|
||||
unsigned int crypto_local_tag;
|
||||
int max_rate;
|
||||
OrtpRtcpFbConfiguration rtcp_fb;
|
||||
OrtpRtcpXrConfiguration rtcp_xr;
|
||||
SalIceCandidate ice_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES];
|
||||
SalIceRemoteCandidate ice_remote_candidates[SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES];
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 0b72fb676c24356a548710c5e3a1d0ee3a1dbd70
|
||||
Subproject commit dba58b24d9ae6772a17513d66aebf55f45e63030
|
||||
2
oRTP
2
oRTP
|
|
@ -1 +1 @@
|
|||
Subproject commit 5aa889bfe539f6b83962334adb9f49aa76bc8303
|
||||
Subproject commit 79e8c769eebb7a60ba55f5bcada0aa200507d017
|
||||
|
|
@ -4381,6 +4381,58 @@ end:
|
|||
ms_free(hellopath);
|
||||
}
|
||||
|
||||
static void generic_nack_received(const OrtpEventData *evd, stats *st) {
|
||||
if (rtcp_is_RTPFB(evd->packet)) {
|
||||
switch (rtcp_RTPFB_get_type(evd->packet)) {
|
||||
case RTCP_RTPFB_NACK:
|
||||
st->number_of_rtcp_generic_nack++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void call_with_generic_nack_rtcp_feedback(void) {
|
||||
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
|
||||
LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
|
||||
LpConfig *lp;
|
||||
LinphoneCall *call_marie;
|
||||
bool_t call_ok;
|
||||
OrtpNetworkSimulatorParams params = { 0 };
|
||||
int dummy = 0;
|
||||
|
||||
params.enabled = TRUE;
|
||||
params.loss_rate = 10;
|
||||
params.consecutive_loss_probability = 0.75;
|
||||
params.mode = OrtpNetworkSimulatorOutbound;
|
||||
linphone_core_set_avpf_mode(marie->lc, LinphoneAVPFEnabled);
|
||||
linphone_core_set_avpf_mode(pauline->lc, LinphoneAVPFEnabled);
|
||||
lp = linphone_core_get_config(pauline->lc);
|
||||
lp_config_set_int(lp, "rtp", "rtcp_fb_generic_nack_enabled", 1);
|
||||
|
||||
|
||||
BC_ASSERT_TRUE(call_ok = call(pauline, marie));
|
||||
if (!call_ok) goto end;
|
||||
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
|
||||
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
|
||||
call_marie = linphone_core_get_current_call(marie->lc);
|
||||
if (call_marie) {
|
||||
rtp_session_enable_network_simulation(call_marie->audiostream->ms.sessions.rtp_session, ¶ms);
|
||||
ortp_ev_dispatcher_connect(media_stream_get_event_dispatcher(&call_marie->audiostream->ms),
|
||||
ORTP_EVENT_RTCP_PACKET_RECEIVED, RTCP_RTPFB, (OrtpEvDispatcherCb)generic_nack_received, &marie->stat);
|
||||
}
|
||||
|
||||
BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_rtcp_generic_nack, 5, 5000));
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
|
||||
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
|
||||
|
||||
end:
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
test_t call_tests[] = {
|
||||
{ "Early declined call", early_declined_call },
|
||||
{ "Call declined", call_declined },
|
||||
|
|
@ -4507,7 +4559,8 @@ test_t call_tests[] = {
|
|||
{ "Simple stereo call with opus", simple_stereo_call_opus },
|
||||
{ "Simple mono call with opus", simple_mono_call_opus },
|
||||
{ "Call with FQDN in SDP", call_with_fqdn_in_sdp},
|
||||
{ "Call with RTP IO mode", call_with_rtp_io_mode }
|
||||
{ "Call with RTP IO mode", call_with_rtp_io_mode },
|
||||
{ "Call with generic NACK RTCP feedback", call_with_generic_nack_rtcp_feedback }
|
||||
};
|
||||
|
||||
test_suite_t call_test_suite = {
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ typedef struct _stats {
|
|||
int video_upload_bandwidth[3];
|
||||
int current_bandwidth_index;
|
||||
|
||||
int number_of_rtcp_generic_nack;
|
||||
}stats;
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue