Janus客戶端修改WebRTC原始碼支援會議室功能
阿新 • • 發佈:2018-11-04
Janus客戶端使用最新版本的WebRTC的so,發現subscribe組時,不能看到火狐客戶端推送的視訊
分析日誌,原因是接收rtp包的receiver的sink中沒有被註冊任何接受者,所以解碼後的資料幀沒有被回撥到應用層。
經過分析,剛開始以為是mid不一致所致,後來發現,是底層庫對sendonly做了特殊處理:
火狐的SDP:mid為video字串
a=group:BUNDLE video a=msid-semantic: WMS janus m=video 9 UDP/TLS/RTP/SAVPF 96 c=IN IP4 11.12.115.200 a=sendonly a=mid:video a=rtcp-mux
Webrtc中生成的SDP:mid則為0
a=group:BUNDLE 0 1
a=msid-semantic: WMS ARDAMS
m=video 9 UDP/TLS/RTP/SAVPF 127 97 98 99 100 101 125 103 104
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:sOgE
a=ice-pwd:OAEMHfMMr26hgYbs70QwRuVT
a=ice-options:trickle renomination
a=mid:0
而WebRTC庫中建立Peerconnection物件時,會預先建立一個transceiver(sender和receiver),但mid預設為0
修改前的程式碼:
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>> PeerConnection::AssociateTransceiver(cricket::ContentSource source, SdpType type, size_t mline_index, const ContentInfo& content, const ContentInfo* old_local_content, const ContentInfo* old_remote_content) { //... if (source == cricket::CS_LOCAL) { // Find the RtpTransceiver that corresponds to this m= section, using the // mapping between transceivers and m= section indices established when // creating the offer. if (!transceiver) { transceiver = GetTransceiverByMLineIndex(mline_index); } if (!transceiver) { LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "Unknown transceiver"); } } else { RTC_DCHECK_EQ(source, cricket::CS_REMOTE); // If the m= section is sendrecv or recvonly, and there are RtpTransceivers // of the same type... if (!transceiver RtpTransceiverDirectionHasRecv(media_desc->direction())) { RTC_LOG(LS_INFO) << "continue find=" << media_desc->direction(); transceiver = FindAvailableTransceiverToReceive(media_desc->type()); } // If no RtpTransceiver was found in the previous step, create one with a // recvonly direction. if (!transceiver) { RTC_LOG(LS_INFO) << "Adding " << cricket::MediaTypeToString(media_desc->type()) << " transceiver for MID=" << content.name << " at i=" << mline_index << " in response to the remote description."; auto sender = CreateSender(media_desc->type(), nullptr, {rtc::CreateRandomUuid()}); std::string receiver_id; if (!media_desc->streams().empty()) { receiver_id = media_desc->streams()[0].id; } else { receiver_id = rtc::CreateRandomUuid(); } auto receiver = CreateReceiver(media_desc->type(), receiver_id); transceiver = CreateAndAddTransceiver(sender, receiver); transceiver->internal()->set_direction( RtpTransceiverDirection::kRecvOnly); } } rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>> PeerConnection::GetAssociatedTransceiver(const std::string& mid) const { RTC_DCHECK(IsUnifiedPlan()); for (auto transceiver : transceivers_) { RTC_LOG(LS_INFO) << ", mid:" << mid; if (transceiver->mid() == mid) { return transceiver; } } RTC_LOG(LS_INFO) << "GetAssociatedTransceiver is null, mid:" << mid; return nullptr; }
修改後的程式碼:
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
PeerConnection::AssociateTransceiver(cricket::ContentSource source,
SdpType type,
size_t mline_index,
const ContentInfo& content,
const ContentInfo* old_local_content,
const ContentInfo* old_remote_content)
{
//...
const MediaContentDescription* media_desc = content.media_description();
auto transceiver = GetAssociatedTransceiver(content.name);
if (source == cricket::CS_LOCAL) {
// Find the RtpTransceiver that corresponds to this m= section, using the
// mapping between transceivers and m= section indices established when
// creating the offer.
if (!transceiver) {
transceiver = GetTransceiverByMLineIndex(mline_index);
}
if (!transceiver) {
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
"Unknown transceiver");
}
} else {
RTC_DCHECK_EQ(source, cricket::CS_REMOTE);
// If the m= section is sendrecv or recvonly, and there are RtpTransceivers
// of the same type...
//modify start.
if (!transceiver) {
RTC_LOG(LS_INFO) << "continue find=" << media_desc->direction();
transceiver = FindAvailableTransceiverToReceive(media_desc->type());
//remote sendonly ,so the client is recvonly
if (!RtpTransceiverDirectionHasRecv(media_desc->direction())) {
transceiver->internal()->set_direction(
RtpTransceiverDirection::kRecvOnly);
}
}
//modify end.
// If no RtpTransceiver was found in the previous step, create one with a
// recvonly direction.
if (!transceiver) {
RTC_LOG(LS_INFO) << "Adding "
<< cricket::MediaTypeToString(media_desc->type())
<< " transceiver for MID=" << content.name
<< " at i=" << mline_index
<< " in response to the remote description.";
auto sender =
CreateSender(media_desc->type(), nullptr, {rtc::CreateRandomUuid()});
std::string receiver_id;
if (!media_desc->streams().empty()) {
receiver_id = media_desc->streams()[0].id;
} else {
receiver_id = rtc::CreateRandomUuid();
}
auto receiver = CreateReceiver(media_desc->type(), receiver_id);
transceiver = CreateAndAddTransceiver(sender, receiver);
transceiver->internal()->set_direction(
RtpTransceiverDirection::kRecvOnly);
}
}
}