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