metaRTC实现了sfu 和 p2p两种模式,支持srs和zlm 两种推送已经p2p server 模式,如果要实现自己的信令系统其实也比较简单, 最近实现了metaRTC的基于mqtt的信令,同时可以进行p2p和服务器转发,方便自己的设备和系统融合,现就信令系统的流程以及涉及的函数进行一个梳理:如下,按此流程可以实现自己的信令系统(信令|为好奇者提供的WebRTC (webrtcforthecurious.com))
metaRTC 修改信令的涉及到的地方
IPC应用
1、yangipc/YangIpc.c
创建IPC
这里可以设置自定义的ice server 信息
strcpy(session->avinfo.rtc.iceServerIP,"182.92.163.143");
并通过yang_ipc_listen 函数实现开始sdp 交互
void yang_create_ipc(YangIpc* ipc){
if(ipc==NULL) return;
YangIpcSession* session=&ipc->session;
YangIni ini;
yang_create_ini(&ini,(char*)"yang_config.ini");
ini.initAvinfo(ini.filename,&session->avinfo);
yang_destroy_ini(&ini);
session->avinfo.video.videoEncoderFormat=YangI420;
session->avinfo.enc.createMeta=0;
yang_ipc_initAvinfo(session);
yang_setLogLevel(session->avinfo.sys.logLevel);
yang_setLogFile(session->avinfo.sys.hasLogFile);
session->avinfo.sys.httpPort=1988;
session->avinfo.sys.mediaServer=Yang_Server_P2p;//Yang_Server_Srs/Yang_Server_Zlm/Yang_Server_P2p
session->avinfo.sys.rtcLocalPort=10000+yang_random()%15000;
memset(session->avinfo.sys.localIp,0,sizeof(session->avinfo.sys.localIp));
yang_getLocalInfo(session->avinfo.sys.localIp);
session->hasAudio=yangtrue;
//using h264 h265
session->avinfo.video.videoEncoderType=Yang_VED_264;//Yang_VED_265;
// session->streams.m_streamState=this;
session->avinfo.audio.hasAec=1;
//session->channeldataRecv.context=this;
//session->channeldataRecv.receiveData=g_ipc_receiveData;
session->avinfo.rtc.usingDatachannel=1;
strcpy(session->avinfo.rtc.iceServerIP,"182.92.163.143");
session->avinfo.rtc.iceStunPort=3478;
session->avinfo.rtc.hasIceServer=0;
session->videoBuffer = (YangVideoEncoderBuffer2*)calloc(sizeof(YangVideoEncoderBuffer2),1);//new YangVideoEncoderBuffer(2);
yang_create_videoEncoderBuffer2(session->videoBuffer,2);
yang_ipc_initRtc(session);
ipc->start=yang_ipc_listen;
ipc->init=yang_ipc_init;
ipc->checkAlive=yang_ipc_checkAlive;
}
2、yangipc/YangIpc.c
此函数 实现信令交互开始流程,通过yang_start_p2pserver实现信令监听线程,如果有连接后就是实现http协议的offer获取
并在g_ipc_receive函数里面处理remotesdp (offer),可以改成自己的信令处理,获取到offer ,直接调用g_ipc_receive函数,不用原来提供的p2pserver
void yang_ipc_listen(YangIpcSession* session){
yang_create_p2pserver(&session->p2pServer,session->avinfo.sys.httpPort);
session->p2pServer.receive=g_ipc_receive;
session->p2pServer.user=session;
yang_start_p2pserver(&session->p2pServer);
}
void g_ipc_receive(char *data, int32_t nb_data,char* response,char* remoteIp, void *user) {
if (user == NULL) return;
YangIpcSession *session = (YangIpcSession*) user;
yang_ipc_startRtc(session,remoteIp, data,response);
}
3、yangipc/YangIpcRtc.c
此函数接收远端remotesdp (offer) ,然后回传本地sdp localsdp (answer)原来采用的是http的模式实现的,函数回调指针实现函数重载
此函数如果需要实现自己的信令系统需要替换掉answer 回传的相关函数 ret = sh->createHttpAnswer(&sh->peer,answer);
int32_t yang_ipc_rtcrecv_addPeer(YangIpcRtcSession* session,char* sdp,char* answer,char* remoteIp,int32_t localPort,int* phasplay)
int32_t yang_ipc_rtcrecv_addPeer(YangIpcRtcSession* session,char* sdp,char* answer,char* remoteIp,int32_t localPort,int* phasplay){
int32_t ret = 0;
YangPeerConnection* sh=(YangPeerConnection*)calloc(sizeof(YangPeerConnection),1);
memset(&sh->peer.streamconfig,0,sizeof(sh->peer.streamconfig));
sh->peer.streamconfig.uid=session->uidSeq++;
sh->peer.streamconfig.localPort=localPort;
sh->peer.streamconfig.isServer=1;
sh->peer.streamconfig.streamOptType=Yang_Stream_Both;
strcpy(sh->peer.streamconfig.remoteIp,remoteIp);
sh->peer.streamconfig.sslCallback.context=session;
sh->peer.streamconfig.sslCallback.sslAlert=g_ipc_rtcrecv_sslAlert;
sh->peer.streamconfig.recvCallback.context=session;
sh->peer.streamconfig.recvCallback.receiveAudio=g_ipc_rtcrecv_receiveAudio;
sh->peer.streamconfig.recvCallback.receiveVideo=g_ipc_rtcrecv_receiveVideo;
sh->peer.streamconfig.recvCallback.receiveMsg=g_ipc_rtcrecv_receiveMsg;
memcpy(&sh->peer.streamconfig.rtcCallback,&session->rtcCallback,sizeof(YangRtcCallback));
sh->peer.avinfo=session->avinfo;
yang_create_peerConnection(sh);
sh->init(&sh->peer);
if (sh->isConnected(&sh->peer)) return Yang_Ok;
if(session->avinfo->rtc.hasIceServer) sh->requestStunServer(&sh->peer);
ret = sh->setRemoteDescription(&sh->peer,sdp);
if (ret) return ret;
//取得answer传回对端
ret = sh->createHttpAnswer(&sh->peer,answer);
session->pushs.insert(&session->pushs.vec,sh);
if(sh->peer.streamconfig.streamOptType==Yang_Stream_Both||sh->peer.streamconfig.streamOptType==Yang_Stream_Play){
//m_playCount++;
//yang_post_message(YangM_P2p_Play_Start,0,NULL);
}
// if(m_context) m_context->streams.connectNotify(sh->peer.streamconfig.uid,sh->peer.streamconfig.streamOptType, true);
if(session->pushs.vec.vsize==1){
//yang_reindex(session->in_audioBuffer);
yang_reindex2(session->in_videoBuffer);
}
//if(m_p2pRtcI) m_p2pRtcI->sendKeyframe();
*phasplay=sh->peer.streamconfig.streamOptType==Yang_Stream_Both?1:0;
return Yang_Ok;
}
基于服务器转发的flutter 跨平台应用,
采用 go pion库实现webrtc rtp数据包的转发
n, _, readErr := track.Read(b)
if readErr != nil {
log.Debug(readErr)
pps.bVideoStop = true
continue
//break
}
stream.SendStreamVideo(b[:n])
网页从服务器拉流