修改Janus,支援datachannel通過rtp通道傳輸
阿新 • • 發佈:2018-11-04
Janus的datachannel支援的協議主要是:“DTLS/SCTP”、"UDP/DTLS/SCTP",而RTP通道使用的是"UDP/TLS/RTP/SAVPF",修改的思路包括SDP返回的修改,RTP資料包中提取datachannel包對應SSRC的包。
1、給janus_ice_stream結構體新增data的ssrc欄位和初始化:
guint32 data_ssrc_peer;//[email protected] guint32 data_ssrc, sequence_data; int janus_sdp_process(void *ice_handle, janus_sdp *remote_sdp, gboolean update) 方法中增加如下邏輯: if(!strcasecmp(m->proto, "UDP/DTLS/SCTP") || !strcasecmp(m->proto, "UDP/TLS/RTP/SAVPF")) { stream->data_ssrc = janus_random_uint32(); /* FIXME Should we look for conflicts? */ stream->sequence_data = janus_random_uint32(); janus_flags_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_NEW_DATACHAN_SDP); janus_flags_clear(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_DATA_CHANNELS);//
[email protected] add } else { janus_flags_clear(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_NEW_DATACHAN_SDP); }
2、SDP返回資料:
m->fmts = g_list_append(m->fmts, g_strdup("109")); janus_sdp_attribute *aa = janus_sdp_attribute_create("rtpmap", "109 google-data/90000"); m->attributes = g_list_append(m->attributes, aa); m->ptypes = g_list_append(m->ptypes, GINT_TO_POINTER(109));
3、接收RTP資料函式janus_ice_cb_nice_recv中,增加對datachannel的資料處理的邏輯:
if (header->type == 109 || stream->data_ssrc_peer == packet_ssrc){
/* Pass the data to the responsible plugin */
janus_plugin *plugin = (janus_plugin *)handle->app;
if(plugin && plugin->incoming_data &&
!g_atomic_int_get(&handle->app_handle->stopped) &&
!g_atomic_int_get(&handle->destroyed)){
plugin->incoming_data(handle->app_handle, (char *)buf + RTP_HEADER_SIZE, buflen - RTP_HEADER_SIZE);
}
return;
}
4、傳送RTP資料時,使用RTP通道傳送datachannel的資料:
void janus_plugin_relay_data(janus_plugin_session *plugin_session, char *buf, int len) {
if((plugin_session < (janus_plugin_session *)0x1000) || g_atomic_int_get(&plugin_session->stopped) || buf == NULL || len < 1)
return;
janus_ice_handle *handle = (janus_ice_handle *)plugin_session->gateway_handle;
if(!handle || janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_STOP)
|| janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT)){
return;
}
#ifdef HAVE_SCTP
if (janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_NEW_DATACHAN_SDP)){
janus_ice_relay_data_withrtp(handle, buf, len);//relay daa with rtp only.
}else{
janus_ice_relay_data(handle, buf, len);
}
#else
JANUS_LOG(LOG_WARN, "Asked to relay data, but Data Channels support has not been compiled...\n");
#endif
}
void janus_ice_relay_data_withrtp(janus_ice_handle *handle, char *buf, int len) {
struct timeval now;
if(!handle || handle->queued_packets == NULL || buf == NULL || len < 1){
return;
}
/* Queue this packet */
janus_ice_queued_packet *pkt = g_malloc(sizeof(janus_ice_queued_packet));
pkt->data = g_malloc(RTP_HEADER_SIZE+len+SRTP_MAX_TAG_LEN+4);
janus_rtp_header *header = (janus_rtp_header *)pkt->data;
header->ssrc = (handle->stream->data_ssrc);
header->type = 109;
header->version = 2;
header->markerbit = 1;
header->extension = 0;
handle->stream->sequence_data++;
header->seq_number = (handle->stream->sequence_data + 100);
gettimeofday(&now,0);
header->timestamp = htonl(now.tv_sec);
memcpy((char *)pkt->data + RTP_HEADER_SIZE, buf, len);
pkt->length = RTP_HEADER_SIZE + len;
pkt->type = JANUS_ICE_PACKET_DATA_WITH_RTP;
pkt->control = FALSE;
pkt->encrypted = FALSE;
pkt->retransmission = FALSE;
pkt->added = janus_get_monotonic_time();
janus_ice_queue_packet(handle, pkt);
}
傳送函式static gboolean janus_ice_outgoing_traffic_handle的邏輯中,對ssrc的處理需要修改為:
header->ssrc = htonl(video ? stream->video_ssrc : ((pkt->type == JANUS_ICE_PACKET_DATA_WITH_RTP)?stream->data_ssrc : stream->audio_ssrc));