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 loss_rate_estimation() { bool_t supported = ms_filter_codec_supported("pcma"); if( supported ) { LossRateEstimatorCtx ctx; stream_manager_t * marielle, * margaux; int loss_rate = 15; start_adaptive_stream(MSAudio, &marielle, &margaux, PCMA8_PAYLOAD_TYPE, 8000, 0, loss_rate, 0, 0); ctx.estimator=ortp_loss_rate_estimator_new(120, 2500, marielle->audio_stream->ms.sessions.rtp_session); ctx.q = ortp_ev_queue_new(); rtp_session_register_event_queue(marielle->audio_stream->ms.sessions.rtp_session, ctx.q); ctx.loss_rate = loss_rate; /*loss rate should be the initial one*/ wait_for_until_with_parse_events(&marielle->audio_stream->ms, &margaux->audio_stream->ms, &loss_rate, 100, 10000, event_queue_cb,&ctx,NULL,NULL); /*let's set some duplication. loss rate should NOT be changed */ rtp_session_set_duplication_ratio(marielle->audio_stream->ms.sessions.rtp_session, 10); wait_for_until_with_parse_events(&marielle->audio_stream->ms, &margaux->audio_stream->ms, &loss_rate, 100, 10000, event_queue_cb,&ctx,NULL,NULL); stop_adaptive_stream(marielle,margaux); ortp_loss_rate_estimator_destroy(ctx.estimator); ortp_ev_queue_destroy(ctx.q); } }
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 void start_adaptive_stream(StreamType type, stream_manager_t ** pmarielle, stream_manager_t ** pmargaux, int payload, int initial_bitrate, int target_bw, float loss_rate, int latency, float dup_ratio) { OrtpNetworkSimulatorParams params={0}; params.enabled=TRUE; params.loss_rate=loss_rate; params.max_bandwidth=target_bw; params.latency=latency; int pause_time=0; MediaStream *marielle_ms,*margaux_ms; #if VIDEO_ENABLED MSWebCam * marielle_webcam=ms_web_cam_manager_get_default_cam (ms_web_cam_manager_get()); #endif stream_manager_t *marielle=*pmarielle=stream_manager_new(type); stream_manager_t *margaux=*pmargaux=stream_manager_new(type); if (type == AudioStreamType){ marielle_ms=&marielle->audio_stream->ms; margaux_ms=&margaux->audio_stream->ms; }else{ marielle_ms=&marielle->video_stream->ms; margaux_ms=&margaux->video_stream->ms; } /* Disable avpf. */ PayloadType* pt = rtp_profile_get_payload(&rtp_profile, VP8_PAYLOAD_TYPE); CU_ASSERT_PTR_NOT_NULL_FATAL(pt); payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED); media_stream_enable_adaptive_bitrate_control(marielle_ms,TRUE); rtp_session_set_duplication_ratio(marielle_ms->sessions.rtp_session, dup_ratio); if (marielle->type == AudioStreamType){ audio_manager_start(marielle,payload,margaux->local_rtp,initial_bitrate,HELLO_16K_1S_FILE,NULL); ms_filter_call_method(marielle->audio_stream->soundread,MS_FILE_PLAYER_LOOP,&pause_time); audio_manager_start(margaux,payload,marielle->local_rtp,0,NULL,RECORDED_16K_1S_FILE); }else{ #if VIDEO_ENABLED video_manager_start(marielle,payload,margaux->local_rtp,0,marielle_webcam); video_stream_set_direction(margaux->video_stream,VideoStreamRecvOnly); video_manager_start(margaux,payload,marielle->local_rtp,0,NULL); #else ms_fatal("Unsupported stream type [%s]",ms_stream_type_to_string(marielle->type)); #endif } rtp_session_enable_network_simulation(margaux_ms->sessions.rtp_session,¶ms); }
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); } }
void start_adaptive_stream(MSFormatType type, stream_manager_t ** pmarielle, stream_manager_t ** pmargaux, int payload, int initial_bitrate, int max_bw, float loss_rate, int latency, float dup_ratio) { int pause_time=0; PayloadType* pt; MediaStream *marielle_ms,*margaux_ms; OrtpNetworkSimulatorParams params={0}; #if VIDEO_ENABLED MSWebCam * marielle_webcam=ms_web_cam_manager_get_default_cam (ms_web_cam_manager_get()); #endif stream_manager_t *marielle=*pmarielle=stream_manager_new(type); stream_manager_t *margaux=*pmargaux=stream_manager_new(type); char* file = ms_strdup_printf("%s/%s", mediastreamer2_tester_get_file_root(), HELLO_16K_1S_FILE); char* recorded_file = ms_strdup_printf("%s/%s", mediastreamer2_tester_get_writable_dir(), RECORDED_16K_1S_FILE); marielle->user_data = recorded_file; params.enabled=TRUE; params.loss_rate=loss_rate; params.max_bandwidth=max_bw; params.latency=latency; if (type == MSAudio){ marielle_ms=&marielle->audio_stream->ms; margaux_ms=&margaux->audio_stream->ms; }else{ marielle_ms=&marielle->video_stream->ms; margaux_ms=&margaux->video_stream->ms; } /* Disable avpf. */ pt = rtp_profile_get_payload(&rtp_profile, VP8_PAYLOAD_TYPE); CU_ASSERT_PTR_NOT_NULL_FATAL(pt); payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED); media_stream_enable_adaptive_bitrate_control(marielle_ms,TRUE); media_stream_set_adaptive_bitrate_algorithm(marielle_ms, MSQosAnalyzerAlgorithmStateful); rtp_session_set_duplication_ratio(marielle_ms->sessions.rtp_session, dup_ratio); if (marielle->type == MSAudio){ audio_manager_start(marielle,payload,margaux->local_rtp,initial_bitrate,file,NULL); ms_filter_call_method(marielle->audio_stream->soundread,MS_FILE_PLAYER_LOOP,&pause_time); audio_manager_start(margaux,payload,marielle->local_rtp,0,NULL,recorded_file); }else{ #if VIDEO_ENABLED video_manager_start(marielle,payload,margaux->local_rtp,0,marielle_webcam); video_stream_set_direction(margaux->video_stream,VideoStreamRecvOnly); video_manager_start(margaux,payload,marielle->local_rtp,0,NULL); #else ms_fatal("Unsupported stream type [%s]",ms_format_type_to_string(marielle->type)); #endif } ms_qos_analyzer_set_on_action_suggested(ms_bitrate_controller_get_qos_analyzer(marielle_ms->rc), qos_analyzer_on_action_suggested, *pmarielle); rtp_session_enable_network_simulation(margaux_ms->sessions.rtp_session,¶ms); ms_free(recorded_file); ms_free(file); }