Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2023-10-11 11:56:50 +08:00
commit d6590573ed
22 changed files with 198 additions and 235 deletions

View file

@ -2876,8 +2876,8 @@ SourceMediaStream::AddDirectTrackListenerImpl(already_AddRefed<DirectMediaStream
TrackID aTrackID)
{
MOZ_ASSERT(IsTrackIDExplicit(aTrackID));
TrackData* data;
bool found = false;
TrackData* updateData = nullptr;
StreamTracks::Track* track = nullptr;
bool isAudio = false;
bool isVideo = false;
RefPtr<DirectMediaStreamTrackListener> listener = aListener;
@ -2886,44 +2886,29 @@ SourceMediaStream::AddDirectTrackListenerImpl(already_AddRefed<DirectMediaStream
{
MutexAutoLock lock(mMutex);
data = FindDataForTrack(aTrackID);
found = !!data;
if (found) {
isAudio = data->mData->GetType() == MediaSegment::AUDIO;
isVideo = data->mData->GetType() == MediaSegment::VIDEO;
updateData = FindDataForTrack(aTrackID);
track = FindTrack(aTrackID);
if (track) {
isAudio = track->GetType() == MediaSegment::AUDIO;
isVideo = track->GetType() == MediaSegment::VIDEO;
}
// The track might be removed from mUpdateTrack but still exist in
// mTracks.
auto streamTrack = FindTrack(aTrackID);
bool foundTrack = !!streamTrack;
if (foundTrack) {
MediaStreamVideoSink* videoSink = listener->AsMediaStreamVideoSink();
if (track && isVideo && listener->AsMediaStreamVideoSink()) {
// Re-send missed VideoSegment to new added MediaStreamVideoSink.
if (streamTrack->GetType() == MediaSegment::VIDEO && videoSink) {
VideoSegment videoSegment;
if (mTracks.GetForgottenDuration() < streamTrack->GetSegment()->GetDuration()) {
videoSegment.AppendSlice(*streamTrack->GetSegment(),
mTracks.GetForgottenDuration(),
streamTrack->GetSegment()->GetDuration());
} else {
VideoSegment* streamTrackSegment = static_cast<VideoSegment*>(streamTrack->GetSegment());
VideoChunk* lastChunk = streamTrackSegment->GetLastChunk();
if (lastChunk) {
StreamTime startTime = streamTrackSegment->GetDuration() - lastChunk->GetDuration();
videoSegment.AppendSlice(*streamTrackSegment,
startTime,
streamTrackSegment->GetDuration());
}
}
if (found) {
videoSegment.AppendSlice(*data->mData, 0, data->mData->GetDuration());
}
videoSink->SetCurrentFrames(videoSegment);
VideoSegment* trackSegment = static_cast<VideoSegment*>(track->GetSegment());
VideoSegment videoSegment;
if (mTracks.GetForgottenDuration() < trackSegment->GetDuration()) {
videoSegment.AppendSlice(*trackSegment,
mTracks.GetForgottenDuration(),
trackSegment->GetDuration());
}
if (updateData) {
videoSegment.AppendSlice(*updateData->mData, 0, updateData->mData->GetDuration());
}
listener->NotifyRealtimeTrackData(Graph(), 0, videoSegment);
}
if (found && (isAudio || isVideo)) {
if (track && (isAudio || isVideo)) {
for (auto entry : mDirectTrackListeners) {
if (entry.mListener == listener &&
(entry.mTrackID == TRACK_ANY || entry.mTrackID == aTrackID)) {
@ -2939,7 +2924,7 @@ SourceMediaStream::AddDirectTrackListenerImpl(already_AddRefed<DirectMediaStream
sourceListener->mTrackID = aTrackID;
}
}
if (!found) {
if (!track) {
STREAM_LOG(LogLevel::Warning, ("Couldn't find source track for direct track listener %p",
listener.get()));
listener->NotifyDirectListenerInstalled(
@ -2953,9 +2938,15 @@ SourceMediaStream::AddDirectTrackListenerImpl(already_AddRefed<DirectMediaStream
MOZ_ASSERT(true);
return;
}
STREAM_LOG(LogLevel::Debug, ("Added direct track listener %p", listener.get()));
STREAM_LOG(LogLevel::Debug, ("Added direct track listener %p. ended=%d",
listener.get(), !updateData));
listener->NotifyDirectListenerInstalled(
DirectMediaStreamTrackListener::InstallationResult::SUCCESS);
if (!updateData) {
// The track exists but the mUpdateTracks entry was removed.
// This means that the track has ended.
listener->NotifyEnded();
}
}
void

View file

@ -38,6 +38,16 @@ const PC_RECEIVER_CID = Components.ID("{d974b814-8fde-411c-8c45-b86791b81030}");
const PC_COREQUEST_CID = Components.ID("{74b2122d-65a8-4824-aa9e-3d664cb75dc2}");
const PC_DTMF_SENDER_CID = Components.ID("{3610C242-654E-11E6-8EC0-6D1BE389A607}");
function logMsg(msg, file, line, flag, winID) {
let scriptErrorClass = Cc["@mozilla.org/scripterror;1"];
let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
scriptError.initWithWindowID(msg, file, null, line, 0, flag,
"content javascript", winID);
let console = Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService);
console.logMessage(scriptError);
};
// Global list of PeerConnection objects, so they can be cleaned up when
// a page is torn down. (Maps inner window ID to an array of PC objects).
function GlobalPCList() {
@ -217,9 +227,7 @@ GlobalPCList.prototype = {
};
var _globalPCList = new GlobalPCList();
function RTCIceCandidate() {
this.candidate = this.sdpMid = this.sdpMLineIndex = null;
}
function RTCIceCandidate() {}
RTCIceCandidate.prototype = {
classDescription: "RTCIceCandidate",
classID: PC_ICE_CID,
@ -230,15 +238,11 @@ RTCIceCandidate.prototype = {
init: function(win) { this._win = win; },
__init: function(dict) {
this.candidate = dict.candidate;
this.sdpMid = dict.sdpMid;
this.sdpMLineIndex = ("sdpMLineIndex" in dict)? dict.sdpMLineIndex : null;
Object.assign(this, dict);
}
};
function RTCSessionDescription() {
this.type = this.sdp = null;
}
function RTCSessionDescription() {}
RTCSessionDescription.prototype = {
classDescription: "RTCSessionDescription",
classID: PC_SESSION_CID,
@ -246,11 +250,41 @@ RTCSessionDescription.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer]),
init: function(win) { this._win = win; },
init: function(win) {
this._win = win;
this._winID = this._win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
},
__init: function(dict) {
this.type = dict.type;
this.sdp = dict.sdp;
__init: function({ type, sdp }) {
Object.assign(this, { _type: type, _sdp: sdp });
},
get type() { return this._type; },
set type(type) {
this.warn();
this._type = type;
},
get sdp() { return this._sdp; },
set sdp(sdp) {
this.warn();
this._sdp = sdp;
},
warn: function() {
if (!this._warned) {
// Warn once per RTCSessionDescription about deprecated writable usage.
this.logWarning("RTCSessionDescription's members are readonly! " +
"Writing to them is deprecated and will break soon!");
this._warned = true;
}
},
logWarning: function(msg) {
let err = this._win.Error();
logMsg(msg, err.fileName, err.lineNumber, Ci.nsIScriptError.warningFlag,
this._winID);
}
};
@ -645,13 +679,7 @@ RTCPeerConnection.prototype = {
},
logMsg: function(msg, file, line, flag) {
let scriptErrorClass = Cc["@mozilla.org/scripterror;1"];
let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
scriptError.initWithWindowID(msg, file, null, line, 0, flag,
"content javascript", this._winID);
let console = Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService);
console.logMessage(scriptError);
return logMsg(msg, file, line, flag, this._winID);
},
getEH: function(type) {
@ -711,8 +739,7 @@ RTCPeerConnection.prototype = {
this._impl.createOffer(options);
}));
p = this._addIdentityAssertion(p, origin);
return p.then(
sdp => new this._win.RTCSessionDescription({ type: "offer", sdp: sdp }));
return p.then(sdp => Cu.cloneInto({ type: "offer", sdp: sdp }, this._win));
});
});
},
@ -746,9 +773,7 @@ RTCPeerConnection.prototype = {
this._impl.createAnswer();
}));
p = this._addIdentityAssertion(p, origin);
return p.then(sdp => {
return new this._win.RTCSessionDescription({ type: "answer", sdp: sdp });
});
return p.then(sdp => Cu.cloneInto({ type: "answer", sdp: sdp }, this._win));
});
});
},
@ -957,12 +982,15 @@ RTCPeerConnection.prototype = {
containsTrickle(topSection) || sections.every(containsTrickle);
},
addIceCandidate: function(c, onSuccess, onError) {
return this._legacyCatchAndCloseGuard(onSuccess, onError, () => {
if (!c.candidate && !c.sdpMLineIndex) {
throw new this._win.DOMException("Invalid candidate passed to addIceCandidate!",
"InvalidParameterError");
if (!c) {
// TODO: Implement processing for end-of-candidates (bug 1318167)
return Promise.resolve();
}
if (c.sdpMid === null && c.sdpMLineIndex === null) {
throw new this._win.DOMException("Invalid candidate (both sdpMid and sdpMLineIndex are null).",
"TypeError");
}
return this._chain(() => new this._win.Promise((resolve, reject) => {
this._onAddIceCandidateSuccess = resolve;
@ -1106,8 +1134,7 @@ RTCPeerConnection.prototype = {
return null;
}
return new this._win.RTCSessionDescription({ type: this._localType,
sdp: sdp });
return new this._win.RTCSessionDescription({ type: this._localType, sdp });
},
get remoteDescription() {
@ -1116,8 +1143,7 @@ RTCPeerConnection.prototype = {
if (sdp.length == 0) {
return null;
}
return new this._win.RTCSessionDescription({ type: this._remoteType,
sdp: sdp });
return new this._win.RTCSessionDescription({ type: this._remoteType, sdp });
},
get peerIdentity() { return this._peerIdentity; },

View file

@ -222,7 +222,7 @@ public:
Dispatch();
}
const T& ReturnValue() const {
T ReturnValue() const {
if (mSuccess) {
return mSuccessValue;
} else {

View file

@ -86,8 +86,7 @@ function testMultipleFingerprints() {
fingerprintSdp(fingerprints.slice(1)) +
offer.sdp.slice(match.index);
var desc = new RTCSessionDescription({ type: 'offer', sdp: sdp });
return pcStrict.setRemoteDescription(desc);
return pcStrict.setRemoteDescription({ type: 'offer', sdp });
})
.then(() => {
ok(true, 'Modified fingerprints were accepted');

View file

@ -334,7 +334,7 @@ PeerConnectionTest.prototype.createOffer = function(peer) {
*
* @param {PeerConnectionWrapper} peer
The peer connection wrapper to run the command on
* @param {RTCSessionDescription} desc
* @param {RTCSessionDescriptionInit} desc
* Session description for the local description request
*/
PeerConnectionTest.prototype.setLocalDescription =
@ -403,7 +403,7 @@ PeerConnectionTest.prototype.setOfferOptions = function(options) {
*
* @param {PeerConnectionWrapper} peer
The peer connection wrapper to run the command on
* @param {RTCSessionDescription} desc
* @param {RTCSessionDescriptionInit} desc
* Session description for the remote description request
*/
PeerConnectionTest.prototype.setRemoteDescription =
@ -1064,7 +1064,7 @@ PeerConnectionWrapper.prototype = {
* Sets the local description and automatically handles the failure case.
*
* @param {object} desc
* RTCSessionDescription for the local description request
* RTCSessionDescriptionInit for the local description request
*/
setLocalDescription : function(desc) {
this.observedNegotiationNeeded = undefined;
@ -1078,7 +1078,7 @@ PeerConnectionWrapper.prototype = {
* causes the test case to fail if the call succeeds.
*
* @param {object} desc
* RTCSessionDescription for the local description request
* RTCSessionDescriptionInit for the local description request
* @returns {Promise}
* A promise that resolves to the expected error
*/
@ -1095,7 +1095,7 @@ PeerConnectionWrapper.prototype = {
* Sets the remote description and automatically handles the failure case.
*
* @param {object} desc
* RTCSessionDescription for the remote description request
* RTCSessionDescriptionInit for the remote description request
*/
setRemoteDescription : function(desc) {
this.observedNegotiationNeeded = undefined;
@ -1115,7 +1115,7 @@ PeerConnectionWrapper.prototype = {
* causes the test case to fail if the call succeeds.
*
* @param {object} desc
* RTCSessionDescription for the remote description request
* RTCSessionDescriptionInit for the remote description request
* @returns {Promise}
* a promise that resolve to the returned error
*/

View file

@ -118,7 +118,7 @@ var commandsPeerConnectionInitial = [
test.setupSignalingClient();
test.registerSignalingCallback("ice_candidate", function (message) {
var pc = test.pcRemote ? test.pcRemote : test.pcLocal;
pc.storeOrAddIceCandidate(new RTCIceCandidate(message.ice_candidate));
pc.storeOrAddIceCandidate(message.ice_candidate);
});
test.registerSignalingCallback("end_of_trickle_ice", function (message) {
test.signalingMessagesFinished();

View file

@ -19,9 +19,9 @@
test.chain.insertAfter("PC_LOCAL_SET_LOCAL_DESCRIPTION", [
function PC_LOCAL_ADD_CANDIDATE_EARLY(test) {
var candidate = new RTCIceCandidate(
{candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
sdpMLineIndex: 0});
var candidate = {
candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
sdpMLineIndex: 0};
return test.pcLocal._pc.addIceCandidate(candidate).then(
generateErrorCallback("addIceCandidate should have failed."),
err => {
@ -54,23 +54,23 @@
}
);
},
function PC_REMOTE_ADD_CANDIDATE_MISSING_INDEX(test) {
// Note: it is probably not a good idea to automatically fill a missing
// MLineIndex with a default value of zero, see bug 1157034
function PC_REMOTE_ADD_MISSING_MID_AND_MISSING_INDEX(test) {
var broken = new RTCIceCandidate(
{candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host"});
return test.pcRemote._pc.addIceCandidate(broken)
.then(
// FIXME this needs to be updated once bug 1157034 is fixed
todo(false, "Missing index in got automatically set to a valid value bz://1157034")
generateErrorCallback("addIceCandidate should have failed."),
err => {
is(err.name, "TypeError", "Error is TypeError");
}
);
},
function PC_REMOTE_ADD_VALID_CANDIDATE(test) {
var candidate = new RTCIceCandidate(
{candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
sdpMLineIndex: 0});
var candidate = {
candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
sdpMLineIndex: 0};
return test.pcRemote._pc.addIceCandidate(candidate)
.then(ok(true, "Successfully added valid ICE candidate"));
.then(() => ok(true, "Successfully added valid ICE candidate"));
},
// bug 1095793
function PC_REMOTE_ADD_MISMATCHED_MID_AND_LEVEL_CANDIDATE(test) {
@ -79,20 +79,23 @@
sdpMLineIndex: 0,
sdpMid: "sdparta_1"});
return test.pcRemote._pc.addIceCandidate(bogus)
.then(
generateErrorCallback("addIceCandidate should have failed."),
err => {
is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError");
}
);
.then(generateErrorCallback("addIceCandidate should have failed."),
err => is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError"));
},
function PC_REMOTE_ADD_MID_AND_MISSING_INDEX(test) {
var candidate = new RTCIceCandidate(
{candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
sdpMid: "sdparta_0"});
return test.pcRemote._pc.addIceCandidate(candidate)
.then(() => ok(true, "Successfully added valid ICE candidate"));
},
function PC_REMOTE_ADD_MATCHING_MID_AND_LEVEL_CANDIDATE(test) {
var candidate = new mozRTCIceCandidate(
var candidate = new RTCIceCandidate(
{candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
sdpMLineIndex: 0,
sdpMid: "sdparta_0"});
return test.pcRemote._pc.addIceCandidate(candidate)
.then(ok(true, "Successfully added valid ICE candidate with matching mid and level"));
.then(() => ok(true, "Successfully added valid ICE candidate with matching mid and level"));
}
]);
test.run();

View file

@ -21,12 +21,12 @@ function PC_REMOTE_SETUP_NULL_ICE_HANDLER(test) {
test.pcRemote.setupIceCandidateHandler(test, function() {}, function () {});
}
function PC_REMOTE_ADD_FAKE_ICE_CANDIDATE(test) {
var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0});
var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0};
test.pcRemote.storeOrAddIceCandidate(cand);
info(test.pcRemote + " Stored fake candidate: " + JSON.stringify(cand));
}
function PC_LOCAL_ADD_FAKE_ICE_CANDIDATE(test) {
var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0});
var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0};
test.pcLocal.storeOrAddIceCandidate(cand);
info(test.pcLocal + " Stored fake candidate: " + JSON.stringify(cand));
}

View file

@ -27,8 +27,7 @@
function testSetLocalDescriptionError() {
var pc = new RTCPeerConnection();
info ("Testing setLocalDescription error");
return pc.setLocalDescription(new RTCSessionDescription({ sdp: "Picklechips!",
type: "offer" }))
return pc.setLocalDescription({ sdp: "Picklechips!", type: "offer" })
.then(generateErrorCallback("setLocalDescription with nonsense SDP should fail"),
validateReason);
};
@ -36,8 +35,7 @@
function testSetRemoteDescriptionError() {
var pc = new RTCPeerConnection();
info ("Testing setRemoteDescription error");
return pc.setRemoteDescription(new RTCSessionDescription({ sdp: "Who?",
type: "offer" }))
return pc.setRemoteDescription({ sdp: "Who?", type: "offer" })
.then(generateErrorCallback("setRemoteDescription with nonsense SDP should fail"),
validateReason);
};

View file

@ -20,12 +20,12 @@ function PC_REMOTE_SETUP_NULL_ICE_HANDLER(test) {
test.pcRemote.setupIceCandidateHandler(test, function() {}, function () {});
}
function PC_REMOTE_ADD_FAKE_ICE_CANDIDATE(test) {
var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0});
var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0};
test.pcRemote.storeOrAddIceCandidate(cand);
info(test.pcRemote + " Stored fake candidate: " + JSON.stringify(cand));
}
function PC_LOCAL_ADD_FAKE_ICE_CANDIDATE(test) {
var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0});
var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0};
test.pcLocal.storeOrAddIceCandidate(cand);
info(test.pcLocal + " Stored fake candidate: " + JSON.stringify(cand));
}

View file

@ -37,10 +37,9 @@
},
function PC_REMOTE_ROLLBACK(test) {
return test.setLocalDescription(
test.pcRemote,
new RTCSessionDescription({ type: "rollback", sdp: ""}),
STABLE);
return test.setLocalDescription(test.pcRemote,
{ type: "rollback", sdp: "" },
STABLE);
},
// Rolling back should shut down gathering

View file

@ -23,10 +23,9 @@
},
function PC_REMOTE_ROLLBACK(test) {
return test.setLocalDescription(
test.pcRemote,
new RTCSessionDescription({ type: "rollback", sdp: ""}),
STABLE);
return test.setLocalDescription(test.pcRemote,
{ type: "rollback", sdp: "" },
STABLE);
},
// Rolling back should shut down gathering

View file

@ -35,10 +35,8 @@
},
function PC_REMOTE_ROLLBACK(test) {
return test.setRemoteDescription(
test.pcRemote,
new RTCSessionDescription({ type: "rollback" }),
STABLE)
return test.setRemoteDescription(test.pcRemote, { type: "rollback" },
STABLE)
.then(() => test.pcRemote.rollbackRemoteTracksIfNotNegotiated());
},

View file

@ -20,10 +20,8 @@
function PC_REMOTE_ROLLBACK(test) {
// We still haven't negotiated the tracks
test.pcRemote.expectNegotiationNeeded();
return test.setRemoteDescription(
test.pcRemote,
new RTCSessionDescription({ type: "rollback" }),
STABLE)
return test.setRemoteDescription(test.pcRemote, { type: "rollback" },
STABLE)
.then(() => test.pcRemote.rollbackRemoteTracksIfNotNegotiated());
},

View file

@ -51,10 +51,8 @@
},
function PC_REMOTE_ROLLBACK(test) {
return test.setRemoteDescription(
test.pcRemote,
new RTCSessionDescription({ type: "rollback" }),
STABLE);
return test.setRemoteDescription(test.pcRemote, { type: "rollback" },
STABLE);
},
function PC_LOCAL_ROLLBACK(test) {

View file

@ -42,11 +42,9 @@
test.pcLocal.iceCheckingIceRollbackExpected = true;
},
function PC_LOCAL_ROLLBACK(test) {
return test.setLocalDescription(
test.pcLocal,
new RTCSessionDescription({ type: "rollback",
sdp: ""}),
STABLE);
return test.setLocalDescription(test.pcLocal,
{ type: "rollback", sdp: ""},
STABLE);
},
// Rolling back should shut down gathering
function PC_LOCAL_WAIT_FOR_END_OF_TRICKLE(test) {

View file

@ -8,16 +8,16 @@
*/
dictionary RTCIceCandidateInit {
DOMString? candidate = null;
required DOMString candidate;
DOMString? sdpMid = null;
unsigned short sdpMLineIndex;
unsigned short? sdpMLineIndex = null;
};
[Pref="media.peerconnection.enabled",
JSImplementation="@mozilla.org/dom/rtcicecandidate;1",
Constructor(optional RTCIceCandidateInit candidateInitDict)]
Constructor(RTCIceCandidateInit candidateInitDict)]
interface RTCIceCandidate {
attribute DOMString? candidate;
attribute DOMString candidate;
attribute DOMString? sdpMid;
attribute unsigned short? sdpMLineIndex;

View file

@ -7,7 +7,7 @@
* http://w3c.github.io/webrtc-pc/#interface-definition
*/
callback RTCSessionDescriptionCallback = void (RTCSessionDescription sdp);
callback RTCSessionDescriptionCallback = void (RTCSessionDescriptionInit description);
callback RTCPeerConnectionErrorCallback = void (DOMError error);
callback RTCStatsCallback = void (RTCStatsReport report);
@ -84,14 +84,14 @@ interface RTCPeerConnection : EventTarget {
optional DOMString username);
[Pref="media.peerconnection.identity.enabled"]
Promise<DOMString> getIdentityAssertion();
Promise<RTCSessionDescription> createOffer (optional RTCOfferOptions options);
Promise<RTCSessionDescription> createAnswer (optional RTCAnswerOptions options);
Promise<void> setLocalDescription (RTCSessionDescription description);
Promise<void> setRemoteDescription (RTCSessionDescription description);
Promise<RTCSessionDescriptionInit> createOffer (optional RTCOfferOptions options);
Promise<RTCSessionDescriptionInit> createAnswer (optional RTCAnswerOptions options);
Promise<void> setLocalDescription (RTCSessionDescriptionInit description);
Promise<void> setRemoteDescription (RTCSessionDescriptionInit description);
readonly attribute RTCSessionDescription? localDescription;
readonly attribute RTCSessionDescription? remoteDescription;
readonly attribute RTCSignalingState signalingState;
Promise<void> addIceCandidate (RTCIceCandidate candidate);
Promise<void> addIceCandidate ((RTCIceCandidateInit or RTCIceCandidate)? candidate);
readonly attribute boolean? canTrickleIceCandidates;
readonly attribute RTCIceGatheringState iceGatheringState;
readonly attribute RTCIceConnectionState iceConnectionState;
@ -155,10 +155,10 @@ partial interface RTCPeerConnection {
optional RTCOfferOptions options);
Promise<void> createAnswer (RTCSessionDescriptionCallback successCallback,
RTCPeerConnectionErrorCallback failureCallback);
Promise<void> setLocalDescription (RTCSessionDescription description,
Promise<void> setLocalDescription (RTCSessionDescriptionInit description,
VoidFunction successCallback,
RTCPeerConnectionErrorCallback failureCallback);
Promise<void> setRemoteDescription (RTCSessionDescription description,
Promise<void> setRemoteDescription (RTCSessionDescriptionInit description,
VoidFunction successCallback,
RTCPeerConnectionErrorCallback failureCallback);
Promise<void> addIceCandidate (RTCIceCandidate candidate,

View file

@ -15,16 +15,17 @@ enum RTCSdpType {
};
dictionary RTCSessionDescriptionInit {
RTCSdpType? type = null;
DOMString? sdp = "";
required RTCSdpType type;
DOMString sdp = "";
};
[Pref="media.peerconnection.enabled",
JSImplementation="@mozilla.org/dom/rtcsessiondescription;1",
Constructor(optional RTCSessionDescriptionInit descriptionInitDict)]
interface RTCSessionDescription {
attribute RTCSdpType? type;
attribute DOMString? sdp;
// These should be readonly, but writing causes deprecation warnings for a bit
attribute RTCSdpType type;
attribute DOMString sdp;
jsonifier;
};

View file

@ -1202,7 +1202,7 @@ void MediaPipeline::PacketReceived(TransportLayer *layer,
}
class MediaPipelineTransmit::PipelineListener
: public DirectMediaStreamTrackListener
: public MediaStreamVideoSink
{
friend class MediaPipelineTransmit;
public:
@ -1290,15 +1290,17 @@ public:
void NotifyDirectListenerInstalled(InstallationResult aResult) override;
void NotifyDirectListenerUninstalled() override;
// Implement MediaStreamVideoSink
void SetCurrentFrames(const VideoSegment& aSegment) override;
void ClearFrames() override {}
private:
void UnsetTrackIdImpl() {
MutexAutoLock lock(mMutex);
track_id_ = track_id_external_ = TRACK_INVALID;
}
void NewData(MediaStreamGraph* graph,
StreamTime offset,
const MediaSegment& media);
void NewData(const MediaSegment& media, TrackRate aRate = 0);
RefPtr<MediaSessionConduit> conduit_;
RefPtr<AudioProxyThread> audio_processing_;
@ -1387,34 +1389,6 @@ protected:
};
#endif
class MediaPipelineTransmit::PipelineVideoSink :
public MediaStreamVideoSink
{
public:
explicit PipelineVideoSink(const RefPtr<MediaSessionConduit>& conduit,
MediaPipelineTransmit::PipelineListener* listener)
: conduit_(conduit)
, pipelineListener_(listener)
{
}
virtual void SetCurrentFrames(const VideoSegment& aSegment) override;
virtual void ClearFrames() override {}
private:
~PipelineVideoSink() {
// release conduit on mainthread. Must use forget()!
nsresult rv = NS_DispatchToMainThread(new
ConduitDeleteEvent(conduit_.forget()));
MOZ_ASSERT(!NS_FAILED(rv),"Could not dispatch conduit shutdown to main");
if (NS_FAILED(rv)) {
MOZ_CRASH();
}
}
RefPtr<MediaSessionConduit> conduit_;
MediaPipelineTransmit::PipelineListener* pipelineListener_;
};
MediaPipelineTransmit::MediaPipelineTransmit(
const std::string& pc,
nsCOMPtr<nsIEventTarget> main_thread,
@ -1429,7 +1403,6 @@ MediaPipelineTransmit::MediaPipelineTransmit(
MediaPipeline(pc, TRANSMIT, main_thread, sts_thread, track_id, level,
conduit, rtp_transport, rtcp_transport, filter),
listener_(new PipelineListener(conduit)),
video_sink_(new PipelineVideoSink(conduit, listener_)),
domtrack_(domtrack)
{
if (!IsVideo()) {
@ -1487,10 +1460,6 @@ void MediaPipelineTransmit::AttachToTrack(const std::string& track_id) {
domtrack_->AddDirectListener(listener_);
domtrack_->AddListener(listener_);
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
domtrack_->AddDirectListener(video_sink_);
#endif
#ifndef MOZILLA_INTERNAL_API
// this enables the unit tests that can't fiddle with principals and the like
listener_->SetEnabled(true);
@ -1539,7 +1508,6 @@ MediaPipelineTransmit::DetachMedia()
if (domtrack_) {
domtrack_->RemoveDirectListener(listener_);
domtrack_->RemoveListener(listener_);
domtrack_->RemoveDirectListener(video_sink_);
domtrack_ = nullptr;
}
// Let the listener be destroyed with the pipeline (or later).
@ -1742,7 +1710,14 @@ NotifyRealtimeTrackData(MediaStreamGraph* graph,
this << ", offset=" << offset <<
", duration=" << media.GetDuration());
NewData(graph, offset, media);
if (media.GetType() == MediaSegment::VIDEO) {
// We have to call the upstream NotifyRealtimeTrackData and
// MediaStreamVideoSink will route them to SetCurrentFrames.
MediaStreamVideoSink::NotifyRealtimeTrackData(graph, offset, media);
return;
}
NewData(media, graph->GraphRate());
}
void MediaPipelineTransmit::PipelineListener::
@ -1751,10 +1726,17 @@ NotifyQueuedChanges(MediaStreamGraph* graph,
const MediaSegment& queued_media) {
MOZ_MTLOG(ML_DEBUG, "MediaPipeline::NotifyQueuedChanges()");
// ignore non-direct data if we're also getting direct data
if (!direct_connect_) {
NewData(graph, offset, queued_media);
if (queued_media.GetType() == MediaSegment::VIDEO) {
// We always get video from SetCurrentFrames().
return;
}
if (direct_connect_) {
// ignore non-direct data if we're also getting direct data
return;
}
NewData(queued_media, graph->GraphRate());
}
void MediaPipelineTransmit::PipelineListener::
@ -1773,9 +1755,7 @@ NotifyDirectListenerUninstalled() {
}
void MediaPipelineTransmit::PipelineListener::
NewData(MediaStreamGraph* graph,
StreamTime offset,
const MediaSegment& media) {
NewData(const MediaSegment& media, TrackRate aRate /* = 0 */) {
if (!active_) {
MOZ_MTLOG(ML_DEBUG, "Discarding packets because transport not ready");
return;
@ -1793,49 +1773,27 @@ NewData(MediaStreamGraph* graph,
// track type and it's destined for us
// See bug 784517
if (media.GetType() == MediaSegment::AUDIO) {
AudioSegment* audio = const_cast<AudioSegment *>(
static_cast<const AudioSegment *>(&media));
MOZ_RELEASE_ASSERT(aRate > 0);
AudioSegment::ChunkIterator iter(*audio);
while(!iter.IsEnded()) {
TrackRate rate;
#ifdef USE_FAKE_MEDIA_STREAMS
rate = Fake_MediaStream::GraphRate();
#else
rate = graph->GraphRate();
#endif
audio_processing_->QueueAudioChunk(rate, *iter, enabled_);
iter.Next();
AudioSegment* audio = const_cast<AudioSegment *>(static_cast<const AudioSegment*>(&media));
for(AudioSegment::ChunkIterator iter(*audio); !iter.IsEnded(); iter.Next()) {
audio_processing_->QueueAudioChunk(aRate, *iter, enabled_);
}
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
} else {
// Ignore
VideoSegment* video = const_cast<VideoSegment *>(static_cast<const VideoSegment*>(&media));
VideoSegment::ChunkIterator iter(*video);
for(VideoSegment::ChunkIterator iter(*video); !iter.IsEnded(); iter.Next()) {
converter_->QueueVideoChunk(*iter, !enabled_);
}
#endif // MOZILLA_EXTERNAL_LINKAGE
}
}
void MediaPipelineTransmit::PipelineVideoSink::
void MediaPipelineTransmit::PipelineListener::
SetCurrentFrames(const VideoSegment& aSegment)
{
MOZ_ASSERT(pipelineListener_);
if (!pipelineListener_->active_) {
MOZ_MTLOG(ML_DEBUG, "Discarding packets because transport not ready");
return;
}
if (conduit_->type() != MediaSessionConduit::VIDEO) {
// Ignore data of wrong kind in case we have a muxed stream
return;
}
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
VideoSegment* video = const_cast<VideoSegment *>(&aSegment);
VideoSegment::ChunkIterator iter(*video);
while(!iter.IsEnded()) {
pipelineListener_->converter_->QueueVideoChunk(*iter, !pipelineListener_->enabled_);
iter.Next();
}
#endif
NewData(aSegment);
}
class TrackAddedCallback {

View file

@ -349,7 +349,6 @@ public:
// Separate classes to allow ref counting
class PipelineListener;
class VideoFrameFeeder;
class PipelineVideoSink;
protected:
~MediaPipelineTransmit();
@ -361,7 +360,6 @@ public:
RefPtr<VideoFrameFeeder> feeder_;
RefPtr<VideoFrameConverter> converter_;
#endif
RefPtr<PipelineVideoSink> video_sink_;
dom::MediaStreamTrack* domtrack_;
};

View file

@ -70,6 +70,7 @@ public:
gGraph = new MediaStreamGraph();
return gGraph;
}
uint32_t GraphRate() { return 16000; }
};
}
@ -186,8 +187,6 @@ class Fake_MediaStream {
public:
Fake_MediaStream () : mListeners(), mTrackListeners(), mMutex("Fake MediaStream") {}
static uint32_t GraphRate() { return 16000; }
void AddListener(Fake_MediaStreamListener *aListener) {
mozilla::MutexAutoLock lock(mMutex);
mListeners.insert(aListener);