int media_stream_set_srtp_send_key(MediaStream *stream, MSCryptoSuite suite, const char* key){ if (!media_stream_srtp_supported()) { ms_error("ortp srtp support disabled in oRTP or mediastreamer2"); return -1; } #ifdef ORTP_HAVE_SRTP { uint32_t ssrc; bool_t updated=FALSE; if (check_srtp_session_created(stream)==-1) return -1; /*check if a previous key was configured, in which case remove it*/ ssrc=rtp_session_get_send_ssrc(stream->sessions.rtp_session); if (ssrc!=0){ /*careful: remove_stream takes the SSRC in network byte order...*/ if (ortp_srtp_remove_stream(stream->sessions.srtp_session,htonl(ssrc))==0) updated=TRUE; } ms_message("media_stream_set_srtp_send_key(): %s key %s",updated ? "changing to" : "starting with", key); return add_srtp_stream(stream->sessions.srtp_session,suite,ssrc,key,FALSE); } #else return -1; #endif }
static bool_t simple_analyzer_process_rtcp(MSQosAnalyzer *objbase, mblk_t *rtcp){ MSSimpleQosAnalyzer *obj=(MSSimpleQosAnalyzer*)objbase; rtpstats_t *cur; const report_block_t *rb=NULL; bool_t got_stats=FALSE; if (rtcp_is_SR(rtcp)){ rb=rtcp_SR_get_report_block(rtcp,0); }else if (rtcp_is_RR(rtcp)){ rb=rtcp_RR_get_report_block(rtcp,0); } if (rb && report_block_get_ssrc(rb)==rtp_session_get_send_ssrc(obj->session)){ obj->curindex++; cur=&obj->stats[obj->curindex % STATS_HISTORY]; if (obj->clockrate==0){ PayloadType *pt=rtp_profile_get_payload(rtp_session_get_send_profile(obj->session),rtp_session_get_send_payload_type(obj->session)); if (pt!=NULL) obj->clockrate=pt->clock_rate; else return FALSE; } if (ortp_loss_rate_estimator_process_report_block(objbase->lre,&obj->session->rtp,rb)){ cur->lost_percentage=ortp_loss_rate_estimator_get_value(objbase->lre); cur->int_jitter=1000.0*(float)report_block_get_interarrival_jitter(rb)/(float)obj->clockrate; cur->rt_prop=rtp_session_get_round_trip_propagation(obj->session); ms_message("MSSimpleQosAnalyzer: lost_percentage=%f, int_jitter=%f ms, rt_prop=%f sec", cur->lost_percentage,cur->int_jitter,cur->rt_prop); got_stats=TRUE; } } return got_stats; }
static mblk_t * make_rtcp_fb_sli(RtpSession *session, uint16_t first, uint16_t number, uint8_t picture_id) { int size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + sizeof(rtcp_fb_sli_fci_t); mblk_t *h = allocb(size, 0); rtcp_common_header_t *ch; rtcp_fb_header_t *fbh; rtcp_fb_sli_fci_t *fci; /* Fill SLI */ ch = (rtcp_common_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_common_header_t); fbh = (rtcp_fb_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_header_t); fci = (rtcp_fb_sli_fci_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_sli_fci_t); fbh->packet_sender_ssrc = htonl(rtp_session_get_send_ssrc(session)); fbh->media_source_ssrc = htonl(rtp_session_get_recv_ssrc(session)); rtcp_fb_sli_fci_set_first(fci, first); rtcp_fb_sli_fci_set_number(fci, number); rtcp_fb_sli_fci_set_picture_id(fci, picture_id); /* Fill common header */ rtcp_common_header_init(ch, session, RTCP_PSFB, RTCP_PSFB_SLI, msgdsize(h)); return h; }
static mblk_t * make_rtcp_fb_fir(RtpSession *session) { int size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + sizeof(rtcp_fb_fir_fci_t); mblk_t *h = allocb(size, 0); rtcp_common_header_t *ch; rtcp_fb_header_t *fbh; rtcp_fb_fir_fci_t *fci; /* Fill FIR */ ch = (rtcp_common_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_common_header_t); fbh = (rtcp_fb_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_header_t); fci = (rtcp_fb_fir_fci_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_fir_fci_t); fbh->packet_sender_ssrc = htonl(0); fbh->media_source_ssrc = htonl(rtp_session_get_recv_ssrc(session)); fci->ssrc = htonl(rtp_session_get_send_ssrc(session)); fci->seq_nr = session->rtcp.rtcp_fb_fir_seq_nr++; fci->pad1 = 0; fci->pad2 = 0; /* Fill common header */ rtcp_common_header_init(ch, session, RTCP_PSFB, RTCP_PSFB_FIR, msgdsize(h)); return h; }
static mblk_t * make_rtcp_fb_tmmbn(RtpSession *session, uint32_t ssrc) { int size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + sizeof(rtcp_fb_tmmbr_fci_t); mblk_t *h = allocb(size, 0); rtcp_common_header_t *ch; rtcp_fb_header_t *fbh; rtcp_fb_tmmbr_fci_t *fci; if (!session->rtcp.tmmbr_info.received) return NULL; /* Fill TMMBN */ ch = (rtcp_common_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_common_header_t); fbh = (rtcp_fb_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_header_t); fci = (rtcp_fb_tmmbr_fci_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_tmmbr_fci_t); fbh->packet_sender_ssrc = htonl(rtp_session_get_send_ssrc(session)); fbh->media_source_ssrc = htonl(0); memcpy(fci, rtcp_RTPFB_tmmbr_get_fci(session->rtcp.tmmbr_info.received), sizeof(rtcp_fb_tmmbr_fci_t)); fci->ssrc = htonl(ssrc); /* Fill common header */ rtcp_common_header_init(ch, session, RTCP_RTPFB, RTCP_RTPFB_TMMBN, msgdsize(h)); return h; }
bool_t video_stream_enable_strp(VideoStream* stream, enum ortp_srtp_crypto_suite_t suite, const char* snd_key, const char* rcv_key) { // assign new srtp transport to stream->session // with 2 Master Keys RtpTransport *rtp_tpt, *rtcp_tpt; if (!ortp_srtp_supported()) { ms_error("ortp srtp support not enabled"); return FALSE; } ms_message("%s: stream=%p key='%s' key='%s'", __FUNCTION__, stream, snd_key, rcv_key); stream->srtp_session = ortp_srtp_create_configure_session(suite, rtp_session_get_send_ssrc(stream->session), snd_key, rcv_key); if (!stream->srtp_session) { return FALSE; } // TODO: check who will free rtp_tpt ? srtp_transport_new(stream->srtp_session, &rtp_tpt, &rtcp_tpt); rtp_session_set_transports(stream->session, rtp_tpt, rtcp_tpt); return TRUE; }
static mblk_t * make_rtcp_fb_rpsi(RtpSession *session, uint8_t *bit_string, uint16_t bit_string_len) { uint16_t bit_string_len_in_bytes; int additional_bytes; int size; mblk_t *h; rtcp_common_header_t *ch; rtcp_fb_header_t *fbh; rtcp_fb_rpsi_fci_t *fci; int i; /* Calculate packet size and allocate memory. */ bit_string_len_in_bytes = (bit_string_len / 8) + (((bit_string_len % 8) == 0) ? 0 : 1); additional_bytes = bit_string_len_in_bytes - 2; if (additional_bytes < 0) additional_bytes = 0; size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + sizeof(rtcp_fb_rpsi_fci_t) + additional_bytes; h = allocb(size, 0); /* Fill RPSI */ ch = (rtcp_common_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_common_header_t); fbh = (rtcp_fb_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_header_t); fci = (rtcp_fb_rpsi_fci_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_rpsi_fci_t); fbh->packet_sender_ssrc = htonl(rtp_session_get_send_ssrc(session)); fbh->media_source_ssrc = htonl(rtp_session_get_recv_ssrc(session)); if (bit_string_len <= 16) { fci->pb = 16 - bit_string_len; memset(&fci->bit_string, 0, 2); } else { fci->pb = (bit_string_len - 16) % 32; memset(&fci->bit_string, 0, bit_string_len_in_bytes); } fci->payload_type = rtp_session_get_recv_payload_type(session) & 0x7F; memcpy(&fci->bit_string, bit_string, bit_string_len / 8); for (i = 0; i < (bit_string_len % 8); i++) { fci->bit_string[bit_string_len_in_bytes - 1] |= (bit_string[bit_string_len_in_bytes - 1] & (1 << (7 - i))); } /* Fill common header */ rtcp_common_header_init(ch, session, RTCP_PSFB, RTCP_PSFB_RPSI, msgdsize(h)); return h; }
static mblk_t * make_rtcp_fb_pli(RtpSession *session) { int size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t); mblk_t *h= allocb(size, 0); rtcp_common_header_t *ch; rtcp_fb_header_t *fbh; /* Fill PLI */ ch = (rtcp_common_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_common_header_t); fbh = (rtcp_fb_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_header_t); fbh->packet_sender_ssrc = htonl(rtp_session_get_send_ssrc(session)); fbh->media_source_ssrc = htonl(rtp_session_get_recv_ssrc(session)); /* Fill common header */ rtcp_common_header_init(ch, session, RTCP_PSFB, RTCP_PSFB_PLI, msgdsize(h)); return h; }
static mblk_t * make_rtcp_fb_tmmbr(RtpSession *session, uint64_t mxtbr, uint16_t measured_overhead) { int size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + sizeof(rtcp_fb_tmmbr_fci_t); mblk_t *h = allocb(size, 0); rtcp_common_header_t *ch; rtcp_fb_header_t *fbh; rtcp_fb_tmmbr_fci_t *fci; uint8_t mxtbr_exp = 0; uint32_t mxtbr_mantissa = 0; /* Compute mxtbr exp and mantissa */ while (mxtbr >= (1 << 17)) { mxtbr >>= 1; mxtbr_exp++; } mxtbr_mantissa = mxtbr & 0x0001FFFF; /* Fill TMMBR */ ch = (rtcp_common_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_common_header_t); fbh = (rtcp_fb_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_header_t); fci = (rtcp_fb_tmmbr_fci_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_tmmbr_fci_t); fbh->packet_sender_ssrc = htonl(rtp_session_get_send_ssrc(session)); fbh->media_source_ssrc = htonl(0); fci->ssrc = htonl(rtp_session_get_recv_ssrc(session)); rtcp_fb_tmmbr_fci_set_mxtbr_exp(fci, mxtbr_exp); rtcp_fb_tmmbr_fci_set_mxtbr_mantissa(fci, mxtbr_mantissa); rtcp_fb_tmmbr_fci_set_measured_overhead(fci, measured_overhead); /* Fill common header */ rtcp_common_header_init(ch, session, RTCP_RTPFB, RTCP_RTPFB_TMMBR, msgdsize(h)); /* Store packet to be able to retransmit. */ if (session->rtcp.tmmbr_info.sent) freemsg(session->rtcp.tmmbr_info.sent); session->rtcp.tmmbr_info.sent = copymsg(h); return h; }
static mblk_t * make_rtcp_fb_generic_nack(RtpSession *session, uint16_t pid, uint16_t blp) { int size = sizeof(rtcp_common_header_t) + sizeof(rtcp_fb_header_t) + sizeof(rtcp_fb_generic_nack_fci_t); mblk_t *h = allocb(size, 0); rtcp_common_header_t *ch; rtcp_fb_header_t *fbh; rtcp_fb_generic_nack_fci_t *fci; ch = (rtcp_common_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_common_header_t); fbh = (rtcp_fb_header_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_header_t); fci = (rtcp_fb_generic_nack_fci_t *)h->b_wptr; h->b_wptr += sizeof(rtcp_fb_generic_nack_fci_t); fbh->packet_sender_ssrc = htonl(rtp_session_get_send_ssrc(session)); fbh->media_source_ssrc = htonl(0); rtcp_fb_generic_nack_fci_set_pid(fci, pid); rtcp_fb_generic_nack_fci_set_blp(fci, blp); /* Fill common header */ rtcp_common_header_init(ch, session, RTCP_RTPFB, RTCP_RTPFB_NACK, msgdsize(h)); return h; }
void linphone_reporting_update_media_info(LinphoneCall * call, int stats_type) { MediaStream * stream = NULL; const PayloadType * local_payload = NULL; const PayloadType * remote_payload = NULL; const LinphoneCallParams * current_params = linphone_call_get_current_params(call); reporting_session_report_t * report = call->log->reporting.reports[stats_type]; char * dialog_id; // call->op might be already released if hanging up in state LinphoneCallOutgoingInit if (!media_report_enabled(call, stats_type) || call->op == NULL) return; dialog_id = sal_op_get_dialog_id(call->op); STR_REASSIGN(report->info.call_id, ms_strdup(call->log->call_id)); STR_REASSIGN(report->local_metrics.user_agent, ms_strdup(linphone_core_get_user_agent(call->core))); STR_REASSIGN(report->remote_metrics.user_agent, ms_strdup(linphone_call_get_remote_user_agent(call))); // RFC states: "LocalGroupID provides the identification for the purposes // of aggregation for the local endpoint.". STR_REASSIGN(report->info.local_addr.group, ms_strdup_printf("%s-%s-%s" , dialog_id ? dialog_id : "" , "local" , report->local_metrics.user_agent ? report->local_metrics.user_agent : "" ) ); STR_REASSIGN(report->info.remote_addr.group, ms_strdup_printf("%s-%s-%s" , dialog_id ? dialog_id : "" , "remote" , report->remote_metrics.user_agent ? report->remote_metrics.user_agent : "" ) ); if (call->dir == LinphoneCallIncoming) { STR_REASSIGN(report->info.remote_addr.id, linphone_address_as_string(call->log->from)); STR_REASSIGN(report->info.local_addr.id, linphone_address_as_string(call->log->to)); STR_REASSIGN(report->info.orig_id, ms_strdup(report->info.remote_addr.id)); } else { STR_REASSIGN(report->info.remote_addr.id, linphone_address_as_string(call->log->to)); STR_REASSIGN(report->info.local_addr.id, linphone_address_as_string(call->log->from)); STR_REASSIGN(report->info.orig_id, ms_strdup(report->info.local_addr.id)); } report->local_metrics.timestamps.start = call->log->start_date_time; report->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); /*we use same timestamps for remote too*/ report->remote_metrics.timestamps.start = call->log->start_date_time; report->remote_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); /*yet we use the same payload config for local and remote, since this is the largest use case*/ if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) { stream = &call->audiostream->ms; local_payload = linphone_call_params_get_used_audio_codec(current_params); remote_payload = local_payload; } else if (stats_type == LINPHONE_CALL_STATS_VIDEO && call->videostream != NULL) { stream = &call->videostream->ms; local_payload = linphone_call_params_get_used_video_codec(current_params); remote_payload = local_payload; } else if (stats_type == LINPHONE_CALL_STATS_TEXT && call->textstream != NULL) { stream = &call->textstream->ms; local_payload = linphone_call_params_get_used_text_codec(current_params); remote_payload = local_payload; } if (stream != NULL) { RtpSession * session = stream->sessions.rtp_session; report->info.local_addr.ssrc = rtp_session_get_send_ssrc(session); report->info.remote_addr.ssrc = rtp_session_get_recv_ssrc(session); if (stream->qi != NULL){ report->local_metrics.quality_estimates.moslq = ms_quality_indicator_get_average_lq_rating(stream->qi) >= 0 ? MAX(1, ms_quality_indicator_get_average_lq_rating(stream->qi)) : -1; report->local_metrics.quality_estimates.moscq = ms_quality_indicator_get_average_rating(stream->qi) >= 0 ? MAX(1, ms_quality_indicator_get_average_rating(stream->qi)) : -1; } } STR_REASSIGN(report->dialog_id, ms_strdup_printf("%s;%u", dialog_id ? dialog_id : "", report->info.local_addr.ssrc)); if (local_payload != NULL) { report->local_metrics.session_description.payload_type = local_payload->type; if (local_payload->mime_type!=NULL) STR_REASSIGN(report->local_metrics.session_description.payload_desc, ms_strdup(local_payload->mime_type)); report->local_metrics.session_description.sample_rate = local_payload->clock_rate; if (local_payload->recv_fmtp!=NULL) STR_REASSIGN(report->local_metrics.session_description.fmtp, ms_strdup(local_payload->recv_fmtp)); } if (remote_payload != NULL) { report->remote_metrics.session_description.payload_type = remote_payload->type; STR_REASSIGN(report->remote_metrics.session_description.payload_desc, ms_strdup(remote_payload->mime_type)); report->remote_metrics.session_description.sample_rate = remote_payload->clock_rate; STR_REASSIGN(report->remote_metrics.session_description.fmtp, ms_strdup(remote_payload->recv_fmtp)); } ms_free(dialog_id); }
static bool_t stateful_analyzer_process_rtcp(MSQosAnalyzer *objbase, mblk_t *rtcp){ MSStatefulQosAnalyzer *obj=(MSStatefulQosAnalyzer*)objbase; const report_block_t *rb=NULL; if (rtcp_is_SR(rtcp)){ rb=rtcp_SR_get_report_block(rtcp,0); }else if (rtcp_is_RR(rtcp)){ rb=rtcp_RR_get_report_block(rtcp,0); } if (rb && report_block_get_ssrc(rb)==rtp_session_get_send_ssrc(obj->session)){ if (ortp_loss_rate_estimator_process_report_block(objbase->lre,&obj->session->rtp,rb)){ int i; float loss_rate = ortp_loss_rate_estimator_get_value(objbase->lre); float up_bw = stateful_qos_analyzer_upload_bandwidth(obj,report_block_get_high_ext_seq(rb)); obj->curindex++; /*flush bandwidth estimation measures for seq number lower than remote report block received*/ for (i=0;i<BW_HISTORY;i++){ if (obj->upload_bandwidth[i].seq_number<report_block_get_high_ext_seq(rb)){ obj->upload_bandwidth[i].seq_number=0; obj->upload_bandwidth[i].up_bandwidth=0.f; } } /* Always skip the first report, since values might be erroneous due to initialization of multiples objects (encoder/decoder/stats computing..) Instead assume loss rate is a good estimation of network capacity */ if (obj->curindex==1) { obj->network_loss_rate=loss_rate; return TRUE; } obj->latest=ms_new0(rtcpstatspoint_t, 1); obj->latest->timestamp=ms_time(0); obj->latest->bandwidth=up_bw; obj->latest->loss_percent=loss_rate; obj->latest->rtt=rtp_session_get_round_trip_propagation(obj->session); obj->rtcpstatspoint=ms_list_insert_sorted(obj->rtcpstatspoint, obj->latest, (MSCompareFunc)sort_by_bandwidth); /*if the measure was 0% loss, reset to 0% every measures below it*/ if (obj->latest->loss_percent < 1e-5){ MSList *it=obj->rtcpstatspoint; MSList *latest_pos=ms_list_find(obj->rtcpstatspoint,obj->latest); while (it!=latest_pos->next){ ((rtcpstatspoint_t *)it->data)->loss_percent=0.f; it = it->next; } } ms_message("MSStatefulQosAnalyzer[%p]: one more %d: %f %f", obj, obj->curindex-1, obj->latest->bandwidth, obj->latest->loss_percent); if (ms_list_size(obj->rtcpstatspoint) > ESTIM_HISTORY){ int prev_size = ms_list_size(obj->rtcpstatspoint); /*clean everything which occurred 60 sec or more ago*/ time_t clear_time = ms_time(0) - 60; obj->rtcpstatspoint = ms_list_remove_custom(obj->rtcpstatspoint, (MSCompareFunc)earlier_than, &clear_time); ms_message("MSStatefulQosAnalyzer[%p]: reached list maximum capacity " "(count=%d) --> Cleaned list (count=%d)", obj, prev_size, ms_list_size(obj->rtcpstatspoint)); } return TRUE; } } return FALSE; }
static bool_t stateful_analyzer_process_rtcp(MSQosAnalyzer *objbase, mblk_t *rtcp){ MSStatefulQosAnalyzer *obj=(MSStatefulQosAnalyzer*)objbase; rtpstats_t *cur; const report_block_t *rb=NULL; if (rtcp_is_SR(rtcp)){ rb=rtcp_SR_get_report_block(rtcp,0); }else if (rtcp_is_RR(rtcp)){ rb=rtcp_RR_get_report_block(rtcp,0); } if (rb && report_block_get_ssrc(rb)==rtp_session_get_send_ssrc(obj->session)){ double up_bw = stateful_qos_analyzer_upload_bandwidth(obj); int total_emitted=stateful_qos_analyzer_get_total_emitted(obj, rb); obj->curindex++; cur=&obj->stats[obj->curindex % STATS_HISTORY]; if (obj->clockrate==0){ PayloadType *pt=rtp_profile_get_payload(rtp_session_get_send_profile(obj->session),rtp_session_get_send_payload_type(obj->session)); if (pt!=NULL) obj->clockrate=pt->clock_rate; else return FALSE; } cur->lost_percentage=100.0*(float)report_block_get_fraction_lost(rb)/256.0; cur->int_jitter=1000.0*(float)report_block_get_interarrival_jitter(rb)/(float)obj->clockrate; cur->rt_prop=rtp_session_get_round_trip_propagation(obj->session); ms_message("MSSimpleQosAnalyzer: lost_percentage=%f, int_jitter=%f ms, rt_prop=%f sec",cur->lost_percentage,cur->int_jitter,cur->rt_prop); if (obj->curindex>2){ double loss_rate = cur->lost_percentage/100.0; int cum_loss=report_block_get_cum_packet_loss(rb); int cum_loss_curr=cum_loss - obj->cum_loss_prev; int uniq_emitted=report_block_get_high_ext_seq(rb) - obj->previous_ext_high_seq_num_rec; if (obj->previous_ext_high_seq_num_rec > 0){ loss_rate=(1. - (uniq_emitted - cum_loss_curr) * 1.f / total_emitted); ms_debug("MSQosStatefulAnalyzer[%p]: RECEIVE estimated loss rate=%f vs 'real'=%f", obj, loss_rate, report_block_get_fraction_lost(rb)/256.); } obj->latest=ms_new0(rtcpstatspoint_t, 1); obj->latest->timestamp=ms_time(0); obj->latest->bandwidth=up_bw; obj->latest->loss_percent=MAX(0,loss_rate); obj->latest->rtt=cur->rt_prop; obj->rtcpstatspoint=ms_list_insert_sorted(obj->rtcpstatspoint, obj->latest, (MSCompareFunc)sort_points); if (obj->latest->loss_percent < 1e-5){ MSList *it=obj->rtcpstatspoint; MSList *latest_pos=ms_list_find(obj->rtcpstatspoint,obj->latest); while (it!=latest_pos->next){ ((rtcpstatspoint_t *)it->data)->loss_percent=0.f; it = it->next; } } ms_debug("MSQosStatefulAnalyzer[%p]: one more %d: %f %f", obj, obj->curindex-2, obj->latest->bandwidth, obj->latest->loss_percent); if (ms_list_size(obj->rtcpstatspoint) > ESTIM_HISTORY){ #ifdef DEBUG int prev_size = ms_list_size(obj->rtcpstatspoint); #endif /*clean everything which occurred 60 sec or more ago*/ time_t clear_time = ms_time(0) - 60; obj->rtcpstatspoint = ms_list_remove_custom(obj->rtcpstatspoint, (MSCompareFunc)earlier_than, &clear_time); ms_debug("MSQosStatefulAnalyzer[%p]: Reached list maximum capacity (count=%d) --> Cleaned list (count=%d)", obj, prev_size, ms_list_size(obj->rtcpstatspoint)); } } obj->cum_loss_prev=report_block_get_cum_packet_loss(rb); obj->previous_ext_high_seq_num_rec=report_block_get_high_ext_seq(rb); } return rb!=NULL; }