--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -1318,16 +1318,41 @@ class RTCPeerConnection {
this._queueTaskWithClosedCheck(() => {
if (this._negotiationNeeded) {
this.dispatchEvent(new this._win.Event("negotiationneeded"));
}
});
}
+ _processTrackAdditionsAndRemovals() {
+ let postProcessing = {
+ updateStreamFunctions: [],
+ muteTracks: [],
+ trackEvents: []
+ };
+
+ for (let transceiver of this._transceivers) {
+ transceiver.receiver.processTrackAdditionsAndRemovals(transceiver,
+ postProcessing);
+ }
+
+ for (let f of postProcessing.updateStreamFunctions) {
+ f();
+ }
+
+ for (let t of postProcessing.muteTracks) {
+ t.mutedChanged(true);
+ }
+
+ for (let ev of postProcessing.trackEvents) {
+ this.dispatchEvent(ev);
+ }
+ }
+
// TODO(Bug 1241291): Legacy event, remove eventually
_fireLegacyAddStreamEvents() {
for (let stream of this._newStreams) {
let ev = new this._win.MediaStreamEvent("addstream", { stream });
this.dispatchEvent(ev);
}
this._newStreams = [];
}
@@ -1650,16 +1675,17 @@ class PeerConnectionObserver {
onSetLocalDescriptionSuccess() {
this._dompc._syncTransceivers();
this._dompc._onSetLocalDescriptionSuccess();
}
onSetRemoteDescriptionSuccess() {
this._dompc._syncTransceivers();
+ this._dompc._processTrackAdditionsAndRemovals();
this._dompc._fireLegacyAddStreamEvents();
this._dompc._onSetRemoteDescriptionSuccess();
}
onSetLocalDescriptionError(code, message) {
this._localType = null;
this._dompc._onSetLocalDescriptionFailure(this.newError(message, code));
}
@@ -1816,49 +1842,16 @@ class PeerConnectionObserver {
{ stream }));
}
_getTransceiverWithRecvTrack(webrtcTrackId) {
return this._dompc.getTransceivers().find(
transceiver => transceiver.remoteTrackIdIs(webrtcTrackId));
}
- onTrack(webrtcTrackId, streamIds) {
- let pc = this._dompc;
- let matchingTransceiver = this._getTransceiverWithRecvTrack(webrtcTrackId);
-
- // Get or create MediaStreams, and add the new track to them.
- let streams = streamIds.map(id => this._dompc._getOrCreateStream(id));
-
- streams.forEach(stream => {
- stream.addTrack(matchingTransceiver.receiver.track);
- // Adding tracks from JS does not result in the stream getting
- // onaddtrack, so we need to do that here. The mediacapture spec says
- // this needs to be queued, also.
- pc._queueTaskWithClosedCheck(() => {
- stream.dispatchEvent(
- new pc._win.MediaStreamTrackEvent(
- "addtrack", { track: matchingTransceiver.receiver.track }));
- });
- });
-
-
- let ev = new pc._win.RTCTrackEvent("track", {
- receiver: matchingTransceiver.receiver,
- track: matchingTransceiver.receiver.track,
- streams,
- transceiver: matchingTransceiver });
- this.dispatchEvent(ev);
-
- // Fire legacy event as well for a little bit.
- ev = new pc._win.MediaStreamTrackEvent("addtrack",
- { track: matchingTransceiver.receiver.track });
- this.dispatchEvent(ev);
- }
-
onTransceiverNeeded(kind, transceiverImpl) {
this._dompc._onTransceiverNeeded(kind, transceiverImpl);
}
notifyDataChannel(channel) {
this.dispatchEvent(new this._dompc._win.RTCDataChannelEvent("datachannel",
{ channel }));
}
@@ -2070,16 +2063,19 @@ setupPrototype(RTCRtpSender, {
class RTCRtpReceiver {
constructor(pc, transceiverImpl) {
// We do not set the track here; that is done when _transceiverImpl is set
Object.assign(this,
{
_pc: pc,
_transceiverImpl: transceiverImpl,
track: transceiverImpl.getReceiveTrack(),
+ _remoteSetSendBit: false,
+ _ontrackFired: false,
+ streamIds: [],
// Sync and contributing sources must be kept cached so that timestamps
// remain stable, as the timestamp offset can vary
// note key = entry.source + entry.sourceType
_rtpSources: new Map(),
_rtpSourcesJsTimestamp: null,
});
}
@@ -2131,18 +2127,16 @@ class RTCRtpReceiver {
removeKeys.push(entry.source + entry.sourceType);
}
}
for (let delKey of removeKeys) {
this._rtpSources.delete(delKey);
}
}
-
-
_getRtpSourcesByType(type) {
this._fetchRtpSources();
// Only return the values from within the last 10 seconds as per the spec
let cutoffTime = this._rtpSourcesJsTimestamp - 10 * 1000;
let sources = [...this._rtpSources.values()].filter(
(entry) => {
return entry.sourceType == type &&
(entry.timestamp + entry.sourceClockOffset) >= cutoffTime;
@@ -2157,16 +2151,77 @@ class RTCRtpReceiver {
getContributingSources() {
return this._getRtpSourcesByType("contributing");
}
getSynchronizationSources() {
return this._getRtpSourcesByType("synchronization");
}
+ setStreamIds(streamIds) {
+ this.streamIds = streamIds;
+ }
+
+ setRemoteSendBit(sendBit) {
+ this._remoteSetSendBit = sendBit;
+ }
+
+ processTrackAdditionsAndRemovals(transceiver,
+ {updateStreamFunctions, muteTracks, trackEvents}) {
+ let streamsWithTrack = this.streamIds
+ .map(id => this._pc._getOrCreateStream(id));
+
+ let streamsWithoutTrack = this._pc.getRemoteStreams()
+ .filter(s => !this.streamIds.includes(s.id));
+
+ updateStreamFunctions.push(...streamsWithTrack.map(stream => () => {
+ if (!stream.getTracks().includes(this.track)) {
+ stream.addTrack(this.track);
+ // Adding tracks from JS does not result in the stream getting
+ // onaddtrack, so we need to do that here.
+ stream.dispatchEvent(
+ new this._pc._win.MediaStreamTrackEvent(
+ "addtrack", { track: this.track }));
+ }
+ }));
+
+ updateStreamFunctions.push(...streamsWithoutTrack.map(stream => () => {
+ // Content JS might remove this track from the stream before this function fires (ugh)
+ if (stream.getTracks().includes(this.track)) {
+ stream.removeTrack(this.track);
+ // Removing tracks from JS does not result in the stream getting
+ // onremovetrack, so we need to do that here.
+ stream.dispatchEvent(
+ new this._pc._win.MediaStreamTrackEvent(
+ "removetrack", { track: this.track }));
+ }
+ }));
+
+ if (!this._remoteSetSendBit) {
+ // remote used "recvonly" or "inactive"
+ this._ontrackFired = false;
+ if (!this.track.muted) {
+ muteTracks.push(this.track);
+ }
+ } else if (!this._ontrackFired) {
+ // remote used "sendrecv" or "sendonly", and we haven't fired ontrack
+ let ev = new this._pc._win.RTCTrackEvent("track", {
+ receiver: this.__DOM_IMPL__,
+ track: this.track,
+ streams: streamsWithTrack,
+ transceiver });
+ trackEvents.push(ev);
+ this._ontrackFired = true;
+
+ // Fire legacy event as well for a little bit.
+ ev = new this._pc._win.MediaStreamTrackEvent("addtrack",
+ { track: this.track });
+ trackEvents.push(ev);
+ }
+ }
}
setupPrototype(RTCRtpReceiver, {
classID: PC_RECEIVER_CID,
contractID: PC_RECEIVER_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
});
class RTCRtpTransceiver {
--- a/dom/webidl/MediaStreamTrack.webidl
+++ b/dom/webidl/MediaStreamTrack.webidl
@@ -90,9 +90,12 @@ interface MediaStreamTrack : EventTarget
// MediaTrackCapabilities getCapabilities ();
MediaTrackConstraints getConstraints ();
[NeedsCallerType]
MediaTrackSettings getSettings ();
[Throws, NeedsCallerType]
Promise<void> applyConstraints (optional MediaTrackConstraints constraints);
// attribute EventHandler onoverconstrained;
+
+ [ChromeOnly]
+ void mutedChanged(boolean muted);
};
--- a/dom/webidl/PeerConnectionObserver.webidl
+++ b/dom/webidl/PeerConnectionObserver.webidl
@@ -31,17 +31,16 @@ interface PeerConnectionObserver
/* Data channel callbacks */
void notifyDataChannel(DataChannel channel);
/* Notification of one of several types of state changed */
void onStateChange(PCObserverStateType state);
/* Changes to MediaStreamTracks */
void onRemoveStream(MediaStream stream);
- void onTrack(DOMString webrtcTrackId, sequence<DOMString> streamIds);
/* Transceiver management; called when setRemoteDescription causes a
transceiver to be created on the C++ side */
void onTransceiverNeeded(DOMString kind, TransceiverImpl transceiverImpl);
/* DTMF callback */
void onDTMFToneChange(MediaStreamTrack track, DOMString tone);
--- a/dom/webidl/RTCRtpReceiver.webidl
+++ b/dom/webidl/RTCRtpReceiver.webidl
@@ -9,9 +9,18 @@
[Pref="media.peerconnection.enabled",
JSImplementation="@mozilla.org/dom/rtpreceiver;1"]
interface RTCRtpReceiver {
readonly attribute MediaStreamTrack track;
Promise<RTCStatsReport> getStats();
sequence<RTCRtpContributingSource> getContributingSources();
sequence<RTCRtpSynchronizationSource> getSynchronizationSources();
+
+ [ChromeOnly]
+ void setStreamIds(sequence<DOMString> streamIds);
+ [ChromeOnly]
+ void setRemoteSendBit(boolean sendBit);
+ [ChromeOnly]
+ void processTrackAdditionsAndRemovals(
+ RTCRtpTransceiver transceiver,
+ object postProcessing);
};
--- a/media/webrtc/signaling/gtest/jsep_session_unittest.cpp
+++ b/media/webrtc/signaling/gtest/jsep_session_unittest.cpp
@@ -508,23 +508,16 @@ protected:
JsepTrack GetTrackOff(size_t index, SdpMediaSection::MediaType type) {
return GetTrack(*mSessionOff, type, index);
}
JsepTrack GetTrackAns(size_t index, SdpMediaSection::MediaType type) {
return GetTrack(*mSessionAns, type, index);
}
- size_t CountRtpTypes() const {
- return std::count_if(
- types.begin(), types.end(),
- [](SdpMediaSection::MediaType type)
- {return type != SdpMediaSection::MediaType::kApplication;});
- }
-
bool Equals(const SdpFingerprintAttributeList::Fingerprint& f1,
const SdpFingerprintAttributeList::Fingerprint& f2) const {
if (f1.hashFunc != f2.hashFunc) {
return false;
}
if (f1.fingerprint != f2.fingerprint) {
return false;
@@ -1634,57 +1627,37 @@ TEST_P(JsepSessionTest, GetDescriptions)
TEST_P(JsepSessionTest, RenegotiationNoChange)
{
AddTracks(*mSessionOff);
std::string offer = CreateOffer();
SetLocalOffer(offer);
SetRemoteOffer(offer);
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(CountRtpTypes(), added.size());
- ASSERT_EQ(0U, removed.size());
-
AddTracks(*mSessionAns);
std::string answer = CreateAnswer();
SetLocalAnswer(answer);
SetRemoteAnswer(answer);
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(CountRtpTypes(), added.size());
- ASSERT_EQ(0U, removed.size());
-
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
std::vector<RefPtr<JsepTransceiver>> origOffererTransceivers
= DeepCopy(mSessionOff->GetTransceivers());
std::vector<RefPtr<JsepTransceiver>> origAnswererTransceivers
= DeepCopy(mSessionAns->GetTransceivers());
std::string reoffer = CreateOffer();
SetLocalOffer(reoffer);
SetRemoteOffer(reoffer);
- added = mSessionAns->GetRemoteTracksAdded();
- removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(0U, removed.size());
-
std::string reanswer = CreateAnswer();
SetLocalAnswer(reanswer);
SetRemoteAnswer(reanswer);
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(0U, removed.size());
-
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
auto newOffererTransceivers = mSessionOff->GetTransceivers();
auto newAnswererTransceivers = mSessionAns->GetTransceivers();
ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers));
ASSERT_TRUE(Equals(origAnswererTransceivers, newAnswererTransceivers));
@@ -1693,57 +1666,37 @@ TEST_P(JsepSessionTest, RenegotiationNoC
// Disabled: See Bug 1329028
TEST_P(JsepSessionTest, DISABLED_RenegotiationSwappedRolesNoChange)
{
AddTracks(*mSessionOff);
std::string offer = CreateOffer();
SetLocalOffer(offer);
SetRemoteOffer(offer);
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(types.size(), added.size());
- ASSERT_EQ(0U, removed.size());
-
AddTracks(*mSessionAns);
std::string answer = CreateAnswer();
SetLocalAnswer(answer);
SetRemoteAnswer(answer);
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(types.size(), added.size());
- ASSERT_EQ(0U, removed.size());
-
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
auto offererTransceivers = DeepCopy(mSessionOff->GetTransceivers());
auto answererTransceivers = DeepCopy(mSessionAns->GetTransceivers());
SwapOfferAnswerRoles();
std::string reoffer = CreateOffer();
SetLocalOffer(reoffer);
SetRemoteOffer(reoffer);
- added = mSessionAns->GetRemoteTracksAdded();
- removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(0U, removed.size());
-
std::string reanswer = CreateAnswer();
SetLocalAnswer(reanswer);
SetRemoteAnswer(reanswer);
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(0U, removed.size());
-
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kPassive);
auto newOffererTransceivers = mSessionOff->GetTransceivers();
auto newAnswererTransceivers = mSessionAns->GetTransceivers();
ASSERT_TRUE(Equals(offererTransceivers, newAnswererTransceivers));
ASSERT_TRUE(Equals(answererTransceivers, newOffererTransceivers));
@@ -1771,28 +1724,16 @@ TEST_P(JsepSessionTest, RenegotiationOff
AddTracks(*mSessionOff, extraTypes);
types.insert(types.end(), extraTypes.begin(), extraTypes.end());
OfferAnswer(CHECK_SUCCESS);
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(2U, added.size());
- ASSERT_EQ(0U, removed.size());
- ASSERT_EQ(SdpMediaSection::kAudio, added[0].GetMediaType());
- ASSERT_EQ(SdpMediaSection::kVideo, added[1].GetMediaType());
-
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(0U, removed.size());
-
auto newOffererTransceivers = mSessionOff->GetTransceivers();
auto newAnswererTransceivers = mSessionAns->GetTransceivers();
ASSERT_LE(2U, newOffererTransceivers.size());
newOffererTransceivers.resize(newOffererTransceivers.size() - 2);
ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers));
ASSERT_LE(2U, newAnswererTransceivers.size());
@@ -1833,28 +1774,16 @@ TEST_P(JsepSessionTest, RenegotiationAns
std::string answer = CreateAnswer();
SetLocalAnswer(answer, CHECK_SUCCESS);
SetRemoteAnswer(answer, CHECK_SUCCESS);
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(0U, removed.size());
-
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(2U, added.size());
- ASSERT_EQ(0U, removed.size());
- ASSERT_EQ(SdpMediaSection::kAudio, added[0].GetMediaType());
- ASSERT_EQ(SdpMediaSection::kVideo, added[1].GetMediaType());
-
auto newOffererTransceivers = mSessionOff->GetTransceivers();
auto newAnswererTransceivers = mSessionAns->GetTransceivers();
ASSERT_LE(2U, newOffererTransceivers.size());
newOffererTransceivers.resize(newOffererTransceivers.size() - 2);
ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers));
ASSERT_LE(2U, newAnswererTransceivers.size());
@@ -1884,30 +1813,16 @@ TEST_P(JsepSessionTest, RenegotiationBot
AddTracks(*mSessionOff, extraTypes);
types.insert(types.end(), extraTypes.begin(), extraTypes.end());
OfferAnswer(CHECK_SUCCESS);
ValidateSetupAttribute(*mSessionOff, SdpSetupAttribute::kActpass);
ValidateSetupAttribute(*mSessionAns, SdpSetupAttribute::kActive);
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(2U, added.size());
- ASSERT_EQ(0U, removed.size());
- ASSERT_EQ(SdpMediaSection::kAudio, added[0].GetMediaType());
- ASSERT_EQ(SdpMediaSection::kVideo, added[1].GetMediaType());
-
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(2U, added.size());
- ASSERT_EQ(0U, removed.size());
- ASSERT_EQ(SdpMediaSection::kAudio, added[0].GetMediaType());
- ASSERT_EQ(SdpMediaSection::kVideo, added[1].GetMediaType());
-
auto newOffererTransceivers = mSessionOff->GetTransceivers();
auto newAnswererTransceivers = mSessionAns->GetTransceivers();
ASSERT_LE(2U, newOffererTransceivers.size());
newOffererTransceivers.resize(newOffererTransceivers.size() - 2);
ASSERT_TRUE(Equals(origOffererTransceivers, newOffererTransceivers));
ASSERT_LE(2U, newAnswererTransceivers.size());
@@ -1981,42 +1896,33 @@ TEST_P(JsepSessionTest, RenegotiationOff
return;
}
OfferAnswer();
std::string offer = CreateOffer();
SetLocalOffer(offer);
- JsepTransceiver* transceiver = GetNegotiatedTransceiver(*mSessionOff, 0);
+ RefPtr<JsepTransceiver> transceiver =
+ GetNegotiatedTransceiver(*mSessionOff, 0);
ASSERT_TRUE(transceiver);
std::string streamId = transceiver->mSendTrack.GetStreamIds()[0];
std::string trackId = transceiver->mSendTrack.GetTrackId();
std::string msidToReplace("a=msid:");
msidToReplace += streamId;
msidToReplace += " ";
msidToReplace += trackId;
size_t msidOffset = offer.find(msidToReplace);
ASSERT_NE(std::string::npos, msidOffset);
offer.replace(msidOffset, msidToReplace.size(), "a=msid:foo bar");
SetRemoteOffer(offer);
-
- std::vector<JsepTrack> removedTracks = mSessionAns->GetRemoteTracksRemoved();
- std::vector<JsepTrack> addedTracks = mSessionAns->GetRemoteTracksAdded();
-
- ASSERT_EQ(1U, removedTracks.size());
- ASSERT_FALSE(IsNull(removedTracks[0]));
- ASSERT_EQ(streamId, removedTracks[0].GetStreamIds()[0]);
- ASSERT_EQ(trackId, removedTracks[0].GetTrackId());
-
- ASSERT_EQ(1U, addedTracks.size());
- ASSERT_FALSE(IsNull(addedTracks[0]));
- ASSERT_EQ("foo", addedTracks[0].GetStreamIds()[0]);
- ASSERT_EQ("bar", addedTracks[0].GetTrackId());
+ transceiver = GetNegotiatedTransceiver(*mSessionAns, 0);
+ ASSERT_EQ("foo", transceiver->mRecvTrack.GetStreamIds()[0]);
+ ASSERT_EQ("bar", transceiver->mRecvTrack.GetTrackId());
std::string answer = CreateAnswer();
SetLocalAnswer(answer);
SetRemoteAnswer(answer);
}
// The JSEP draft explicitly forbids changing the msid on an m-section, but
// that is a new restriction that older versions of Firefox do not follow.
@@ -2031,42 +1937,34 @@ TEST_P(JsepSessionTest, RenegotiationAns
OfferAnswer();
std::string offer = CreateOffer();
SetLocalOffer(offer);
SetRemoteOffer(offer);
std::string answer = CreateAnswer();
SetLocalAnswer(answer);
- JsepTransceiver* transceiver = GetNegotiatedTransceiver(*mSessionAns, 0);
+ RefPtr<JsepTransceiver> transceiver =
+ GetNegotiatedTransceiver(*mSessionAns, 0);
ASSERT_TRUE(transceiver);
std::string streamId = transceiver->mSendTrack.GetStreamIds()[0];
std::string trackId = transceiver->mSendTrack.GetTrackId();
std::string msidToReplace("a=msid:");
msidToReplace += streamId;
msidToReplace += " ";
msidToReplace += trackId;
size_t msidOffset = answer.find(msidToReplace);
ASSERT_NE(std::string::npos, msidOffset);
answer.replace(msidOffset, msidToReplace.size(), "a=msid:foo bar");
SetRemoteAnswer(answer);
- std::vector<JsepTrack> removedTracks = mSessionOff->GetRemoteTracksRemoved();
- std::vector<JsepTrack> addedTracks = mSessionOff->GetRemoteTracksAdded();
-
- ASSERT_EQ(1U, removedTracks.size());
- ASSERT_FALSE(IsNull(removedTracks[0]));
- ASSERT_EQ(streamId, removedTracks[0].GetStreamIds()[0]);
- ASSERT_EQ(trackId, removedTracks[0].GetTrackId());
-
- ASSERT_EQ(1U, addedTracks.size());
- ASSERT_FALSE(IsNull(addedTracks[0]));
- ASSERT_EQ("foo", addedTracks[0].GetStreamIds()[0]);
- ASSERT_EQ("bar", addedTracks[0].GetTrackId());
+ transceiver = GetNegotiatedTransceiver(*mSessionOff, 0);
+ ASSERT_EQ("foo", transceiver->mRecvTrack.GetStreamIds()[0]);
+ ASSERT_EQ("bar", transceiver->mRecvTrack.GetTrackId());
}
TEST_P(JsepSessionTest, RenegotiationOffererStopsTransceiver)
{
AddTracks(*mSessionOff);
AddTracks(*mSessionAns);
if (types.back() == SdpMediaSection::kApplication) {
return;
@@ -2080,30 +1978,16 @@ TEST_P(JsepSessionTest, RenegotiationOff
DeepCopy(mSessionAns->GetTransceivers());
// Avoid bundle transport side effects; don't stop the BUNDLE-tag!
mSessionOff->GetTransceivers().back()->Stop();
JsepTrack removedTrack(mSessionOff->GetTransceivers().back()->mSendTrack);
OfferAnswer(CHECK_SUCCESS);
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(1U, removed.size());
-
- ASSERT_EQ(removedTrack.GetMediaType(), removed[0].GetMediaType());
- ASSERT_EQ(removedTrack.GetStreamIds(), removed[0].GetStreamIds());
- ASSERT_EQ(removedTrack.GetTrackId(), removed[0].GetTrackId());
-
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(1U, removed.size());
-
// Last m-section should be disabled
auto offer = GetParsedLocalDescription(*mSessionOff);
const SdpMediaSection* msection =
&offer->GetMediaSection(offer->GetMediaSectionCount() - 1);
ASSERT_TRUE(msection);
ValidateDisabledMSection(msection);
// Last m-section should be disabled
@@ -2149,30 +2033,16 @@ TEST_P(JsepSessionTest, RenegotiationAns
= DeepCopy(mSessionAns->GetTransceivers());
// Avoid bundle transport side effects; don't stop the BUNDLE-tag!
mSessionAns->GetTransceivers().back()->Stop();
JsepTrack removedTrack(mSessionAns->GetTransceivers().back()->mSendTrack);
OfferAnswer(CHECK_SUCCESS);
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(0U, removed.size());
-
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(1U, removed.size());
-
- ASSERT_EQ(removedTrack.GetMediaType(), removed[0].GetMediaType());
- ASSERT_EQ(removedTrack.GetStreamIds(), removed[0].GetStreamIds());
- ASSERT_EQ(removedTrack.GetTrackId(), removed[0].GetTrackId());
-
// Last m-section should be sendrecv
auto offer = GetParsedLocalDescription(*mSessionOff);
const SdpMediaSection* msection =
&offer->GetMediaSection(offer->GetMediaSectionCount() - 1);
ASSERT_TRUE(msection);
ASSERT_TRUE(msection->IsReceiving());
ASSERT_TRUE(msection->IsSending());
@@ -2218,34 +2088,16 @@ TEST_P(JsepSessionTest, RenegotiationBot
// Avoid bundle transport side effects; don't stop the BUNDLE-tag!
mSessionOff->GetTransceivers().back()->Stop();
JsepTrack removedTrackOffer(mSessionOff->GetTransceivers().back()->mSendTrack);
mSessionAns->GetTransceivers().back()->Stop();
JsepTrack removedTrackAnswer(mSessionAns->GetTransceivers().back()->mSendTrack);
OfferAnswer(CHECK_SUCCESS);
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(1U, removed.size());
-
- ASSERT_EQ(removedTrackOffer.GetMediaType(), removed[0].GetMediaType());
- ASSERT_EQ(removedTrackOffer.GetStreamIds(), removed[0].GetStreamIds());
- ASSERT_EQ(removedTrackOffer.GetTrackId(), removed[0].GetTrackId());
-
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(1U, removed.size());
-
- ASSERT_EQ(removedTrackAnswer.GetMediaType(), removed[0].GetMediaType());
- ASSERT_EQ(removedTrackAnswer.GetStreamIds(), removed[0].GetStreamIds());
- ASSERT_EQ(removedTrackAnswer.GetTrackId(), removed[0].GetTrackId());
-
// Last m-section should be disabled
auto offer = GetParsedLocalDescription(*mSessionOff);
const SdpMediaSection* msection =
&offer->GetMediaSection(offer->GetMediaSectionCount() - 1);
ASSERT_TRUE(msection);
ValidateDisabledMSection(msection);
// Last m-section should be disabled
@@ -2300,28 +2152,16 @@ TEST_P(JsepSessionTest, RenegotiationBot
std::vector<SdpMediaSection::MediaType> extraTypes;
extraTypes.push_back(removedType);
AddTracks(*mSessionAns, extraTypes);
AddTracks(*mSessionOff, extraTypes);
types.insert(types.end(), extraTypes.begin(), extraTypes.end());
OfferAnswer(CHECK_SUCCESS);
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(1U, added.size());
- ASSERT_EQ(0U, removed.size());
- ASSERT_EQ(removedType, added[0].GetMediaType());
-
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(1U, added.size());
- ASSERT_EQ(0U, removed.size());
- ASSERT_EQ(removedType, added[0].GetMediaType());
-
auto newOffererTransceivers = mSessionOff->GetTransceivers();
auto newAnswererTransceivers = mSessionAns->GetTransceivers();
ASSERT_EQ(origOffererTransceivers.size() + 1, newOffererTransceivers.size());
ASSERT_EQ(origAnswererTransceivers.size() + 1,
newAnswererTransceivers.size());
// Ensure that the m-section was re-used; no gaps
@@ -2347,26 +2187,18 @@ TEST_P(JsepSessionTest, RenegotiationBot
}
OfferAnswer();
mSessionOff->GetTransceivers()[0]->Stop();
mSessionOff->GetTransceivers()[1]->Stop();
OfferAnswer(CHECK_SUCCESS);
-
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(2U, removed.size());
-
- added = mSessionOff->GetRemoteTracksAdded();
- removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(2U, removed.size());
+ ASSERT_TRUE(mSessionAns->GetTransceivers()[0]->IsStopped());
+ ASSERT_TRUE(mSessionAns->GetTransceivers()[1]->IsStopped());
}
TEST_P(JsepSessionTest, RenegotiationOffererReplacesTrack)
{
AddTracks(*mSessionOff);
AddTracks(*mSessionAns);
if (types.front() == SdpMediaSection::kApplication) {
@@ -2377,20 +2209,20 @@ TEST_P(JsepSessionTest, RenegotiationOff
mSessionOff->GetTransceivers()[0]->mSendTrack.UpdateTrackIds(
std::vector<std::string>(1, "newstream"), "newtrack");
OfferAnswer(CHECK_SUCCESS);
// Latest JSEP spec says the msid never changes, so the other side will not
// notice track replacement.
- auto added = mSessionAns->GetRemoteTracksAdded();
- auto removed = mSessionAns->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(0U, removed.size());
+ ASSERT_NE("newtrack",
+ mSessionAns->GetTransceivers()[0]->mRecvTrack.GetTrackId());
+ ASSERT_NE("newstream",
+ mSessionAns->GetTransceivers()[0]->mRecvTrack.GetStreamIds()[0]);
}
TEST_P(JsepSessionTest, RenegotiationAnswererReplacesTrack)
{
AddTracks(*mSessionOff);
AddTracks(*mSessionAns);
if (types.front() == SdpMediaSection::kApplication) {
@@ -2401,20 +2233,20 @@ TEST_P(JsepSessionTest, RenegotiationAns
mSessionAns->GetTransceivers()[0]->mSendTrack.UpdateTrackIds(
std::vector<std::string>(1, "newstream"), "newtrack");
OfferAnswer(CHECK_SUCCESS);
// Latest JSEP spec says the msid never changes, so the other side will not
// notice track replacement.
- auto added = mSessionOff->GetRemoteTracksAdded();
- auto removed = mSessionOff->GetRemoteTracksRemoved();
- ASSERT_EQ(0U, added.size());
- ASSERT_EQ(0U, removed.size());
+ ASSERT_NE("newtrack",
+ mSessionOff->GetTransceivers()[0]->mRecvTrack.GetTrackId());
+ ASSERT_NE("newstream",
+ mSessionOff->GetTransceivers()[0]->mRecvTrack.GetStreamIds()[0]);
}
// Tests whether auto-assigned remote msids (ie; what happens when the other
// side doesn't use msid attributes) are stable across renegotiation.
TEST_P(JsepSessionTest, RenegotiationAutoAssignedMsidIsStable)
{
AddTracks(*mSessionOff);
std::string offer = CreateOffer();
@@ -4739,17 +4571,19 @@ TEST_P(JsepSessionTest, TestRejectOfferR
std::string offer = CreateOffer();
SetLocalOffer(offer);
SetRemoteOffer(offer);
ASSERT_EQ(NS_OK,
mSessionAns->SetRemoteDescription(kJsepSdpRollback, ""));
ASSERT_EQ(kJsepStateStable, mSessionAns->GetState());
- ASSERT_EQ(CountRtpTypes(), mSessionAns->GetRemoteTracksRemoved().size());
+ for (const auto& transceiver : mSessionAns->GetTransceivers()) {
+ ASSERT_EQ(0U, transceiver->mRecvTrack.GetStreamIds().size());
+ }
ASSERT_EQ(NS_OK,
mSessionOff->SetLocalDescription(kJsepSdpRollback, ""));
ASSERT_EQ(kJsepStateStable, mSessionOff->GetState());
OfferAnswer();
}
--- a/media/webrtc/signaling/src/jsep/JsepSession.h
+++ b/media/webrtc/signaling/src/jsep/JsepSession.h
@@ -127,20 +127,16 @@ public:
{
std::stable_sort(Codecs().begin(), Codecs().end(), sorter);
for (auto& transceiver : GetTransceivers()) {
transceiver->mSendTrack.SortCodecs(sorter);
transceiver->mRecvTrack.SortCodecs(sorter);
}
}
- // Helpful for firing events.
- virtual std::vector<JsepTrack> GetRemoteTracksAdded() const = 0;
- virtual std::vector<JsepTrack> GetRemoteTracksRemoved() const = 0;
-
virtual const std::vector<RefPtr<JsepTransceiver>>&
GetTransceivers() const = 0;
virtual std::vector<RefPtr<JsepTransceiver>>& GetTransceivers() = 0;
virtual nsresult AddTransceiver(RefPtr<JsepTransceiver> transceiver) = 0;
// Basic JSEP operations.
virtual nsresult CreateOffer(const JsepOfferOptions& options,
std::string* offer) = 0;
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
@@ -183,28 +183,16 @@ JsepSessionImpl::AddAudioRtpExtension(co
nsresult
JsepSessionImpl::AddVideoRtpExtension(const std::string& extensionName,
SdpDirectionAttribute::Direction direction)
{
return AddRtpExtension(mVideoRtpExtensions, extensionName, direction);
}
-std::vector<JsepTrack>
-JsepSessionImpl::GetRemoteTracksAdded() const
-{
- return mRemoteTracksAdded;
-}
-
-std::vector<JsepTrack>
-JsepSessionImpl::GetRemoteTracksRemoved() const
-{
- return mRemoteTracksRemoved;
-}
-
nsresult
JsepSessionImpl::CreateOfferMsection(const JsepOfferOptions& options,
JsepTransceiver& transceiver,
Sdp* local)
{
JsepTrack& sendTrack(transceiver.mSendTrack);
JsepTrack& recvTrack(transceiver.mRecvTrack);
@@ -1380,22 +1368,16 @@ JsepSessionImpl::SetRemoteDescriptionAns
mCurrentLocalDescription = Move(mPendingLocalDescription);
MOZ_ASSERT(mIsOfferer);
mWasOffererLastTime = true;
SetState(kJsepStateStable);
return NS_OK;
}
-static bool
-TrackIdCompare(const JsepTrack& t1, const JsepTrack& t2)
-{
- return t1.GetTrackId() < t2.GetTrackId();
-}
-
JsepTransceiver*
JsepSessionImpl::GetTransceiverForLevel(size_t level)
{
for (RefPtr<JsepTransceiver>& transceiver : mTransceivers) {
if (transceiver->HasLevel() && (transceiver->GetLevel() == level)) {
return transceiver.get();
}
}
@@ -1465,88 +1447,53 @@ JsepSessionImpl::GetTransceiverForRemote
nsresult rv = AddTransceiver(newTransceiver);
NS_ENSURE_SUCCESS(rv, nullptr);
return mTransceivers.back().get();
}
nsresult
JsepSessionImpl::UpdateTransceiversFromRemoteDescription(const Sdp& remote)
{
- std::vector<JsepTrack> oldRemoteTracks;
- std::vector<JsepTrack> newRemoteTracks;
-
// Iterate over the sdp, updating remote tracks as we go
for (size_t i = 0; i < remote.GetMediaSectionCount(); ++i) {
const SdpMediaSection& msection = remote.GetMediaSection(i);
JsepTransceiver* transceiver(GetTransceiverForRemote(msection));
if (!transceiver) {
return NS_ERROR_FAILURE;
}
- bool isRtp =
- msection.GetMediaType() != SdpMediaSection::MediaType::kApplication;
-
- if (isRtp && transceiver->mRecvTrack.GetActive()) {
- oldRemoteTracks.push_back(transceiver->mRecvTrack);
- }
-
if (!mSdpHelper.MsectionIsDisabled(msection)) {
transceiver->Associate(msection.GetAttributeList().GetMid());
} else {
transceiver->Disassociate();
// This cannot be rolled back.
transceiver->Stop();
continue;
}
- if (!isRtp) {
+ if (msection.GetMediaType() == SdpMediaSection::MediaType::kApplication) {
continue;
}
// Interop workaround for endpoints that don't support msid.
- // If the receiver has no ids, set some initial values, one way or another.
+ // Ensures that there is a default track id set.
+ // TODO(bug 1426005): Remove this
if (msection.IsSending() && transceiver->mRecvTrack.GetTrackId().empty()) {
std::vector<std::string> streamIds;
std::string trackId;
nsresult rv = GetRemoteIds(remote, msection, &streamIds, &trackId);
NS_ENSURE_SUCCESS(rv, rv);
transceiver->mRecvTrack.UpdateTrackIds(streamIds, trackId);
}
transceiver->mRecvTrack.UpdateRecvTrack(remote, msection);
-
- if (msection.IsSending()) {
- newRemoteTracks.push_back(transceiver->mRecvTrack);
- }
}
- std::sort(oldRemoteTracks.begin(), oldRemoteTracks.end(), TrackIdCompare);
- std::sort(newRemoteTracks.begin(), newRemoteTracks.end(), TrackIdCompare);
-
- mRemoteTracksAdded.clear();
- mRemoteTracksRemoved.clear();
-
- std::set_difference(
- oldRemoteTracks.begin(),
- oldRemoteTracks.end(),
- newRemoteTracks.begin(),
- newRemoteTracks.end(),
- std::inserter(mRemoteTracksRemoved, mRemoteTracksRemoved.begin()),
- TrackIdCompare);
-
- std::set_difference(
- newRemoteTracks.begin(),
- newRemoteTracks.end(),
- oldRemoteTracks.begin(),
- oldRemoteTracks.end(),
- std::inserter(mRemoteTracksAdded, mRemoteTracksAdded.begin()),
- TrackIdCompare);
-
return NS_OK;
}
bool
JsepSessionImpl::WasMsectionDisabledLastNegotiation(size_t level) const
{
const Sdp* answer(GetAnswer());
@@ -1599,36 +1546,34 @@ JsepSessionImpl::RollbackRemoteOffer()
for (size_t i = 0; i < mTransceivers.size(); ++i) {
RefPtr<JsepTransceiver>& transceiver(mTransceivers[i]);
if (i < mOldTransceivers.size()) {
transceiver->Rollback(*mOldTransceivers[i]);
continue;
}
// New transceiver!
- if (!transceiver->HasAddTrackMagic() &&
- transceiver->WasCreatedBySetRemote()) {
+ bool shouldRemove = !transceiver->HasAddTrackMagic() &&
+ transceiver->WasCreatedBySetRemote();
+
+ // 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()));
+ transceiver->Rollback(*temp);
+
+ if (shouldRemove) {
transceiver->Stop();
- transceiver->Disassociate();
- transceiver->ClearLevel();
transceiver->SetRemoved();
mTransceivers.erase(mTransceivers.begin() + i);
--i;
- continue;
}
-
- // Transceiver has been "touched" by addTrack; let it live, but unhook it
- // from everything.
- RefPtr<JsepTransceiver> temp(
- new JsepTransceiver(transceiver->GetMediaType()));
- transceiver->Rollback(*temp);
}
mOldTransceivers.clear();
- std::swap(mRemoteTracksAdded, mRemoteTracksRemoved);
}
nsresult
JsepSessionImpl::ValidateLocalDescription(const Sdp& description)
{
// TODO(bug 1095226): Better checking.
if (!mGeneratedLocalDescription) {
JSEP_SET_ERROR("Calling SetLocal without first calling CreateOffer/Answer"
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.h
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.h
@@ -90,20 +90,16 @@ public:
SdpDirectionAttribute::Direction::kSendrecv) override;
virtual std::vector<JsepCodecDescription*>&
Codecs() override
{
return mSupportedCodecs.values;
}
- virtual std::vector<JsepTrack> GetRemoteTracksAdded() const override;
-
- virtual std::vector<JsepTrack> GetRemoteTracksRemoved() const override;
-
virtual nsresult CreateOffer(const JsepOfferOptions& options,
std::string* offer) override;
virtual nsresult CreateAnswer(const JsepAnswerOptions& options,
std::string* answer) override;
virtual std::string GetLocalDescription(JsepDescriptionPendingOrCurrent type)
const override;
@@ -248,19 +244,16 @@ private:
nsresult EnableOfferMsection(SdpMediaSection* msection);
mozilla::Sdp* GetParsedLocalDescription(JsepDescriptionPendingOrCurrent type)
const;
mozilla::Sdp* GetParsedRemoteDescription(JsepDescriptionPendingOrCurrent type)
const;
const Sdp* GetAnswer() const;
- // By the most recent SetRemoteDescription
- std::vector<JsepTrack> mRemoteTracksAdded;
- std::vector<JsepTrack> mRemoteTracksRemoved;
// !!!NOT INDEXED BY LEVEL!!! These are in the order they were created in. The
// level mapping is done with JsepTransceiver::mLevel.
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;
bool mIsOfferer;
bool mWasOffererLastTime;
--- a/media/webrtc/signaling/src/jsep/JsepTrack.h
+++ b/media/webrtc/signaling/src/jsep/JsepTrack.h
@@ -93,17 +93,18 @@ private:
class JsepTrack
{
public:
JsepTrack(mozilla::SdpMediaSection::MediaType type,
sdp::Direction direction)
: mType(type),
mDirection(direction),
- mActive(false)
+ mActive(false),
+ mRemoteSetSendBit(false)
{
}
virtual ~JsepTrack() {}
void UpdateTrackIds(const std::vector<std::string>& streamIds,
const std::string& trackId)
{
@@ -120,18 +121,22 @@ public:
void UpdateRecvTrack(const Sdp& sdp, const SdpMediaSection& msection)
{
MOZ_ASSERT(mDirection == sdp::kRecv);
MOZ_ASSERT(
msection.GetMediaType() != SdpMediaSection::MediaType::kApplication);
std::string error;
SdpHelper helper(&error);
+ mRemoteSetSendBit = msection.IsSending();
+
if (msection.IsSending()) {
(void)helper.GetIdsFromMsid(sdp, msection, &mStreamIds, &mTrackId);
+ } else {
+ mStreamIds.clear();
}
// We do this whether or not the track is active
SetCNAME(helper.GetCNAME(msection));
mSsrcs.clear();
if (msection.GetAttributeList().HasAttribute(
SdpAttribute::kSsrcAttribute)) {
for (auto& ssrcAttr : msection.GetAttributeList().GetSsrc().mSsrcs) {
@@ -154,16 +159,17 @@ public:
mType = rhs.mType;
mStreamIds = rhs.mStreamIds;
mTrackId = rhs.mTrackId;
mCNAME = rhs.mCNAME;
mDirection = rhs.mDirection;
mJsEncodeConstraints = rhs.mJsEncodeConstraints;
mSsrcs = rhs.mSsrcs;
mActive = rhs.mActive;
+ mRemoteSetSendBit = rhs.mRemoteSetSendBit;
for (const JsepCodecDescription* codec : rhs.mPrototypeCodecs.values) {
mPrototypeCodecs.values.push_back(codec->Clone());
}
if (rhs.mNegotiatedDetails) {
mNegotiatedDetails.reset(
new JsepTrackNegotiatedDetails(*rhs.mNegotiatedDetails));
}
@@ -222,16 +228,22 @@ public:
}
void
SetActive(bool active)
{
mActive = active;
}
+ bool
+ GetRemoteSetSendBit() const
+ {
+ return mRemoteSetSendBit;
+ }
+
virtual void PopulateCodecs(
const std::vector<JsepCodecDescription*>& prototype);
template <class UnaryFunction>
void ForEachCodec(UnaryFunction func)
{
std::for_each(mPrototypeCodecs.values.begin(),
mPrototypeCodecs.values.end(), func);
@@ -345,13 +357,14 @@ private:
PtrVector<JsepCodecDescription> mPrototypeCodecs;
// Holds encoding params/constraints from JS. Simulcast happens when there are
// multiple of these. If there are none, we assume unconstrained unicast with
// no rid.
std::vector<JsConstraints> mJsEncodeConstraints;
UniquePtr<JsepTrackNegotiatedDetails> mNegotiatedDetails;
std::vector<uint32_t> mSsrcs;
bool mActive;
+ bool mRemoteSetSendBit;
};
} // namespace mozilla
#endif
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -1769,46 +1769,16 @@ static void DeferredSetRemote(const std:
if (!PeerConnectionCtx::GetInstance()->isReady()) {
MOZ_CRASH("Why is DeferredSetRemote being executed when the "
"PeerConnectionCtx isn't ready?");
}
wrapper.impl()->SetRemoteDescription(aAction, aSdp.c_str());
}
}
-void
-PeerConnectionImpl::FireOnTrackEvents(RefPtr<PeerConnectionObserver>& aPco)
-{
- for (auto& track : mJsepSession->GetRemoteTracksAdded()) {
- if (track.GetMediaType() == mozilla::SdpMediaSection::kApplication) {
- // Ignore datachannel
- continue;
- }
-
- MOZ_ASSERT(!track.GetTrackId().empty());
-
- nsString trackId = NS_ConvertUTF8toUTF16(track.GetTrackId().c_str());
-
- dom::Sequence<nsString> streamIds;
- for (const std::string& streamId : track.GetStreamIds()) {
- // If this fails, oh well.
- streamIds.AppendElement(
- NS_ConvertASCIItoUTF16(streamId.c_str()), fallible);
- }
-
- JSErrorResult jrv;
- aPco->OnTrack(trackId, streamIds, jrv);
- if (jrv.Failed()) {
- CSFLogError(LOGTAG, ": OnTrack(%s) failed! Error: %u",
- track.GetTrackId().c_str(),
- jrv.ErrorCodeAsInt());
- }
- }
-}
-
NS_IMETHODIMP
PeerConnectionImpl::SetRemoteDescription(int32_t action, const char* aSDP)
{
PC_AUTO_ENTER_API_CALL(true);
if (!aSDP) {
CSFLogError(LOGTAG, "%s - aSDP is NULL", __FUNCTION__);
return NS_ERROR_FAILURE;
@@ -1925,21 +1895,16 @@ PeerConnectionImpl::SetRemoteDescription
__FUNCTION__, mHandle.c_str(), static_cast<int>(rv));
MOZ_CRASH();
return NS_ERROR_FAILURE;
}
}
UpdateSignalingState(sdpType == mozilla::kJsepSdpRollback);
- // This needs to be done before we fire ontrack events
- pco->SyncTransceivers(jrv);
-
- FireOnTrackEvents(pco);
-
pco->OnSetRemoteDescriptionSuccess(jrv);
startCallTelem();
}
return NS_OK;
}
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -356,18 +356,16 @@ public:
NS_IMETHODIMP SetLocalDescription (int32_t aAction, const char* aSDP);
void SetLocalDescription (int32_t aAction, const nsAString& aSDP, ErrorResult &rv)
{
rv = SetLocalDescription(aAction, NS_ConvertUTF16toUTF8(aSDP).get());
}
- void FireOnTrackEvents(RefPtr<PeerConnectionObserver>& aPco);
-
NS_IMETHODIMP SetRemoteDescription (int32_t aAction, const char* aSDP);
void SetRemoteDescription (int32_t aAction, const nsAString& aSDP, ErrorResult &rv)
{
rv = SetRemoteDescription(aAction, NS_ConvertUTF16toUTF8(aSDP).get());
}
NS_IMETHODIMP_TO_ERRORRESULT(GetStats, ErrorResult &rv,
--- a/media/webrtc/signaling/src/peerconnection/TransceiverImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/TransceiverImpl.cpp
@@ -517,31 +517,45 @@ TransceiverImpl::SyncWithJS(dom::RTCRtpT
} else {
if (mJsepTransceiver->mSendTrack.GetActive()) {
aJsTransceiver.SetCurrentDirection(
dom::RTCRtpTransceiverDirection::Sendonly, aRv);
} else {
aJsTransceiver.SetCurrentDirection(
dom::RTCRtpTransceiverDirection::Inactive, aRv);
}
-
- // If negotiation stops a track from receiving (ie; m-section is
- // negotiated "sendonly" or "inactive"), we mark the track muted. We do
- // _not_ do the reverse; we need to wait for RTP to unmute according to
- // the spec. That happens in MediaPipeline.
- if (!mReceiveTrack->Muted()) {
- mReceiveTrack->MutedChanged(true);
- }
}
if (aRv.Failed()) {
return;
}
}
+ RefPtr<dom::RTCRtpReceiver> receiver = aJsTransceiver.GetReceiver(aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+
+ // receive stream ids from JSEP
+ dom::Sequence<nsString> receiveStreamIds;
+ for (const auto& id : mJsepTransceiver->mRecvTrack.GetStreamIds()) {
+ receiveStreamIds.AppendElement(NS_ConvertUTF8toUTF16(id.c_str()),
+ fallible);
+ }
+ receiver->SetStreamIds(receiveStreamIds, aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+
+ receiver->SetRemoteSendBit(mJsepTransceiver->mRecvTrack.GetRemoteSetSendBit(),
+ aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+
// AddTrack magic from JS
if (aJsTransceiver.GetAddTrackMagic(aRv)) {
mJsepTransceiver->SetAddTrackMagic();
}
if (aRv.Failed()) {
return;
}