Linphone_android jni下音视频流、初始化流程分析

来源:互联网 发布:手机知乎如何退出 编辑:程序博客网 时间:2024/06/06 12:23
本来流程顺序上面做了排版(函数内部的流程,加了tab缩进的)方便理解, 但是发表之后,还是乱了。
流程顺序基本理清了,可以复制到notepad++,手动加下缩进吧。
主流程是序号 1、2、...
函数内部流程,简单点的标“=>”表示下,复杂的就安装节序号标了。

入口在linphonecall.c中,linphone_call_init_media_streams(call),函数内部包含三个函数:
void linphone_call_init_media_streams(LinphoneCall *call){   linphone_call_init_audio_stream(call);   linphone_call_init_video_stream(call);   linphone_call_init_text_stream(call);}

A、 linphone_call_init_audio_stream(call) 音频流的初始化
1、char* rtcp_tool = linphone_core_get_user_agent(lc)
=>sal_get_user_agent(lc->sal),定义在sal.h,实现在sal_impl.c中;
=>belle_sip_header_user_agent_get_products_as_string(sal->user_agent, char[] user_agent,254),实现在belle_sip_headers_impl.c中;
=>list* list = user_agent->produtcts,
遍历list,将list->data的数据存在char[] user_agent中,并返回user_agent。
2、if call->audiostream !=null , call有问题,return;
3、if (call->sessions[call->main_audio_stream_index].rtp_session = null )
{
3.1、SalMulticastRole multicast_role = linphone_call_get_multicast_role(call,SalStreamType:SalAudio) :明确我发在通话中的角色(字面理解)
=> 检查call->op是否构建。
SalMediaDescription remotedesc = sal_call_get_remote_media_description(call->op),实现在sal_op_call.c中
=> return SalOp->base.remote_media;
SalMediaDescription localdesc = call->localdesc;
如果localDesc和remotedesc都不存在,且call的dir是outgoing,
继续判断, 如果外面的入参SalStreamType是SalAudio,且call->params->audio_multicast_enable 为true
则multicast_role 为SalMulticastSender;
else 如果localldesc存在,且(remotedesc不存在 或 sal_call_is_offerer(call->op)为true),感觉像是别人发起的call,且sdp_offering为ture
其中的sal_call_is_offerer 只是return call->op->sdp_offering;
找到本地支持的最优媒体流,stream_desc = sal_media_description_find_best_stream(localdesc,type)实现在sal.c中;
else 如果remotedesc存在,但sal_call_is_offerer(call->op)为false;
3.2、找到对方支持的最优媒体流,stream_desc = sal_media_description_find_best_stream(remotedesc, type); <==else结束
3.3、如果stream_desc存在,从它里面获取multicast_role;
3.4、外部继续做了remotedesc = sal_call_get_remote_media_description(call->op);
3.5、如果remotedesc存在,从中获取最优流媒体配置 :stream_desc = sal_media_description_find_best_stream(remotedesc, SalAudio);
3.6、初始化call的音频流属性call->audiostream=audiostream=audio_stream_new2() ,定义在mediastream.h,实现在audiostream.c
call->audiostream=audiostream=audio_stream_new2(lc->factory,linphone_call_get_bind_ip_for_stream(call,call->main_audio_stream_index),
multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_audio_stream_index].rtp_port,
multicast_role == SalMulticastReceiver ?0/*disabled for now*/: call->media_ports[call->main_audio_stream_index].rtcp_port);
{
//其中第二个参数 :linphone_call_get_bind_ip_for_stream(call,call->main_audio_stream_index);
该函数主要功能是从call->core->config中找出“rtp”session下的“bind_address”值。如果没有的话,再根据发送\接收者的身份分别从call->media_ports中找PortConfig的multicast_ip值;
分析audio_stream_new2();实现在audiostream.c中;
第一步,构建MSMediaStreamSessions
session.rtp_session= ms_create_duplex_rtp_session(xxx),定义在mediastream.h,实现在mediastream.c;
=> rtp_session_new(RTP_SESSION_SENDRECV)。创建一个可收发的RtpSession,实现在rtpsession.c;
然后设置了一堆RtpSession的属性;
第二步,根据factory和session构建AudioStream: audio_stream_new_with_sessions(factory, &sessions);
=> a、先 new AudioStream: stream;
b、MSFilterDesc *ec_desc=ms_factory_lookup_filter_by_name(factory,"MSWebRTCAEC"),实现在msfactory.c;
第二个参数是过滤器的名字。
=> 主要功能是从遍历factory->desc_list,取item->data,如果与过滤器名字一致,则返回这个item->data;
c、指定OrtpRtcpXR的回调:rtcp_xr_media_cbs。stream初始化完了会用到。
d、初始化mediastream :media_stream_init(&stream->ms,factory, sessions); 实现在mediastream.c
主要设置stream的属性,包括event_dispatcher、event_queue、factory,并且注册rtpsession到event_queue;
e、设置factory的属性:enable_statistics,并reset statistics;
frtp_session_resync(rtpsession),同步化rtpsession,用于当接收的rtp stream时间戳不连续时进行同步;
g、继续设置stream的属性:包括:
stream->ms.rtpsend=ms_factory_create_filter(factory, MS_RTP_SEND_ID);
stream->ms.ice_check_list=NULL;
stream->ms.qi=ms_quality_indicator_new(stream->ms.sessions.rtp_session);
ms_quality_indicator_set_label(stream->ms.qi,"audio");
stream->ms.process_rtcp=audio_stream_process_rtcp;
if (ec_desc!=NULL){
stream->ec=ms_factory_create_filter_from_desc(factory, ec_desc);
}else{
stream->ec=ms_factory_create_filter(factory, MS_SPEEX_EC_ID );
}
stream->play_dtmfs=TRUE;
stream->use_gc=FALSE;
stream->use_agc=FALSE;
stream->use_ng=FALSE;
stream->features=AUDIO_STREAM_FEATURE_ALL;
h、rtp_session_set_rtcp_xr_media_callbacks(rtpsession,rtcp_xr_media_cbs),实现在rtcp_xr.c中;应该是给RtpSession设置监听回调;
} //,audio_stream初始化完成;
3.7、如果multicast_role == SalMulticastReceiver =》linphone_call_join_multicast_group():处理是不是需要加入会话组
3.8、继续,rtp_session_enable_network_simulation() 实现在netsim.c中。貌似是想打开网络;
3.9、audio_stream_set_rtcp_information(),设置audiostream中的RtpSession的源信息;实现在mediastream.c中;
3.10、rtp_session_set_symmetric_rtp(RtpSession,linphone_core_symmetric_rtp_enabled(lc)),实现在rtpsession.c,设置rtpsession的均衡性?
第二个参数:主要检查lc->config中"rtp"的session,下的"symmetric"值,默认给1;
3.11、setup_dtls_params(call,stream),如果call的媒体加密方式是DTLS的时候,设置stream的加密方式;
3.12、如果lc支持ZRTP的加密方式,又对Call和audiostream做了些处理
setZrtpCryptoTypesParameters(&params,call->core);设置params上
linphone_core_get_srtp_crypto_suites(lc);从lc中读取些srtp_suites,遍历其item,并设置属性到params上;
audio_stream_enable_zrtp(call->audiostream,&params);设置到audioStream是session.zrtp_context上
3.13、media_stream_reclaim_sessions(&audiostream->ms, &call->sessions[call->main_audio_stream_index]); 把audioStream的session信息拷贝到call的session里面;
}
4、如果call->media_ports[].rtp_port 没有设置,调用port_config_set_random_choosed(),将audiostream下RtpSession的loc_port值设置给call。
5、检查lc->config下“rtp”session的“audio_dscp”字段值,如果有值的话,将其设置到audiostream上,audio_stream_set_dscp(audiostream,dscp);实现在mediastream.h
6、检查lc->sound_conf.ea如果为真:获取lc->config下"sound" section下的 "el_type"字段值。并根据不同类型,调用audio_stream_enable_echo_limiter(),感觉是设置声音门限的。
7、检查lc->config下"sound"下section的"eq_location"字段值,来设置audiostream->eq_loc为 MSEqualizerMic 或 MSEqualizerHP; (均衡器位置)
8、audio_stream_enable_gain_control(audiostream,true)。开启audiostream的增益控制,stream->use_gc = true:
9、检查lc->config下"sound"下section的"noisegate"的门限开关。并设置到audiostream,audio_stream_enable_noise_gate();
10、从lc中获取audio_features,并设置到audiostream,audio_stream_set_features(audiostream,linphone_core_get_audio_features(lc));第二个参数在misc.c下;
11、如果lc->rtptf存在:
rtp_session_get_transports(RtpSession,&,&),在rtpsession_inet.c下,从RtpSession中读取rtp.gs.tr和rtcp.gs.tr;
分别设置rtp和rtcp的transport endpoint到对应的steam.rtp_port和stream.rtcp_port;
12、新建一个ortp的event_queue,call->audiostream_app_evq = ortp_ev_queue_new();
13、将audiostream的session.rtp_session注册到event_quere中。rtp_session_register_event_queue();
14、最后调用 _linphone_call_prepare_ice_for_stream(call,call->main_audio_stream_index,FALSE);
如果call->core的firewall_policy是UseIce、并且call->ice_session不为空时才做的处理。


