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);
}
}
}