当前位置:网站首页>基于Webrtc和Janus的多人视频会议系统开发6 - 从Janus服务器订阅媒体流
基于Webrtc和Janus的多人视频会议系统开发6 - 从Janus服务器订阅媒体流
2022-08-04 05:32:00 【睏哥RTC】
由于前段时间一直忙于开发,没有及时记录开发过程中遇到的问题,现在只能靠回忆来写一些印象深刻的坑了,本篇文章先把本系列的最后一篇补上,前面只是做到了把流推上去,现在还需要把流订阅下来。
记得当时是遇到几个问题的,其中一个是订阅其他流后,自己发布的视频就没有声音了,其他问题已经记不清楚了,大家如果遇到什么问题说下说不定能帮助想起了。
感接时有点疑惑,推流时已经建立了peerconnection,收流时是不是可以直接用这个connection就行了,查了些资料,如果只是两个人通讯确实可行,不过对于我们这个需要拉多个人视频的就不合适了,出发在connection上加上区分流所属用户字段,那就复杂了也没比较,janus也不支持,所以实际的peerconnection是这样的:
推流的peerconnection归推流,拉流的peerconnection归拉流,互补相干.
你在连接Janus,join到一个房间后,如果有另外一个用户publish流成功,你会收到一个信令告诉你有人发布媒体了,并告诉你详细信息,这时发起一个subscribe必须要把该用户的streamname带上,这个是关键,关键,关键,只有这样Janus才知道这个peerconnection是要发该用户的数据的。
Janus收到该信令后,会发起createoffer流程,等待该信令把Janus的SDP发过来,然后我们再回复里把answer 的SDP回复过去(publish是我们发offer,Janus回answer),就完成了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
}
然后是创建初始化peerconnection来收集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, 调用后每次ICE状态回调,主要这三个函数就可以了:
OnIceCandidate
OnIceGatheringChange
OnAddStream
在OnIceCandidate把IceCandidate信令发给Janus, 在OnIceGatheringChange把IceComplete信令发给Janus,
OnAddStream里设置remote帧来了后的回调处理类:
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
}
然后在帧回调里处理对方的帧预览就可以啦。
边栏推荐
- 多线程顺序输出
- JDBC第一学之进行数据库连接时出现The server time zone.....解决办法
- IEEE802.X protocol suite
- LeetCode_Nov_5th_Week
- tmux概念和使用
- A code example of the PCL method in the domain of DG (Domain Generalization)
- LeetCode_Nov_3rd_Week
- const int * a 与 int * const a 的定义与区别
- C语言静态变量static的分析
- Question 1000: Input two integers a and b, calculate the sum of a+b, this question is multiple sets of test data
猜你喜欢
管道重定向
MNIST Handwritten Digit Recognition - Image Analysis Method for Binary Classification
arm-2-基础阶段
Tencent and NetEase have taken action one after another. What is the metaverse that is so popular that it is out of the circle?
C语言静态变量static的分析
LeetCode_Nov_5th_Week
C语言结构体(必须掌握版)
淘宝分布式文件系统存储(二)
file editor
"A minute" Copy siege lion log 】 【 run MindSpore LeNet model
随机推荐
FAREWARE ADDRESS
华为鲲鹏arm服务器下使用webrtc和boost踩坑记--编译篇
Implementation of CAS lock-free queue
Thunderbolt turns off automatic updates
Miscellaneous [development] [VS Code] remote - SSD retry failed
使用cef离屏渲染技术实现在线教育课件和webrtc视频回放融合录制
Stream API
Object.requireNonNull 方法说明
EL表达式
多线程顺序输出
Amazon Cloud Technology Build On 2022 - AIot Season 2 IoT Special Experiment Experience
网络通信与Socket编程概述
Cut the hit pro subtitles export of essays
管道重定向
jdbc:mysql://localhost:3306/student?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8时报错
安装MySQL的详细步骤
FAREWARE ADDRESS
第三章 标准单元库(下)
MNIST Handwritten Digit Recognition - Building a Perceptron from Zero for Two-Classification
Shell脚本执行的三种方式