mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1829667: Make JsepTransceiver non-refcounted. r=mjf,webidl,mccr8
Involves substantial refactoring to make most access by-value (or through functional-style in-place modifications) for safety. Differential Revision: https://phabricator.services.mozilla.com/D176423
This commit is contained in:
parent
e533a4c3dd
commit
c7504aeccf
@ -1391,11 +1391,14 @@ export class RTCPeerConnection {
|
||||
transceiver.setDirectionInternal("sendonly");
|
||||
}
|
||||
} else {
|
||||
transceiver = this._addTransceiverNoEvents(track, {
|
||||
streams,
|
||||
direction: "sendrecv",
|
||||
});
|
||||
transceiver.setAddTrackMagic();
|
||||
transceiver = this._addTransceiverNoEvents(
|
||||
track,
|
||||
{
|
||||
streams,
|
||||
direction: "sendrecv",
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
this.updateNegotiationNeeded();
|
||||
@ -1431,7 +1434,7 @@ export class RTCPeerConnection {
|
||||
this.updateNegotiationNeeded();
|
||||
}
|
||||
|
||||
_addTransceiverNoEvents(sendTrackOrKind, init) {
|
||||
_addTransceiverNoEvents(sendTrackOrKind, init, addTrackMagic) {
|
||||
let sendTrack = null;
|
||||
let kind;
|
||||
if (typeof sendTrackOrKind == "string") {
|
||||
@ -1449,7 +1452,7 @@ export class RTCPeerConnection {
|
||||
}
|
||||
|
||||
try {
|
||||
return this._pc.addTransceiver(init, kind, sendTrack);
|
||||
return this._pc.addTransceiver(init, kind, sendTrack, addTrackMagic);
|
||||
} catch (e) {
|
||||
// Exceptions thrown by c++ code do not propagate. In most cases, that's
|
||||
// fine because we're using Promises, which can be copied. But this is
|
||||
|
@ -877,17 +877,14 @@ nsresult PeerConnectionImpl::GetDatachannelParameters(
|
||||
*mmsset = false;
|
||||
transportId->clear();
|
||||
|
||||
RefPtr<JsepTransceiver> datachannelTransceiver;
|
||||
for (const auto& transceiver : mJsepSession->GetTransceivers()) {
|
||||
if ((transceiver->GetMediaType() == SdpMediaSection::kApplication) &&
|
||||
transceiver->mSendTrack.GetNegotiatedDetails()) {
|
||||
datachannelTransceiver = transceiver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Maybe<const JsepTransceiver> datachannelTransceiver =
|
||||
mJsepSession->FindTransceiver([](const JsepTransceiver& aTransceiver) {
|
||||
return aTransceiver.GetMediaType() == SdpMediaSection::kApplication;
|
||||
});
|
||||
|
||||
if (!datachannelTransceiver ||
|
||||
!datachannelTransceiver->mTransport.mComponents) {
|
||||
!datachannelTransceiver->mTransport.mComponents ||
|
||||
!datachannelTransceiver->mSendTrack.GetNegotiatedDetails()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -942,7 +939,7 @@ nsresult PeerConnectionImpl::GetDatachannelParameters(
|
||||
}
|
||||
|
||||
nsresult PeerConnectionImpl::AddRtpTransceiverToJsepSession(
|
||||
RefPtr<JsepTransceiver>& transceiver) {
|
||||
JsepTransceiver& transceiver) {
|
||||
nsresult res = ConfigureJsepSessionCodecs();
|
||||
if (NS_FAILED(res)) {
|
||||
CSFLogError(LOGTAG, "Failed to configure codecs");
|
||||
@ -965,7 +962,7 @@ static Maybe<SdpMediaSection::MediaType> ToSdpMediaType(
|
||||
|
||||
already_AddRefed<RTCRtpTransceiver> PeerConnectionImpl::AddTransceiver(
|
||||
const dom::RTCRtpTransceiverInit& aInit, const nsAString& aKind,
|
||||
dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv) {
|
||||
dom::MediaStreamTrack* aSendTrack, bool aAddTrackMagic, ErrorResult& aRv) {
|
||||
// Copy, because we might need to modify
|
||||
RTCRtpTransceiverInit init(aInit);
|
||||
|
||||
@ -976,9 +973,8 @@ already_AddRefed<RTCRtpTransceiver> PeerConnectionImpl::AddTransceiver(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<JsepTransceiver> jsepTransceiver =
|
||||
new JsepTransceiver(*type, *mUuidGen);
|
||||
jsepTransceiver->SetRtxIsAllowed(mRtxIsAllowed);
|
||||
JsepTransceiver jsepTransceiver(*type, *mUuidGen);
|
||||
jsepTransceiver.SetRtxIsAllowed(mRtxIsAllowed);
|
||||
|
||||
// Do this last, since it is not possible to roll back.
|
||||
nsresult rv = AddRtpTransceiverToJsepSession(jsepTransceiver);
|
||||
@ -1074,9 +1070,9 @@ already_AddRefed<RTCRtpTransceiver> PeerConnectionImpl::AddTransceiver(
|
||||
}
|
||||
|
||||
RefPtr<RTCRtpTransceiver> transceiver = CreateTransceiver(
|
||||
jsepTransceiver->GetUuid(),
|
||||
jsepTransceiver->GetMediaType() == SdpMediaSection::kVideo, init,
|
||||
aSendTrack, aRv);
|
||||
jsepTransceiver.GetUuid(),
|
||||
jsepTransceiver.GetMediaType() == SdpMediaSection::kVideo, init,
|
||||
aSendTrack, aAddTrackMagic, aRv);
|
||||
|
||||
if (aRv.Failed()) {
|
||||
// Would be nice if we could peek at the rv without stealing it, so we
|
||||
@ -1177,22 +1173,19 @@ PeerConnectionImpl::CreateDataChannel(
|
||||
|
||||
CSFLogDebug(LOGTAG, "%s: making DOMDataChannel", __FUNCTION__);
|
||||
|
||||
RefPtr<JsepTransceiver> dcTransceiver;
|
||||
for (auto& transceiver : mJsepSession->GetTransceivers()) {
|
||||
if (transceiver->GetMediaType() == SdpMediaSection::kApplication) {
|
||||
dcTransceiver = transceiver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Maybe<JsepTransceiver> dcTransceiver =
|
||||
mJsepSession->FindTransceiver([](const JsepTransceiver& aTransceiver) {
|
||||
return aTransceiver.GetMediaType() == SdpMediaSection::kApplication;
|
||||
});
|
||||
|
||||
if (!dcTransceiver) {
|
||||
dcTransceiver = new JsepTransceiver(
|
||||
SdpMediaSection::MediaType::kApplication, *mUuidGen);
|
||||
mJsepSession->AddTransceiver(dcTransceiver);
|
||||
if (dcTransceiver) {
|
||||
dcTransceiver->RestartDatachannelTransceiver();
|
||||
mJsepSession->SetTransceiver(*dcTransceiver);
|
||||
} else {
|
||||
mJsepSession->AddTransceiver(
|
||||
JsepTransceiver(SdpMediaSection::MediaType::kApplication, *mUuidGen));
|
||||
}
|
||||
|
||||
dcTransceiver->RestartDatachannelTransceiver();
|
||||
|
||||
RefPtr<nsDOMDataChannel> retval;
|
||||
rv = NS_NewDOMDataChannel(dataChannel.forget(), mWindow,
|
||||
getter_AddRefs(retval));
|
||||
@ -1364,47 +1357,49 @@ void PeerConnectionImpl::RunNextOperation(ErrorResult& aError) {
|
||||
|
||||
void PeerConnectionImpl::SyncToJsep() {
|
||||
for (const auto& transceiver : mTransceivers) {
|
||||
transceiver->SyncToJsep();
|
||||
transceiver->SyncToJsep(*mJsepSession);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::SyncFromJsep() {
|
||||
CSFLogDebug(LOGTAG, "%s", __FUNCTION__);
|
||||
for (const auto& jsepTransceiver : mJsepSession->GetTransceivers()) {
|
||||
if (jsepTransceiver->GetMediaType() ==
|
||||
SdpMediaSection::MediaType::kApplication) {
|
||||
continue;
|
||||
}
|
||||
mJsepSession->ForEachTransceiver(
|
||||
[this, self = RefPtr<PeerConnectionImpl>(this)](
|
||||
const JsepTransceiver& jsepTransceiver) {
|
||||
if (jsepTransceiver.GetMediaType() ==
|
||||
SdpMediaSection::MediaType::kApplication) {
|
||||
return;
|
||||
}
|
||||
|
||||
CSFLogDebug(LOGTAG, "%s: Looking for match", __FUNCTION__);
|
||||
RefPtr<RTCRtpTransceiver> transceiver;
|
||||
for (auto& temp : mTransceivers) {
|
||||
if (temp->GetJsepTransceiverId() == jsepTransceiver->GetUuid()) {
|
||||
CSFLogDebug(LOGTAG, "%s: Found match", __FUNCTION__);
|
||||
transceiver = temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CSFLogDebug(LOGTAG, "%s: Looking for match", __FUNCTION__);
|
||||
RefPtr<RTCRtpTransceiver> transceiver;
|
||||
for (auto& temp : mTransceivers) {
|
||||
if (temp->GetJsepTransceiverId() == jsepTransceiver.GetUuid()) {
|
||||
CSFLogDebug(LOGTAG, "%s: Found match", __FUNCTION__);
|
||||
transceiver = temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!transceiver) {
|
||||
CSFLogDebug(LOGTAG, "%s: No match, making new", __FUNCTION__);
|
||||
dom::RTCRtpTransceiverInit init;
|
||||
init.mDirection = RTCRtpTransceiverDirection::Recvonly;
|
||||
IgnoredErrorResult rv;
|
||||
transceiver = CreateTransceiver(
|
||||
jsepTransceiver->GetUuid(),
|
||||
jsepTransceiver->GetMediaType() == SdpMediaSection::kVideo, init,
|
||||
nullptr, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
mTransceivers.AppendElement(transceiver);
|
||||
}
|
||||
if (!transceiver) {
|
||||
CSFLogDebug(LOGTAG, "%s: No match, making new", __FUNCTION__);
|
||||
dom::RTCRtpTransceiverInit init;
|
||||
init.mDirection = RTCRtpTransceiverDirection::Recvonly;
|
||||
IgnoredErrorResult rv;
|
||||
transceiver = CreateTransceiver(
|
||||
jsepTransceiver.GetUuid(),
|
||||
jsepTransceiver.GetMediaType() == SdpMediaSection::kVideo, init,
|
||||
nullptr, false, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
mTransceivers.AppendElement(transceiver);
|
||||
}
|
||||
|
||||
CSFLogDebug(LOGTAG, "%s: Syncing transceiver", __FUNCTION__);
|
||||
transceiver->SyncFromJsep();
|
||||
}
|
||||
CSFLogDebug(LOGTAG, "%s: Syncing transceiver", __FUNCTION__);
|
||||
transceiver->SyncFromJsep(*mJsepSession);
|
||||
});
|
||||
}
|
||||
|
||||
already_AddRefed<dom::Promise> PeerConnectionImpl::MakePromise(
|
||||
@ -1592,9 +1587,6 @@ PeerConnectionImpl::CreateOffer(const JsepOfferOptions& aOptions) {
|
||||
*buildJSErrorData(result, errorString), rv);
|
||||
} else {
|
||||
mJsepSession = std::move(uncommittedJsepSession);
|
||||
for (auto& transceiver : mTransceivers) {
|
||||
transceiver->SetJsepSession(mJsepSession.get());
|
||||
}
|
||||
mPCObserver->OnCreateOfferSuccess(ObString(offer.c_str()), rv);
|
||||
}
|
||||
}));
|
||||
@ -1631,9 +1623,6 @@ PeerConnectionImpl::CreateAnswer() {
|
||||
*buildJSErrorData(result, errorString), rv);
|
||||
} else {
|
||||
mJsepSession = std::move(uncommittedJsepSession);
|
||||
for (auto& transceiver : mTransceivers) {
|
||||
transceiver->SetJsepSession(mJsepSession.get());
|
||||
}
|
||||
mPCObserver->OnCreateAnswerSuccess(ObString(answer.c_str()), rv);
|
||||
}
|
||||
}));
|
||||
@ -3012,9 +3001,6 @@ void PeerConnectionImpl::DoSetDescriptionSuccessPostProcessing(
|
||||
}
|
||||
|
||||
mJsepSession = std::move(mUncommittedJsepSession);
|
||||
for (auto& transceiver : mTransceivers) {
|
||||
transceiver->SetJsepSession(mJsepSession.get());
|
||||
}
|
||||
|
||||
auto newSignalingState = GetSignalingState();
|
||||
SyncFromJsep();
|
||||
@ -3981,30 +3967,33 @@ bool PeerConnectionImpl::ShouldForceProxy() const {
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::EnsureTransports(const JsepSession& aSession) {
|
||||
for (const auto& transceiver : aSession.GetTransceivers()) {
|
||||
if (transceiver->HasOwnTransport()) {
|
||||
mJsepSession->ForEachTransceiver([this,
|
||||
self = RefPtr<PeerConnectionImpl>(this)](
|
||||
const JsepTransceiver& transceiver) {
|
||||
if (transceiver.HasOwnTransport()) {
|
||||
mTransportHandler->EnsureProvisionalTransport(
|
||||
transceiver->mTransport.mTransportId,
|
||||
transceiver->mTransport.mLocalUfrag,
|
||||
transceiver->mTransport.mLocalPwd,
|
||||
transceiver->mTransport.mComponents);
|
||||
transceiver.mTransport.mTransportId,
|
||||
transceiver.mTransport.mLocalUfrag, transceiver.mTransport.mLocalPwd,
|
||||
transceiver.mTransport.mComponents);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
GatherIfReady();
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::UpdateRTCDtlsTransports(bool aMarkAsStable) {
|
||||
for (const auto& jsepTransceiver : mJsepSession->GetTransceivers()) {
|
||||
std::string transportId = jsepTransceiver->mTransport.mTransportId;
|
||||
if (transportId.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (!mTransportIdToRTCDtlsTransport.count(transportId)) {
|
||||
mTransportIdToRTCDtlsTransport.emplace(
|
||||
transportId, new RTCDtlsTransport(GetParentObject()));
|
||||
}
|
||||
}
|
||||
mJsepSession->ForEachTransceiver(
|
||||
[this, self = RefPtr<PeerConnectionImpl>(this)](
|
||||
const JsepTransceiver& jsepTransceiver) {
|
||||
std::string transportId = jsepTransceiver.mTransport.mTransportId;
|
||||
if (transportId.empty()) {
|
||||
return;
|
||||
}
|
||||
if (!mTransportIdToRTCDtlsTransport.count(transportId)) {
|
||||
mTransportIdToRTCDtlsTransport.emplace(
|
||||
transportId, new RTCDtlsTransport(GetParentObject()));
|
||||
}
|
||||
});
|
||||
|
||||
for (auto& transceiver : mTransceivers) {
|
||||
std::string transportId = transceiver->GetTransportId();
|
||||
@ -4042,17 +4031,19 @@ nsresult PeerConnectionImpl::UpdateTransports(const JsepSession& aSession,
|
||||
const bool forceIceTcp) {
|
||||
std::set<std::string> finalTransports;
|
||||
Maybe<std::string> sctpTransport;
|
||||
for (const auto& transceiver : aSession.GetTransceivers()) {
|
||||
if (transceiver->GetMediaType() == SdpMediaSection::kApplication &&
|
||||
transceiver->HasTransport()) {
|
||||
sctpTransport = Some(transceiver->mTransport.mTransportId);
|
||||
}
|
||||
mJsepSession->ForEachTransceiver(
|
||||
[&, this, self = RefPtr<PeerConnectionImpl>(this)](
|
||||
const JsepTransceiver& transceiver) {
|
||||
if (transceiver.GetMediaType() == SdpMediaSection::kApplication &&
|
||||
transceiver.HasTransport()) {
|
||||
sctpTransport = Some(transceiver.mTransport.mTransportId);
|
||||
}
|
||||
|
||||
if (transceiver->HasOwnTransport()) {
|
||||
finalTransports.insert(transceiver->mTransport.mTransportId);
|
||||
UpdateTransport(*transceiver, forceIceTcp);
|
||||
}
|
||||
}
|
||||
if (transceiver.HasOwnTransport()) {
|
||||
finalTransports.insert(transceiver.mTransport.mTransportId);
|
||||
UpdateTransport(transceiver, forceIceTcp);
|
||||
}
|
||||
});
|
||||
|
||||
// clean up the unused RTCDtlsTransports
|
||||
RemoveRTCDtlsTransportsExcept(finalTransports);
|
||||
@ -4447,7 +4438,7 @@ void PeerConnectionImpl::EnsureIceGathering(bool aDefaultRouteOnly,
|
||||
|
||||
already_AddRefed<dom::RTCRtpTransceiver> PeerConnectionImpl::CreateTransceiver(
|
||||
const std::string& aId, bool aIsVideo, const RTCRtpTransceiverInit& aInit,
|
||||
dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv) {
|
||||
dom::MediaStreamTrack* aSendTrack, bool aAddTrackMagic, ErrorResult& aRv) {
|
||||
PeerConnectionCtx* ctx = PeerConnectionCtx::GetInstance();
|
||||
if (!mCall) {
|
||||
mCall = WebrtcCallWrapper::Create(
|
||||
@ -4458,6 +4449,12 @@ already_AddRefed<dom::RTCRtpTransceiver> PeerConnectionImpl::CreateTransceiver(
|
||||
ctx->GetSharedWebrtcState());
|
||||
}
|
||||
|
||||
if (aAddTrackMagic) {
|
||||
mJsepSession->ApplyToTransceiver(aId, [](JsepTransceiver& aTransceiver) {
|
||||
aTransceiver.SetAddTrackMagic();
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<RTCRtpTransceiver> transceiver = new RTCRtpTransceiver(
|
||||
mWindow, PrivacyRequested(), this, mTransportHandler, mJsepSession.get(),
|
||||
aId, aIsVideo, mSTSThread.get(), aSendTrack, mCall.get(), mIdGenerator);
|
||||
@ -4467,8 +4464,6 @@ already_AddRefed<dom::RTCRtpTransceiver> PeerConnectionImpl::CreateTransceiver(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
transceiver->SyncToJsep();
|
||||
|
||||
if (aSendTrack) {
|
||||
// implement checking for peerIdentity (where failure == black/silence)
|
||||
Document* doc = mWindow->GetExtantDoc();
|
||||
|
@ -296,7 +296,7 @@ class PeerConnectionImpl final
|
||||
|
||||
already_AddRefed<dom::RTCRtpTransceiver> AddTransceiver(
|
||||
const dom::RTCRtpTransceiverInit& aInit, const nsAString& aKind,
|
||||
dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv);
|
||||
dom::MediaStreamTrack* aSendTrack, bool aAddTrackMagic, ErrorResult& aRv);
|
||||
|
||||
bool CheckNegotiationNeeded();
|
||||
bool CreatedSender(const dom::RTCRtpSender& aSender) const;
|
||||
@ -614,7 +614,7 @@ class PeerConnectionImpl final
|
||||
std::string* transportId,
|
||||
bool* client) const;
|
||||
|
||||
nsresult AddRtpTransceiverToJsepSession(RefPtr<JsepTransceiver>& transceiver);
|
||||
nsresult AddRtpTransceiverToJsepSession(JsepTransceiver& transceiver);
|
||||
|
||||
void RecordIceRestartStatistics(JsepSdpType type);
|
||||
|
||||
@ -825,7 +825,7 @@ class PeerConnectionImpl final
|
||||
already_AddRefed<dom::RTCRtpTransceiver> CreateTransceiver(
|
||||
const std::string& aId, bool aIsVideo,
|
||||
const dom::RTCRtpTransceiverInit& aInit,
|
||||
dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv);
|
||||
dom::MediaStreamTrack* aSendTrack, bool aAddTrackMagic, ErrorResult& aRv);
|
||||
|
||||
std::string GetTransportIdMatchingSendTrack(
|
||||
const dom::MediaStreamTrack& aTrack) const;
|
||||
|
@ -892,12 +892,12 @@ std::string RTCRtpReceiver::GetMid() const {
|
||||
|
||||
JsepTransceiver& RTCRtpReceiver::GetJsepTransceiver() {
|
||||
MOZ_ASSERT(mTransceiver);
|
||||
return *mTransceiver->GetJsepTransceiver();
|
||||
return mTransceiver->GetJsepTransceiver();
|
||||
}
|
||||
|
||||
const JsepTransceiver& RTCRtpReceiver::GetJsepTransceiver() const {
|
||||
MOZ_ASSERT(mTransceiver);
|
||||
return *mTransceiver->GetJsepTransceiver();
|
||||
return mTransceiver->GetJsepTransceiver();
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
@ -74,10 +74,6 @@ RTCRtpSender::RTCRtpSender(nsPIDOMWindowInner* aWindow, PeerConnectionImpl* aPc,
|
||||
|
||||
if (aConduit->type() == MediaSessionConduit::AUDIO) {
|
||||
mDtmf = new RTCDTMFSender(aWindow, mTransceiver);
|
||||
GetJsepTransceiver().mSendTrack.SetMaxEncodings(1);
|
||||
} else {
|
||||
GetJsepTransceiver().mSendTrack.SetMaxEncodings(
|
||||
webrtc::kMaxSimulcastStreams);
|
||||
}
|
||||
mPipeline->SetTrack(mSenderTrack);
|
||||
|
||||
@ -91,7 +87,7 @@ RTCRtpSender::RTCRtpSender(nsPIDOMWindowInner* aWindow, PeerConnectionImpl* aPc,
|
||||
if (aEncodings.Length()) {
|
||||
// This sender was created by addTransceiver with sendEncodings.
|
||||
mParameters.mEncodings = aEncodings;
|
||||
SetJsepRids(mParameters);
|
||||
mSimulcastEnvelopeSet = true;
|
||||
mozilla::glean::rtcrtpsender::used_sendencodings.AddToNumerator(1);
|
||||
} else {
|
||||
// This sender was created by addTrack, sRD(offer), or addTransceiver
|
||||
@ -724,7 +720,7 @@ already_AddRefed<Promise> RTCRtpSender::SetParameters(
|
||||
MaybeUpdateConduit();
|
||||
|
||||
if (compatModeAllowedRidChange) {
|
||||
SetJsepRids(paramsCopy);
|
||||
mSimulcastEnvelopeSet = true;
|
||||
}
|
||||
|
||||
// If the media stack is successfully configured with parameters,
|
||||
@ -841,22 +837,6 @@ void RTCRtpSender::CheckAndRectifyEncodings(
|
||||
}
|
||||
}
|
||||
|
||||
void RTCRtpSender::SetJsepRids(const RTCRtpSendParameters& aParameters) {
|
||||
MOZ_ASSERT(aParameters.mEncodings.Length());
|
||||
|
||||
std::vector<std::string> rids;
|
||||
for (const auto& encoding : aParameters.mEncodings) {
|
||||
if (encoding.mRid.WasPassed()) {
|
||||
rids.push_back(NS_ConvertUTF16toUTF8(encoding.mRid.Value()).get());
|
||||
} else {
|
||||
rids.push_back("");
|
||||
}
|
||||
}
|
||||
|
||||
GetJsepTransceiver().mSendTrack.SetRids(rids);
|
||||
mSimulcastEnvelopeSet = true;
|
||||
}
|
||||
|
||||
void RTCRtpSender::GetParameters(RTCRtpSendParameters& aParameters) {
|
||||
MOZ_ASSERT(mParameters.mEncodings.Length());
|
||||
// If sender.[[LastReturnedParameters]] is not null, return
|
||||
@ -1206,10 +1186,10 @@ void RTCRtpSender::SetTrack(const RefPtr<MediaStreamTrack>& aTrack) {
|
||||
mSenderTrack = aTrack;
|
||||
SeamlessTrackSwitch(aTrack);
|
||||
if (aTrack) {
|
||||
// RFC says:
|
||||
// RFC says (in the section on remote rollback):
|
||||
// However, an RtpTransceiver MUST NOT be removed if a track was attached
|
||||
// to the RtpTransceiver via the addTrack method.
|
||||
GetJsepTransceiver().SetOnlyExistsBecauseOfSetRemote(false);
|
||||
mAddTrackCalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1314,6 +1294,29 @@ void RTCRtpSender::SyncToJsep(JsepTransceiver& aJsepTransceiver) const {
|
||||
}
|
||||
|
||||
aJsepTransceiver.mSendTrack.UpdateStreamIds(streamIds);
|
||||
|
||||
if (mSimulcastEnvelopeSet) {
|
||||
std::vector<std::string> rids;
|
||||
for (const auto& encoding : mParameters.mEncodings) {
|
||||
if (encoding.mRid.WasPassed()) {
|
||||
rids.push_back(NS_ConvertUTF16toUTF8(encoding.mRid.Value()).get());
|
||||
} else {
|
||||
rids.push_back("");
|
||||
}
|
||||
}
|
||||
|
||||
aJsepTransceiver.mSendTrack.SetRids(rids);
|
||||
}
|
||||
|
||||
if (mTransceiver->IsVideo()) {
|
||||
aJsepTransceiver.mSendTrack.SetMaxEncodings(webrtc::kMaxSimulcastStreams);
|
||||
} else {
|
||||
aJsepTransceiver.mSendTrack.SetMaxEncodings(1);
|
||||
}
|
||||
|
||||
if (mAddTrackCalled) {
|
||||
aJsepTransceiver.SetOnlyExistsBecauseOfSetRemote(false);
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<RTCRtpSender::VideoConfig> RTCRtpSender::GetNewVideoConfig() {
|
||||
@ -1579,7 +1582,7 @@ RefPtr<MediaPipelineTransmit> RTCRtpSender::GetPipeline() const {
|
||||
std::string RTCRtpSender::GetMid() const { return mTransceiver->GetMidAscii(); }
|
||||
|
||||
JsepTransceiver& RTCRtpSender::GetJsepTransceiver() {
|
||||
return *mTransceiver->GetJsepTransceiver();
|
||||
return mTransceiver->GetJsepTransceiver();
|
||||
}
|
||||
|
||||
void RTCRtpSender::UpdateDtmfSender() {
|
||||
|
@ -138,7 +138,6 @@ class RTCRtpSender : public nsISupports,
|
||||
|
||||
std::string GetMid() const;
|
||||
JsepTransceiver& GetJsepTransceiver();
|
||||
void SetJsepRids(const RTCRtpSendParameters& aParameters);
|
||||
static void ApplyJsEncodingToConduitEncoding(
|
||||
const RTCRtpEncodingParameters& aJsEncoding,
|
||||
VideoCodecConfig::Encoding* aConduitEncoding);
|
||||
@ -157,6 +156,7 @@ class RTCRtpSender : public nsISupports,
|
||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||
RefPtr<PeerConnectionImpl> mPc;
|
||||
RefPtr<dom::MediaStreamTrack> mSenderTrack;
|
||||
bool mAddTrackCalled = false;
|
||||
RTCRtpSendParameters mParameters;
|
||||
Maybe<RTCRtpSendParameters> mPendingParameters;
|
||||
uint32_t mNumSetParametersCalls = 0;
|
||||
|
@ -164,7 +164,7 @@ RTCRtpTransceiver::RTCRtpTransceiver(
|
||||
mPc(aPc),
|
||||
mTransportHandler(aTransportHandler),
|
||||
mTransceiverId(aTransceiverId),
|
||||
mJsepTransceiver(aJsepSession->GetTransceiver(mTransceiverId)),
|
||||
mJsepTransceiver(*aJsepSession->GetTransceiver(mTransceiverId)),
|
||||
mStsThread(aStsThread),
|
||||
mCallWrapper(aCallWrapper),
|
||||
mSendTrack(aSendTrack),
|
||||
@ -449,7 +449,7 @@ bool RTCRtpTransceiver::ConduitHasPluginID(uint64_t aPluginID) {
|
||||
return mConduit && mConduit->HasCodecPluginID(aPluginID);
|
||||
}
|
||||
|
||||
void RTCRtpTransceiver::SyncFromJsep() {
|
||||
void RTCRtpTransceiver::SyncFromJsep(const JsepSession& aSession) {
|
||||
MOZ_MTLOG(ML_DEBUG, mPc->GetHandle()
|
||||
<< "[" << mMid.Ref() << "]: " << __FUNCTION__
|
||||
<< " Syncing from JSEP transceiver");
|
||||
@ -459,35 +459,35 @@ void RTCRtpTransceiver::SyncFromJsep() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto jsepTransceiver = GetJsepTransceiver();
|
||||
mJsepTransceiver = *aSession.GetTransceiver(mTransceiverId);
|
||||
|
||||
// Transceivers can stop due to JSEP negotiation, so we need to check that
|
||||
if (jsepTransceiver->IsStopped()) {
|
||||
if (mJsepTransceiver.IsStopped()) {
|
||||
StopImpl();
|
||||
}
|
||||
|
||||
mReceiver->SyncFromJsep(*jsepTransceiver);
|
||||
mSender->SyncFromJsep(*jsepTransceiver);
|
||||
mReceiver->SyncFromJsep(mJsepTransceiver);
|
||||
mSender->SyncFromJsep(mJsepTransceiver);
|
||||
|
||||
// mid from JSEP
|
||||
if (jsepTransceiver->IsAssociated()) {
|
||||
mMid = jsepTransceiver->GetMid();
|
||||
if (mJsepTransceiver.IsAssociated()) {
|
||||
mMid = mJsepTransceiver.GetMid();
|
||||
} else {
|
||||
mMid = std::string();
|
||||
}
|
||||
|
||||
// currentDirection from JSEP, but not if "this transceiver has never been
|
||||
// represented in an offer/answer exchange"
|
||||
if (jsepTransceiver->HasLevel() && jsepTransceiver->IsNegotiated()) {
|
||||
if (jsepTransceiver->mRecvTrack.GetActive()) {
|
||||
if (jsepTransceiver->mSendTrack.GetActive()) {
|
||||
if (mJsepTransceiver.HasLevel() && mJsepTransceiver.IsNegotiated()) {
|
||||
if (mJsepTransceiver.mRecvTrack.GetActive()) {
|
||||
if (mJsepTransceiver.mSendTrack.GetActive()) {
|
||||
mCurrentDirection.SetValue(dom::RTCRtpTransceiverDirection::Sendrecv);
|
||||
mHasBeenUsedToSend = true;
|
||||
} else {
|
||||
mCurrentDirection.SetValue(dom::RTCRtpTransceiverDirection::Recvonly);
|
||||
}
|
||||
} else {
|
||||
if (jsepTransceiver->mSendTrack.GetActive()) {
|
||||
if (mJsepTransceiver.mSendTrack.GetActive()) {
|
||||
mCurrentDirection.SetValue(dom::RTCRtpTransceiverDirection::Sendonly);
|
||||
mHasBeenUsedToSend = true;
|
||||
} else {
|
||||
@ -496,28 +496,25 @@ void RTCRtpTransceiver::SyncFromJsep() {
|
||||
}
|
||||
}
|
||||
|
||||
mShouldRemove = jsepTransceiver->IsRemoved();
|
||||
mHasTransport = jsepTransceiver->HasLevel() && !jsepTransceiver->IsStopped();
|
||||
mShouldRemove = mJsepTransceiver.IsRemoved();
|
||||
mHasTransport = mJsepTransceiver.HasLevel() && !mJsepTransceiver.IsStopped();
|
||||
}
|
||||
|
||||
void RTCRtpTransceiver::SyncToJsep() const {
|
||||
void RTCRtpTransceiver::SyncToJsep(JsepSession& aSession) const {
|
||||
MOZ_MTLOG(ML_DEBUG, mPc->GetHandle()
|
||||
<< "[" << mMid.Ref() << "]: " << __FUNCTION__
|
||||
<< " Syncing to JSEP transceiver");
|
||||
|
||||
auto jsepTransceiver = GetJsepTransceiver();
|
||||
mReceiver->SyncToJsep(*jsepTransceiver);
|
||||
mSender->SyncToJsep(*jsepTransceiver);
|
||||
jsepTransceiver->mJsDirection = ToSdpDirection(mDirection);
|
||||
if (mStopped) {
|
||||
jsepTransceiver->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Unify with SyncFromJsep
|
||||
void RTCRtpTransceiver::SetJsepSession(JsepSession* aJsepSession) {
|
||||
mJsepTransceiver = aJsepSession->GetTransceiver(mTransceiverId);
|
||||
MOZ_RELEASE_ASSERT(mJsepTransceiver);
|
||||
aSession.ApplyToTransceiver(
|
||||
mTransceiverId, [this, self = RefPtr<const RTCRtpTransceiver>(this)](
|
||||
JsepTransceiver& aTransceiver) {
|
||||
mReceiver->SyncToJsep(aTransceiver);
|
||||
mSender->SyncToJsep(aTransceiver);
|
||||
aTransceiver.mJsDirection = ToSdpDirection(mDirection);
|
||||
if (mStopped) {
|
||||
aTransceiver.Stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void RTCRtpTransceiver::GetKind(nsAString& aKind) const {
|
||||
@ -565,12 +562,6 @@ void RTCRtpTransceiver::SetDirectionInternal(
|
||||
mDirection = aDirection;
|
||||
}
|
||||
|
||||
void RTCRtpTransceiver::SetAddTrackMagic() {
|
||||
// We do this immediately, without waiting for a SyncToJsep, because this is
|
||||
// set at transceiver creation time.
|
||||
GetJsepTransceiver()->SetAddTrackMagic();
|
||||
}
|
||||
|
||||
bool RTCRtpTransceiver::ShouldRemove() const { return mShouldRemove; }
|
||||
|
||||
bool RTCRtpTransceiver::CanSendDTMF() const {
|
||||
@ -589,8 +580,8 @@ bool RTCRtpTransceiver::CanSendDTMF() const {
|
||||
|
||||
// Ok, it looks like the connection is up and sending. Did we negotiate
|
||||
// telephone-event?
|
||||
JsepTrackNegotiatedDetails* details =
|
||||
GetJsepTransceiver()->mSendTrack.GetNegotiatedDetails();
|
||||
const JsepTrackNegotiatedDetails* details =
|
||||
mJsepTransceiver.mSendTrack.GetNegotiatedDetails();
|
||||
if (NS_WARN_IF(!details || !details->GetEncodingCount())) {
|
||||
// What?
|
||||
return false;
|
||||
@ -648,12 +639,11 @@ static void JsepCodecDescToAudioCodecConfig(
|
||||
// TODO: This and the next function probably should move to JsepTransceiver
|
||||
Maybe<const std::vector<UniquePtr<JsepCodecDescription>>&>
|
||||
RTCRtpTransceiver::GetNegotiatedSendCodecs() const {
|
||||
auto jsepTransceiver = GetJsepTransceiver();
|
||||
if (!jsepTransceiver->mSendTrack.GetActive()) {
|
||||
if (!mJsepTransceiver.mSendTrack.GetActive()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
const auto* details = jsepTransceiver->mSendTrack.GetNegotiatedDetails();
|
||||
const auto* details = mJsepTransceiver.mSendTrack.GetNegotiatedDetails();
|
||||
if (!details) {
|
||||
return Nothing();
|
||||
}
|
||||
@ -667,12 +657,11 @@ RTCRtpTransceiver::GetNegotiatedSendCodecs() const {
|
||||
|
||||
Maybe<const std::vector<UniquePtr<JsepCodecDescription>>&>
|
||||
RTCRtpTransceiver::GetNegotiatedRecvCodecs() const {
|
||||
auto jsepTransceiver = GetJsepTransceiver();
|
||||
if (!jsepTransceiver->mRecvTrack.GetActive()) {
|
||||
if (!mJsepTransceiver.mRecvTrack.GetActive()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
const auto* details = jsepTransceiver->mRecvTrack.GetNegotiatedDetails();
|
||||
const auto* details = mJsepTransceiver.mRecvTrack.GetNegotiatedDetails();
|
||||
if (!details) {
|
||||
return Nothing();
|
||||
}
|
||||
|
@ -102,25 +102,21 @@ class RTCRtpTransceiver : public nsISupports, public nsWrapperCache {
|
||||
void Stop(ErrorResult& aRv);
|
||||
void SetDirectionInternal(RTCRtpTransceiverDirection aDirection);
|
||||
bool HasBeenUsedToSend() const { return mHasBeenUsedToSend; }
|
||||
void SetAddTrackMagic();
|
||||
|
||||
bool CanSendDTMF() const;
|
||||
bool Stopped() const { return mStopped; }
|
||||
void SyncToJsep() const;
|
||||
void SyncFromJsep();
|
||||
void SetJsepSession(JsepSession* aJsepSession);
|
||||
void SyncToJsep(JsepSession& aSession) const;
|
||||
void SyncFromJsep(const JsepSession& aSession);
|
||||
std::string GetMidAscii() const;
|
||||
|
||||
void SetDtlsTransport(RTCDtlsTransport* aDtlsTransport, bool aStable);
|
||||
void RollbackToStableDtlsTransport();
|
||||
|
||||
std::string GetTransportId() const {
|
||||
return mJsepTransceiver->mTransport.mTransportId;
|
||||
return mJsepTransceiver.mTransport.mTransportId;
|
||||
}
|
||||
|
||||
RefPtr<JsepTransceiver> GetJsepTransceiver() const {
|
||||
return mJsepTransceiver;
|
||||
}
|
||||
JsepTransceiver& GetJsepTransceiver() { return mJsepTransceiver; }
|
||||
|
||||
bool IsVideo() const;
|
||||
|
||||
@ -193,7 +189,8 @@ class RTCRtpTransceiver : public nsISupports, public nsWrapperCache {
|
||||
RefPtr<PeerConnectionImpl> mPc;
|
||||
RefPtr<MediaTransportHandler> mTransportHandler;
|
||||
const std::string mTransceiverId;
|
||||
RefPtr<JsepTransceiver> mJsepTransceiver;
|
||||
// Copy of latest from the JSEP engine.
|
||||
JsepTransceiver mJsepTransceiver;
|
||||
nsCOMPtr<nsISerialEventTarget> mStsThread;
|
||||
// state for webrtc.org that is shared between all transceivers
|
||||
RefPtr<WebrtcCallWrapper> mCallWrapper;
|
||||
|
@ -113,8 +113,8 @@ class JsepSession {
|
||||
void ForEachCodec(UnaryFunction& function) {
|
||||
std::for_each(Codecs().begin(), Codecs().end(), function);
|
||||
for (auto& transceiver : GetTransceivers()) {
|
||||
transceiver->mSendTrack.ForEachCodec(function);
|
||||
transceiver->mRecvTrack.ForEachCodec(function);
|
||||
transceiver.mSendTrack.ForEachCodec(function);
|
||||
transceiver.mRecvTrack.ForEachCodec(function);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,24 +122,63 @@ class JsepSession {
|
||||
void SortCodecs(BinaryPredicate& sorter) {
|
||||
std::stable_sort(Codecs().begin(), Codecs().end(), sorter);
|
||||
for (auto& transceiver : GetTransceivers()) {
|
||||
transceiver->mSendTrack.SortCodecs(sorter);
|
||||
transceiver->mRecvTrack.SortCodecs(sorter);
|
||||
transceiver.mSendTrack.SortCodecs(sorter);
|
||||
transceiver.mRecvTrack.SortCodecs(sorter);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns transceivers in the order they were added.
|
||||
virtual const std::vector<RefPtr<JsepTransceiver>>& GetTransceivers()
|
||||
const = 0;
|
||||
virtual std::vector<RefPtr<JsepTransceiver>>& GetTransceivers() = 0;
|
||||
RefPtr<JsepTransceiver> GetTransceiver(const std::string& aId) const {
|
||||
for (const auto& transceiver : GetTransceivers()) {
|
||||
if (transceiver->GetUuid() == aId) {
|
||||
return transceiver;
|
||||
// Would be nice to have this return a Maybe containing the return of
|
||||
// |aFunction|, but Maybe cannot contain a void.
|
||||
template <typename UnaryFunction>
|
||||
bool ApplyToTransceiver(const std::string& aId, UnaryFunction&& aFunction) {
|
||||
for (auto& transceiver : GetTransceivers()) {
|
||||
if (transceiver.GetUuid() == aId) {
|
||||
std::forward<UnaryFunction>(aFunction)(transceiver);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
virtual void AddTransceiver(RefPtr<JsepTransceiver> transceiver) = 0;
|
||||
|
||||
template <typename UnaryFunction>
|
||||
void ForEachTransceiver(UnaryFunction&& aFunction) {
|
||||
for (auto& transceiver : GetTransceivers()) {
|
||||
std::forward<UnaryFunction>(aFunction)(transceiver);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename UnaryFunction>
|
||||
void ForEachTransceiver(UnaryFunction&& aFunction) const {
|
||||
for (const auto& transceiver : GetTransceivers()) {
|
||||
std::forward<UnaryFunction>(aFunction)(transceiver);
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<const JsepTransceiver> GetTransceiver(const std::string& aId) const {
|
||||
for (const auto& transceiver : GetTransceivers()) {
|
||||
if (transceiver.GetUuid() == aId) {
|
||||
return Some(transceiver);
|
||||
}
|
||||
}
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
template <typename MatchFunction>
|
||||
Maybe<const JsepTransceiver> FindTransceiver(MatchFunction&& aFunc) const {
|
||||
for (const auto& transceiver : GetTransceivers()) {
|
||||
if (std::forward<MatchFunction>(aFunc)(transceiver)) {
|
||||
return Some(transceiver);
|
||||
}
|
||||
}
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
bool SetTransceiver(const JsepTransceiver& aNew) {
|
||||
return ApplyToTransceiver(aNew.GetUuid(),
|
||||
[aNew](JsepTransceiver& aOld) { aOld = aNew; });
|
||||
}
|
||||
|
||||
virtual void AddTransceiver(const JsepTransceiver& transceiver) = 0;
|
||||
|
||||
class Result {
|
||||
public:
|
||||
@ -211,14 +250,14 @@ class JsepSession {
|
||||
memset(sending, 0, sizeof(sending));
|
||||
|
||||
for (const auto& transceiver : GetTransceivers()) {
|
||||
if (transceiver->mRecvTrack.GetActive() ||
|
||||
transceiver->GetMediaType() == SdpMediaSection::kApplication) {
|
||||
receiving[transceiver->mRecvTrack.GetMediaType()]++;
|
||||
if (transceiver.mRecvTrack.GetActive() ||
|
||||
transceiver.GetMediaType() == SdpMediaSection::kApplication) {
|
||||
receiving[transceiver.mRecvTrack.GetMediaType()]++;
|
||||
}
|
||||
|
||||
if (transceiver->mSendTrack.GetActive() ||
|
||||
transceiver->GetMediaType() == SdpMediaSection::kApplication) {
|
||||
sending[transceiver->mSendTrack.GetMediaType()]++;
|
||||
if (transceiver.mSendTrack.GetActive() ||
|
||||
transceiver.GetMediaType() == SdpMediaSection::kApplication) {
|
||||
sending[transceiver.mSendTrack.GetMediaType()]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -230,6 +269,11 @@ class JsepSession {
|
||||
void SetRtxIsAllowed(bool aRtxIsAllowed) { mRtxIsAllowed = aRtxIsAllowed; }
|
||||
|
||||
protected:
|
||||
friend class JsepSessionTest;
|
||||
// Returns transceivers in the order they were added.
|
||||
virtual std::vector<JsepTransceiver>& GetTransceivers() = 0;
|
||||
virtual const std::vector<JsepTransceiver>& GetTransceivers() const = 0;
|
||||
|
||||
const std::string mName;
|
||||
JsepSignalingState mState;
|
||||
uint32_t mNegotiations;
|
||||
|
@ -91,14 +91,6 @@ JsepSessionImpl::JsepSessionImpl(const JsepSessionImpl& aOrig)
|
||||
: nullptr),
|
||||
mSdpHelper(&mLastError),
|
||||
mParser(new HybridSdpParser()) {
|
||||
for (const auto& transceiver : aOrig.mTransceivers) {
|
||||
// Deep copy
|
||||
mTransceivers.push_back(new JsepTransceiver(*transceiver));
|
||||
}
|
||||
for (const auto& transceiver : aOrig.mOldTransceivers) {
|
||||
// Deep copy
|
||||
mOldTransceivers.push_back(new JsepTransceiver(*transceiver));
|
||||
}
|
||||
for (const auto& codec : aOrig.mSupportedCodecs) {
|
||||
mSupportedCodecs.emplace_back(codec->Clone());
|
||||
}
|
||||
@ -145,20 +137,20 @@ JsepSessionImpl::GetLocalIceCredentials() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
void JsepSessionImpl::AddTransceiver(RefPtr<JsepTransceiver> aTransceiver) {
|
||||
void JsepSessionImpl::AddTransceiver(const JsepTransceiver& aTransceiver) {
|
||||
mLastError.clear();
|
||||
MOZ_MTLOG(ML_DEBUG, "[" << mName << "]: Adding transceiver "
|
||||
<< aTransceiver->GetUuid());
|
||||
InitTransceiver(*aTransceiver);
|
||||
MOZ_MTLOG(ML_DEBUG,
|
||||
"[" << mName << "]: Adding transceiver " << aTransceiver.GetUuid());
|
||||
#ifdef DEBUG
|
||||
if (aTransceiver->GetMediaType() == SdpMediaSection::kApplication) {
|
||||
if (aTransceiver.GetMediaType() == SdpMediaSection::kApplication) {
|
||||
// Make sure we don't add more than one DataChannel transceiver
|
||||
for (const auto& transceiver : mTransceivers) {
|
||||
MOZ_ASSERT(transceiver->GetMediaType() != SdpMediaSection::kApplication);
|
||||
MOZ_ASSERT(transceiver.GetMediaType() != SdpMediaSection::kApplication);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mTransceivers.push_back(aTransceiver);
|
||||
InitTransceiver(mTransceivers.back());
|
||||
}
|
||||
|
||||
void JsepSessionImpl::InitTransceiver(JsepTransceiver& aTransceiver) {
|
||||
@ -409,9 +401,11 @@ JsepSession::Result JsepSessionImpl::CreateOffer(
|
||||
NS_ENSURE_SUCCESS(rv, dom::PCError::OperationError);
|
||||
|
||||
for (size_t level = 0;
|
||||
JsepTransceiver* transceiver = GetTransceiverForLocal(level); ++level) {
|
||||
Maybe<JsepTransceiver> transceiver = GetTransceiverForLocal(level);
|
||||
++level) {
|
||||
rv = CreateOfferMsection(options, *transceiver, sdp.get());
|
||||
NS_ENSURE_SUCCESS(rv, dom::PCError::OperationError);
|
||||
SetTransceiver(*transceiver);
|
||||
}
|
||||
|
||||
SetupBundle(sdp.get());
|
||||
@ -568,7 +562,7 @@ JsepSession::Result JsepSessionImpl::CreateAnswer(
|
||||
|
||||
for (size_t i = 0; i < offer.GetMediaSectionCount(); ++i) {
|
||||
// The transceivers are already in place, due to setRemote
|
||||
JsepTransceiver* transceiver(GetTransceiverForLevel(i));
|
||||
Maybe<JsepTransceiver> transceiver(GetTransceiverForLevel(i));
|
||||
if (!transceiver) {
|
||||
JSEP_SET_ERROR("No transceiver for level " << i);
|
||||
MOZ_ASSERT(false);
|
||||
@ -577,6 +571,7 @@ JsepSession::Result JsepSessionImpl::CreateAnswer(
|
||||
rv = CreateAnswerMsection(options, *transceiver, offer.GetMediaSection(i),
|
||||
sdp.get());
|
||||
NS_ENSURE_SUCCESS(rv, dom::PCError::OperationError);
|
||||
SetTransceiver(*transceiver);
|
||||
}
|
||||
|
||||
// Ensure that each bundle-group starts with a mid that has a transport, in
|
||||
@ -814,10 +809,7 @@ JsepSession::Result JsepSessionImpl::SetLocalDescription(
|
||||
|
||||
if (type == kJsepSdpOffer) {
|
||||
// Save in case we need to rollback
|
||||
mOldTransceivers.clear();
|
||||
for (const auto& transceiver : mTransceivers) {
|
||||
mOldTransceivers.push_back(new JsepTransceiver(*transceiver));
|
||||
}
|
||||
mOldTransceivers = mTransceivers;
|
||||
}
|
||||
|
||||
SdpHelper::BundledMids bundledMids;
|
||||
@ -832,7 +824,7 @@ JsepSession::Result JsepSessionImpl::SetLocalDescription(
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < parsed->GetMediaSectionCount(); ++i) {
|
||||
JsepTransceiver* transceiver(GetTransceiverForLevel(i));
|
||||
Maybe<JsepTransceiver> transceiver(GetTransceiverForLevel(i));
|
||||
if (!transceiver) {
|
||||
MOZ_ASSERT(false);
|
||||
JSEP_SET_ERROR("No transceiver for level " << i);
|
||||
@ -845,6 +837,7 @@ JsepSession::Result JsepSessionImpl::SetLocalDescription(
|
||||
|
||||
if (mSdpHelper.MsectionIsDisabled(msection)) {
|
||||
transceiver->mTransport.Close();
|
||||
SetTransceiver(*transceiver);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -860,7 +853,7 @@ JsepSession::Result JsepSessionImpl::SetLocalDescription(
|
||||
}
|
||||
|
||||
if (hasOwnTransport) {
|
||||
EnsureHasOwnTransport(parsed->GetMediaSection(i), transceiver);
|
||||
EnsureHasOwnTransport(parsed->GetMediaSection(i), *transceiver);
|
||||
}
|
||||
|
||||
if (type == kJsepSdpOffer) {
|
||||
@ -876,6 +869,7 @@ JsepSession::Result JsepSessionImpl::SetLocalDescription(
|
||||
transceiver->SetBundleLevel(it->second->GetLevel());
|
||||
}
|
||||
}
|
||||
SetTransceiver(*transceiver);
|
||||
}
|
||||
|
||||
CopyBundleTransports();
|
||||
@ -1024,15 +1018,14 @@ JsepSession::Result JsepSessionImpl::SetRemoteDescription(
|
||||
iceOptions = parsed->GetAttributeList().GetIceOptions().mValues;
|
||||
}
|
||||
|
||||
// Save in case we need to rollback.
|
||||
if (type == kJsepSdpOffer) {
|
||||
mOldTransceivers.clear();
|
||||
for (const auto& transceiver : mTransceivers) {
|
||||
mOldTransceivers.push_back(new JsepTransceiver(*transceiver));
|
||||
if (!transceiver->IsNegotiated()) {
|
||||
// Save in case we need to rollback.
|
||||
mOldTransceivers = mTransceivers;
|
||||
for (auto& transceiver : mTransceivers) {
|
||||
if (!transceiver.IsNegotiated()) {
|
||||
// We chose a level for this transceiver, but never negotiated it.
|
||||
// Discard this state.
|
||||
transceiver->ClearLevel();
|
||||
transceiver.ClearLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1085,18 +1078,19 @@ nsresult JsepSessionImpl::HandleNegotiatedSession(
|
||||
|
||||
// First, set the bundle level on the transceivers
|
||||
for (auto& [mid, transportOwner] : bundledMids) {
|
||||
JsepTransceiver* bundledTransceiver = GetTransceiverForMid(mid);
|
||||
Maybe<JsepTransceiver> bundledTransceiver = GetTransceiverForMid(mid);
|
||||
if (!bundledTransceiver) {
|
||||
JSEP_SET_ERROR("No transceiver for bundled mid " << mid);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
bundledTransceiver->SetBundleLevel(transportOwner->GetLevel());
|
||||
SetTransceiver(*bundledTransceiver);
|
||||
}
|
||||
|
||||
// Now walk through the m-sections, perform negotiation, and update the
|
||||
// transceivers.
|
||||
for (size_t i = 0; i < local->GetMediaSectionCount(); ++i) {
|
||||
JsepTransceiver* transceiver(GetTransceiverForLevel(i));
|
||||
Maybe<JsepTransceiver> transceiver(GetTransceiverForLevel(i));
|
||||
if (!transceiver) {
|
||||
MOZ_ASSERT(false);
|
||||
JSEP_SET_ERROR("No transceiver for level " << i);
|
||||
@ -1112,20 +1106,22 @@ nsresult JsepSessionImpl::HandleNegotiatedSession(
|
||||
transceiver->mSendTrack.SetActive(false);
|
||||
transceiver->mRecvTrack.SetActive(false);
|
||||
transceiver->SetCanRecycle();
|
||||
SetTransceiver(*transceiver);
|
||||
// Do not clear mLevel yet! That will happen on the next negotiation.
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = MakeNegotiatedTransceiver(remote->GetMediaSection(i),
|
||||
local->GetMediaSection(i), transceiver);
|
||||
local->GetMediaSection(i), *transceiver);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
SetTransceiver(*transceiver);
|
||||
}
|
||||
|
||||
CopyBundleTransports();
|
||||
|
||||
std::vector<JsepTrack*> remoteTracks;
|
||||
for (const auto& transceiver : mTransceivers) {
|
||||
remoteTracks.push_back(&transceiver->mRecvTrack);
|
||||
for (auto& transceiver : mTransceivers) {
|
||||
remoteTracks.push_back(&transceiver.mRecvTrack);
|
||||
}
|
||||
JsepTrack::SetUniquePayloadTypes(remoteTracks);
|
||||
|
||||
@ -1139,14 +1135,14 @@ nsresult JsepSessionImpl::HandleNegotiatedSession(
|
||||
|
||||
nsresult JsepSessionImpl::MakeNegotiatedTransceiver(
|
||||
const SdpMediaSection& remote, const SdpMediaSection& local,
|
||||
JsepTransceiver* transceiver) {
|
||||
JsepTransceiver& transceiver) {
|
||||
const SdpMediaSection& answer = *mIsPendingOfferer ? remote : local;
|
||||
|
||||
bool sending = false;
|
||||
bool receiving = false;
|
||||
|
||||
// JS could stop the transceiver after the answer was created.
|
||||
if (!transceiver->IsStopped()) {
|
||||
if (!transceiver.IsStopped()) {
|
||||
if (*mIsPendingOfferer) {
|
||||
receiving = answer.IsSending();
|
||||
sending = answer.IsReceiving();
|
||||
@ -1161,23 +1157,23 @@ nsresult JsepSessionImpl::MakeNegotiatedTransceiver(
|
||||
<< local.GetMediaType() << " sending=" << sending
|
||||
<< " receiving=" << receiving);
|
||||
|
||||
transceiver->SetNegotiated();
|
||||
transceiver.SetNegotiated();
|
||||
|
||||
// Ensure that this is finalized in case we need to copy it below
|
||||
nsresult rv =
|
||||
FinalizeTransport(remote.GetAttributeList(), answer.GetAttributeList(),
|
||||
&transceiver->mTransport);
|
||||
&transceiver.mTransport);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
transceiver->mSendTrack.SetActive(sending);
|
||||
rv = transceiver->mSendTrack.Negotiate(answer, remote, local);
|
||||
transceiver.mSendTrack.SetActive(sending);
|
||||
rv = transceiver.mSendTrack.Negotiate(answer, remote, local);
|
||||
if (NS_FAILED(rv)) {
|
||||
JSEP_SET_ERROR("Answer had no codecs in common with offer in m-section "
|
||||
<< local.GetLevel());
|
||||
return rv;
|
||||
}
|
||||
|
||||
JsepTrack& recvTrack = transceiver->mRecvTrack;
|
||||
JsepTrack& recvTrack = transceiver.mRecvTrack;
|
||||
recvTrack.SetActive(receiving);
|
||||
rv = recvTrack.Negotiate(answer, remote, local);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -1186,7 +1182,7 @@ nsresult JsepSessionImpl::MakeNegotiatedTransceiver(
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (transceiver->HasBundleLevel() && recvTrack.GetSsrcs().empty() &&
|
||||
if (transceiver.HasBundleLevel() && recvTrack.GetSsrcs().empty() &&
|
||||
recvTrack.GetMediaType() != SdpMediaSection::kApplication) {
|
||||
// TODO(bug 1105005): Once we have urn:ietf:params:rtp-hdrext:sdes:mid
|
||||
// support, we should only fire this warning if that extension was not
|
||||
@ -1197,7 +1193,7 @@ nsresult JsepSessionImpl::MakeNegotiatedTransceiver(
|
||||
"dropped.");
|
||||
}
|
||||
|
||||
if (transceiver->mTransport.mComponents == 2) {
|
||||
if (transceiver.mTransport.mComponents == 2) {
|
||||
// RTCP MUX or not.
|
||||
// TODO(bug 1095743): verify that the PTs are consistent with mux.
|
||||
MOZ_MTLOG(ML_DEBUG, "[" << mName << "]: RTCP-MUX is off");
|
||||
@ -1234,10 +1230,10 @@ nsresult JsepSessionImpl::MakeNegotiatedTransceiver(
|
||||
}
|
||||
|
||||
void JsepSessionImpl::EnsureHasOwnTransport(const SdpMediaSection& msection,
|
||||
JsepTransceiver* transceiver) {
|
||||
JsepTransport& transport = transceiver->mTransport;
|
||||
JsepTransceiver& transceiver) {
|
||||
JsepTransport& transport = transceiver.mTransport;
|
||||
|
||||
if (!transceiver->HasOwnTransport()) {
|
||||
if (!transceiver.HasOwnTransport()) {
|
||||
// Transceiver didn't own this transport last time, it won't now either
|
||||
transport.Close();
|
||||
}
|
||||
@ -1245,7 +1241,7 @@ void JsepSessionImpl::EnsureHasOwnTransport(const SdpMediaSection& msection,
|
||||
transport.mLocalUfrag = msection.GetAttributeList().GetIceUfrag();
|
||||
transport.mLocalPwd = msection.GetAttributeList().GetIcePwd();
|
||||
|
||||
transceiver->ClearBundleLevel();
|
||||
transceiver.ClearBundleLevel();
|
||||
|
||||
if (!transport.mComponents) {
|
||||
if (mSdpHelper.HasRtcp(msection.GetProtocol())) {
|
||||
@ -1266,34 +1262,34 @@ void JsepSessionImpl::EnsureHasOwnTransport(const SdpMediaSection& msection,
|
||||
|
||||
void JsepSessionImpl::CopyBundleTransports() {
|
||||
for (auto& transceiver : mTransceivers) {
|
||||
if (transceiver->HasBundleLevel()) {
|
||||
if (transceiver.HasBundleLevel()) {
|
||||
MOZ_MTLOG(ML_DEBUG,
|
||||
"[" << mName << "] Transceiver " << transceiver->GetLevel()
|
||||
"[" << mName << "] Transceiver " << transceiver.GetLevel()
|
||||
<< " is in a bundle; transceiver "
|
||||
<< transceiver->BundleLevel() << " owns the transport.");
|
||||
const JsepTransceiver* transportOwner =
|
||||
GetTransceiverForLevel(transceiver->BundleLevel());
|
||||
<< transceiver.BundleLevel() << " owns the transport.");
|
||||
Maybe<const JsepTransceiver> transportOwner =
|
||||
GetTransceiverForLevel(transceiver.BundleLevel());
|
||||
MOZ_ASSERT(transportOwner);
|
||||
if (transportOwner) {
|
||||
transceiver->mTransport = transportOwner->mTransport;
|
||||
transceiver.mTransport = transportOwner->mTransport;
|
||||
}
|
||||
} else if (transceiver->HasLevel()) {
|
||||
} else if (transceiver.HasLevel()) {
|
||||
MOZ_MTLOG(ML_DEBUG, "[" << mName << "] Transceiver "
|
||||
<< transceiver->GetLevel()
|
||||
<< transceiver.GetLevel()
|
||||
<< " is not necessarily in a bundle.");
|
||||
}
|
||||
if (transceiver->HasLevel()) {
|
||||
if (transceiver.HasLevel()) {
|
||||
MOZ_MTLOG(ML_DEBUG,
|
||||
"[" << mName << "] Transceiver " << transceiver->GetLevel()
|
||||
<< " transport-id: " << transceiver->mTransport.mTransportId
|
||||
<< " components: " << transceiver->mTransport.mComponents);
|
||||
"[" << mName << "] Transceiver " << transceiver.GetLevel()
|
||||
<< " transport-id: " << transceiver.mTransport.mTransportId
|
||||
<< " components: " << transceiver.mTransport.mComponents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult JsepSessionImpl::FinalizeTransport(const SdpAttributeList& remote,
|
||||
const SdpAttributeList& answer,
|
||||
JsepTransport* transport) {
|
||||
JsepTransport* transport) const {
|
||||
if (!transport->mComponents) {
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1382,7 +1378,7 @@ nsresult JsepSessionImpl::CopyPreviousTransportParams(
|
||||
// If newLocal is an offer, this will be the number of components we used
|
||||
// last time, and if it is an answer, this will be the number of
|
||||
// components we've decided we're using now.
|
||||
JsepTransceiver* transceiver(GetTransceiverForLevel(i));
|
||||
Maybe<const JsepTransceiver> transceiver(GetTransceiverForLevel(i));
|
||||
if (!transceiver) {
|
||||
MOZ_ASSERT(false);
|
||||
JSEP_SET_ERROR("No transceiver for level " << i);
|
||||
@ -1545,43 +1541,39 @@ nsresult JsepSessionImpl::SetRemoteDescriptionAnswer(JsepSdpType type,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JsepTransceiver* JsepSessionImpl::GetTransceiverForLevel(size_t level) const {
|
||||
for (const auto& transceiver : mTransceivers) {
|
||||
if (transceiver->HasLevel() && (transceiver->GetLevel() == level)) {
|
||||
return transceiver.get();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
Maybe<JsepTransceiver> JsepSessionImpl::GetTransceiverForLevel(
|
||||
size_t level) const {
|
||||
return FindTransceiver([level](const JsepTransceiver& transceiver) {
|
||||
return transceiver.HasLevel() && (transceiver.GetLevel() == level);
|
||||
});
|
||||
}
|
||||
|
||||
JsepTransceiver* JsepSessionImpl::GetTransceiverForMid(
|
||||
Maybe<JsepTransceiver> JsepSessionImpl::GetTransceiverForMid(
|
||||
const std::string& mid) const {
|
||||
for (const auto& transceiver : mTransceivers) {
|
||||
if (transceiver->IsAssociated() && (transceiver->GetMid() == mid)) {
|
||||
return transceiver.get();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return FindTransceiver([mid](const JsepTransceiver& transceiver) {
|
||||
return transceiver.IsAssociated() && (transceiver.GetMid() == mid);
|
||||
});
|
||||
}
|
||||
|
||||
JsepTransceiver* JsepSessionImpl::GetTransceiverForLocal(size_t level) {
|
||||
if (JsepTransceiver* transceiver = GetTransceiverForLevel(level)) {
|
||||
Maybe<JsepTransceiver> JsepSessionImpl::GetTransceiverForLocal(size_t level) {
|
||||
if (Maybe<JsepTransceiver> transceiver = GetTransceiverForLevel(level)) {
|
||||
if (transceiver->CanRecycle() &&
|
||||
transceiver->GetMediaType() != SdpMediaSection::kApplication) {
|
||||
// Attempt to recycle. If this fails, the old transceiver stays put.
|
||||
transceiver->Disassociate();
|
||||
JsepTransceiver* newTransceiver =
|
||||
Maybe<JsepTransceiver> newTransceiver =
|
||||
FindUnassociatedTransceiver(transceiver->GetMediaType(), false);
|
||||
if (newTransceiver) {
|
||||
newTransceiver->SetLevel(level);
|
||||
transceiver->ClearLevel();
|
||||
transceiver->mSendTrack.ClearRids();
|
||||
SetTransceiver(*newTransceiver);
|
||||
SetTransceiver(*transceiver);
|
||||
return newTransceiver;
|
||||
}
|
||||
}
|
||||
|
||||
SetTransceiver(*transceiver);
|
||||
return transceiver;
|
||||
}
|
||||
|
||||
@ -1589,66 +1581,67 @@ JsepTransceiver* JsepSessionImpl::GetTransceiverForLocal(size_t level) {
|
||||
|
||||
// Look for an RTP transceiver
|
||||
for (auto& transceiver : mTransceivers) {
|
||||
if (transceiver->GetMediaType() != SdpMediaSection::kApplication &&
|
||||
!transceiver->IsStopped() && !transceiver->HasLevel()) {
|
||||
transceiver->SetLevel(level);
|
||||
return transceiver.get();
|
||||
if (transceiver.GetMediaType() != SdpMediaSection::kApplication &&
|
||||
!transceiver.IsStopped() && !transceiver.HasLevel()) {
|
||||
transceiver.SetLevel(level);
|
||||
return Some(transceiver);
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, look for a datachannel
|
||||
for (auto& transceiver : mTransceivers) {
|
||||
if (!transceiver->IsStopped() && !transceiver->HasLevel()) {
|
||||
transceiver->SetLevel(level);
|
||||
return transceiver.get();
|
||||
if (!transceiver.IsStopped() && !transceiver.HasLevel()) {
|
||||
transceiver.SetLevel(level);
|
||||
return Some(transceiver);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
JsepTransceiver* JsepSessionImpl::GetTransceiverForRemote(
|
||||
Maybe<JsepTransceiver> JsepSessionImpl::GetTransceiverForRemote(
|
||||
const SdpMediaSection& msection) {
|
||||
size_t level = msection.GetLevel();
|
||||
if (JsepTransceiver* transceiver = GetTransceiverForLevel(level)) {
|
||||
Maybe<JsepTransceiver> transceiver = GetTransceiverForLevel(level);
|
||||
if (transceiver) {
|
||||
if (!transceiver->CanRecycle()) {
|
||||
return transceiver;
|
||||
}
|
||||
transceiver->Disassociate();
|
||||
transceiver->ClearLevel();
|
||||
transceiver->mSendTrack.ClearRids();
|
||||
SetTransceiver(*transceiver);
|
||||
}
|
||||
|
||||
// No transceiver for |level|
|
||||
|
||||
JsepTransceiver* transceiver =
|
||||
FindUnassociatedTransceiver(msection.GetMediaType(), true /*magic!*/);
|
||||
transceiver = FindUnassociatedTransceiver(msection.GetMediaType(), true);
|
||||
if (transceiver) {
|
||||
transceiver->SetLevel(level);
|
||||
SetTransceiver(*transceiver);
|
||||
return transceiver;
|
||||
}
|
||||
|
||||
// Make a new transceiver
|
||||
RefPtr<JsepTransceiver> newTransceiver(new JsepTransceiver(
|
||||
msection.GetMediaType(), *mUuidGen, SdpDirectionAttribute::kRecvonly));
|
||||
newTransceiver->SetLevel(level);
|
||||
newTransceiver->SetOnlyExistsBecauseOfSetRemote(true);
|
||||
JsepTransceiver newTransceiver(msection.GetMediaType(), *mUuidGen,
|
||||
SdpDirectionAttribute::kRecvonly);
|
||||
newTransceiver.SetLevel(level);
|
||||
newTransceiver.SetOnlyExistsBecauseOfSetRemote(true);
|
||||
AddTransceiver(newTransceiver);
|
||||
return newTransceiver.get();
|
||||
return Some(mTransceivers.back());
|
||||
}
|
||||
|
||||
JsepTransceiver* JsepSessionImpl::GetTransceiverWithTransport(
|
||||
Maybe<JsepTransceiver> JsepSessionImpl::GetTransceiverWithTransport(
|
||||
const std::string& transportId) const {
|
||||
for (const auto& transceiver : mTransceivers) {
|
||||
if (transceiver->HasOwnTransport() &&
|
||||
(transceiver->mTransport.mTransportId == transportId)) {
|
||||
MOZ_ASSERT(transceiver->HasLevel(),
|
||||
if (transceiver.HasOwnTransport() &&
|
||||
(transceiver.mTransport.mTransportId == transportId)) {
|
||||
MOZ_ASSERT(transceiver.HasLevel(),
|
||||
"Transceiver has a transport, but no level!");
|
||||
return transceiver.get();
|
||||
return Some(transceiver);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
nsresult JsepSessionImpl::UpdateTransceiversFromRemoteDescription(
|
||||
@ -1657,7 +1650,7 @@ nsresult JsepSessionImpl::UpdateTransceiversFromRemoteDescription(
|
||||
for (size_t i = 0; i < remote.GetMediaSectionCount(); ++i) {
|
||||
const SdpMediaSection& msection = remote.GetMediaSection(i);
|
||||
|
||||
JsepTransceiver* transceiver(GetTransceiverForRemote(msection));
|
||||
Maybe<JsepTransceiver> transceiver(GetTransceiverForRemote(msection));
|
||||
if (!transceiver) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -1677,10 +1670,12 @@ nsresult JsepSessionImpl::UpdateTransceiversFromRemoteDescription(
|
||||
transceiver->Disassociate();
|
||||
// This cannot be rolled back.
|
||||
transceiver->Stop();
|
||||
SetTransceiver(*transceiver);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msection.GetMediaType() == SdpMediaSection::MediaType::kApplication) {
|
||||
SetTransceiver(*transceiver);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1696,43 +1691,43 @@ nsresult JsepSessionImpl::UpdateTransceiversFromRemoteDescription(
|
||||
// msection is not sending. If the msection is sending, and there are no
|
||||
// a=msid, the previously set default will stay.
|
||||
transceiver->mRecvTrack.RecvTrackSetRemote(remote, msection);
|
||||
SetTransceiver(*transceiver);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JsepTransceiver* JsepSessionImpl::FindUnassociatedTransceiver(
|
||||
Maybe<JsepTransceiver> JsepSessionImpl::FindUnassociatedTransceiver(
|
||||
SdpMediaSection::MediaType type, bool magic) {
|
||||
// Look through transceivers that are not mapped to an m-section
|
||||
for (auto& transceiver : mTransceivers) {
|
||||
if (type == SdpMediaSection::kApplication &&
|
||||
type == transceiver->GetMediaType()) {
|
||||
transceiver->RestartDatachannelTransceiver();
|
||||
return transceiver.get();
|
||||
type == transceiver.GetMediaType()) {
|
||||
transceiver.RestartDatachannelTransceiver();
|
||||
return Some(transceiver);
|
||||
}
|
||||
if (!transceiver->IsStopped() && !transceiver->HasLevel() &&
|
||||
(!magic || transceiver->HasAddTrackMagic()) &&
|
||||
(transceiver->GetMediaType() == type)) {
|
||||
return transceiver.get();
|
||||
if (!transceiver.IsStopped() && !transceiver.HasLevel() &&
|
||||
(!magic || transceiver.HasAddTrackMagic()) &&
|
||||
(transceiver.GetMediaType() == type)) {
|
||||
return Some(transceiver);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
void JsepSessionImpl::RollbackLocalOffer() {
|
||||
for (size_t i = 0; i < mTransceivers.size(); ++i) {
|
||||
auto transceiver = mTransceivers[i];
|
||||
auto& transceiver = mTransceivers[i];
|
||||
if (mOldTransceivers.size() > i) {
|
||||
transceiver->Rollback(*mOldTransceivers[i], false);
|
||||
transceiver.Rollback(mOldTransceivers[i], false);
|
||||
mOldTransceivers[i] = transceiver;
|
||||
continue;
|
||||
}
|
||||
|
||||
RefPtr<JsepTransceiver> temp(
|
||||
new JsepTransceiver(transceiver->GetMediaType(), *mUuidGen));
|
||||
InitTransceiver(*temp);
|
||||
transceiver->Rollback(*temp, false);
|
||||
JsepTransceiver temp(transceiver.GetMediaType(), *mUuidGen);
|
||||
InitTransceiver(temp);
|
||||
transceiver.Rollback(temp, false);
|
||||
mOldTransceivers.push_back(transceiver);
|
||||
}
|
||||
|
||||
@ -1741,10 +1736,10 @@ void JsepSessionImpl::RollbackLocalOffer() {
|
||||
|
||||
void JsepSessionImpl::RollbackRemoteOffer() {
|
||||
for (size_t i = 0; i < mTransceivers.size(); ++i) {
|
||||
auto transceiver = mTransceivers[i];
|
||||
auto& transceiver = mTransceivers[i];
|
||||
if (mOldTransceivers.size() > i) {
|
||||
// Some stuff cannot be rolled back. Save this information.
|
||||
transceiver->Rollback(*mOldTransceivers[i], true);
|
||||
transceiver.Rollback(mOldTransceivers[i], true);
|
||||
mOldTransceivers[i] = transceiver;
|
||||
continue;
|
||||
}
|
||||
@ -1752,14 +1747,13 @@ void JsepSessionImpl::RollbackRemoteOffer() {
|
||||
// New transceiver!
|
||||
// We rollback even for transceivers we will remove, just to ensure we end
|
||||
// up at the starting state.
|
||||
RefPtr<JsepTransceiver> temp(
|
||||
new JsepTransceiver(transceiver->GetMediaType(), *mUuidGen));
|
||||
InitTransceiver(*temp);
|
||||
transceiver->Rollback(*temp, true);
|
||||
JsepTransceiver temp(transceiver.GetMediaType(), *mUuidGen);
|
||||
InitTransceiver(temp);
|
||||
transceiver.Rollback(temp, true);
|
||||
|
||||
if (transceiver->OnlyExistsBecauseOfSetRemote()) {
|
||||
transceiver->Stop();
|
||||
transceiver->SetRemoved();
|
||||
if (transceiver.OnlyExistsBecauseOfSetRemote()) {
|
||||
transceiver.Stop();
|
||||
transceiver.SetRemoved();
|
||||
}
|
||||
mOldTransceivers.push_back(transceiver);
|
||||
}
|
||||
@ -2197,7 +2191,7 @@ JsepSession::Result JsepSessionImpl::AddRemoteIceCandidate(
|
||||
return Result();
|
||||
}
|
||||
|
||||
JsepTransceiver* transceiver = nullptr;
|
||||
Maybe<JsepTransceiver> transceiver;
|
||||
if (!mid.empty()) {
|
||||
transceiver = GetTransceiverForMid(mid);
|
||||
} else if (level.isSome()) {
|
||||
@ -2249,7 +2243,8 @@ nsresult JsepSessionImpl::AddLocalIceCandidate(const std::string& candidate,
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
JsepTransceiver* transceiver = GetTransceiverWithTransport(transportId);
|
||||
Maybe<const JsepTransceiver> transceiver =
|
||||
GetTransceiverWithTransport(transportId);
|
||||
if (!transceiver || !transceiver->IsAssociated()) {
|
||||
// mainly here to make some testing less complicated, but also just in case
|
||||
return NS_OK;
|
||||
@ -2292,20 +2287,20 @@ nsresult JsepSessionImpl::UpdateDefaultCandidate(
|
||||
for (const auto& transceiver : mTransceivers) {
|
||||
// We set the default address for bundled m-sections, but not candidate
|
||||
// attributes. Ugh.
|
||||
if (transceiver->mTransport.mTransportId == transportId) {
|
||||
MOZ_ASSERT(transceiver->HasLevel(),
|
||||
if (transceiver.mTransport.mTransportId == transportId) {
|
||||
MOZ_ASSERT(transceiver.HasLevel(),
|
||||
"Transceiver has a transport, but no level! "
|
||||
"This should never happen.");
|
||||
std::string defaultRtcpCandidateAddrCopy(defaultRtcpCandidateAddr);
|
||||
if (mState == kJsepStateStable) {
|
||||
if (transceiver->mTransport.mComponents == 1) {
|
||||
if (transceiver.mTransport.mComponents == 1) {
|
||||
// We know we're doing rtcp-mux by now. Don't create an rtcp attr.
|
||||
defaultRtcpCandidateAddrCopy = "";
|
||||
defaultRtcpCandidatePort = 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t level = transceiver->GetLevel();
|
||||
size_t level = transceiver.GetLevel();
|
||||
if (level >= sdp->GetMediaSectionCount()) {
|
||||
MOZ_ASSERT(false, "Transceiver's level is too large!");
|
||||
JSEP_SET_ERROR("Transceiver's level is too large!");
|
||||
@ -2404,8 +2399,8 @@ bool JsepSessionImpl::CheckNegotiationNeeded() const {
|
||||
MOZ_ASSERT(mState == kJsepStateStable);
|
||||
|
||||
for (const auto& transceiver : mTransceivers) {
|
||||
if (transceiver->IsStopped()) {
|
||||
if (transceiver->IsAssociated()) {
|
||||
if (transceiver.IsStopped()) {
|
||||
if (transceiver.IsAssociated()) {
|
||||
MOZ_MTLOG(ML_DEBUG, "[" << mName
|
||||
<< "]: Negotiation needed because of "
|
||||
"stopped transceiver that still has a mid.");
|
||||
@ -2414,7 +2409,7 @@ bool JsepSessionImpl::CheckNegotiationNeeded() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!transceiver->IsAssociated()) {
|
||||
if (!transceiver.IsAssociated()) {
|
||||
MOZ_MTLOG(ML_DEBUG, "[" << mName
|
||||
<< "]: Negotiation needed because of "
|
||||
"unassociated (but not stopped) transceiver.");
|
||||
@ -2428,16 +2423,16 @@ bool JsepSessionImpl::CheckNegotiationNeeded() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!transceiver->HasLevel()) {
|
||||
if (!transceiver.HasLevel()) {
|
||||
MOZ_CRASH("Associated transceivers should always have a level.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (transceiver->GetMediaType() == SdpMediaSection::kApplication) {
|
||||
if (transceiver.GetMediaType() == SdpMediaSection::kApplication) {
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t level = transceiver->GetLevel();
|
||||
size_t level = transceiver.GetLevel();
|
||||
if (NS_WARN_IF(mCurrentLocalDescription->GetMediaSectionCount() <= level) ||
|
||||
NS_WARN_IF(mCurrentRemoteDescription->GetMediaSectionCount() <=
|
||||
level)) {
|
||||
@ -2450,7 +2445,7 @@ bool JsepSessionImpl::CheckNegotiationNeeded() const {
|
||||
const SdpMediaSection& remote =
|
||||
mCurrentRemoteDescription->GetMediaSection(level);
|
||||
|
||||
if (transceiver->mJsDirection & sdp::kSend) {
|
||||
if (transceiver.mJsDirection & sdp::kSend) {
|
||||
std::vector<std::string> sdpMsids;
|
||||
if (local.GetAttributeList().HasAttribute(SdpAttribute::kMsidAttribute)) {
|
||||
for (const auto& msidAttr : local.GetAttributeList().GetMsid().mMsids) {
|
||||
@ -2462,7 +2457,7 @@ bool JsepSessionImpl::CheckNegotiationNeeded() const {
|
||||
std::sort(sdpMsids.begin(), sdpMsids.end());
|
||||
|
||||
std::vector<std::string> jsepMsids;
|
||||
for (const auto& jsepMsid : transceiver->mSendTrack.GetStreamIds()) {
|
||||
for (const auto& jsepMsid : transceiver.mSendTrack.GetStreamIds()) {
|
||||
jsepMsids.push_back(jsepMsid);
|
||||
}
|
||||
std::sort(jsepMsids.begin(), jsepMsids.end());
|
||||
@ -2489,8 +2484,8 @@ bool JsepSessionImpl::CheckNegotiationNeeded() const {
|
||||
}
|
||||
|
||||
if (mIsCurrentOfferer.isSome() && *mIsCurrentOfferer) {
|
||||
if ((local.GetDirection() != transceiver->mJsDirection) &&
|
||||
reverse(remote.GetDirection()) != transceiver->mJsDirection) {
|
||||
if ((local.GetDirection() != transceiver.mJsDirection) &&
|
||||
reverse(remote.GetDirection()) != transceiver.mJsDirection) {
|
||||
MOZ_MTLOG(ML_DEBUG, "[" << mName
|
||||
<< "]: Negotiation needed because "
|
||||
"the direction on our offer, and the remote "
|
||||
@ -2499,7 +2494,7 @@ bool JsepSessionImpl::CheckNegotiationNeeded() const {
|
||||
return true;
|
||||
}
|
||||
} else if (local.GetDirection() !=
|
||||
(transceiver->mJsDirection & reverse(remote.GetDirection()))) {
|
||||
(transceiver.mJsDirection & reverse(remote.GetDirection()))) {
|
||||
MOZ_MTLOG(
|
||||
ML_DEBUG,
|
||||
"[" << mName
|
||||
|
@ -57,6 +57,11 @@ class JsepSessionCopyableStuff {
|
||||
std::vector<std::pair<size_t, std::string>> mLastSdpParsingErrors;
|
||||
bool mEncodeTrackId = true;
|
||||
SsrcGenerator mSsrcGenerator;
|
||||
// !!!NOT INDEXED BY LEVEL!!! The level mapping is done with
|
||||
// JsepTransceiver::mLevel. The keys are UUIDs.
|
||||
std::vector<JsepTransceiver> mTransceivers;
|
||||
// So we can rollback. Not as simple as just going back to the old, though...
|
||||
std::vector<JsepTransceiver> mOldTransceivers;
|
||||
};
|
||||
|
||||
class JsepSessionImpl : public JsepSession, public JsepSessionCopyableStuff {
|
||||
@ -167,16 +172,7 @@ class JsepSessionImpl : public JsepSession, public JsepSessionCopyableStuff {
|
||||
virtual std::set<std::pair<std::string, std::string>> GetLocalIceCredentials()
|
||||
const override;
|
||||
|
||||
virtual const std::vector<RefPtr<JsepTransceiver>>& GetTransceivers()
|
||||
const override {
|
||||
return mTransceivers;
|
||||
}
|
||||
|
||||
virtual std::vector<RefPtr<JsepTransceiver>>& GetTransceivers() override {
|
||||
return mTransceivers;
|
||||
}
|
||||
|
||||
virtual void AddTransceiver(RefPtr<JsepTransceiver> transceiver) override;
|
||||
virtual void AddTransceiver(const JsepTransceiver& transceiver) override;
|
||||
|
||||
virtual bool CheckNegotiationNeeded() const override;
|
||||
|
||||
@ -185,6 +181,15 @@ class JsepSessionImpl : public JsepSession, public JsepSessionCopyableStuff {
|
||||
override;
|
||||
|
||||
private:
|
||||
friend class JsepSessionTest;
|
||||
virtual const std::vector<JsepTransceiver>& GetTransceivers() const override {
|
||||
return mTransceivers;
|
||||
}
|
||||
|
||||
virtual std::vector<JsepTransceiver>& GetTransceivers() override {
|
||||
return mTransceivers;
|
||||
}
|
||||
|
||||
// Non-const so it can set mLastError
|
||||
nsresult CreateGenericSDP(UniquePtr<Sdp>* sdp);
|
||||
void AddExtmap(SdpMediaSection* msection);
|
||||
@ -208,16 +213,17 @@ class JsepSessionImpl : public JsepSession, public JsepSessionCopyableStuff {
|
||||
nsresult ValidateOffer(const Sdp& offer);
|
||||
nsresult ValidateAnswer(const Sdp& offer, const Sdp& answer);
|
||||
nsresult UpdateTransceiversFromRemoteDescription(const Sdp& remote);
|
||||
JsepTransceiver* GetTransceiverForLevel(size_t level) const;
|
||||
JsepTransceiver* GetTransceiverForMid(const std::string& mid) const;
|
||||
JsepTransceiver* GetTransceiverForLocal(size_t level);
|
||||
JsepTransceiver* GetTransceiverForRemote(const SdpMediaSection& msection);
|
||||
JsepTransceiver* GetTransceiverWithTransport(
|
||||
Maybe<JsepTransceiver> GetTransceiverForLevel(size_t level) const;
|
||||
Maybe<JsepTransceiver> GetTransceiverForMid(const std::string& mid) const;
|
||||
Maybe<JsepTransceiver> GetTransceiverForLocal(size_t level);
|
||||
Maybe<JsepTransceiver> GetTransceiverForRemote(
|
||||
const SdpMediaSection& msection);
|
||||
Maybe<JsepTransceiver> GetTransceiverWithTransport(
|
||||
const std::string& transportId) const;
|
||||
// The w3c and IETF specs have a lot of "magical" behavior that happens when
|
||||
// addTrack is used. This was a deliberate design choice. Sadface.
|
||||
JsepTransceiver* FindUnassociatedTransceiver(SdpMediaSection::MediaType type,
|
||||
bool magic);
|
||||
Maybe<JsepTransceiver> FindUnassociatedTransceiver(
|
||||
SdpMediaSection::MediaType type, bool magic);
|
||||
// Called for rollback of local description
|
||||
void RollbackLocalOffer();
|
||||
// Called for rollback of remote description
|
||||
@ -241,14 +247,14 @@ class JsepSessionImpl : public JsepSession, public JsepSessionCopyableStuff {
|
||||
SdpSetupAttribute::Role* rolep);
|
||||
nsresult MakeNegotiatedTransceiver(const SdpMediaSection& remote,
|
||||
const SdpMediaSection& local,
|
||||
JsepTransceiver* transceiverOut);
|
||||
JsepTransceiver& transceiverOut);
|
||||
void EnsureHasOwnTransport(const SdpMediaSection& msection,
|
||||
JsepTransceiver* transceiver);
|
||||
JsepTransceiver& transceiver);
|
||||
void CopyBundleTransports();
|
||||
|
||||
nsresult FinalizeTransport(const SdpAttributeList& remote,
|
||||
const SdpAttributeList& answer,
|
||||
JsepTransport* transport);
|
||||
JsepTransport* transport) const;
|
||||
|
||||
nsresult GetNegotiatedBundledMids(SdpHelper::BundledMids* bundledMids);
|
||||
|
||||
@ -263,12 +269,6 @@ class JsepSessionImpl : public JsepSession, public JsepSessionCopyableStuff {
|
||||
|
||||
void InitTransceiver(JsepTransceiver& aTransceiver);
|
||||
|
||||
// !!!NOT INDEXED BY LEVEL!!! The level mapping is done with
|
||||
// JsepTransceiver::mLevel. The keys are UUIDs.
|
||||
std::vector<RefPtr<JsepTransceiver>> mTransceivers;
|
||||
// So we can rollback. Not as simple as just going back to the old, though...
|
||||
std::vector<RefPtr<JsepTransceiver>> mOldTransceivers;
|
||||
|
||||
UniquePtr<JsepUuidGenerator> mUuidGen;
|
||||
UniquePtr<Sdp> mGeneratedOffer; // Created but not set.
|
||||
UniquePtr<Sdp> mGeneratedAnswer; // Created but not set.
|
||||
|
@ -13,8 +13,6 @@
|
||||
#include "jsep/JsepTransport.h"
|
||||
#include "jsep/JsepTrack.h"
|
||||
|
||||
#include <mozilla/OwningNonNull.h>
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsError.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -27,9 +25,6 @@ class JsepUuidGenerator {
|
||||
};
|
||||
|
||||
class JsepTransceiver {
|
||||
private:
|
||||
~JsepTransceiver(){};
|
||||
|
||||
public:
|
||||
explicit JsepTransceiver(SdpMediaSection::MediaType type,
|
||||
JsepUuidGenerator& aUuidGen,
|
||||
@ -51,24 +46,12 @@ class JsepTransceiver {
|
||||
}
|
||||
}
|
||||
|
||||
// Can't use default copy c'tor because of the refcount members. Ugh.
|
||||
JsepTransceiver(const JsepTransceiver& orig)
|
||||
: mJsDirection(orig.mJsDirection),
|
||||
mSendTrack(orig.mSendTrack),
|
||||
mRecvTrack(orig.mRecvTrack),
|
||||
mTransport(orig.mTransport),
|
||||
mUuid(orig.mUuid),
|
||||
mMid(orig.mMid),
|
||||
mLevel(orig.mLevel),
|
||||
mBundleLevel(orig.mBundleLevel),
|
||||
mAddTrackMagic(orig.mAddTrackMagic),
|
||||
mOnlyExistsBecauseOfSetRemote(orig.mOnlyExistsBecauseOfSetRemote),
|
||||
mStopped(orig.mStopped),
|
||||
mRemoved(orig.mRemoved),
|
||||
mNegotiated(orig.mNegotiated),
|
||||
mCanRecycle(orig.mCanRecycle) {}
|
||||
JsepTransceiver(const JsepTransceiver& orig) = default;
|
||||
JsepTransceiver(JsepTransceiver&& orig) = default;
|
||||
JsepTransceiver& operator=(const JsepTransceiver& aRhs) = default;
|
||||
JsepTransceiver& operator=(JsepTransceiver&& aRhs) = default;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(JsepTransceiver);
|
||||
~JsepTransceiver() = default;
|
||||
|
||||
void Rollback(JsepTransceiver& oldTransceiver, bool aRemote) {
|
||||
MOZ_ASSERT(oldTransceiver.GetMediaType() == GetMediaType());
|
||||
@ -130,6 +113,7 @@ class JsepTransceiver {
|
||||
void RestartDatachannelTransceiver() {
|
||||
MOZ_RELEASE_ASSERT(GetMediaType() == SdpMediaSection::kApplication);
|
||||
mStopped = false;
|
||||
mCanRecycle = false;
|
||||
}
|
||||
|
||||
void SetRemoved() { mRemoved = true; }
|
||||
|
@ -45,7 +45,8 @@ interface PeerConnectionImpl {
|
||||
[Throws]
|
||||
RTCRtpTransceiver addTransceiver(RTCRtpTransceiverInit init,
|
||||
DOMString kind,
|
||||
MediaStreamTrack? sendTrack);
|
||||
MediaStreamTrack? sendTrack,
|
||||
boolean addTrackMagic);
|
||||
sequence<RTCRtpTransceiver> getTransceivers();
|
||||
|
||||
[Throws]
|
||||
|
@ -38,8 +38,6 @@ interface RTCRtpTransceiver {
|
||||
// TODO: bug 1396922
|
||||
// undefined setCodecPreferences(sequence<RTCRtpCodecCapability> codecs);
|
||||
|
||||
[ChromeOnly]
|
||||
undefined setAddTrackMagic();
|
||||
[ChromeOnly]
|
||||
undefined setDirectionInternal(RTCRtpTransceiverDirection direction);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user