From 98f2508be596de011740228d973996608da53cd6 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 18 Jun 2015 14:33:11 +0200 Subject: [PATCH] Allow linphone to be configured to use RTP sessions for input/output of audio and video streams. --- coreapi/linphonecall.c | 127 +++++++++++++++++++++++++++++++++-------- coreapi/linphonecore.c | 3 +- coreapi/private.h | 2 + gtk/videowindow.c | 24 ++++---- mediastreamer2 | 2 +- oRTP | 2 +- 6 files changed, 123 insertions(+), 37 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index ef5d93643..511265742 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2513,6 +2513,30 @@ void static set_dtls_fingerprint_on_all_streams(LinphoneCall *call) { return; } +static RtpSession * create_audio_rtp_io_session(LinphoneCall *call) { + PayloadType *pt; + LinphoneCore *lc = call->core; + const char *local_ip = lp_config_get_string(lc->config, "sound", "rtp_local_addr", "127.0.0.1"); + const char *remote_ip = lp_config_get_string(lc->config, "sound", "rtp_remote_addr", "127.0.0.1"); + int local_port = lp_config_get_int(lc->config, "sound", "rtp_local_port", 17076); + int remote_port = lp_config_get_int(lc->config, "sound", "rtp_remote_port", 17078); + int ptnum = lp_config_get_int(lc->config, "sound", "rtp_ptnum", 0); + const char *rtpmap = lp_config_get_string(lc->config, "sound", "rtp_map", "pcmu/8000/1"); + RtpSession *rtp_session = NULL; + pt = rtp_profile_get_payload_from_rtpmap(call->audio_profile, rtpmap); + if (pt != NULL) { + call->rtp_io_audio_profile = rtp_profile_new("RTP IO audio profile"); + rtp_profile_set_payload(call->rtp_io_audio_profile, ptnum, payload_type_clone(pt)); + rtp_session = ms_create_duplex_rtp_session(local_ip, local_port, -1); + rtp_session_set_profile(rtp_session, call->rtp_io_audio_profile); + rtp_session_set_remote_addr_and_port(rtp_session, remote_ip, remote_port, -1); + rtp_session_enable_rtcp(rtp_session, FALSE); + rtp_session_set_payload_type(rtp_session, ptnum); + rtp_session_set_jitter_compensation(rtp_session, linphone_core_get_audio_jittcomp(lc)); + } + return rtp_session; +} + static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){ LinphoneCore *lc=call->core; LpConfig* conf; @@ -2527,6 +2551,8 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b const char *recfile; const SalStreamDescription *local_st_desc; int crypto_idx; + AudioStreamIO io = { 0 }; + bool_t use_rtp_io = lp_config_get_int(lc->config, "sound", "rtp_io", FALSE); snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version()); @@ -2542,6 +2568,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt); if (used_pt!=-1){ + bool_t ok = TRUE; call->current_params->audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt); if (playcard==NULL) { ms_warning("No card defined for playback !"); @@ -2573,7 +2600,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b } } /*if playfile are supplied don't use soundcards*/ - if (lc->use_files) { + if (lc->use_files || use_rtp_io) { captcard=NULL; playcard=NULL; } @@ -2612,22 +2639,32 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b if (is_multicast) rtp_session_set_multicast_ttl(call->audiostream->ms.sessions.rtp_session,stream->ttl); - audio_stream_start_full( - call->audiostream, - call->audio_profile, - rtp_addr, - stream->rtp_port, - stream->rtcp_addr[0]!='\0' ? stream->rtcp_addr : call->resultdesc->addr, - (linphone_core_rtcp_enabled(lc) && !is_multicast) ? (stream->rtcp_port ? stream->rtcp_port : stream->rtp_port+1) : 0, - used_pt, - linphone_core_get_audio_jittcomp(lc), - playfile, - recfile, - playcard, - captcard, - use_ec + if (lc->use_files) { + io.input_file = playfile; + io.output_file = recfile; + } else if (use_rtp_io) { + io.rtp_session = create_audio_rtp_io_session(call); + if (io.rtp_session == NULL) { + ok = FALSE; + } + } else { + io.playback_card = playcard; + io.capture_card = captcard; + } + if (ok == TRUE) { + audio_stream_start_from_io(call->audiostream, + call->audio_profile, + rtp_addr, + stream->rtp_port, + stream->rtcp_addr[0]!='\0' ? stream->rtcp_addr : call->resultdesc->addr, + (linphone_core_rtcp_enabled(lc) && !is_multicast) ? (stream->rtcp_port ? stream->rtcp_port : stream->rtp_port+1) : 0, + used_pt, + linphone_core_get_audio_jittcomp(lc), + use_ec, + &io ); - post_configure_audio_streams(call, muted && !send_ringbacktone); + post_configure_audio_streams(call, muted && !send_ringbacktone); + } media_stream_session_encryption_mandatory_enable(&call->audiostream->ms.sessions,linphone_core_is_media_encryption_mandatory(call->core)); @@ -2650,6 +2687,29 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, bool_t muted, b } } +static RtpSession * create_video_rtp_io_session(LinphoneCall *call) { + PayloadType *pt; + LinphoneCore *lc = call->core; + const char *local_ip = lp_config_get_string(lc->config, "video", "rtp_local_addr", "127.0.0.1"); + const char *remote_ip = lp_config_get_string(lc->config, "video", "rtp_remote_addr", "127.0.0.1"); + int local_port = lp_config_get_int(lc->config, "video", "rtp_local_port", 19076); + int remote_port = lp_config_get_int(lc->config, "video", "rtp_remote_port", 19078); + int ptnum = lp_config_get_int(lc->config, "video", "rtp_ptnum", 0); + const char *rtpmap = lp_config_get_string(lc->config, "video", "rtp_map", "vp8/90000/1"); + RtpSession *rtp_session = NULL; + pt = rtp_profile_get_payload_from_rtpmap(call->video_profile, rtpmap); + if (pt != NULL) { + call->rtp_io_video_profile = rtp_profile_new("RTP IO video profile"); + rtp_profile_set_payload(call->rtp_io_video_profile, ptnum, payload_type_clone(pt)); + rtp_session = ms_create_duplex_rtp_session(local_ip, local_port, -1); + rtp_session_set_profile(rtp_session, call->rtp_io_video_profile); + rtp_session_set_remote_addr_and_port(rtp_session, remote_ip, remote_port, -1); + rtp_session_enable_rtcp(rtp_session, FALSE); + rtp_session_set_payload_type(rtp_session, ptnum); + } + return rtp_session; +} + static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inputs_muted){ #ifdef VIDEO_ENABLED LinphoneCore *lc=call->core; @@ -2657,7 +2717,8 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu const SalStreamDescription *vstream; MSFilter* source = NULL; bool_t reused_preview = FALSE; - + bool_t use_rtp_io = lp_config_get_int(lc->config, "video", "rtp_io", FALSE); + VideoStreamIO io = { 0 }; /* shutdown preview */ if (lc->previewstream!=NULL) { @@ -2746,7 +2807,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu rtp_session_set_multicast_ttl(call->videostream->ms.sessions.rtp_session,vstream->ttl); video_stream_use_video_preset(call->videostream, lp_config_get_string(lc->config, "video", "preset", NULL)); - if( lc->video_conf.reuse_preview_source && source ){ + if (lc->video_conf.reuse_preview_source && source) { ms_message("video_stream_start_with_source kept: %p", source); video_stream_start_with_source(call->videostream, call->video_profile, rtp_addr, vstream->rtp_port, @@ -2755,11 +2816,23 @@ static void linphone_call_start_video_stream(LinphoneCall *call, bool_t all_inpu used_pt, linphone_core_get_video_jittcomp(lc), cam, source); reused_preview = TRUE; } else { - video_stream_start(call->videostream, - call->video_profile, rtp_addr, vstream->rtp_port, - rtcp_addr, - (linphone_core_rtcp_enabled(lc) && !is_multicast) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0, - used_pt, linphone_core_get_video_jittcomp(lc), cam); + bool_t ok = TRUE; + if (use_rtp_io) { + io.rtp_session = create_video_rtp_io_session(call); + if (io.rtp_session == NULL) { + ok = FALSE; + ms_warning("Cannot create video RTP IO session"); + } + } else { + io.cam = cam; + } + if (ok) { + video_stream_start_from_io(call->videostream, + call->video_profile, rtp_addr, vstream->rtp_port, + rtcp_addr, + (linphone_core_rtcp_enabled(lc) && !is_multicast) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0, + used_pt, linphone_core_get_video_jittcomp(lc), &io); + } } media_stream_session_encryption_mandatory_enable(&call->videostream->ms.sessions,linphone_core_is_media_encryption_mandatory(call->core)); } @@ -3056,6 +3129,14 @@ void linphone_call_stop_media_streams(LinphoneCall *call){ call->video_profile=NULL; unset_rtp_profile(call,1); } + if (call->rtp_io_audio_profile) { + rtp_profile_destroy(call->rtp_io_audio_profile); + call->rtp_io_audio_profile = NULL; + } + if (call->rtp_io_video_profile) { + rtp_profile_destroy(call->rtp_io_video_profile); + call->rtp_io_video_profile = NULL; + } } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 8f5e8ba7f..8950308a9 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -6527,6 +6527,7 @@ void linphone_core_soundcard_hint_check( LinphoneCore* lc){ MSList* the_calls = lc->calls; LinphoneCall* call = NULL; bool_t dont_need_sound = TRUE; + bool_t use_rtp_io = lp_config_get_int(lc->config, "sound", "rtp_input", FALSE); /* check if the remaining calls are paused */ while( the_calls ){ @@ -6539,7 +6540,7 @@ void linphone_core_soundcard_hint_check( LinphoneCore* lc){ } /* if no more calls or all calls are paused, we can free the soundcard */ - if ( (lc->calls==NULL || dont_need_sound) && !lc->use_files){ + if ( (lc->calls==NULL || dont_need_sound) && !lc->use_files && !use_rtp_io){ ms_message("Notifying soundcard that we don't need it anymore for calls."); notify_soundcard_usage(lc,FALSE); } diff --git a/coreapi/private.h b/coreapi/private.h index 6bc191ab0..deae8cac2 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -222,6 +222,8 @@ struct _LinphoneCall{ SalMediaDescription *resultdesc; struct _RtpProfile *audio_profile; struct _RtpProfile *video_profile; + struct _RtpProfile *rtp_io_audio_profile; + struct _RtpProfile *rtp_io_video_profile; struct _LinphoneCallLog *log; LinphoneAddress *me; /*Either from or to based on call dir*/ SalOp *op; diff --git a/gtk/videowindow.c b/gtk/videowindow.c index 07a22bf29..f0a8b2e5b 100644 --- a/gtk/videowindow.c +++ b/gtk/videowindow.c @@ -292,17 +292,19 @@ void linphone_gtk_in_call_show_video(LinphoneCall *call){ GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window"); const LinphoneCallParams *params=linphone_call_get_current_params(call); LinphoneCore *lc=linphone_gtk_get_core(); - - if (linphone_call_get_state(call)!=LinphoneCallPaused && params && linphone_call_params_video_enabled(params)){ - if (video_window==NULL){ - video_window=create_video_window(call); - g_object_set_data(G_OBJECT(callview),"video_window",video_window); - } - linphone_core_set_native_video_window_id(lc,get_native_handle(gtk_widget_get_window(video_window))); - }else{ - if (video_window){ - gtk_widget_destroy(video_window); - g_object_set_data(G_OBJECT(callview),"video_window",NULL); + + if (((bool_t)lp_config_get_int(linphone_core_get_config(lc), "video", "rtp_io", FALSE)) == FALSE) { + if (linphone_call_get_state(call)!=LinphoneCallPaused && params && linphone_call_params_video_enabled(params)){ + if (video_window==NULL){ + video_window=create_video_window(call); + g_object_set_data(G_OBJECT(callview),"video_window",video_window); + } + linphone_core_set_native_video_window_id(lc,get_native_handle(gtk_widget_get_window(video_window))); + }else{ + if (video_window){ + gtk_widget_destroy(video_window); + g_object_set_data(G_OBJECT(callview),"video_window",NULL); + } } } } diff --git a/mediastreamer2 b/mediastreamer2 index 85f0d4278..d348ca973 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 85f0d427898c83fe1f92d735f8d53198fc77d145 +Subproject commit d348ca973af095425510e184b6800413a0dd0c14 diff --git a/oRTP b/oRTP index 7170e5c62..75baaa535 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 7170e5c6242b305114c681940ec78260847122ff +Subproject commit 75baaa5353f202172428c106e86202242e264a0f