原文地址:http://blog.csdn.net/firstime_tzjz/article/details/7819574
1、pjsip 是否采用 srtp 来传输媒体流是由两方面控制的:
(1)、pjsip是否支持 srtp 协议:
在 pjsua_call_media_init 中首先判断是采用 ICE 还是 UDP:
由此可见,要禁用 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 中创建的,相应代码为:
退出监听线程事件的触发是在 stream_destroy 中完成的,相应代码为: