static float stateful_qos_analyzer_upload_bandwidth(MSStatefulQosAnalyzer *obj, uint32_t seq_num){ int latest_bw; float bw_per_seqnum=0.f; float bw_per_avg=0.f; /*First method to compute bandwidth*/ if (obj->upload_bandwidth_count){ bw_per_avg=obj->upload_bandwidth_sum/obj->upload_bandwidth_count; } obj->upload_bandwidth_count=0; obj->upload_bandwidth_sum=0; for (latest_bw=0;latest_bw<BW_HISTORY;++latest_bw){ ms_debug("MSStatefulQosAnalyzer[%p]:\t%u\t-->\t%f", obj, obj->upload_bandwidth[latest_bw].seq_number, obj->upload_bandwidth[latest_bw].up_bandwidth); } if (obj->upload_bandwidth[(obj->upload_bandwidth_cur+1)%BW_HISTORY].seq_number>seq_num){ ms_warning("MSStatefulQosAnalyzer[%p]: saved to much points - seq_number lower " "than oldest measure! Increase BW_HISTORY or reduce ptime!", obj); }else{ int count = 0; latest_bw=obj->upload_bandwidth_cur; /*Get the average of all measures with seq number lower than the one from the report*/ for (latest_bw=0; latest_bw<BW_HISTORY; ++latest_bw){ if (obj->upload_bandwidth[latest_bw].seq_number>0 && obj->upload_bandwidth[latest_bw].seq_number<seq_num){ count++; bw_per_seqnum+=obj->upload_bandwidth[latest_bw].up_bandwidth; } } // invalid, no measures available if (count==0){ ms_error("MSStatefulQosAnalyzer[%p]: no measures available to compute bandwidth for ext_seq=%u", obj, seq_num); bw_per_seqnum = rtp_session_get_send_bandwidth(obj->session)/1000.0; }else{ bw_per_seqnum /= count;//((BW_HISTORY + obj->upload_bandwidth_cur - latest_bw) % BW_HISTORY); ms_debug("MSStatefulQosAnalyzer[%p]: found average bandwidth for seq_num=%u", obj, seq_num); } } ms_message("MSStatefulQosAnalyzer[%p]: bw_curent=%f vs bw_per_avg=%f vs bw_per_seqnum=%f" , obj , rtp_session_get_send_bandwidth(obj->session)/1000.0 , bw_per_avg , bw_per_seqnum); obj->upload_bandwidth_latest = bw_per_seqnum; return obj->upload_bandwidth_latest; }
static void stateful_analyzer_update(MSQosAnalyzer *objbase){ MSStatefulQosAnalyzer *obj=(MSStatefulQosAnalyzer*)objbase; static time_t last_measure; if (last_measure != ms_time(0)){ obj->upload_bandwidth_count++; obj->upload_bandwidth_sum+=rtp_session_get_send_bandwidth(obj->session)/1000.0; } last_measure = ms_time(0); if (obj->burst_duration_ms>0){ switch (obj->burst_state){ case MSStatefulQosAnalyzerBurstEnable:{ obj->burst_state=MSStatefulQosAnalyzerBurstInProgress; ortp_gettimeofday(&obj->start_time, NULL); rtp_session_set_duplication_ratio(obj->session, obj->burst_ratio); obj->start_seq_number=obj->last_seq_number=obj->session->rtp.snd_seq; } case MSStatefulQosAnalyzerBurstInProgress: { struct timeval now; double elapsed; ortp_gettimeofday(&now,NULL); elapsed=((now.tv_sec-obj->start_time.tv_sec)*1000.0) + ((now.tv_usec-obj->start_time.tv_usec)/1000.0); obj->last_seq_number=obj->session->rtp.snd_seq; if (elapsed > obj->burst_duration_ms){ obj->burst_state=MSStatefulQosAnalyzerBurstDisable; rtp_session_set_duplication_ratio(obj->session, 0); } } case MSStatefulQosAnalyzerBurstDisable: { } } } }
static void stateful_analyzer_update(MSQosAnalyzer *objbase){ MSStatefulQosAnalyzer *obj=(MSStatefulQosAnalyzer*)objbase; static time_t last_measure; /* Every seconds, save the bandwidth used. This is needed to know how much bandwidth was used when receiving a receiver report. Since the report contains the "last sequence number", it allows us to precisely know which interval to consider */ if (last_measure != ms_time(0)){ obj->upload_bandwidth_count++; obj->upload_bandwidth_sum+=rtp_session_get_send_bandwidth(obj->session)/1000.0; /* Save bandwidth used at this time */ obj->upload_bandwidth[obj->upload_bandwidth_cur].seq_number = rtp_session_get_seq_number(obj->session); obj->upload_bandwidth[obj->upload_bandwidth_cur].up_bandwidth = rtp_session_get_send_bandwidth(obj->session)/1000.0; obj->upload_bandwidth_cur = (obj->upload_bandwidth_cur+1)%BW_HISTORY; } last_measure = ms_time(0); if (obj->burst_duration_ms>0){ switch (obj->burst_state){ case MSStatefulQosAnalyzerBurstEnable:{ obj->burst_state=MSStatefulQosAnalyzerBurstInProgress; ortp_gettimeofday(&obj->start_time, NULL); rtp_session_set_duplication_ratio(obj->session, obj->burst_ratio); } case MSStatefulQosAnalyzerBurstInProgress: { struct timeval now; float elapsed; ortp_gettimeofday(&now,NULL); elapsed=((now.tv_sec-obj->start_time.tv_sec)*1000.0) + ((now.tv_usec-obj->start_time.tv_usec)/1000.0); if (elapsed > obj->burst_duration_ms){ obj->burst_state=MSStatefulQosAnalyzerBurstDisable; rtp_session_set_duplication_ratio(obj->session, 0); } } case MSStatefulQosAnalyzerBurstDisable: { } } } }
static double stateful_qos_analyzer_upload_bandwidth(MSStatefulQosAnalyzer *obj){ #ifdef DEBUG double up_bw=rtp_session_get_send_bandwidth(obj->session)/1000.0; #endif if (obj->upload_bandwidth_count){ obj->upload_bandwidth_latest=obj->upload_bandwidth_sum/obj->upload_bandwidth_count; } obj->upload_bandwidth_count=0; obj->upload_bandwidth_sum=0; ms_debug("MSQosStatefulAnalyzer[%p]: latest_up_bw=%f vs sum_up_bw=%f", obj, up_bw, obj->upload_bandwidth_latest); return obj->upload_bandwidth_latest; }
static void upload_bandwidth_computation() { bool_t supported = ms_filter_codec_supported("pcma"); if( supported ) { stream_manager_t * marielle, * margaux; int i; start_adaptive_stream(AudioStreamType, &marielle, &margaux, PCMA8_PAYLOAD_TYPE, 8000, 0, 0, 0, 0); media_stream_enable_adaptive_bitrate_control(&marielle->audio_stream->ms,FALSE); for (i = 0; i < 5; i++){ rtp_session_set_duplication_ratio(marielle->audio_stream->ms.sessions.rtp_session, i); iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 2*(i+1)); /*since PCMA uses 80kbit/s, upload bandwidth should just be 80+80*duplication_ratio kbit/s */ CU_ASSERT_TRUE(fabs(rtp_session_get_send_bandwidth(marielle->audio_stream->ms.sessions.rtp_session)/1000. - 80.*(i+1)) < 1.f); } stop_adaptive_stream(marielle,margaux); } }
float media_stream_get_up_bw(const MediaStream *stream) { return rtp_session_get_send_bandwidth(stream->sessions.rtp_session); }