
由于我前一段时间忙于开发,所以我没有及时记录开发过程中遇到的问题. 现在我只能通过记忆来写一些令人印象深刻的凹坑. 本文首先填充了本系列的最后一篇文章,前面只是将其向上推,现在您需要订阅该流.
我记得我当时遇到了一些问题. 其中之一是,订阅其他视频流后,我发布的视频没有声音. 其他问题已经不清楚. 如果您遇到任何问题,也许可以帮忙记住.
当我感到连接时,我有点困惑. 推送流时,我已建立对等连接. 收集流时是否可以直接使用此连接?我检查了一些信息. 如果只有两个人进行交流,这确实是可行的,但是我们需要拉更多的个人视频不适合. 开始添加一个用户字段来区分流属于连接,它很复杂并且没有比较,而janus不支持它web视频会议,因此实际的对等连接是这样的:


pushconnection对等连接归因于push流,pull flow对等连接归因于pull流,互补且一致.
连接到Janus并加入会议室后,如果另一个用户成功发布了流,您将收到一条信号,通知您有人已经发布了媒体并告诉您详细信息. 这时,有必要发起一个“订阅”来带来用户的流名称,这是密钥,密钥,密钥,只有Janus知道此对等连接是要发送用户数据.

Janus收到信令后,它将启动createoffer进程,等待信令发送Janus的SDP,然后我们将在答复中答复答案的SDP(发布是我们的报价web视频会议,Janus返回答案) ,SDP交换完成:
void KKRtcConnection::onJanusPeerSdp(std::string sdptype, std::string sdp)
{
webrtc::SdpParseError error;
rtc::Optional<SdpType> type_maybe = webrtc::SdpTypeFromString(sdptype);
if (!type_maybe) {
RTC_LOG(LS_ERROR) << "Unknown SDP type: " << sdptype;
return;
}
SdpType type = *type_maybe;
if (!InitializePeerConnection())
{
///onError callback
return;
}
std::unique_ptr<webrtc::SessionDescriptionInterface> session_description = webrtc::CreateSessionDescription(type, sdp, &error);
if (!session_description) {
blog(emLOG_WARNING, "%s Can't parse received session description message. SdpParseError was: %s",__func__ ,error.description.c_str() );
return;
}
blog(emLOG_INFO, "%s Received session description ",__func__);
peer_connection_->SetRemoteDescription(DummySetSessionDescriptionObserver::Create(), session_description.release());
if (type == SdpType::kOffer) {
peer_connection_->CreateAnswer(this, NULL);
}
#ifdef DEBUG_LOG
blog(emLOG_INFO, " curthreadId:%u %s proccess end(%d) handleId=%d", rtc::CurrentThreadId(), __func__, __LINE__,handleid_);
#endif
}
然后创建一个初始对等连接以收集ICE:

peer_connection_factory_ = webrtc::CreatePeerConnectionFactory( rtc::Thread::Current(), rtc::Thread::Current(),
reinterpret_cast<webrtc::AudioDeviceModule *>(adm_.get()),
webrtc::CreateBuiltinAudioEncoderFactory(),
webrtc::CreateBuiltinAudioDecoderFactory(), NULL,NULL);
webrtc::PeerConnectionInterface::RTCConfiguration config;
webrtc::FakeConstraints constraints;
if (dtls)
{
constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, "true");
}
else
{
constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, "false");
}
constraints.AddOptional(webrtc::MediaConstraintsInterface::kCpuOveruseDetection, "false");
peer_connection_ = peer_connection_factory_->CreatePeerConnection(config, &constraints, NULL, NULL, this);
auto ptr = new rtc::RefCountedObject<KKRTCStatus>();
peer_connection_->GetStats(ptr);
CreatePeerConnection调用设置了回调接口PeerConnectionObserver this的实现类this,每次在调用后调用ICE状态回调时,这三个主要功能就足够了:
OnIceCandidate

OnIceGatheringChange
OnAddStream
IceCandidate在OnIceCandidate上向Janus发送信号,IceComplete在OnIceGatheringChange上向Janus发送信号,
在远程帧进入OnAddStream之后设置回调处理类:
void KKRtcConnection::OnAddStream( rtc::scoped_refptr<webrtc::MediaStreamInterface> stream)
{
#ifdef DEBUG_LOG
blog(emLOG_INFO,"%s %d", __func__ ,stream->id() );
#endif
webrtc::VideoTrackVector tracks = stream->GetVideoTracks();
// Only render the first track.
if (!tracks.empty()) {
webrtc::VideoTrackInterface* track = tracks[0];
rendered_track_ = track;
rendered_track_->AddOrUpdateSink(this, rtc::VideoSinkWants());
}
stream->Release();
#ifdef DEBUG_LOG
blog(emLOG_INFO, " curthreadId:%u %s proccess end(%d) handleId=%d", rtc::CurrentThreadId(), __func__, __LINE__, handleid_);
#endif
}
然后您可以在框架回调中处理另一方的框架预览.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/ruanjian/article-247166-1.html
从哪里开始
想得美台独