- 初始化
rtp在switch_rtp.c中实现,里面不仅包括rtp,还包括跟媒体传输相关的几个组件,rtcp、dtmf、 srtp、zrtp,本次先完成rtp部分。在core初始化的时候,同样会进行rtp初始化。
- SWITCH_DECLARE(void) switch_rtp_init(switch_memory_pool_t *pool)
- {
- #ifdef ENABLE_ZRTP
- const char *zid_string = switch_core_get_variable_pdup("switch_serial", pool);
- const char *zrtp_enabled = switch_core_get_variable_pdup("zrtp_enabled", pool);
- zrtp_config_t zrtp_config;
- char zrtp_cache_path[256] = "";
- zrtp_on = zrtp_enabled ? switch_true(zrtp_enabled) : 0;
- #endif
- if (global_init) {
- return;
- }
- switch_core_hash_init(&alloc_hash);
- #ifdef ENABLE_SRTP
- srtp_init();
- #endif
- switch_mutex_init(&port_lock, SWITCH_MUTEX_NESTED, pool);
- global_init = 1;
- } );
初始化通过宏进行加密相关的ZRTP和SRTP初始化,除了这些,还有一个全局初始化标志global_init。
- switch_rtp_new
- SWITCH_DECLARE(switch_rtp_t *) switch_rtp_new(const char *rx_host,
- switch_port_t rx_port,
- const char *tx_host,
- switch_port_t tx_port,
- switch_payload_t payload,
- uint32_t samples_per_interval,
- uint32_t ms_per_packet,
- switch_rtp_flag_t flags[SWITCH_RTP_FLAG_INVALID], char *timer_name, const char **err, switch_memory_pool_t *pool)
- {
- switch_rtp_t *rtp_session = NULL;
- if (switch_rtp_create(&rtp_session, payload, samples_per_interval, ms_per_packet, flags, timer_name, err, pool) != SWITCH_STATUS_SUCCESS) {
- goto end;
- }
- switch_mutex_lock(rtp_session->flag_mutex);
- if (switch_rtp_set_local_address(rtp_session, rx_host, rx_port, err) != SWITCH_STATUS_SUCCESS) {
- switch_mutex_unlock(rtp_session->flag_mutex);
- rtp_session = NULL;
- goto end;
- }
- if (switch_rtp_set_remote_address(rtp_session, tx_host, tx_port, 0, SWITCH_TRUE, err) != SWITCH_STATUS_SUCCESS) {
- switch_mutex_unlock(rtp_session->flag_mutex);
- rtp_session = NULL;
- goto end;
- }
- end:
- if (rtp_session) {
- switch_mutex_unlock(rtp_session->flag_mutex);
- rtp_session->ready = 2;
- rtp_session->rx_host = switch_core_strdup(rtp_session->pool, rx_host);
- rtp_session->rx_port = rx_port;
- switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH);
- switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_DETECT_SSRC);
- } else {
- switch_rtp_release_port(rx_host, rx_port);
- }
- return rtp_session;
- }
在新建rtp的时候,先使用create创建rtp实例,然后设置远程和本地的ip:port对。rtp实例的成员很多,这里就先不展开。
- switch_rtp_zerocopy_read_frame
上一章在media提到,会调用switch_rtp_zerocopy_read_frame读一帧,其中的zerocopy表示不拷贝数据,而是返回数据指针。
- SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp_session, switch_frame_t *frame, switch_io_flag_t io_flags)
- {
- int bytes = 0;
- if (!switch_rtp_ready(rtp_session)) {
- return SWITCH_STATUS_FALSE;
- }
- bytes = rtp_common_read(rtp_session, &frame->payload, &frame->pmap, &frame->flags, io_flags);
- frame->data = RTP_BODY(rtp_session);
- frame->packet = &rtp_session->recv_msg;
- frame->packetlen = bytes;
- frame->source = __FILE__;
- switch_set_flag(frame, SFF_RAW_RTP);
- switch_set_flag(frame, SFF_EXTERNAL);
- if (frame->payload == rtp_session->recv_te) {
- switch_set_flag(frame, SFF_RFC2833);
- }
- frame->timestamp = ntohl(rtp_session->last_rtp_hdr.ts);
- frame->seq = (uint16_t) ntohs((uint16_t) rtp_session->last_rtp_hdr.seq);
- frame->ssrc = ntohl(rtp_session->last_rtp_hdr.ssrc);
- frame->m = rtp_session->last_rtp_hdr.m ? SWITCH_TRUE : SWITCH_FALSE;
- frame->datalen = bytes;
- return SWITCH_STATUS_SUCCESS;
- }
调用rtp_common_read读取一个包,然后填充frame指针。data成员指向读到的数据,packet指向rtp头,其它的如ssrc啥的就不说了。
rtp_common_read会根据不同的类型、rtp rtcp srtp zrtp调用不同的读函数,这里只看rtp。
- while (switch_poll(rtp_session->read_pollfd, 1, &fdr, 0) == SWITCH_STATUS_SUCCESS) {
- status = read_rtp_packet(rtp_session, &bytes, flags, pmapP, SWITCH_STATUS_SUCCESS, SWITCH_FALSE);
read_rtp_packet里面调用底层的socket读数据。
- if (poll_status == SWITCH_STATUS_SUCCESS) {
- status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, bytes);
- } else {
- *bytes = 0;
- }
- switch_rtp_write_frame
rtp写一帧跟读相反,先构造一个switch_frame_t结构体,调用底层的socket去发送,然后更新统计信息。这些统计信息主要用于rtcp、jitterbuffer等。
- if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) {
- return -1;
- }
- rtp_session->stats.outbound.raw_bytes += bytes;
- rtp_session->stats.outbound.media_bytes += bytes;
- rtp_session->stats.outbound.media_packet_count++;
- rtp_session->stats.outbound.packet_count++;
- return (int) bytes;