Commit aeed2fa7 authored by Sylvain Berfini's avatar Sylvain Berfini 🎩

Added ortp video bandwidth estimator in bandwidth controller

parent bc087e2a
......@@ -40,6 +40,8 @@ struct _MSBandwidthController{
bctbx_list_t *streams; /*list of MediaStream objects*/
struct _MediaStream *controlled_stream; /*the most bandwidth consuming stream, which is the one flow controlled*/
MSBandwidthControllerStats stats;
bool_t congestion_detected;
float remote_video_bandwidth_available_estimated;
};
/**
* The MSBandwidthController is a object managing several streams (audio, video) and monitoring congestion of inbound streams.
......
......@@ -76,6 +76,7 @@ static void on_congestion_state_changed(const OrtpEventData *evd, void *user_poi
ms, ms_format_type_to_string(ms->type));
return;
}
obj->congestion_detected = evd->info.congestion_detected;
session = obj->controlled_stream->sessions.rtp_session;
if (evd->info.congestion_detected){
/*We are detecting a congestion. First estimate the total bandwidth received at the time of the congestion*/
......@@ -102,11 +103,25 @@ static void on_congestion_state_changed(const OrtpEventData *evd, void *user_poi
rtp_session_send_rtcp_fb_tmmbr(session, (uint64_t)controlled_stream_bandwidth_requested);
}
static void on_video_bandwidth_estimation_available(const OrtpEventData *evd, void *user_pointer) {
MediaStream *ms = (MediaStream*)user_pointer;
MSBandwidthController *obj = ms->bandwidth_controller;
if (!obj->congestion_detected) {
RtpSession *session = obj->controlled_stream->sessions.rtp_session;
float estimated_bitrate = evd->info.video_bandwidth_available;
ms_message("MSBandwidthController: video bandwidth estimation available, sending tmmbr for stream [%p][%s] for target [%f] kbit/s",
obj->controlled_stream, ms_format_type_to_string(obj->controlled_stream->type), estimated_bitrate / 1000);
obj->remote_video_bandwidth_available_estimated = estimated_bitrate;
rtp_session_send_rtcp_fb_tmmbr(session, (uint64_t)estimated_bitrate);
}
}
/*THis function just selects a video stream if any, or an audio stream otherwise.
* It could be refined to select the most consuming stream...*/
static void elect_controlled_stream(MSBandwidthController *obj){
bctbx_list_t *elem;
bool_t done = FALSE;
OrtpVideoBandwidthEstimatorParams params = {0};
obj->controlled_stream = NULL;
for (elem = obj->streams; elem != NULL && !done; elem = elem->next){
......@@ -118,6 +133,10 @@ static void elect_controlled_stream(MSBandwidthController *obj){
case MSVideo:
obj->controlled_stream = ms;
done = TRUE;
ortp_ev_dispatcher_connect(media_stream_get_event_dispatcher(ms), ORTP_EVENT_NEW_VIDEO_BANDWIDTH_ESTIMATION_AVAILABLE, 0,
on_video_bandwidth_estimation_available, ms);
params.enabled = TRUE;
rtp_session_enable_video_bandwidth_estimator(ms->sessions.rtp_session, &params);
break;
case MSText:
break;
......@@ -127,7 +146,6 @@ static void elect_controlled_stream(MSBandwidthController *obj){
}
}
void ms_bandwidth_controller_add_stream(MSBandwidthController *obj, struct _MediaStream *stream){
ortp_ev_dispatcher_connect(media_stream_get_event_dispatcher(stream), ORTP_EVENT_CONGESTION_STATE_CHANGED, 0,
on_congestion_state_changed, stream);
......@@ -138,10 +156,15 @@ void ms_bandwidth_controller_add_stream(MSBandwidthController *obj, struct _Medi
}
void ms_bandwidth_controller_remove_stream(MSBandwidthController *obj, struct _MediaStream *stream){
OrtpVideoBandwidthEstimatorParams params = {0};
if (bctbx_list_find(obj->streams, stream) == NULL) return;
ortp_ev_dispatcher_disconnect(media_stream_get_event_dispatcher(stream), ORTP_EVENT_CONGESTION_STATE_CHANGED, 0,
on_congestion_state_changed);
rtp_session_enable_congestion_detection(stream->sessions.rtp_session, FALSE);
ortp_ev_dispatcher_disconnect(media_stream_get_event_dispatcher(stream), ORTP_EVENT_NEW_VIDEO_BANDWIDTH_ESTIMATION_AVAILABLE, 0,
on_video_bandwidth_estimation_available);
params.enabled = FALSE;
rtp_session_enable_video_bandwidth_estimator(stream->sessions.rtp_session, &params);
stream->bandwidth_controller = NULL;
obj->streams = bctbx_list_remove(obj->streams, stream);
elect_controlled_stream(obj);
......
......@@ -89,6 +89,7 @@ typedef struct _stream_manager_t {
float congestion_bw_estim;
} adaptive_stats;
MSBandwidthController *bw_controller;
void* user_data;
} stream_manager_t ;
......@@ -105,6 +106,7 @@ stream_manager_t * stream_manager_new(MSFormatType type) {
}else{
#if VIDEO_ENABLED
mgr->video_stream=video_stream_new (_factory, mgr->local_rtp, mgr->local_rtcp,FALSE);
mgr->bw_controller = ms_bandwidth_controller_new();
#else
ms_fatal("Unsupported stream type [%s]",ms_format_type_to_string(mgr->type));
#endif
......@@ -124,6 +126,7 @@ static void stream_manager_delete(stream_manager_t * mgr) {
audio_stream_stop(mgr->audio_stream);
}else{
#if VIDEO_ENABLED
ms_bandwidth_controller_destroy(mgr->bw_controller);
video_stream_stop(mgr->video_stream);
#else
ms_fatal("Unsupported stream type [%s]",ms_format_type_to_string(mgr->type));
......@@ -258,9 +261,16 @@ void start_adaptive_stream(MSFormatType type, stream_manager_t ** pmarielle, str
audio_manager_start(margaux,payload,marielle->local_rtp,0,NULL,recorded_file);
}else{
#if VIDEO_ENABLED
struct _MediaStream *margaux_video_stream = &(margaux->video_stream->ms);
OrtpVideoBandwidthEstimatorParams params = {0};
marielle->video_stream->staticimage_webcam_fps_optimization = FALSE;
video_manager_start(marielle,payload,margaux->local_rtp,0,marielle_webcam);
video_stream_set_direction(margaux->video_stream, MediaStreamRecvOnly);
ms_bandwidth_controller_add_stream(margaux->bw_controller, margaux_video_stream);
params.packet_count_min = 5;
params.packets_size_max = 5;
params.enabled = TRUE;
rtp_session_enable_video_bandwidth_estimator(margaux_video_stream->sessions.rtp_session, &params);
video_manager_start(margaux,payload,marielle->local_rtp,0,NULL);
#else
ms_fatal("Unsupported stream type [%s]",ms_format_type_to_string(marielle->type));
......@@ -304,6 +314,9 @@ static void iterate_adaptive_stream(stream_manager_t * marielle, stream_manager_
}
static void stop_adaptive_stream(stream_manager_t *marielle, stream_manager_t *margaux, bool_t destroy_files){
#if VIDEO_ENABLED
ms_bandwidth_controller_remove_stream(margaux->bw_controller, &(margaux->video_stream->ms));
#endif
stream_manager_delete(marielle);
stream_manager_delete(margaux);
}
......@@ -523,14 +536,14 @@ static void upload_bitrate_opus_3g(void) {
void adaptive_video(int max_bw, int exp_min_bw, int exp_max_bw, int loss_rate, int exp_min_loss, int exp_max_loss) {
bool_t supported = ms_filter_codec_supported("VP8");
if( supported ) {
stream_manager_t * marielle, * margaux;
start_adaptive_stream(MSVideo, &marielle, &margaux, VP8_PAYLOAD_TYPE, 300*1000, max_bw*1000, loss_rate, 50,0);
stream_manager_t *marielle, *margaux;
start_adaptive_stream(MSVideo, &marielle, &margaux, VP8_PAYLOAD_TYPE, 300*1000, max_bw*1000, loss_rate, 50, 0, 0);
iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 7);
BC_ASSERT_GREATER(marielle->adaptive_stats.loss_estim, exp_min_loss, int, "%d");
BC_ASSERT_LOWER(marielle->adaptive_stats.loss_estim, exp_max_loss, int, "%d");
BC_ASSERT_GREATER(marielle->adaptive_stats.congestion_bw_estim, exp_min_bw, int, "%d");
BC_ASSERT_LOWER(marielle->adaptive_stats.congestion_bw_estim, exp_max_bw, int, "%d");
stop_adaptive_stream(marielle,margaux,TRUE);
stop_adaptive_stream(marielle, margaux, TRUE);
}
}
......@@ -549,6 +562,18 @@ static void adaptive_vp8_lossy_congestion() {
}
#endif
void video_bandwidth_estimation(int exp_bw_min, int exp_bw_max) {
stream_manager_t * marielle, * margaux;
start_adaptive_stream(MSVideo, &marielle, &margaux, VP8_PAYLOAD_TYPE, THIRDGENERATION_BW*1000, THIRDGENERATION_BW*1000, 0, 50, 0, FALSE);
iterate_adaptive_stream(marielle, margaux, 600000, (int *)&margaux->bw_controller->remote_video_bandwidth_available_estimated, 1);
BC_ASSERT_GREATER(margaux->bw_controller->remote_video_bandwidth_available_estimated, exp_bw_min, int, "%d");
BC_ASSERT_LOWER(margaux->bw_controller->remote_video_bandwidth_available_estimated, exp_bw_max, int, "%d");
stop_adaptive_stream(marielle, margaux, TRUE);
}
static void video_bandwidth_estimator(void) {
video_bandwidth_estimation(300000000, 1000000000); // kbits/s
}
static test_t tests[] = {
TEST_NO_TAG("Packet duplication", packet_duplication),
......@@ -568,6 +593,7 @@ static test_t tests[] = {
TEST_NO_TAG("Network detection [VP8] - congested", adaptive_vp8_congestion),
TEST_NO_TAG("Network detection [VP8] - lossy congested", adaptive_vp8_lossy_congestion),
#endif
TEST_NO_TAG("Video bandwidth estimator", video_bandwidth_estimator),
};
test_suite_t adaptive_test_suite = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment