pjsip学习笔记二

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

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

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

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

  1. /* Create the stop event */  

  2. strm->thread_quit_event = CreateEvent(NULL, FALSE, FALSE, NULL);  

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

[cpp] view plaincopy

  1. SetEvent(stream->thread_quit_event); 


你可能感兴趣的:(pjsip学习笔记二)