pjsip学习笔记-- srtp 相关

原文地址:http://blog.csdn.net/firstime_tzjz/article/details/7819574

1、pjsip 是否采用 srtp 来传输媒体流是由两方面控制的:

(1)、pjsip是否支持 srtp 协议:

在 pjsua_call_media_init 中首先判断是采用 ICE 还是 UDP:

[cpp]  view plain copy
  1. if (pjsua_var.media_cfg.enable_ice) {  
  2.         status = create_ice_media_transport(tcfg, call_med, async);  
  3.             if (async && status == PJ_EPENDING) {  
  4.             /* We will resume call media initialization in the 
  5.              * on_ice_complete() callback. 
  6.              */  
  7.                 call_med->med_create_cb = &call_media_init_cb;  
  8.                 call_med->med_init_cb = cb;  
  9.   
  10.             return PJ_EPENDING;  
  11.         }  
  12.     } else {  
  13.         status = create_udp_media_transport(tcfg, call_med);  
  14.     }  
在该函数最后调用 call_media_init_cb,而该函数中则会强制采用 SRTP 覆盖之前的设定:
[cpp]  view plain copy
  1. #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)  
  2.     /* This function may be called when SRTP transport already exists 
  3.      * (e.g: in re-invite, update), don't need to destroy/re-create. 
  4.      */  
  5.     if (!call_med->tp_orig) {  
  6.     pjmedia_srtp_setting srtp_opt;  
  7.     pjmedia_transport *srtp = NULL;  
  8.   
  9.     /* Check if SRTP requires secure signaling */  
  10.     if (acc->cfg.use_srtp != PJMEDIA_SRTP_DISABLED) {  
  11.         if (security_level < acc->cfg.srtp_secure_signaling) {  
  12.         err_code = PJSIP_SC_NOT_ACCEPTABLE;  
  13.         status = PJSIP_ESESSIONINSECURE;  
  14.         goto on_return;  
  15.         }  
  16.     }  
  17.   
  18.     /* Always create SRTP adapter */  
  19.     pjmedia_srtp_setting_default(&srtp_opt);  
  20.     srtp_opt.close_member_tp = PJ_TRUE;  
  21.   
  22.     /* If media session has been ever established, let's use remote's  
  23.      * preference in SRTP usage policy, especially when it is stricter. 
  24.      */  
  25.     if (call_med->rem_srtp_use > acc->cfg.use_srtp)  
  26.         srtp_opt.use = call_med->rem_srtp_use;  
  27.     else  
  28.         srtp_opt.use = acc->cfg.use_srtp;  
  29.   
  30.     status = pjmedia_transport_srtp_create(pjsua_var.med_endpt,  
  31.                            call_med->tp,  
  32.                            &srtp_opt, &srtp);  
  33.     if (status != PJ_SUCCESS) {  
  34.         err_code = PJSIP_SC_INTERNAL_SERVER_ERROR;  
  35.         goto on_return;  
  36.     }  
  37.   
  38.     /* Set SRTP as current media transport */  
  39.     call_med->tp_orig = call_med->tp;  
  40.     call_med->tp = srtp;  
  41.     }  
  42. #else  
  43.     call_med->tp_orig = call_med->tp;  
  44.     PJ_UNUSED_ARG(security_level);  
  45. #endif  


由此可见,要禁用 SRTP,则必须将宏定义 PJMEDIA_HAS_SRTP 删除或定义为 0。

(2)、在传输媒体流的时候是否使用 SRTP:

srtp->bypass_srtp 是控制是否采用 SRTP 来传输媒体流的变量。首先,stream.c 中的函数 put_frame_imp 调用 pjmedia_transport_send_rtp,该函数中的回调函数(即 stream->transport->op->send_rtp)指向 transport_srtp.c 中的 transport_send_rtp 函数。当srtp->bypass_srtp = 1 的时候,transport_srtp.c 中的 transport_send_rtp 函数调用 pjmedia_transport_send_rtp,而此时该函数中的回调函数(即 stream->transport->member_tp->op->send_rtp)指向的就是 transport_udp.c 中的 transport_send_rtp 函数。因此,这种情况下并没有采用 SRTP 来传输媒体流,此时与直接使用 UDP 传输等效。

 

2、SRTP bypass 模式接收到对方媒体数据后的回调:

首先,stream.c 文件中的 pjmedia_stream_create 函数调用 pjmedia_transport_attach,该函数中的回调函数(即 tp->op->attach)指向 transport_srtp.c 中的 transport_attach,并将 stream.c 文件中的 on_rx_rtp 作为收到媒体数据后的回调传下去。

然后,transport_srtp.c 文件中的 transport_attach 函数调用 pjmedia_transport_attach,该函数中的回调函数(即 srtp->member_tp->op->attach)指向 transport_udp.c 中的 transport_attach,并将 transport_srtp.c 文件中的 srtp_rtp_cb 作为收到媒体数据后的回调传下去。

这样,当 transport_udp.c 收到对方的媒体数据的时候就会去调用 transport_srtp.c 文件中的 srtp_rtp_cb,而 srtp_rtp_cb 则会调用 srtp->rtp_cb。srtp->rtp_cb 指向的则是 stream.c 中的 on_rx_rtp。

即收到对方媒体数据后最终调用的回调函数是 stream.c 中的 on_rx_rtp。

 

3、windows平台下的声音采集和播放:

功能 实现函数 所在文件 调用函数
注册设备 pjmedia_aud_subsys_init audiodev.c pjmedia_endpt_create
初始化设备 factory_init wmme_dev.c init_driver
启动设备 factory_create_stream wmme_dev.c pjmedia_aud_stream_create
启动媒体流 stream_start wmme_dev.c pjmedia_aud_stream_start
声音采集 wmme_dev_thread wmme_dev.c 单独线程
声音播放 wmme_dev_thread wmme_dev.c 单独线程

“启动设备”阶段,factory_create_stream 调用 init_player_stream 创建声音回放的内核事件,调用 init_capture_stream 创建声音采集的内核事件,而 wmme_dev_thread 中对这些事件进行循环监听,监听到有内核事件发生(声音回放、采集或退出监听线程)后就执行该事件。

退出监听线程事件也是在 factory_create_stream 中创建的,相应代码为:

[cpp]  view plain copy
  1. /* Create the stop event */  
  2. strm->thread_quit_event = CreateEvent(NULL, FALSE, FALSE, NULL);  

退出监听线程事件的触发是在 stream_destroy 中完成的,相应代码为:

[cpp]  view plain copy
  1. SetEvent(stream->thread_quit_event);  

你可能感兴趣的:(pjsip学习笔记-- srtp 相关)