B、linphone_call_init_video_stream(LinphoneCall *call)
先检查VIDEO_ENABLED宏标签是否为True,如果false就直接退出了。
如果call->vediostream == null的时候,创建videostream,否则退出了;
1、获取lc->config中的"video"对应的section下的"recv_buf_size";
2、获取video_dscp,linphone_core_get_video_dscp(lc);在lc->config中的"rtp"对应的section的"video_dspc";
3、获取display_filter,linphone_core_get_video_display_filter(lc),在misc.c中;在lc->config中的"video"对应的section中的"displaytype";
4、如果call->sessions[call->main_video_stream_index].rtp_session==NULL
4.1、先明确我方在call中的multicast_role;同audio_stream的初始化流程一样;
4.2、如果multicast_role是receiver,linphone_call_join_multicast_group
4.3、如果if(call->op)存在,获取对方的remotedesc = sal_call_get_remote_media_description(call->op);实际是返回op->base.remote_media;函数实现在sal_op_call.c
4.4、如果remotedesc存在,获取stream_desc = sal_media_description_find_best_stream(remotedesc, SalVideo);根据remotedesc查找支持的最优协议;实现在sal.c
4.5、实例化videostream, video_stream_new2();实现在videostream.c中;
第一步:ms_create_duplex_rtp_session,创建video的RtpSession,实现在mediastream.c中
流程与audio_stream_new2()一样;
第二步:video_stream_new_with_sessions(factory,&session),实现在videostream.c中;
a、直接新建一个VideoStream,
b、构建 OrtpRtcpXr的流媒体回调;
c、设置stream的ms.type和ms.sessions;
d、初始化mediastream :media_stream_init(&stream->ms,factory, sessions); 实现在mediastream.c
主要设置stream的属性,包括event_dispatcher、event_queue、factory,并且注册rtpsession到event_queue;
e、rtp_session_resync(rtpsession),同步化rtpsession,用于当接收的rtp stream时间戳不连续时进行同步;
f、继续设置stream的属性:包括:
stream->ms.rtpsend=ms_factory_create_filter(factory, MS_RTP_SEND_ID);
stream->ms.ice_check_list=NULL;
stream->ms.qi=ms_quality_indicator_new(stream->ms.sessions.rtp_session);
ms_quality_indicator_set_label(stream->ms.qi,"video");
MS_VIDEO_SIZE_ASSIGN(stream->sent_vsize, CIF);
stream->fps=0;
stream->dir=MediaStreamSendRecv;
stream->display_filter_auto_rotate_enabled=0;
stream->freeze_on_error = FALSE;
stream->source_performs_encoding = FALSE;
stream->output_performs_decoding = FALSE;
choose_display_name(stream);
stream->ms.process_rtcp=video_stream_process_rtcp;
if(ms_factory_lookup_filter_by_id(stream->ms.factory, MS_MKV_RECORDER_ID)){
stream->tee3=ms_factory_create_filter(stream->ms.factory, MS_TEE_ID);
stream->recorder_output=ms_factory_create_filter(stream->ms.factory, MS_ITC_SINK_ID);
}
g、rtp_session_set_rtcp_xr_media_callbacks(stream->ms.sessions.rtp_session, &rtcp_xr_media_cbs);实现在rtcp_xr.c中;应该是给RtpSession设置监听回调
stream->staticimage_webcam_fps_optimization = TRUE;
4.6、如果multicast_role是receiver;linphone_call_join_multicast_group();处理是否需要加入会话组;
4.7、rtp_session_enable_network_simulation(),同init_audio_stream中的一样;
4.8、video_stream_set_rtcp_information();设置videostream中的RtpSession的源信息
4.9、rtp_session_set_symmetric_rtp(RtpSession,linphone_core_symmetric_rtp_enabled(lc));将lc->config下"rtp"对应的section下"symmetric"值设置到RtpSession->symmetric_rtp;
4.10、setup_dtls_params()如果call的媒体加密方式是DTLS的时候,设置stream的加密方式;
4.11、如果媒体加密方式是ZRTP时,video_stream_enable_zrtpcall->videostream, call->audiostream),根据已创建的audiostream中的信息激活video_stream中的ZRTP能力;
4.12、media_stream_reclaim_sessions(&videostream->ms, &call->sessions[call->main_video_stream_index]); 把videostream的session信息拷贝到call的session里面;
5、如果call->media_ports[].rtp_port 没有设置,调用port_config_set_random_choosed(),将audiostream下RtpSession的loc_port值设置给call。
6、如果上面第2步获得的dscp存在,将其设置到videostream上,video_stream_set_dscp(audiostream,dscp);实现在mediastream.h
7、video_stream_enable_display_filter_auto_rotate(call->videostream, lp_config_get_int(lc->config,"video","display_filter_auto_rotate",0));实现在videostream.c中;
根据lc->config中的"video"-》"display_fileter_auto_rotate"值,设置到videostream->display_filter_auto_rotato_enabled上;
8、设置video_recv_buf_size;
9、如果第3步中的display_filter不为空,video_stream_set_display_filter_name(); videostream->display_name = display_filter;
10、video_stream_set_event_callback(call->videostream,video_stream_event_cb, call);
第二个参数是个函数名,给videoStream设置回调;
11、如果lc->rtptf存在:
rtp_session_get_transports(RtpSession,&,&),在rtpsession_inet.c下,从RtpSession中读取rtp.gs.tr和rtcp.gs.tr;
分别设置rtp和rtcp的transport endpoint到对应的steam.rtp_port和stream.rtcp_port;
12、新建一个ortp的event_queue,call->videostream_app_evq = ortp_ev_queue_new();
13、将videostream的session.rtp_session注册到event_quere中。rtp_session_register_event_queue();
14、最后调用 _linphone_call_prepare_ice_for_stream(call,call->main_video_stream_index,FALSE);
如果call->core的firewall_policy是UseIce、并且call->ice_session不为空时才做的处理。



0 0
原创粉丝点击