metartc5_jz源码阅读-yang_sdp_genLocalSdp2

int32_t yang_sdp_genLocalSdp2(YangRtcSession *session, int32_t localport,char *dst, YangStreamOptType role) {
	int32_t mediaServer=session->context.avinfo->sys.mediaServer;
	int32_t redPayloadtype=1;
	char *src = (char*) calloc(1, Yang_SDP_BUFFERLEN);

	char randstr[128];

	//创建YangSdp结构体对象
	YangSdp *local_sdp = (YangSdp*) calloc(sizeof(YangSdp), 1);

	//初始化sdp的部分字段
	yang_create_rtcsdp(local_sdp);

	//设置version为0
	strcpy(local_sdp->version, "0");

	//设置username为MetaRtc
	strcpy(local_sdp->username, "MetaRtc");

	//将local_sdp的地址格式化为字符串拷贝到randstr中
	memset(randstr, 0, sizeof(randstr));
	snprintf(randstr, 22, "%" PRId64, (int64_t) &local_sdp);

	//将randstr作为session_id
	strcpy(local_sdp->session_id, randstr);

	//设置session_version为2
	strcpy(local_sdp->session_version, "2");

	//设置网络类型为因特网
	strcpy(local_sdp->nettype, "IN");

	//设置ip地址类型为ipv4
	strcpy(local_sdp->addrtype, "IP4");

	//设置广播地址为0.0.0.0
	strcpy(local_sdp->unicast_address, "0.0.0.0");

	//设置session_name为MetaRtcSession
	strcpy(local_sdp->session_name, "MetaRtcSession");

	//设置msid_semantic为WMS,WMS是WebRTC Media Stream简称,表示本机支持传输多个流,每个流可包含多个track。
	strcpy(local_sdp->msid_semantic, "WMS");

	//设置msids
	yang_create_stringVector(&local_sdp->msids);
	char streamnames[164];
	memset(streamnames, 0, sizeof(streamnames));
	sprintf(streamnames, "%s/%s", session->context.streamConfig->app,session->context.streamConfig->stream);
	yang_insert_stringVector(&local_sdp->msids, streamnames);

	//设置group_policy,0表示音频 1表示视频,BUNDLE表示音频和视频绑定在一起。
	strcpy(local_sdp->group_policy,"BUNDLE 0 1");

	char tmps[5][16];

	//设置media_descs为空。
	yang_create_YangMediaDescVector(&local_sdp->media_descs);
	yang_insert_YangMediaDescVector(&local_sdp->media_descs, NULL);

	//获取到音频媒体描述字段进行设置。
	YangMediaDesc *audio_media_desc = &local_sdp->media_descs.payload[0];

	//设置type为audio
	strcpy(audio_media_desc->type, "audio");

	//设置端口为9
	audio_media_desc->port = 9;

	//设置使用UDP传输RTP数据包,使用TLS加密。
	strcpy(audio_media_desc->protos, "UDP/TLS/RTP/SAVPF");

	//表示rtp和rtcp复用一个端口
	audio_media_desc->rtcp_mux = true;

	//表示希望所见rtcp协议的流量
	audio_media_desc->rtcp_rsize = true;

	//设置音频的mid为0
	strcpy(audio_media_desc->mid, "0");

	//获取到视频媒体描述字段进行设置。
	YangMediaDesc *video_media_desc = &local_sdp->media_descs.payload[1];

	//设置type为video
	strcpy(video_media_desc->type, "video");

	//设置端口为9
	video_media_desc->port = 9;

	//设置使用UDP传输RTP数据包,使用TLS加密。
	strcpy(video_media_desc->protos, "UDP/TLS/RTP/SAVPF");

	//表示rtp和rtcp复用一个端口
	video_media_desc->rtcp_mux = true;

	//表示希望所见rtcp协议的流量
	video_media_desc->rtcp_rsize = true;

	//设置音频的mid为1
	strcpy(video_media_desc->mid, "1");

#if Yang_Enable_Datachannel
	YangMediaDesc *data_media_desc = NULL;

	//如果yang_config.ini或代码中配置enableDatachannel为1时则进行数据通道的sdp配置。
	if(session->context.avinfo->rtc.enableDatachannel){

		//设置media_descs为空
		yang_insert_YangMediaDescVector(&local_sdp->media_descs, NULL);

		//拿到数据通道的描述字段用于配置信息
		data_media_desc=&local_sdp->media_descs.payload[2];

		//设置type为application
		strcpy(data_media_desc->type, "application");

		//设置port为9
		data_media_desc->port = 9;

		//设置UDP传输SCTP协议的数据,使用DTLS加密。
		strcpy(data_media_desc->protos, "UDP/DTLS/SCTP webrtc-datachannel");

		//设置rtcp不复用SCTP通道
		data_media_desc->rtcp_mux = false;

		//设置rtcp不缩减流量
		data_media_desc->rtcp_rsize = false;

		//设置mid为2
		strcpy(data_media_desc->mid, "2");

		//设置音视频和数据通道绑定到一起,0为音频,1为视频,2为数据
		strcpy(local_sdp->group_policy,"BUNDLE 0 1 2");
	}
#endif

	//Yang_Stream_Play表示仅接收音视频
	if (role == Yang_Stream_Play) {
		audio_media_desc->recvonly = true;
		video_media_desc->recvonly = true;

	} else if (role == Yang_Stream_Publish) {
		//Yang_Stream_Publish表示仅发送音视频
		audio_media_desc->sendonly = true;
		video_media_desc->sendonly = true;
	} else if (role == Yang_Stream_Both) {
		//Yang_Stream_Both表示既发送又接收音视频
		audio_media_desc->sendrecv = true;
		video_media_desc->sendrecv = true;
	}
#if Yang_Enable_Datachannel
	//如果数据通道开启了,则激活sctp端口
	if(data_media_desc) data_media_desc->sctp_port = true;
#endif
	//随机4个字节的str到randstr中。
	memset(randstr, 0, sizeof(randstr));
	yang_cstr_random(4, randstr);

	//将随机的randstr设置为ice_ufrag,他和ice_pwd组合用于校验用户p2p对端是否合法。
	memset(session->local_ufrag,0,sizeof(session->local_ufrag));
	strcpy(session->local_ufrag, randstr);
	strcpy(audio_media_desc->session_info.ice_ufrag, randstr);
	strcpy(video_media_desc->session_info.ice_ufrag, randstr);
#if Yang_Enable_Datachannel
	//如果数据通道开启了则同时设置数据通道的ice_ufrag
	if(data_media_desc) strcpy(data_media_desc->session_info.ice_ufrag, randstr);
#endif

	//随机32个字节的str到randstr中。
	memset(randstr, 0, sizeof(randstr));
	yang_cstr_random(32, randstr);

	//将随机的randstr设置为ice_pwd
	strcpy(audio_media_desc->session_info.ice_pwd, randstr);
	strcpy(video_media_desc->session_info.ice_pwd, randstr);
#if Yang_Enable_Datachannel
	//如果数据通道开启了则同时设置数据通道的ice_pwd
	if(data_media_desc) strcpy(data_media_desc->session_info.ice_pwd, randstr);
#endif
	memset(session->localIcePwd,0,sizeof(session->localIcePwd));
	strcpy(session->localIcePwd,randstr);

	//设置fingerprint_algo为sha-256
	strcpy(audio_media_desc->session_info.fingerprint_algo, "sha-256");
	strcpy(video_media_desc->session_info.fingerprint_algo, "sha-256");
#if Yang_Enable_Datachannel
	if(data_media_desc) strcpy(data_media_desc->session_info.fingerprint_algo, "sha-256");
	if(data_media_desc) strcpy(data_media_desc->session_info.ice_options, "trickle");
#endif

//如果开启dtls传输,则设置证书中的fingerprint放到audio,video,data中。
#if Yang_Enable_Dtls
	strcpy(audio_media_desc->session_info.fingerprint,session->context.cer->fingerprint);
	strcpy(video_media_desc->session_info.fingerprint,session->context.cer->fingerprint);
#if Yang_Enable_Datachannel
	if(data_media_desc) strcpy(data_media_desc->session_info.fingerprint,session->context.cer->fingerprint);
#endif
#endif
	//passive表示本机角色为服务器,actpass表示本机角色既可以是服务器也可以是客户端。
	strcpy(audio_media_desc->session_info.setup, session->isServer?"passive":"actpass");
	strcpy(video_media_desc->session_info.setup, session->isServer?"passive":"actpass");
#if Yang_Enable_Datachannel
	if(data_media_desc) strcpy(data_media_desc->session_info.setup, session->isServer?"passive":"actpass");
#endif

	//设置音频传输类型为opus/48000
	yang_create_YangMediaPayloadTypeVector(&audio_media_desc->payload_types);
	yang_insert_YangMediaPayloadTypeVector(&audio_media_desc->payload_types,
			NULL);
	YangMediaPayloadType *audiotype =
			&audio_media_desc->payload_types.payload[0];
	audiotype->payload_type = 111;
	strcpy(audiotype->encoding_name, "opus");
	audiotype->clock_rate = session->context.avinfo->audio.sample; //48000;
	yang_itoa(session->context.avinfo->audio.channel,
			audiotype->encoding_param, 10);

	//设置rtcp的feedback类型为transport-cc
	yang_create_stringVector(&audiotype->rtcp_fb);
	yang_insert_stringVector(&audiotype->rtcp_fb, "transport-cc");

	yang_create_YangMediaPayloadTypeVector(&video_media_desc->payload_types);
	//insert h264/h265
	yang_insert_YangMediaPayloadTypeVector(&video_media_desc->payload_types,NULL);
	
	//设置编码格式支持H264或H265
	YangMediaPayloadType *videotype =&video_media_desc->payload_types.payload[0];
	if (session->context.avinfo->video.videoEncoderType	== Yang_VED_264) {
			videotype->payload_type = 125;
			strcpy(videotype->encoding_name, "H264");
		} else if (session->context.avinfo->video.videoEncoderType == Yang_VED_265) {
			videotype->payload_type = 126;
			strcpy(videotype->encoding_name, "H265");
		}
		yang_sdp_genLocalSdp_payloadType(videotype);

	//设置编码格式支持red
	yang_insert_YangMediaPayloadTypeVector(&video_media_desc->payload_types,NULL);
	videotype =&video_media_desc->payload_types.payload[redPayloadtype];
	strcpy(videotype->encoding_name, "red");
	videotype->payload_type = 114;
	videotype->clock_rate = 90000;

	//设置ssrc
	yang_insert_YangSSRCInfoVector(&audio_media_desc->ssrc_infos, NULL);
	yang_insert_YangSSRCInfoVector(&video_media_desc->ssrc_infos, NULL);
	audio_media_desc->ssrc_infos.payload[0].ssrc = session->context.audioSsrc;
	video_media_desc->ssrc_infos.payload[0].ssrc = session->context.videoSsrc;

	//设置ssrc的cname
	memset(randstr, 0, sizeof(randstr));
	yang_cstr_random(16, randstr);
	strcpy(audio_media_desc->ssrc_infos.payload[0].cname, randstr);
	strcpy(video_media_desc->ssrc_infos.payload[0].cname, randstr);
	strcpy(audio_media_desc->ssrc_infos.payload[0].mslabel, "-");
	strcpy(video_media_desc->ssrc_infos.payload[0].mslabel, "-");

	//随机randstr放入音频的ssrc的msid_tracker和label中
	memset(tmps, 0, 16 * 5);
	yang_cstr_random(8, tmps[0]);
	yang_cstr_random(4, tmps[1]);
	yang_cstr_random(4, tmps[2]);
	yang_cstr_random(4, tmps[3]);
	yang_cstr_random(12, tmps[4]);
	memset(randstr, 0, sizeof(randstr));
	sprintf(randstr, "%s-%s-%s-%s-%s", tmps[0], tmps[1], tmps[2], tmps[3],tmps[4]);
	strcpy(audio_media_desc->ssrc_infos.payload[0].msid, "-");
	strcpy(audio_media_desc->ssrc_infos.payload[0].msid_tracker, randstr);
	strcpy(audio_media_desc->ssrc_infos.payload[0].label, randstr);

	//随机randstr放入视频的ssrc的msid_tracker和label中
	memset(tmps, 0, 16 * 5);
	yang_cstr_random(8, tmps[0]);
	yang_cstr_random(4, tmps[1]);
	yang_cstr_random(4, tmps[2]);
	yang_cstr_random(4, tmps[3]);
	yang_cstr_random(12, tmps[4]);
	memset(randstr, 0, sizeof(randstr));
	sprintf(randstr, "%s-%s-%s-%s-%s", tmps[0], tmps[1], tmps[2], tmps[3],
			tmps[4]);
    strcpy(video_media_desc->ssrc_infos.payload[0].msid, "-");
    strcpy(video_media_desc->ssrc_infos.payload[0].msid_tracker, randstr);
    strcpy(video_media_desc->ssrc_infos.payload[0].label, randstr);

	//如果媒体服务器为p2pServer,则设置candidates数据,这里仅设置了一种candidate类型的数据,其实应该把host,srflx,relay都设置进去,由对端决定最优的线路。
   if(mediaServer==Yang_Server_P2p){
	    yang_create_YangCandidateVector(&audio_media_desc->candidates);
	    yang_create_YangCandidateVector(&video_media_desc->candidates);
		//获取本地端口和ip
	   	int32_t localport=session->context.streamConfig->localPort;
	   	char* localip=session->context.avinfo->sys.localIp;


		//如果iceUsingLocalIp为1,则设置本地ip为本机ip地址
	   	if(session->context.avinfo->rtc.iceUsingLocalIp){
	   		localip=session->context.avinfo->rtc.iceLocalIP;
	   	}else if(session->ice.session.candidateType==YangIceStun&&session->ice.session.server.stunPort>0){
	   		//如果candidateType是stun并且stun端口号有设置,则获取stun的ip,设置为localip和localport.
			struct sockaddr_in addr;
	   		addr.sin_addr.s_addr= session->ice.session.server.stunIp;
	   		localip=inet_ntoa(addr.sin_addr);
	   		localport=session->ice.session.server.stunPort;
	   	}else if(session->ice.session.candidateType==YangIceTurn&&(session->ice.session.isTurnReady||session->ice.session.isTurnAllocated)){
	   		//如果candidateType是turn并且isTurnReady和isTurnAllocated,则获取turn的中继ip,设置为localip和localport.
			struct sockaddr_in addr;
	   		addr.sin_addr.s_addr= session->ice.session.server.relayIp;	   	
            localip=inet_ntoa(addr.sin_addr);       
	   		localport=session->ice.session.server.relayPort;
	   	}else{
	   	}

		//根据localip和localport配置candidate的ip、port和type
	   	yang_sdp_genLocalSdp_candidate(session,audio_media_desc,localip,localport);
		yang_sdp_genLocalSdp_candidate(session,video_media_desc,localip,localport);
#if Yang_Enable_Datachannel
		if(data_media_desc){
			yang_create_YangCandidateVector(&data_media_desc->candidates);
			yang_sdp_genLocalSdp_candidate(session,data_media_desc,localip,localport);
		}
#endif


    }

	//将local_sdp编码到src中。
	YangBuffer buf;
	yang_init_buffer(&buf, src, Yang_SDP_BUFFERLEN);
	yang_rtcsdp_encode(local_sdp, &buf);

	//根据是否server,替换不同的分割字符串。放到dst中。
	if(mediaServer==Yang_Server_P2p&&!session->isServer){
		yang_cstr_replace(src, dst, (char*) "\r\n", (char*) "\n");
	}
	else{
		yang_cstr_replace(src, dst, (char*) "\r\n", (char*) "\\r\\n");
	}

	yang_destroy_rtcsdp(local_sdp);
	yang_free(local_sdp);
	yang_free(src);
	return Yang_Ok;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王方帅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值