libyangpeerconnection8是一个webRTC媒体传输/数据通道的一个轻量级的webRTC库,基于metaRTC8.0的传输模块构建,包含pacer/fec/netEQ/twcc/Sender Side BWE等模块,在弱网对抗/内存优化等效果上有显著提升,可用于ffmpeg/obs等webRTC插件。
libyangpeerconnection8下载地址
YangPeerInfo peerInfo;
memset(&peerInfo, 0, sizeof(YangPeerInfo));
yang_init_peerParam(&peerInfo);
//推流需配置参数,拉流不需要
peerInfo.pushVideo.width = width;
peerInfo.pushVideo.height = height;
peerInfo.pushVideo.fps = 30;
peerInfo.uid = 0;
peerInfo.rtc.isControlled = yangfalse;
peerInfo.rtc.rtcLocalPort = 17000;
//YangCallbackReceive* receive
//YangCallbackIce* ice
//YangCallbackRtc* rtc
//YangCallbackSslAlert* sslAlert
YangPeerConnection8* peer = yang_create_peerConnection8(&peerInfo, receive, ice, rtc, sslAlert);
peer->addAudioTrack(Yang_AED_OPUS);
peer->addVideoTrack(Yang_VED_H264);
//YangSendrecv YangSendonly YangRecvonly
peer->addTransceiver(YangMediaAudio, YangSendonly);
peer->addTransceiver(YangMediaVideo, YangSendonly);
peer->createDataChannel();
//pacer用于推流,拉流不需要
YangRtcPacer* pacer=yang_create_rtcPacer(&peerInfo,yangtrue,yangtrue,NULL);
pacer->attachConnection(peer);//将connection与pacer关联
//delete peer
if(peer){
delete peer;
peer=NULL;
}
//delete pacer
if(pacer){
delete pacer;
pacer=NULL;
}
//通过信令取得对端candidate
peer->addIceCandidate(candidate);
//回调ice candidate
YangCallbackIce ice
void YangCallbackIce::ipc_onIceCandidate(int32_t uid,char* candidateStr){
if (context == NULL) return;
//取得candidateStr 通过信令传到对端
}
//*************************YangRtcDemo.h**************
#include
class YangRtcDemo:public YangCallbackReceive,public YangCallbackIce,public YangCallbackRtc,public YangCallbackSslAlert{
public:
YangRtcDemo();
virtual ~YangRtcDemo();
YangRtcConnectionState m_connState;
public:
void receiveAudio(YangFrame* audioFrame);
//frametype:YANG_Frametype_I YANG_Frametype_P
void receiveVideo(YangFrame* videoFrame);
void receiveMsg(YangFrame* msgFrame);
void onIceStateChange(int32_t uid,YangIceCandidateState iceState);
void onConnectionStateChange(int32_t uid,YangRtcConnectionState connectionState);
void onIceCandidate(int32_t uid,char* sdp);
void onIceGatheringState(int32_t uid,YangIceGatheringState gatherState);
void setMediaConfig(int32_t puid,YangAudioParam* audio,YangVideoParam* video);
void sendRequest(int32_t puid,uint32_t ssrc,YangRequestType req);
void sslCloseAlert(int32_t uid);
}
//*************************YangRtcDemo.cpp**************
void YangRtcDemo::receiveAudio(YangFrame* audioFrame){
//接收音频数据
}
//frametype:YANG_Frametype_I YANG_Frametype_P
void YangRtcDemo::receiveVideo(YangFrame* videoFrame){
//接收视频数据
}
void YangRtcDemo::receiveMsg(YangFrame* msgFrame){
//接收datachannel数据
if (m_dataMsg)
m_dataMsg->receiveMsg(m_dataMsg->user, 0, msgFrame->payload, msgFrame->nb);
}
void YangRtcDemo::onIceStateChange(int32_t uid,YangIceCandidateState iceState){
switch(iceState){
case YangIceSuccess:{
break;
}
case YangIceFail:{
yang_trace("\nYangIceFail remove uid==%d",uid);
disconnectPeer();
break;
}
default:break;
}
}
void YangRtcDemo::onConnectionStateChange(int32_t uid,YangRtcConnectionState connectionState){
switch(connectionState){
case Yang_Conn_State_Connecting:{
break;
}
case Yang_Conn_State_Connected:{
m_connState = connectionState;
break;
}
case Yang_Conn_State_Disconnected:{
m_connState = connectionState;
break;
}
case Yang_Conn_State_Failed:{
yang_trace("\nYang_Conn_State_Failed remove uid==%d",uid);
m_connState = Yang_Conn_State_New;
disconnectPeer();
break;
}
case Yang_Conn_State_Closed:{
break;
}
default:break;
}
}
void YangRtcDemo::onIceCandidate(int32_t uid,char* candidateStr){
//取得candidate传到对端
}
void YangRtcDemo::onIceGatheringState(int32_t uid,YangIceGatheringState gatherState){
}
void YangRtcDemo::setMediaConfig(int32_t puid,YangAudioParam* audio,YangVideoParam* video){
}
void YangRtcDemo::sendRequest(int32_t puid,uint32_t ssrc,YangRequestType req){
//向编码器发送关键帧请求或者码率变化状态
}
void YangRtcDemo::sslCloseAlert(int32_t uid) {
m_connState = Yang_Conn_State_Closed;
}
frametype:YANG_Frametype_I(I帧) YANG_Frametype_P(P帧或B帧)
//I帧 startCode+sps+startCode+pps+startCode+I帧 如:00,00,00,01,67,42,c0,1f,8c,8d,40,50,1e,d0,0f,08,84,6a,00,00,00,01,68,ce,3c,80,00,00,00,01,65,b8,00,04,00,00,13,88,c5
//P帧或B帧 如:00,00,00,01,61,e0,00,40,00,be,41,38,22,93,df
//去掉start code 00,00,00,01,取61,e0,00,40,00,be,41,38,22,93,df
pacer->bufferVideoFrame(videoFrame);
//取得音视频编码后数据
pacer->bufferAudioFrame(audioFrame);
//线程推流
while (yangtrue) {
if(!inited){
inited = yangtrue;
pacer->reset();
}
pacer->process();
}
//implement YangCallbackReceive
void YangIpcRtc::receiveAudio(YangFrame* audioFrame){
//接收到音频data,length,pts
}
//frametype:YANG_Frametype_I YANG_Frametype_P
void YangIpcRtc::receiveVideo(YangFrame* videoFrame){
//接收到视频data,length,pts,frametype
}
//接收datachannel数据
void YangIpcRtc::receiveMsg(YangFrame* msgFrame){
if (m_dataMsg)
m_dataMsg->receiveMsg(m_dataMsg->user, 0, msgFrame->payload, msgFrame->nb);
}
YangPeerInfo peerInfo;
YangPeerConnection8* peer = (YangPeerConnection8*)calloc(1, sizeof(YangPeerConnection8));
//pacer用于推流,拉流不需要
YangRtcPacer* pacer=(YangRtcPacer*)calloc(1,sizeof(YangRtcPacer));
memset(&peerInfo, 0, sizeof(YangPeerInfo));
yang_init_peerParam(&peerInfo);
//推流时需配置参数,拉流不需要
peerInfo.pushVideo.width = width;
peerInfo.pushVideo.height = height;
peerInfo.pushVideo.fps = 30;
peerInfo.uid = 0;
peerInfo.rtc.isControlled = yangfalse;
peerInfo.rtc.rtcLocalPort = 17000;
//YangCallbackReceive* receive
//YangCallbackIce* ice
//YangCallbackRtc* rtc
//YangCallbackSslAlert* sslAlert
yang_create_peerConnection8(peer,&peerInfo, receive, ice, rtc, sslAlert);
peer->addAudioTrack(peer->session,Yang_AED_OPUS);
peer->addVideoTrack(peer->session, Yang_VED_H264);
peer->addTransceiver(peer->session, YangMediaAudio, YangSendonly);
peer->addTransceiver(peer->session, YangMediaVideo, YangSendonly);
peer->createDataChannel(peer->session);
//pacer用于推流,拉流不需要
yang_create_rtcPacer(pacer,&peerInfo,yangtrue,yangtrue,NULL);
pacer->attachConnection(pacer->session,peer);//将connection与pacer关联
//free peer
if(peer){
yang_destroy_peerConnection8(peer);
free peer;
peer=NULL;
}
//free pacer
if(pacer){
yang_destroy_rtcPacer(pacer);
free pacer;
pacer=NULL;
}
//通过信令取得对端candidate
peer->addIceCandidate(&peer->peer,candidate);
//回调函数
static void ipc_onIceCandidate(void* context, int32_t uid,char* sdp){
if (context == NULL) return;
//取得candidate 通过信令传到对端
}
//********************YangCallbackReceive*******************************
static void yang_receiveAudio(void* user,YangFrame* audioFrame){
//接收到音频data,length,pts
}
//frametype:YANG_Frametype_I YANG_Frametype_P
static void yang_receiveVideo(void* user,YangFrame* videoFrame){
//接收到视频data,length,pts,frametype
}
//接收datachannel数据
static void yang_receiveMsg(void* user,YangFrame* msgFrame){
if (m_dataMsg)
m_dataMsg->receiveMsg(m_dataMsg->user, 0, msgFrame->payload, msgFrame->nb);
}
//********************YangCallbackIce*******************************
static void yang_onIceStateChange(void* user,int32_t uid,YangIceCandidateState iceState){
switch(iceState){
case YangIceSuccess:{
break;
}
case YangIceFail:{
yang_trace("\nYangIceFail remove uid==%d",uid);
disconnectPeer();
break;
}
default:break;
}
}
static void yang_onConnectionStateChange(void* user,int32_t uid,YangRtcConnectionState connectionState){
switch(connectionState){
case Yang_Conn_State_Connecting:{
break;
}
case Yang_Conn_State_Connected:{
m_connState = connectionState;
break;
}
case Yang_Conn_State_Disconnected:{
m_connState = connectionState;
break;
}
case Yang_Conn_State_Failed:{
yang_trace("\nYang_Conn_State_Failed remove uid==%d",uid);
m_connState = Yang_Conn_State_New;
disconnectPeer();
break;
}
case Yang_Conn_State_Closed:{
break;
}
default:break;
}
}
static void yang_onIceCandidate(void* user,int32_t uid,char* candidateStr){
//取得candidate传到对端
}
static void yang_onIceGatheringState(int32_t uid,YangIceGatheringState gatherState){
}
//********************YangCallbackRtc*******************************
static void yang_setMediaConfig(void* user,int32_t puid,YangAudioParam* audio,YangVideoParam* video){
}
static void yang_sendRequest(void* user,int32_t puid,uint32_t ssrc,YangRequestType req){
//向编码器发送关键帧请求或者码率变化状态
}
//********************YangCallbackSslAlert*******************************
static void yang_sslCloseAlert(void* user,int32_t uid) {
m_connState = Yang_Conn_State_Closed;
}
frametype:YANG_Frametype_I(I帧) YANG_Frametype_P(P帧或B帧)
//I帧 startCode+sps+startCode+pps+startCode+I帧 如:00,00,00,01,67,42,c0,1f,8c,8d,40,50,1e,d0,0f,08,84,6a,00,00,00,01,68,ce,3c,80,00,00,00,01,65,b8,00,04,00,00,13,88,c5
//P帧或B帧 如:00,00,00,01,61,e0,00,40,00,be,41,38,22,93,df
//去掉start code 00,00,00,01,取61,e0,00,40,00,be,41,38,22,93,df
//取得音视频编码后数据
pacer->bufferVideoFrame(videoFrame);
pacer->bufferAudioFrame(audioFrame);
//线程推流
while (yangtrue) {
if(!inited){
inited = yangtrue;
pacer->reset();
}
pacer->process();
}
pacer->bufferVideoFrame(pacer->session, videoFrame);
pacer->bufferAudioFrame(pacer->session, audioFrame);
//线程推流
while (yangtrue) {
if(!inited){
inited = yangtrue;
pacer->reset(pacer->session);
}
pacer->process(pacer->session);
}
//implement YangCallbackReceive
static void yang_receiveAudio(void* user,YangFrame* audioFrame){
//接收到音频data,length,pts
}
//frametype:YANG_Frametype_I YANG_Frametype_P
static void yang_receiveVideo(void* user,YangFrame* videoFrame){
//接收到视频data,length,pts,frametype
}
//接收datachannel数据
static void yang_receiveMsg(void* user,YangFrame* msgFrame){
if (m_dataMsg)
m_dataMsg->receiveMsg(m_dataMsg->user, 0, msgFrame->payload, msgFrame->nb);
}