Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
5fa0a04b
提交
5fa0a04b
authored
2月 09, 2018
作者:
Brian West
提交者:
Muteesa Fred
7月 24, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update adapter.js
上级
99d2e5e2
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
717 行增加
和
422 行删除
+717
-422
adapter-latest.js
html5/verto/js/src/vendor/adapter-latest.js
+717
-422
verto-min.js
html5/verto/video_demo-live_canvas/js/verto-min.js
+0
-0
verto-min.js
html5/verto/video_demo/js/verto-min.js
+0
-0
没有找到文件。
html5/verto/js/src/vendor/adapter-latest.js
浏览文件 @
5fa0a04b
...
...
@@ -25,9 +25,7 @@ function writeMediaSection(transceiver, caps, type, stream, dtlsRole) {
sdp
+=
'a=mid:'
+
transceiver
.
mid
+
'
\
r
\
n'
;
if
(
transceiver
.
direction
)
{
sdp
+=
'a='
+
transceiver
.
direction
+
'
\
r
\
n'
;
}
else
if
(
transceiver
.
rtpSender
&&
transceiver
.
rtpReceiver
)
{
if
(
transceiver
.
rtpSender
&&
transceiver
.
rtpReceiver
)
{
sdp
+=
'a=sendrecv
\
r
\
n'
;
}
else
if
(
transceiver
.
rtpSender
)
{
sdp
+=
'a=sendonly
\
r
\
n'
;
...
...
@@ -101,7 +99,6 @@ function filterIceServers(iceServers, edgeVersion) {
server
.
urls
=
isString
?
urls
[
0
]
:
urls
;
return
!!
urls
.
length
;
}
return
false
;
});
}
...
...
@@ -215,25 +212,51 @@ function maybeAddCandidate(iceTransport, candidate) {
return
!
alreadyAdded
;
}
// https://w3c.github.io/mediacapture-main/#mediastream
// Helper function to add the track to the stream and
// dispatch the event ourselves.
function
addTrackToStreamAndFireEvent
(
track
,
stream
)
{
stream
.
addTrack
(
track
);
var
e
=
new
Event
(
'addtrack'
);
// TODO: MediaStreamTrackEvent
e
.
track
=
track
;
stream
.
dispatchEvent
(
e
);
}
function
removeTrackFromStreamAndFireEvent
(
track
,
stream
)
{
stream
.
removeTrack
(
track
);
var
e
=
new
Event
(
'removetrack'
);
// TODO: MediaStreamTrackEvent
e
.
track
=
track
;
stream
.
dispatchEvent
(
e
);
}
function
fireAddTrack
(
pc
,
track
,
receiver
,
streams
)
{
var
trackEvent
=
new
Event
(
'track'
);
trackEvent
.
track
=
track
;
trackEvent
.
receiver
=
receiver
;
trackEvent
.
transceiver
=
{
receiver
:
receiver
};
trackEvent
.
streams
=
streams
;
window
.
setTimeout
(
function
()
{
pc
.
_dispatchEvent
(
'track'
,
trackEvent
);
});
}
function
makeError
(
name
,
description
)
{
var
e
=
new
Error
(
description
);
e
.
name
=
name
;
return
e
;
}
module
.
exports
=
function
(
window
,
edgeVersion
)
{
var
RTCPeerConnection
=
function
(
config
)
{
var
self
=
this
;
var
pc
=
this
;
var
_eventTarget
=
document
.
createDocumentFragment
();
[
'addEventListener'
,
'removeEventListener'
,
'dispatchEvent'
]
.
forEach
(
function
(
method
)
{
self
[
method
]
=
_eventTarget
[
method
].
bind
(
_eventTarget
);
pc
[
method
]
=
_eventTarget
[
method
].
bind
(
_eventTarget
);
});
this
.
onicecandidate
=
null
;
this
.
onaddstream
=
null
;
this
.
ontrack
=
null
;
this
.
onremovestream
=
null
;
this
.
onsignalingstatechange
=
null
;
this
.
oniceconnectionstatechange
=
null
;
this
.
onicegatheringstatechange
=
null
;
this
.
onnegotiationneeded
=
null
;
this
.
ondatachannel
=
null
;
this
.
canTrickleIceCandidates
=
null
;
this
.
needNegotiation
=
false
;
...
...
@@ -252,9 +275,8 @@ module.exports = function(window, edgeVersion) {
this
.
usingBundle
=
config
.
bundlePolicy
===
'max-bundle'
;
if
(
config
.
rtcpMuxPolicy
===
'negotiate'
)
{
var
e
=
new
Error
(
'rtcpMuxPolicy
\'
negotiate
\'
is not supported'
);
e
.
name
=
'NotSupportedError'
;
throw
(
e
);
throw
(
makeError
(
'NotSupportedError'
,
'rtcpMuxPolicy
\'
negotiate
\'
is not supported'
));
}
else
if
(
!
config
.
rtcpMuxPolicy
)
{
config
.
rtcpMuxPolicy
=
'require'
;
}
...
...
@@ -302,16 +324,36 @@ module.exports = function(window, edgeVersion) {
this
.
_sdpSessionVersion
=
0
;
this
.
_dtlsRole
=
undefined
;
// role for a=setup to use in answers.
this
.
_isClosed
=
false
;
};
RTCPeerConnection
.
prototype
.
_emitGatheringStateChange
=
function
()
{
var
event
=
new
Event
(
'icegatheringstatechange'
);
// set up event handlers on prototype
RTCPeerConnection
.
prototype
.
onicecandidate
=
null
;
RTCPeerConnection
.
prototype
.
onaddstream
=
null
;
RTCPeerConnection
.
prototype
.
ontrack
=
null
;
RTCPeerConnection
.
prototype
.
onremovestream
=
null
;
RTCPeerConnection
.
prototype
.
onsignalingstatechange
=
null
;
RTCPeerConnection
.
prototype
.
oniceconnectionstatechange
=
null
;
RTCPeerConnection
.
prototype
.
onicegatheringstatechange
=
null
;
RTCPeerConnection
.
prototype
.
onnegotiationneeded
=
null
;
RTCPeerConnection
.
prototype
.
ondatachannel
=
null
;
RTCPeerConnection
.
prototype
.
_dispatchEvent
=
function
(
name
,
event
)
{
if
(
this
.
_isClosed
)
{
return
;
}
this
.
dispatchEvent
(
event
);
if
(
typeof
this
.
onicegatheringstatechange
===
'function'
)
{
this
.
onicegatheringstatechange
(
event
);
if
(
typeof
this
[
'on'
+
name
]
===
'function'
)
{
this
[
'on'
+
name
]
(
event
);
}
};
RTCPeerConnection
.
prototype
.
_emitGatheringStateChange
=
function
()
{
var
event
=
new
Event
(
'icegatheringstatechange'
);
this
.
_dispatchEvent
(
'icegatheringstatechange'
,
event
);
};
RTCPeerConnection
.
prototype
.
getConfiguration
=
function
()
{
return
this
.
_config
;
};
...
...
@@ -342,6 +384,7 @@ module.exports = function(window, edgeVersion) {
sendEncodingParameters
:
null
,
recvEncodingParameters
:
null
,
stream
:
null
,
associatedRemoteMediaStreams
:
[],
wantReceive
:
true
};
if
(
this
.
usingBundle
&&
hasBundleTransport
)
{
...
...
@@ -357,6 +400,19 @@ module.exports = function(window, edgeVersion) {
};
RTCPeerConnection
.
prototype
.
addTrack
=
function
(
track
,
stream
)
{
var
alreadyExists
=
this
.
transceivers
.
find
(
function
(
s
)
{
return
s
.
track
===
track
;
});
if
(
alreadyExists
)
{
throw
makeError
(
'InvalidAccessError'
,
'Track already exists.'
);
}
if
(
this
.
signalingState
===
'closed'
)
{
throw
makeError
(
'InvalidStateError'
,
'Attempted to call addTrack on a closed peerconnection.'
);
}
var
transceiver
;
for
(
var
i
=
0
;
i
<
this
.
transceivers
.
length
;
i
++
)
{
if
(
!
this
.
transceivers
[
i
].
track
&&
...
...
@@ -382,10 +438,10 @@ module.exports = function(window, edgeVersion) {
};
RTCPeerConnection
.
prototype
.
addStream
=
function
(
stream
)
{
var
self
=
this
;
var
pc
=
this
;
if
(
edgeVersion
>=
15025
)
{
stream
.
getTracks
().
forEach
(
function
(
track
)
{
self
.
addTrack
(
track
,
stream
);
pc
.
addTrack
(
track
,
stream
);
});
}
else
{
// Clone is necessary for local demos mostly, attaching directly
...
...
@@ -399,17 +455,54 @@ module.exports = function(window, edgeVersion) {
});
});
clonedStream
.
getTracks
().
forEach
(
function
(
track
)
{
self
.
addTrack
(
track
,
clonedStream
);
pc
.
addTrack
(
track
,
clonedStream
);
});
}
};
RTCPeerConnection
.
prototype
.
removeStream
=
function
(
stream
)
{
var
idx
=
this
.
localStreams
.
indexOf
(
stream
);
if
(
idx
>
-
1
)
{
this
.
localStreams
.
splice
(
idx
,
1
);
this
.
_maybeFireNegotiationNeeded
();
RTCPeerConnection
.
prototype
.
removeTrack
=
function
(
sender
)
{
if
(
!
(
sender
instanceof
window
.
RTCRtpSender
))
{
throw
new
TypeError
(
'Argument 1 of RTCPeerConnection.removeTrack '
+
'does not implement interface RTCRtpSender.'
);
}
var
transceiver
=
this
.
transceivers
.
find
(
function
(
t
)
{
return
t
.
rtpSender
===
sender
;
});
if
(
!
transceiver
)
{
throw
makeError
(
'InvalidAccessError'
,
'Sender was not created by this connection.'
);
}
var
stream
=
transceiver
.
stream
;
transceiver
.
rtpSender
.
stop
();
transceiver
.
rtpSender
=
null
;
transceiver
.
track
=
null
;
transceiver
.
stream
=
null
;
// remove the stream from the set of local streams
var
localStreams
=
this
.
transceivers
.
map
(
function
(
t
)
{
return
t
.
stream
;
});
if
(
localStreams
.
indexOf
(
stream
)
===
-
1
&&
this
.
localStreams
.
indexOf
(
stream
)
>
-
1
)
{
this
.
localStreams
.
splice
(
this
.
localStreams
.
indexOf
(
stream
),
1
);
}
this
.
_maybeFireNegotiationNeeded
();
};
RTCPeerConnection
.
prototype
.
removeStream
=
function
(
stream
)
{
var
pc
=
this
;
stream
.
getTracks
().
forEach
(
function
(
track
)
{
var
sender
=
pc
.
getSenders
().
find
(
function
(
s
)
{
return
s
.
track
===
track
;
});
if
(
sender
)
{
pc
.
removeTrack
(
sender
);
}
});
};
RTCPeerConnection
.
prototype
.
getSenders
=
function
()
{
...
...
@@ -433,7 +526,7 @@ module.exports = function(window, edgeVersion) {
RTCPeerConnection
.
prototype
.
_createIceGatherer
=
function
(
sdpMLineIndex
,
usingBundle
)
{
var
self
=
this
;
var
pc
=
this
;
if
(
usingBundle
&&
sdpMLineIndex
>
0
)
{
return
this
.
transceivers
[
0
].
iceGatherer
;
}
else
if
(
this
.
_iceGatherers
.
length
)
{
...
...
@@ -453,8 +546,8 @@ module.exports = function(window, edgeVersion) {
// polyfill since RTCIceGatherer.state is not implemented in
// Edge 10547 yet.
iceGatherer
.
state
=
end
?
'completed'
:
'gathering'
;
if
(
self
.
transceivers
[
sdpMLineIndex
].
candidates
!==
null
)
{
self
.
transceivers
[
sdpMLineIndex
].
candidates
.
push
(
event
.
candidate
);
if
(
pc
.
transceivers
[
sdpMLineIndex
].
candidates
!==
null
)
{
pc
.
transceivers
[
sdpMLineIndex
].
candidates
.
push
(
event
.
candidate
);
}
};
iceGatherer
.
addEventListener
(
'localcandidate'
,
...
...
@@ -464,7 +557,7 @@ module.exports = function(window, edgeVersion) {
// start gathering from an RTCIceGatherer.
RTCPeerConnection
.
prototype
.
_gather
=
function
(
mid
,
sdpMLineIndex
)
{
var
self
=
this
;
var
pc
=
this
;
var
iceGatherer
=
this
.
transceivers
[
sdpMLineIndex
].
iceGatherer
;
if
(
iceGatherer
.
onlocalcandidate
)
{
return
;
...
...
@@ -474,7 +567,7 @@ module.exports = function(window, edgeVersion) {
iceGatherer
.
removeEventListener
(
'localcandidate'
,
this
.
transceivers
[
sdpMLineIndex
].
bufferCandidates
);
iceGatherer
.
onlocalcandidate
=
function
(
evt
)
{
if
(
self
.
usingBundle
&&
sdpMLineIndex
>
0
)
{
if
(
pc
.
usingBundle
&&
sdpMLineIndex
>
0
)
{
// if we know that we use bundle we can drop candidates with
// ѕdpMLineIndex > 0. If we don't do this then our state gets
// confused since we dispose the extra ice gatherer.
...
...
@@ -502,7 +595,7 @@ module.exports = function(window, edgeVersion) {
}
// update local description.
var
sections
=
SDPUtils
.
splitSections
(
self
.
localDescription
.
sdp
);
var
sections
=
SDPUtils
.
splitSections
(
pc
.
localDescription
.
sdp
);
if
(
!
end
)
{
sections
[
event
.
candidate
.
sdpMLineIndex
+
1
]
+=
'a='
+
event
.
candidate
.
candidate
+
'
\
r
\
n'
;
...
...
@@ -510,32 +603,26 @@ module.exports = function(window, edgeVersion) {
sections
[
event
.
candidate
.
sdpMLineIndex
+
1
]
+=
'a=end-of-candidates
\
r
\
n'
;
}
self
.
localDescription
.
sdp
=
sections
.
join
(
''
);
var
complete
=
self
.
transceivers
.
every
(
function
(
transceiver
)
{
pc
.
localDescription
.
sdp
=
sections
.
join
(
''
);
var
complete
=
pc
.
transceivers
.
every
(
function
(
transceiver
)
{
return
transceiver
.
iceGatherer
&&
transceiver
.
iceGatherer
.
state
===
'completed'
;
});
if
(
self
.
iceGatheringState
!==
'gathering'
)
{
self
.
iceGatheringState
=
'gathering'
;
self
.
_emitGatheringStateChange
();
if
(
pc
.
iceGatheringState
!==
'gathering'
)
{
pc
.
iceGatheringState
=
'gathering'
;
pc
.
_emitGatheringStateChange
();
}
// Emit candidate. Also emit null candidate when all gatherers are
// complete.
if
(
!
end
)
{
self
.
dispatchEvent
(
event
);
if
(
typeof
self
.
onicecandidate
===
'function'
)
{
self
.
onicecandidate
(
event
);
}
pc
.
_dispatchEvent
(
'icecandidate'
,
event
);
}
if
(
complete
)
{
self
.
dispatchEvent
(
new
Event
(
'icecandidate'
));
if
(
typeof
self
.
onicecandidate
===
'function'
)
{
self
.
onicecandidate
(
new
Event
(
'icecandidate'
));
}
self
.
iceGatheringState
=
'complete'
;
self
.
_emitGatheringStateChange
();
pc
.
_dispatchEvent
(
'icecandidate'
,
new
Event
(
'icecandidate'
));
pc
.
iceGatheringState
=
'complete'
;
pc
.
_emitGatheringStateChange
();
}
};
...
...
@@ -551,21 +638,21 @@ module.exports = function(window, edgeVersion) {
// Create ICE transport and DTLS transport.
RTCPeerConnection
.
prototype
.
_createIceAndDtlsTransports
=
function
()
{
var
self
=
this
;
var
pc
=
this
;
var
iceTransport
=
new
window
.
RTCIceTransport
(
null
);
iceTransport
.
onicestatechange
=
function
()
{
self
.
_updateConnectionState
();
pc
.
_updateConnectionState
();
};
var
dtlsTransport
=
new
window
.
RTCDtlsTransport
(
iceTransport
);
dtlsTransport
.
ondtlsstatechange
=
function
()
{
self
.
_updateConnectionState
();
pc
.
_updateConnectionState
();
};
dtlsTransport
.
onerror
=
function
()
{
// onerror does not set state to failed by it
self
.
// onerror does not set state to failed by it
pc
.
Object
.
defineProperty
(
dtlsTransport
,
'state'
,
{
value
:
'failed'
,
writable
:
true
});
self
.
_updateConnectionState
();
pc
.
_updateConnectionState
();
};
return
{
...
...
@@ -621,11 +708,15 @@ module.exports = function(window, edgeVersion) {
delete
p
.
rtx
;
});
}
params
.
encodings
=
transceiver
.
recvEncodingParameters
;
if
(
transceiver
.
recvEncodingParameters
.
length
)
{
params
.
encodings
=
transceiver
.
recvEncodingParameters
;
}
params
.
rtcp
=
{
cname
:
transceiver
.
rtcpParameters
.
cname
,
compound
:
transceiver
.
rtcpParameters
.
compound
};
if
(
transceiver
.
rtcpParameters
.
cname
)
{
params
.
rtcp
.
cname
=
transceiver
.
rtcpParameters
.
cname
;
}
if
(
transceiver
.
sendEncodingParameters
.
length
)
{
params
.
rtcp
.
ssrc
=
transceiver
.
sendEncodingParameters
[
0
].
ssrc
;
}
...
...
@@ -634,20 +725,13 @@ module.exports = function(window, edgeVersion) {
};
RTCPeerConnection
.
prototype
.
setLocalDescription
=
function
(
description
)
{
var
self
=
this
;
var
args
=
arguments
;
var
pc
=
this
;
if
(
!
isActionAllowedInSignalingState
(
'setLocalDescription'
,
description
.
type
,
this
.
signalingState
))
{
return
new
Promise
(
function
(
resolve
,
reject
)
{
var
e
=
new
Error
(
'Can not set local '
+
description
.
type
+
' in state '
+
self
.
signalingState
);
e
.
name
=
'InvalidStateError'
;
if
(
args
.
length
>
2
&&
typeof
args
[
2
]
===
'function'
)
{
args
[
2
].
apply
(
null
,
[
e
]);
}
reject
(
e
);
});
description
.
type
,
this
.
signalingState
)
||
this
.
_isClosed
)
{
return
Promise
.
reject
(
makeError
(
'InvalidStateError'
,
'Can not set local '
+
description
.
type
+
' in state '
+
pc
.
signalingState
));
}
var
sections
;
...
...
@@ -659,19 +743,19 @@ module.exports = function(window, edgeVersion) {
sessionpart
=
sections
.
shift
();
sections
.
forEach
(
function
(
mediaSection
,
sdpMLineIndex
)
{
var
caps
=
SDPUtils
.
parseRtpParameters
(
mediaSection
);
self
.
transceivers
[
sdpMLineIndex
].
localCapabilities
=
caps
;
pc
.
transceivers
[
sdpMLineIndex
].
localCapabilities
=
caps
;
});
this
.
transceivers
.
forEach
(
function
(
transceiver
,
sdpMLineIndex
)
{
self
.
_gather
(
transceiver
.
mid
,
sdpMLineIndex
);
pc
.
_gather
(
transceiver
.
mid
,
sdpMLineIndex
);
});
}
else
if
(
description
.
type
===
'answer'
)
{
sections
=
SDPUtils
.
splitSections
(
self
.
remoteDescription
.
sdp
);
sections
=
SDPUtils
.
splitSections
(
pc
.
remoteDescription
.
sdp
);
sessionpart
=
sections
.
shift
();
var
isIceLite
=
SDPUtils
.
matchPrefix
(
sessionpart
,
'a=ice-lite'
).
length
>
0
;
sections
.
forEach
(
function
(
mediaSection
,
sdpMLineIndex
)
{
var
transceiver
=
self
.
transceivers
[
sdpMLineIndex
];
var
transceiver
=
pc
.
transceivers
[
sdpMLineIndex
];
var
iceGatherer
=
transceiver
.
iceGatherer
;
var
iceTransport
=
transceiver
.
iceTransport
;
var
dtlsTransport
=
transceiver
.
dtlsTransport
;
...
...
@@ -680,7 +764,7 @@ module.exports = function(window, edgeVersion) {
// treat bundle-only as not-rejected.
var
rejected
=
SDPUtils
.
isRejected
(
mediaSection
)
&&
!
SDPUtils
.
matchPrefix
(
mediaSection
,
'a=bundle-only'
).
length
===
1
;
SDPUtils
.
matchPrefix
(
mediaSection
,
'a=bundle-only'
).
length
===
0
;
if
(
!
rejected
&&
!
transceiver
.
isDatachannel
)
{
var
remoteIceParameters
=
SDPUtils
.
getIceParameters
(
...
...
@@ -691,8 +775,8 @@ module.exports = function(window, edgeVersion) {
remoteDtlsParameters
.
role
=
'server'
;
}
if
(
!
self
.
usingBundle
||
sdpMLineIndex
===
0
)
{
self
.
_gather
(
transceiver
.
mid
,
sdpMLineIndex
);
if
(
!
pc
.
usingBundle
||
sdpMLineIndex
===
0
)
{
pc
.
_gather
(
transceiver
.
mid
,
sdpMLineIndex
);
if
(
iceTransport
.
state
===
'new'
)
{
iceTransport
.
start
(
iceGatherer
,
remoteIceParameters
,
isIceLite
?
'controlling'
:
'controlled'
);
...
...
@@ -708,7 +792,7 @@ module.exports = function(window, edgeVersion) {
// Start the RTCRtpSender. The RTCRtpReceiver for this
// transceiver has already been started in setRemoteDescription.
self
.
_transceive
(
transceiver
,
pc
.
_transceive
(
transceiver
,
params
.
codecs
.
length
>
0
,
false
);
}
...
...
@@ -731,34 +815,17 @@ module.exports = function(window, edgeVersion) {
'"'
);
}
// If a success callback was provided, emit ICE candidates after it
// has been executed. Otherwise, emit callback after the Promise is
// resolved.
var
cb
=
arguments
.
length
>
1
&&
typeof
arguments
[
1
]
===
'function'
&&
arguments
[
1
];
return
new
Promise
(
function
(
resolve
)
{
if
(
cb
)
{
cb
.
apply
(
null
);
}
resolve
();
});
return
Promise
.
resolve
();
};
RTCPeerConnection
.
prototype
.
setRemoteDescription
=
function
(
description
)
{
var
self
=
this
;
var
args
=
arguments
;
var
pc
=
this
;
if
(
!
isActionAllowedInSignalingState
(
'setRemoteDescription'
,
description
.
type
,
this
.
signalingState
))
{
return
new
Promise
(
function
(
resolve
,
reject
)
{
var
e
=
new
Error
(
'Can not set remote '
+
description
.
type
+
' in state '
+
self
.
signalingState
);
e
.
name
=
'InvalidStateError'
;
if
(
args
.
length
>
2
&&
typeof
args
[
2
]
===
'function'
)
{
args
[
2
].
apply
(
null
,
[
e
]);
}
reject
(
e
);
});
description
.
type
,
this
.
signalingState
)
||
this
.
_isClosed
)
{
return
Promise
.
reject
(
makeError
(
'InvalidStateError'
,
'Can not set remote '
+
description
.
type
+
' in state '
+
pc
.
signalingState
));
}
var
streams
=
{};
...
...
@@ -787,7 +854,7 @@ module.exports = function(window, edgeVersion) {
var
kind
=
SDPUtils
.
getKind
(
mediaSection
);
// treat bundle-only as not-rejected.
var
rejected
=
SDPUtils
.
isRejected
(
mediaSection
)
&&
!
SDPUtils
.
matchPrefix
(
mediaSection
,
'a=bundle-only'
).
length
===
1
;
SDPUtils
.
matchPrefix
(
mediaSection
,
'a=bundle-only'
).
length
===
0
;
var
protocol
=
lines
[
0
].
substr
(
2
).
split
(
' '
)[
2
];
var
direction
=
SDPUtils
.
getDirection
(
mediaSection
,
sessionpart
);
...
...
@@ -797,7 +864,7 @@ module.exports = function(window, edgeVersion) {
// Reject datachannels which are not implemented yet.
if
(
kind
===
'application'
&&
protocol
===
'DTLS/SCTP'
)
{
self
.
transceivers
[
sdpMLineIndex
]
=
{
pc
.
transceivers
[
sdpMLineIndex
]
=
{
mid
:
mid
,
isDatachannel
:
true
};
...
...
@@ -843,30 +910,30 @@ module.exports = function(window, edgeVersion) {
// Check if we can use BUNDLE and dispose transports.
if
((
description
.
type
===
'offer'
||
description
.
type
===
'answer'
)
&&
!
rejected
&&
usingBundle
&&
sdpMLineIndex
>
0
&&
self
.
transceivers
[
sdpMLineIndex
])
{
self
.
_disposeIceAndDtlsTransports
(
sdpMLineIndex
);
self
.
transceivers
[
sdpMLineIndex
].
iceGatherer
=
self
.
transceivers
[
0
].
iceGatherer
;
self
.
transceivers
[
sdpMLineIndex
].
iceTransport
=
self
.
transceivers
[
0
].
iceTransport
;
self
.
transceivers
[
sdpMLineIndex
].
dtlsTransport
=
self
.
transceivers
[
0
].
dtlsTransport
;
if
(
self
.
transceivers
[
sdpMLineIndex
].
rtpSender
)
{
self
.
transceivers
[
sdpMLineIndex
].
rtpSender
.
setTransport
(
self
.
transceivers
[
0
].
dtlsTransport
);
pc
.
transceivers
[
sdpMLineIndex
])
{
pc
.
_disposeIceAndDtlsTransports
(
sdpMLineIndex
);
pc
.
transceivers
[
sdpMLineIndex
].
iceGatherer
=
pc
.
transceivers
[
0
].
iceGatherer
;
pc
.
transceivers
[
sdpMLineIndex
].
iceTransport
=
pc
.
transceivers
[
0
].
iceTransport
;
pc
.
transceivers
[
sdpMLineIndex
].
dtlsTransport
=
pc
.
transceivers
[
0
].
dtlsTransport
;
if
(
pc
.
transceivers
[
sdpMLineIndex
].
rtpSender
)
{
pc
.
transceivers
[
sdpMLineIndex
].
rtpSender
.
setTransport
(
pc
.
transceivers
[
0
].
dtlsTransport
);
}
if
(
self
.
transceivers
[
sdpMLineIndex
].
rtpReceiver
)
{
self
.
transceivers
[
sdpMLineIndex
].
rtpReceiver
.
setTransport
(
self
.
transceivers
[
0
].
dtlsTransport
);
if
(
pc
.
transceivers
[
sdpMLineIndex
].
rtpReceiver
)
{
pc
.
transceivers
[
sdpMLineIndex
].
rtpReceiver
.
setTransport
(
pc
.
transceivers
[
0
].
dtlsTransport
);
}
}
if
(
description
.
type
===
'offer'
&&
!
rejected
)
{
transceiver
=
self
.
transceivers
[
sdpMLineIndex
]
||
self
.
_createTransceiver
(
kind
);
transceiver
=
pc
.
transceivers
[
sdpMLineIndex
]
||
pc
.
_createTransceiver
(
kind
);
transceiver
.
mid
=
mid
;
if
(
!
transceiver
.
iceGatherer
)
{
transceiver
.
iceGatherer
=
self
.
_createIceGatherer
(
sdpMLineIndex
,
transceiver
.
iceGatherer
=
pc
.
_createIceGatherer
(
sdpMLineIndex
,
usingBundle
);
}
...
...
@@ -895,6 +962,7 @@ module.exports = function(window, edgeVersion) {
ssrc
:
(
2
*
sdpMLineIndex
+
2
)
*
1001
}];
// TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams
var
isNewTrack
=
false
;
if
(
direction
===
'sendrecv'
||
direction
===
'sendonly'
)
{
isNewTrack
=
!
transceiver
.
rtpReceiver
;
...
...
@@ -905,7 +973,9 @@ module.exports = function(window, edgeVersion) {
var
stream
;
track
=
rtpReceiver
.
track
;
// FIXME: does not work with Plan B.
if
(
remoteMsid
)
{
if
(
remoteMsid
&&
remoteMsid
.
stream
===
'-'
)
{
// no-op. a stream id of '-' means: no associated stream.
}
else
if
(
remoteMsid
)
{
if
(
!
streams
[
remoteMsid
.
stream
])
{
streams
[
remoteMsid
.
stream
]
=
new
window
.
MediaStream
();
Object
.
defineProperty
(
streams
[
remoteMsid
.
stream
],
'id'
,
{
...
...
@@ -926,9 +996,22 @@ module.exports = function(window, edgeVersion) {
}
stream
=
streams
.
default
;
}
stream
.
addTrack
(
track
);
if
(
stream
)
{
addTrackToStreamAndFireEvent
(
track
,
stream
);
transceiver
.
associatedRemoteMediaStreams
.
push
(
stream
);
}
receiverList
.
push
([
track
,
rtpReceiver
,
stream
]);
}
}
else
if
(
transceiver
.
rtpReceiver
&&
transceiver
.
rtpReceiver
.
track
)
{
transceiver
.
associatedRemoteMediaStreams
.
forEach
(
function
(
s
)
{
var
nativeTrack
=
s
.
getTracks
().
find
(
function
(
t
)
{
return
t
.
id
===
transceiver
.
rtpReceiver
.
track
.
id
;
});
if
(
nativeTrack
)
{
removeTrackFromStreamAndFireEvent
(
nativeTrack
,
s
);
}
});
transceiver
.
associatedRemoteMediaStreams
=
[];
}
transceiver
.
localCapabilities
=
localCapabilities
;
...
...
@@ -940,11 +1023,11 @@ module.exports = function(window, edgeVersion) {
// Start the RTCRtpReceiver now. The RTPSender is started in
// setLocalDescription.
self
.
_transceive
(
self
.
transceivers
[
sdpMLineIndex
],
pc
.
_transceive
(
pc
.
transceivers
[
sdpMLineIndex
],
false
,
isNewTrack
);
}
else
if
(
description
.
type
===
'answer'
&&
!
rejected
)
{
transceiver
=
self
.
transceivers
[
sdpMLineIndex
];
transceiver
=
pc
.
transceivers
[
sdpMLineIndex
];
iceGatherer
=
transceiver
.
iceGatherer
;
iceTransport
=
transceiver
.
iceTransport
;
dtlsTransport
=
transceiver
.
dtlsTransport
;
...
...
@@ -952,11 +1035,11 @@ module.exports = function(window, edgeVersion) {
sendEncodingParameters
=
transceiver
.
sendEncodingParameters
;
localCapabilities
=
transceiver
.
localCapabilities
;
self
.
transceivers
[
sdpMLineIndex
].
recvEncodingParameters
=
pc
.
transceivers
[
sdpMLineIndex
].
recvEncodingParameters
=
recvEncodingParameters
;
self
.
transceivers
[
sdpMLineIndex
].
remoteCapabilities
=
pc
.
transceivers
[
sdpMLineIndex
].
remoteCapabilities
=
remoteCapabilities
;
self
.
transceivers
[
sdpMLineIndex
].
rtcpParameters
=
rtcpParameters
;
pc
.
transceivers
[
sdpMLineIndex
].
rtcpParameters
=
rtcpParameters
;
if
(
cands
.
length
&&
iceTransport
.
state
===
'new'
)
{
if
((
isIceLite
||
isComplete
)
&&
...
...
@@ -979,10 +1062,11 @@ module.exports = function(window, edgeVersion) {
}
}
self
.
_transceive
(
transceiver
,
pc
.
_transceive
(
transceiver
,
direction
===
'sendrecv'
||
direction
===
'recvonly'
,
direction
===
'sendrecv'
||
direction
===
'sendonly'
);
// TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams
if
(
rtpReceiver
&&
(
direction
===
'sendrecv'
||
direction
===
'sendonly'
))
{
track
=
rtpReceiver
.
track
;
...
...
@@ -990,13 +1074,13 @@ module.exports = function(window, edgeVersion) {
if
(
!
streams
[
remoteMsid
.
stream
])
{
streams
[
remoteMsid
.
stream
]
=
new
window
.
MediaStream
();
}
streams
[
remoteMsid
.
stream
].
addTrack
(
track
);
addTrackToStreamAndFireEvent
(
track
,
streams
[
remoteMsid
.
stream
]
);
receiverList
.
push
([
track
,
rtpReceiver
,
streams
[
remoteMsid
.
stream
]]);
}
else
{
if
(
!
streams
.
default
)
{
streams
.
default
=
new
window
.
MediaStream
();
}
streams
.
default
.
addTrack
(
track
);
addTrackToStreamAndFireEvent
(
track
,
streams
.
default
);
receiverList
.
push
([
track
,
rtpReceiver
,
streams
.
default
]);
}
}
else
{
...
...
@@ -1028,15 +1112,12 @@ module.exports = function(window, edgeVersion) {
Object
.
keys
(
streams
).
forEach
(
function
(
sid
)
{
var
stream
=
streams
[
sid
];
if
(
stream
.
getTracks
().
length
)
{
if
(
self
.
remoteStreams
.
indexOf
(
stream
)
===
-
1
)
{
self
.
remoteStreams
.
push
(
stream
);
if
(
pc
.
remoteStreams
.
indexOf
(
stream
)
===
-
1
)
{
pc
.
remoteStreams
.
push
(
stream
);
var
event
=
new
Event
(
'addstream'
);
event
.
stream
=
stream
;
window
.
setTimeout
(
function
()
{
self
.
dispatchEvent
(
event
);
if
(
typeof
self
.
onaddstream
===
'function'
)
{
self
.
onaddstream
(
event
);
}
pc
.
_dispatchEvent
(
'addstream'
,
event
);
});
}
...
...
@@ -1046,28 +1127,24 @@ module.exports = function(window, edgeVersion) {
if
(
stream
.
id
!==
item
[
2
].
id
)
{
return
;
}
var
trackEvent
=
new
Event
(
'track'
);
trackEvent
.
track
=
track
;
trackEvent
.
receiver
=
receiver
;
trackEvent
.
transceiver
=
{
receiver
:
receiver
};
trackEvent
.
streams
=
[
stream
];
window
.
setTimeout
(
function
()
{
self
.
dispatchEvent
(
trackEvent
);
if
(
typeof
self
.
ontrack
===
'function'
)
{
self
.
ontrack
(
trackEvent
);
}
});
fireAddTrack
(
pc
,
track
,
receiver
,
[
stream
]);
});
}
});
receiverList
.
forEach
(
function
(
item
)
{
if
(
item
[
2
])
{
return
;
}
fireAddTrack
(
pc
,
item
[
0
],
item
[
1
],
[]);
});
// check whether addIceCandidate({}) was called within four seconds after
// setRemoteDescription.
window
.
setTimeout
(
function
()
{
if
(
!
(
self
&&
self
.
transceivers
))
{
if
(
!
(
pc
&&
pc
.
transceivers
))
{
return
;
}
self
.
transceivers
.
forEach
(
function
(
transceiver
)
{
pc
.
transceivers
.
forEach
(
function
(
transceiver
)
{
if
(
transceiver
.
iceTransport
&&
transceiver
.
iceTransport
.
state
===
'new'
&&
transceiver
.
iceTransport
.
getRemoteCandidates
().
length
>
0
)
{
...
...
@@ -1078,12 +1155,7 @@ module.exports = function(window, edgeVersion) {
});
},
4000
);
return
new
Promise
(
function
(
resolve
)
{
if
(
args
.
length
>
1
&&
typeof
args
[
1
]
===
'function'
)
{
args
[
1
].
apply
(
null
);
}
resolve
();
});
return
Promise
.
resolve
();
};
RTCPeerConnection
.
prototype
.
close
=
function
()
{
...
...
@@ -1107,6 +1179,7 @@ module.exports = function(window, edgeVersion) {
}
});
// FIXME: clean up tracks, local streams, remote streams, etc
this
.
_isClosed
=
true
;
this
.
_updateSignalingState
(
'closed'
);
};
...
...
@@ -1114,29 +1187,23 @@ module.exports = function(window, edgeVersion) {
RTCPeerConnection
.
prototype
.
_updateSignalingState
=
function
(
newState
)
{
this
.
signalingState
=
newState
;
var
event
=
new
Event
(
'signalingstatechange'
);
this
.
dispatchEvent
(
event
);
if
(
typeof
this
.
onsignalingstatechange
===
'function'
)
{
this
.
onsignalingstatechange
(
event
);
}
this
.
_dispatchEvent
(
'signalingstatechange'
,
event
);
};
// Determine whether to fire the negotiationneeded event.
RTCPeerConnection
.
prototype
.
_maybeFireNegotiationNeeded
=
function
()
{
var
self
=
this
;
var
pc
=
this
;
if
(
this
.
signalingState
!==
'stable'
||
this
.
needNegotiation
===
true
)
{
return
;
}
this
.
needNegotiation
=
true
;
window
.
setTimeout
(
function
()
{
if
(
self
.
needNegotiation
===
false
)
{
if
(
pc
.
needNegotiation
===
false
)
{
return
;
}
self
.
needNegotiation
=
false
;
pc
.
needNegotiation
=
false
;
var
event
=
new
Event
(
'negotiationneeded'
);
self
.
dispatchEvent
(
event
);
if
(
typeof
self
.
onnegotiationneeded
===
'function'
)
{
self
.
onnegotiationneeded
(
event
);
}
pc
.
_dispatchEvent
(
'negotiationneeded'
,
event
);
},
0
);
};
...
...
@@ -1176,22 +1243,16 @@ module.exports = function(window, edgeVersion) {
if
(
newState
!==
this
.
iceConnectionState
)
{
this
.
iceConnectionState
=
newState
;
var
event
=
new
Event
(
'iceconnectionstatechange'
);
this
.
dispatchEvent
(
event
);
if
(
typeof
this
.
oniceconnectionstatechange
===
'function'
)
{
this
.
oniceconnectionstatechange
(
event
);
}
this
.
_dispatchEvent
(
'iceconnectionstatechange'
,
event
);
}
};
RTCPeerConnection
.
prototype
.
createOffer
=
function
()
{
var
self
=
this
;
var
args
=
arguments
;
var
offerOptions
;
if
(
arguments
.
length
===
1
&&
typeof
arguments
[
0
]
!==
'function'
)
{
offerOptions
=
arguments
[
0
];
}
else
if
(
arguments
.
length
===
3
)
{
offerOptions
=
arguments
[
2
];
var
pc
=
this
;
if
(
this
.
_isClosed
)
{
return
Promise
.
reject
(
makeError
(
'InvalidStateError'
,
'Can not call createOffer after close'
));
}
var
numAudioTracks
=
this
.
transceivers
.
filter
(
function
(
t
)
{
...
...
@@ -1202,6 +1263,7 @@ module.exports = function(window, edgeVersion) {
}).
length
;
// Determine number of audio and video tracks we need to send/recv.
var
offerOptions
=
arguments
[
0
];
if
(
offerOptions
)
{
// Reject Chrome legacy constraints.
if
(
offerOptions
.
mandatory
||
offerOptions
.
optional
)
{
...
...
@@ -1265,8 +1327,8 @@ module.exports = function(window, edgeVersion) {
transceiver
.
mid
=
mid
;
if
(
!
transceiver
.
iceGatherer
)
{
transceiver
.
iceGatherer
=
self
.
_createIceGatherer
(
sdpMLineIndex
,
self
.
usingBundle
);
transceiver
.
iceGatherer
=
pc
.
_createIceGatherer
(
sdpMLineIndex
,
pc
.
usingBundle
);
}
var
localCapabilities
=
window
.
RTCRtpSender
.
getCapabilities
(
kind
);
...
...
@@ -1320,11 +1382,11 @@ module.exports = function(window, edgeVersion) {
this
.
transceivers
.
forEach
(
function
(
transceiver
,
sdpMLineIndex
)
{
sdp
+=
writeMediaSection
(
transceiver
,
transceiver
.
localCapabilities
,
'offer'
,
transceiver
.
stream
,
self
.
_dtlsRole
);
'offer'
,
transceiver
.
stream
,
pc
.
_dtlsRole
);
sdp
+=
'a=rtcp-rsize
\
r
\
n'
;
if
(
transceiver
.
iceGatherer
&&
self
.
iceGatheringState
!==
'new'
&&
(
sdpMLineIndex
===
0
||
!
self
.
usingBundle
))
{
if
(
transceiver
.
iceGatherer
&&
pc
.
iceGatheringState
!==
'new'
&&
(
sdpMLineIndex
===
0
||
!
pc
.
usingBundle
))
{
transceiver
.
iceGatherer
.
getLocalCandidates
().
forEach
(
function
(
cand
)
{
cand
.
component
=
1
;
sdp
+=
'a='
+
SDPUtils
.
writeCandidate
(
cand
)
+
'
\
r
\
n'
;
...
...
@@ -1340,19 +1402,16 @@ module.exports = function(window, edgeVersion) {
type
:
'offer'
,
sdp
:
sdp
});
return
new
Promise
(
function
(
resolve
)
{
if
(
args
.
length
>
0
&&
typeof
args
[
0
]
===
'function'
)
{
args
[
0
].
apply
(
null
,
[
desc
]);
resolve
();
return
;
}
resolve
(
desc
);
});
return
Promise
.
resolve
(
desc
);
};
RTCPeerConnection
.
prototype
.
createAnswer
=
function
()
{
var
self
=
this
;
var
args
=
arguments
;
var
pc
=
this
;
if
(
this
.
_isClosed
)
{
return
Promise
.
reject
(
makeError
(
'InvalidStateError'
,
'Can not call createAnswer after close'
));
}
var
sdp
=
SDPUtils
.
writeSessionBoilerplate
(
this
.
_sdpSessionId
,
this
.
_sdpSessionVersion
++
);
...
...
@@ -1406,7 +1465,7 @@ module.exports = function(window, edgeVersion) {
}
sdp
+=
writeMediaSection
(
transceiver
,
commonCapabilities
,
'answer'
,
transceiver
.
stream
,
self
.
_dtlsRole
);
'answer'
,
transceiver
.
stream
,
pc
.
_dtlsRole
);
if
(
transceiver
.
rtcpParameters
&&
transceiver
.
rtcpParameters
.
reducedSize
)
{
sdp
+=
'a=rtcp-rsize
\
r
\
n'
;
...
...
@@ -1417,18 +1476,10 @@ module.exports = function(window, edgeVersion) {
type
:
'answer'
,
sdp
:
sdp
});
return
new
Promise
(
function
(
resolve
)
{
if
(
args
.
length
>
0
&&
typeof
args
[
0
]
===
'function'
)
{
args
[
0
].
apply
(
null
,
[
desc
]);
resolve
();
return
;
}
resolve
(
desc
);
});
return
Promise
.
resolve
(
desc
);
};
RTCPeerConnection
.
prototype
.
addIceCandidate
=
function
(
candidate
)
{
var
err
;
var
sections
;
if
(
!
candidate
||
candidate
.
candidate
===
''
)
{
for
(
var
j
=
0
;
j
<
this
.
transceivers
.
length
;
j
++
)
{
...
...
@@ -1446,9 +1497,8 @@ module.exports = function(window, edgeVersion) {
}
else
if
(
!
(
candidate
.
sdpMLineIndex
!==
undefined
||
candidate
.
sdpMid
))
{
throw
new
TypeError
(
'sdpMLineIndex or sdpMid required'
);
}
else
if
(
!
this
.
remoteDescription
)
{
err
=
new
Error
(
'Can not add ICE candidate without '
+
'a remote description'
);
err
.
name
=
'InvalidStateError'
;
return
Promise
.
reject
(
makeError
(
'InvalidStateError'
,
'Can not add ICE candidate without a remote description'
));
}
else
{
var
sdpMLineIndex
=
candidate
.
sdpMLineIndex
;
if
(
candidate
.
sdpMid
)
{
...
...
@@ -1479,42 +1529,27 @@ module.exports = function(window, edgeVersion) {
if
(
sdpMLineIndex
===
0
||
(
sdpMLineIndex
>
0
&&
transceiver
.
iceTransport
!==
this
.
transceivers
[
0
].
iceTransport
))
{
if
(
!
maybeAddCandidate
(
transceiver
.
iceTransport
,
cand
))
{
err
=
new
Error
(
'Can not add ICE candidate'
);
err
.
name
=
'OperationError'
;
return
Promise
.
reject
(
makeError
(
'OperationError'
,
'Can not add ICE candidate'
))
;
}
}
if
(
!
err
)
{
// update the remoteDescription.
var
candidateString
=
candidate
.
candidate
.
trim
();
if
(
candidateString
.
indexOf
(
'a='
)
===
0
)
{
candidateString
=
candidateString
.
substr
(
2
);
}
sections
=
SDPUtils
.
splitSections
(
this
.
remoteDescription
.
sdp
);
sections
[
sdpMLineIndex
+
1
]
+=
'a='
+
(
cand
.
type
?
candidateString
:
'end-of-candidates'
)
+
'
\
r
\
n'
;
this
.
remoteDescription
.
sdp
=
sections
.
join
(
''
);
// update the remoteDescription.
var
candidateString
=
candidate
.
candidate
.
trim
();
if
(
candidateString
.
indexOf
(
'a='
)
===
0
)
{
candidateString
=
candidateString
.
substr
(
2
);
}
sections
=
SDPUtils
.
splitSections
(
this
.
remoteDescription
.
sdp
);
sections
[
sdpMLineIndex
+
1
]
+=
'a='
+
(
cand
.
type
?
candidateString
:
'end-of-candidates'
)
+
'
\
r
\
n'
;
this
.
remoteDescription
.
sdp
=
sections
.
join
(
''
);
}
else
{
err
=
new
Error
(
'Can not add ICE candidate'
);
err
.
name
=
'OperationError'
;
return
Promise
.
reject
(
makeError
(
'OperationError'
,
'Can not add ICE candidate'
))
;
}
}
var
args
=
arguments
;
return
new
Promise
(
function
(
resolve
,
reject
)
{
if
(
err
)
{
if
(
args
.
length
>
2
&&
typeof
args
[
2
]
===
'function'
)
{
args
[
2
].
apply
(
null
,
[
err
]);
}
reject
(
err
);
}
else
{
if
(
args
.
length
>
1
&&
typeof
args
[
1
]
===
'function'
)
{
args
[
1
].
apply
(
null
);
}
resolve
();
}
});
return
Promise
.
resolve
();
};
RTCPeerConnection
.
prototype
.
getStats
=
function
()
{
...
...
@@ -1527,8 +1562,6 @@ module.exports = function(window, edgeVersion) {
}
});
});
var
cb
=
arguments
.
length
>
1
&&
typeof
arguments
[
1
]
===
'function'
&&
arguments
[
1
];
var
fixStatsType
=
function
(
stat
)
{
return
{
inboundrtp
:
'inbound-rtp'
,
...
...
@@ -1548,13 +1581,74 @@ module.exports = function(window, edgeVersion) {
results
.
set
(
id
,
result
[
id
]);
});
});
if
(
cb
)
{
cb
.
apply
(
null
,
results
);
}
resolve
(
results
);
});
});
};
// legacy callback shims. Should be moved to adapter.js some days.
var
methods
=
[
'createOffer'
,
'createAnswer'
];
methods
.
forEach
(
function
(
method
)
{
var
nativeMethod
=
RTCPeerConnection
.
prototype
[
method
];
RTCPeerConnection
.
prototype
[
method
]
=
function
()
{
var
args
=
arguments
;
if
(
typeof
args
[
0
]
===
'function'
||
typeof
args
[
1
]
===
'function'
)
{
// legacy
return
nativeMethod
.
apply
(
this
,
[
arguments
[
2
]])
.
then
(
function
(
description
)
{
if
(
typeof
args
[
0
]
===
'function'
)
{
args
[
0
].
apply
(
null
,
[
description
]);
}
},
function
(
error
)
{
if
(
typeof
args
[
1
]
===
'function'
)
{
args
[
1
].
apply
(
null
,
[
error
]);
}
});
}
return
nativeMethod
.
apply
(
this
,
arguments
);
};
});
methods
=
[
'setLocalDescription'
,
'setRemoteDescription'
,
'addIceCandidate'
];
methods
.
forEach
(
function
(
method
)
{
var
nativeMethod
=
RTCPeerConnection
.
prototype
[
method
];
RTCPeerConnection
.
prototype
[
method
]
=
function
()
{
var
args
=
arguments
;
if
(
typeof
args
[
1
]
===
'function'
||
typeof
args
[
2
]
===
'function'
)
{
// legacy
return
nativeMethod
.
apply
(
this
,
arguments
)
.
then
(
function
()
{
if
(
typeof
args
[
1
]
===
'function'
)
{
args
[
1
].
apply
(
null
);
}
},
function
(
error
)
{
if
(
typeof
args
[
2
]
===
'function'
)
{
args
[
2
].
apply
(
null
,
[
error
]);
}
});
}
return
nativeMethod
.
apply
(
this
,
arguments
);
};
});
// getStats is special. It doesn't have a spec legacy method yet we support
// getStats(something, cb) without error callbacks.
[
'getStats'
].
forEach
(
function
(
method
)
{
var
nativeMethod
=
RTCPeerConnection
.
prototype
[
method
];
RTCPeerConnection
.
prototype
[
method
]
=
function
()
{
var
args
=
arguments
;
if
(
typeof
args
[
1
]
===
'function'
)
{
return
nativeMethod
.
apply
(
this
,
arguments
)
.
then
(
function
()
{
if
(
typeof
args
[
1
]
===
'function'
)
{
args
[
1
].
apply
(
null
);
}
});
}
return
nativeMethod
.
apply
(
this
,
arguments
);
};
});
return
RTCPeerConnection
;
};
...
...
@@ -2261,14 +2355,6 @@ module.exports = function(dependencies, opts) {
var
logging
=
utils
.
log
;
var
browserDetails
=
utils
.
detectBrowser
(
window
);
// Export to the adapter global object visible in the browser.
var
adapter
=
{
browserDetails
:
browserDetails
,
extractVersion
:
utils
.
extractVersion
,
disableLog
:
utils
.
disableLog
,
disableWarnings
:
utils
.
disableWarnings
};
// Uncomment the line below if you want logging to occur, including logging
// for the switch statement below. Can also be turned on in the browser via
// adapter.disableLog(false), but then logging from the switch statement below
...
...
@@ -2282,6 +2368,15 @@ module.exports = function(dependencies, opts) {
var
safariShim
=
require
(
'./safari/safari_shim'
)
||
null
;
var
commonShim
=
require
(
'./common_shim'
)
||
null
;
// Export to the adapter global object visible in the browser.
var
adapter
=
{
browserDetails
:
browserDetails
,
commonShim
:
commonShim
,
extractVersion
:
utils
.
extractVersion
,
disableLog
:
utils
.
disableLog
,
disableWarnings
:
utils
.
disableWarnings
};
// Shim browser if found.
switch
(
browserDetails
.
browser
)
{
case
'chrome'
:
...
...
@@ -2304,6 +2399,8 @@ module.exports = function(dependencies, opts) {
chromeShim
.
shimGetSendersWithDtmf
(
window
);
commonShim
.
shimRTCIceCandidate
(
window
);
commonShim
.
shimMaxMessageSize
(
window
);
commonShim
.
shimSendThrowTypeError
(
window
);
break
;
case
'firefox'
:
if
(
!
firefoxShim
||
!
firefoxShim
.
shimPeerConnection
||
...
...
@@ -2323,6 +2420,8 @@ module.exports = function(dependencies, opts) {
firefoxShim
.
shimRemoveStream
(
window
);
commonShim
.
shimRTCIceCandidate
(
window
);
commonShim
.
shimMaxMessageSize
(
window
);
commonShim
.
shimSendThrowTypeError
(
window
);
break
;
case
'edge'
:
if
(
!
edgeShim
||
!
edgeShim
.
shimPeerConnection
||
!
options
.
shimEdge
)
{
...
...
@@ -2339,6 +2438,9 @@ module.exports = function(dependencies, opts) {
edgeShim
.
shimReplaceTrack
(
window
);
// the edge shim implements the full RTCIceCandidate object.
commonShim
.
shimMaxMessageSize
(
window
);
commonShim
.
shimSendThrowTypeError
(
window
);
break
;
case
'safari'
:
if
(
!
safariShim
||
!
options
.
shimSafari
)
{
...
...
@@ -2359,6 +2461,8 @@ module.exports = function(dependencies, opts) {
safariShim
.
shimCreateOfferLegacy
(
window
);
commonShim
.
shimRTCIceCandidate
(
window
);
commonShim
.
shimMaxMessageSize
(
window
);
commonShim
.
shimSendThrowTypeError
(
window
);
break
;
default
:
logging
(
'Unsupported browser!'
);
...
...
@@ -2382,7 +2486,8 @@ module.exports = function(dependencies, opts) {
var
utils
=
require
(
'../utils.js'
);
var
logging
=
utils
.
log
;
var
chromeShim
=
{
module
.
exports
=
{
shimGetUserMedia
:
require
(
'./getusermedia'
),
shimMediaStream
:
function
(
window
)
{
window
.
MediaStream
=
window
.
MediaStream
||
window
.
webkitMediaStream
;
},
...
...
@@ -2447,6 +2552,13 @@ var chromeShim = {
}
return
origSetRemoteDescription
.
apply
(
pc
,
arguments
);
};
}
else
if
(
!
(
'RTCRtpTransceiver'
in
window
))
{
utils
.
wrapPeerConnectionEvent
(
window
,
'track'
,
function
(
e
)
{
if
(
!
e
.
transceiver
)
{
e
.
transceiver
=
{
receiver
:
e
.
receiver
};
}
return
e
;
});
}
},
...
...
@@ -2598,12 +2710,88 @@ var chromeShim = {
}
},
shimAddTrackRemoveTrackWithNative
:
function
(
window
)
{
// shim addTrack/removeTrack with native variants in order to make
// the interactions with legacy getLocalStreams behave as in other browsers.
// Keeps a mapping stream.id => [stream, rtpsenders...]
window
.
RTCPeerConnection
.
prototype
.
getLocalStreams
=
function
()
{
var
pc
=
this
;
this
.
_shimmedLocalStreams
=
this
.
_shimmedLocalStreams
||
{};
return
Object
.
keys
(
this
.
_shimmedLocalStreams
).
map
(
function
(
streamId
)
{
return
pc
.
_shimmedLocalStreams
[
streamId
][
0
];
});
};
var
origAddTrack
=
window
.
RTCPeerConnection
.
prototype
.
addTrack
;
window
.
RTCPeerConnection
.
prototype
.
addTrack
=
function
(
track
,
stream
)
{
if
(
!
stream
)
{
return
origAddTrack
.
apply
(
this
,
arguments
);
}
this
.
_shimmedLocalStreams
=
this
.
_shimmedLocalStreams
||
{};
var
sender
=
origAddTrack
.
apply
(
this
,
arguments
);
if
(
!
this
.
_shimmedLocalStreams
[
stream
.
id
])
{
this
.
_shimmedLocalStreams
[
stream
.
id
]
=
[
stream
,
sender
];
}
else
if
(
this
.
_shimmedLocalStreams
[
stream
.
id
].
indexOf
(
sender
)
===
-
1
)
{
this
.
_shimmedLocalStreams
[
stream
.
id
].
push
(
sender
);
}
return
sender
;
};
var
origAddStream
=
window
.
RTCPeerConnection
.
prototype
.
addStream
;
window
.
RTCPeerConnection
.
prototype
.
addStream
=
function
(
stream
)
{
var
pc
=
this
;
this
.
_shimmedLocalStreams
=
this
.
_shimmedLocalStreams
||
{};
stream
.
getTracks
().
forEach
(
function
(
track
)
{
var
alreadyExists
=
pc
.
getSenders
().
find
(
function
(
s
)
{
return
s
.
track
===
track
;
});
if
(
alreadyExists
)
{
throw
new
DOMException
(
'Track already exists.'
,
'InvalidAccessError'
);
}
});
var
existingSenders
=
pc
.
getSenders
();
origAddStream
.
apply
(
this
,
arguments
);
var
newSenders
=
pc
.
getSenders
().
filter
(
function
(
newSender
)
{
return
existingSenders
.
indexOf
(
newSender
)
===
-
1
;
});
this
.
_shimmedLocalStreams
[
stream
.
id
]
=
[
stream
].
concat
(
newSenders
);
};
var
origRemoveStream
=
window
.
RTCPeerConnection
.
prototype
.
removeStream
;
window
.
RTCPeerConnection
.
prototype
.
removeStream
=
function
(
stream
)
{
this
.
_shimmedLocalStreams
=
this
.
_shimmedLocalStreams
||
{};
delete
this
.
_shimmedLocalStreams
[
stream
.
id
];
return
origRemoveStream
.
apply
(
this
,
arguments
);
};
var
origRemoveTrack
=
window
.
RTCPeerConnection
.
prototype
.
removeTrack
;
window
.
RTCPeerConnection
.
prototype
.
removeTrack
=
function
(
sender
)
{
var
pc
=
this
;
this
.
_shimmedLocalStreams
=
this
.
_shimmedLocalStreams
||
{};
if
(
sender
)
{
Object
.
keys
(
this
.
_shimmedLocalStreams
).
forEach
(
function
(
streamId
)
{
var
idx
=
pc
.
_shimmedLocalStreams
[
streamId
].
indexOf
(
sender
);
if
(
idx
!==
-
1
)
{
pc
.
_shimmedLocalStreams
[
streamId
].
splice
(
idx
,
1
);
}
if
(
pc
.
_shimmedLocalStreams
[
streamId
].
length
===
1
)
{
delete
pc
.
_shimmedLocalStreams
[
streamId
];
}
});
}
return
origRemoveTrack
.
apply
(
this
,
arguments
);
};
},
shimAddTrackRemoveTrack
:
function
(
window
)
{
var
browserDetails
=
utils
.
detectBrowser
(
window
);
// shim addTrack and removeTrack.
if
(
window
.
RTCPeerConnection
.
prototype
.
addTrack
&&
browserDetails
.
version
>=
6
4
)
{
return
;
browserDetails
.
version
>=
6
5
)
{
return
this
.
shimAddTrackRemoveTrackWithNative
(
window
)
;
}
// also shim pc.getLocalStreams when addTrack is shimmed
...
...
@@ -2611,11 +2799,11 @@ var chromeShim = {
var
origGetLocalStreams
=
window
.
RTCPeerConnection
.
prototype
.
getLocalStreams
;
window
.
RTCPeerConnection
.
prototype
.
getLocalStreams
=
function
()
{
var
self
=
this
;
var
pc
=
this
;
var
nativeStreams
=
origGetLocalStreams
.
apply
(
this
);
self
.
_reverseStreams
=
self
.
_reverseStreams
||
{};
pc
.
_reverseStreams
=
pc
.
_reverseStreams
||
{};
return
nativeStreams
.
map
(
function
(
stream
)
{
return
self
.
_reverseStreams
[
stream
.
id
];
return
pc
.
_reverseStreams
[
stream
.
id
];
});
};
...
...
@@ -2841,7 +3029,7 @@ var chromeShim = {
var
browserDetails
=
utils
.
detectBrowser
(
window
);
// The RTCPeerConnection object.
if
(
!
window
.
RTCPeerConnection
)
{
if
(
!
window
.
RTCPeerConnection
&&
window
.
webkitRTCPeerConnection
)
{
window
.
RTCPeerConnection
=
function
(
pcConfig
,
pcConstraints
)
{
// Translate iceTransportPolicy to iceTransports,
// see https://code.google.com/p/webrtc/issues/detail?id=4869
...
...
@@ -2897,7 +3085,7 @@ var chromeShim = {
var
origGetStats
=
window
.
RTCPeerConnection
.
prototype
.
getStats
;
window
.
RTCPeerConnection
.
prototype
.
getStats
=
function
(
selector
,
successCallback
,
errorCallback
)
{
var
self
=
this
;
var
pc
=
this
;
var
args
=
arguments
;
// If selector is a function then we are in the old style stats so just
...
...
@@ -2952,7 +3140,7 @@ var chromeShim = {
// promise-support
return
new
Promise
(
function
(
resolve
,
reject
)
{
origGetStats
.
apply
(
self
,
[
origGetStats
.
apply
(
pc
,
[
function
(
response
)
{
resolve
(
makeMapStats
(
fixChromeStats_
(
response
)));
},
reject
]);
...
...
@@ -2966,9 +3154,9 @@ var chromeShim = {
var
nativeMethod
=
window
.
RTCPeerConnection
.
prototype
[
method
];
window
.
RTCPeerConnection
.
prototype
[
method
]
=
function
()
{
var
args
=
arguments
;
var
self
=
this
;
var
pc
=
this
;
var
promise
=
new
Promise
(
function
(
resolve
,
reject
)
{
nativeMethod
.
apply
(
self
,
[
args
[
0
],
resolve
,
reject
]);
nativeMethod
.
apply
(
pc
,
[
args
[
0
],
resolve
,
reject
]);
});
if
(
args
.
length
<
2
)
{
return
promise
;
...
...
@@ -2991,12 +3179,12 @@ var chromeShim = {
[
'createOffer'
,
'createAnswer'
].
forEach
(
function
(
method
)
{
var
nativeMethod
=
window
.
RTCPeerConnection
.
prototype
[
method
];
window
.
RTCPeerConnection
.
prototype
[
method
]
=
function
()
{
var
self
=
this
;
var
pc
=
this
;
if
(
arguments
.
length
<
1
||
(
arguments
.
length
===
1
&&
typeof
arguments
[
0
]
===
'object'
))
{
var
opts
=
arguments
.
length
===
1
?
arguments
[
0
]
:
undefined
;
return
new
Promise
(
function
(
resolve
,
reject
)
{
nativeMethod
.
apply
(
self
,
[
resolve
,
reject
,
opts
]);
nativeMethod
.
apply
(
pc
,
[
resolve
,
reject
,
opts
]);
});
}
return
nativeMethod
.
apply
(
this
,
arguments
);
...
...
@@ -3031,18 +3219,6 @@ var chromeShim = {
}
};
// Expose public methods.
module
.
exports
=
{
shimMediaStream
:
chromeShim
.
shimMediaStream
,
shimOnTrack
:
chromeShim
.
shimOnTrack
,
shimAddTrackRemoveTrack
:
chromeShim
.
shimAddTrackRemoveTrack
,
shimGetSendersWithDtmf
:
chromeShim
.
shimGetSendersWithDtmf
,
shimSourceObject
:
chromeShim
.
shimSourceObject
,
shimPeerConnection
:
chromeShim
.
shimPeerConnection
,
shimGetUserMedia
:
require
(
'./getusermedia'
)
};
},{
"../utils.js"
:
13
,
"./getusermedia"
:
6
}],
6
:[
function
(
require
,
module
,
exports
){
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
...
...
@@ -3299,57 +3475,6 @@ module.exports = function(window) {
var
SDPUtils
=
require
(
'sdp'
);
var
utils
=
require
(
'./utils'
);
// Wraps the peerconnection event eventNameToWrap in a function
// which returns the modified event object.
function
wrapPeerConnectionEvent
(
window
,
eventNameToWrap
,
wrapper
)
{
if
(
!
window
.
RTCPeerConnection
)
{
return
;
}
var
proto
=
window
.
RTCPeerConnection
.
prototype
;
var
nativeAddEventListener
=
proto
.
addEventListener
;
proto
.
addEventListener
=
function
(
nativeEventName
,
cb
)
{
if
(
nativeEventName
!==
eventNameToWrap
)
{
return
nativeAddEventListener
.
apply
(
this
,
arguments
);
}
var
wrappedCallback
=
function
(
e
)
{
cb
(
wrapper
(
e
));
};
this
.
_eventMap
=
this
.
_eventMap
||
{};
this
.
_eventMap
[
cb
]
=
wrappedCallback
;
return
nativeAddEventListener
.
apply
(
this
,
[
nativeEventName
,
wrappedCallback
]);
};
var
nativeRemoveEventListener
=
proto
.
removeEventListener
;
proto
.
removeEventListener
=
function
(
nativeEventName
,
cb
)
{
if
(
nativeEventName
!==
eventNameToWrap
||
!
this
.
_eventMap
||
!
this
.
_eventMap
[
cb
])
{
return
nativeRemoveEventListener
.
apply
(
this
,
arguments
);
}
var
unwrappedCb
=
this
.
_eventMap
[
cb
];
delete
this
.
_eventMap
[
cb
];
return
nativeRemoveEventListener
.
apply
(
this
,
[
nativeEventName
,
unwrappedCb
]);
};
Object
.
defineProperty
(
proto
,
'on'
+
eventNameToWrap
,
{
get
:
function
()
{
return
this
[
'_on'
+
eventNameToWrap
];
},
set
:
function
(
cb
)
{
if
(
this
[
'_on'
+
eventNameToWrap
])
{
this
.
removeEventListener
(
eventNameToWrap
,
this
[
'_on'
+
eventNameToWrap
]);
delete
this
[
'_on'
+
eventNameToWrap
];
}
if
(
cb
)
{
this
.
addEventListener
(
eventNameToWrap
,
this
[
'_on'
+
eventNameToWrap
]
=
cb
);
}
}
});
}
module
.
exports
=
{
shimRTCIceCandidate
:
function
(
window
)
{
// foundation is arbitrarily chosen as an indicator for full support for
...
...
@@ -3388,7 +3513,7 @@ module.exports = {
// Hook up the augmented candidate in onicecandidate and
// addEventListener('icecandidate', ...)
wrapPeerConnectionEvent
(
window
,
'icecandidate'
,
function
(
e
)
{
utils
.
wrapPeerConnectionEvent
(
window
,
'icecandidate'
,
function
(
e
)
{
if
(
e
.
candidate
)
{
Object
.
defineProperty
(
e
,
'candidate'
,
{
value
:
new
window
.
RTCIceCandidate
(
e
.
candidate
),
...
...
@@ -3450,6 +3575,165 @@ module.exports = {
}
return
nativeSetAttribute
.
apply
(
this
,
arguments
);
};
},
shimMaxMessageSize
:
function
(
window
)
{
if
(
window
.
RTCSctpTransport
||
!
window
.
RTCPeerConnection
)
{
return
;
}
var
browserDetails
=
utils
.
detectBrowser
(
window
);
if
(
!
(
'sctp'
in
window
.
RTCPeerConnection
.
prototype
))
{
Object
.
defineProperty
(
window
.
RTCPeerConnection
.
prototype
,
'sctp'
,
{
get
:
function
()
{
return
typeof
this
.
_sctp
===
'undefined'
?
null
:
this
.
_sctp
;
}
});
}
var
sctpInDescription
=
function
(
description
)
{
var
sections
=
SDPUtils
.
splitSections
(
description
.
sdp
);
sections
.
shift
();
return
sections
.
some
(
function
(
mediaSection
)
{
var
mLine
=
SDPUtils
.
parseMLine
(
mediaSection
);
return
mLine
&&
mLine
.
kind
===
'application'
&&
mLine
.
protocol
.
indexOf
(
'SCTP'
)
!==
-
1
;
});
};
var
getRemoteFirefoxVersion
=
function
(
description
)
{
// TODO: Is there a better solution for detecting Firefox?
var
match
=
description
.
sdp
.
match
(
/mozilla...THIS_IS_SDPARTA-
(\d
+
)
/
);
if
(
match
===
null
||
match
.
length
<
2
)
{
return
-
1
;
}
var
version
=
parseInt
(
match
[
1
],
10
);
// Test for NaN (yes, this is ugly)
return
version
!==
version
?
-
1
:
version
;
};
var
getCanSendMaxMessageSize
=
function
(
remoteIsFirefox
)
{
// Every implementation we know can send at least 64 KiB.
// Note: Although Chrome is technically able to send up to 256 KiB, the
// data does not reach the other peer reliably.
// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419
var
canSendMaxMessageSize
=
65536
;
if
(
browserDetails
.
browser
===
'firefox'
)
{
if
(
browserDetails
.
version
<
57
)
{
if
(
remoteIsFirefox
===
-
1
)
{
// FF < 57 will send in 16 KiB chunks using the deprecated PPID
// fragmentation.
canSendMaxMessageSize
=
16384
;
}
else
{
// However, other FF (and RAWRTC) can reassemble PPID-fragmented
// messages. Thus, supporting ~2 GiB when sending.
canSendMaxMessageSize
=
2147483637
;
}
}
else
{
// Currently, all FF >= 57 will reset the remote maximum message size
// to the default value when a data channel is created at a later
// stage. :(
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
canSendMaxMessageSize
=
browserDetails
.
version
===
57
?
65535
:
65536
;
}
}
return
canSendMaxMessageSize
;
};
var
getMaxMessageSize
=
function
(
description
,
remoteIsFirefox
)
{
// Note: 65536 bytes is the default value from the SDP spec. Also,
// every implementation we know supports receiving 65536 bytes.
var
maxMessageSize
=
65536
;
// FF 57 has a slightly incorrect default remote max message size, so
// we need to adjust it here to avoid a failure when sending.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697
if
(
browserDetails
.
browser
===
'firefox'
&&
browserDetails
.
version
===
57
)
{
maxMessageSize
=
65535
;
}
var
match
=
SDPUtils
.
matchPrefix
(
description
.
sdp
,
'a=max-message-size:'
);
if
(
match
.
length
>
0
)
{
maxMessageSize
=
parseInt
(
match
[
0
].
substr
(
19
),
10
);
}
else
if
(
browserDetails
.
browser
===
'firefox'
&&
remoteIsFirefox
!==
-
1
)
{
// If the maximum message size is not present in the remote SDP and
// both local and remote are Firefox, the remote peer can receive
// ~2 GiB.
maxMessageSize
=
2147483637
;
}
return
maxMessageSize
;
};
var
origSetRemoteDescription
=
window
.
RTCPeerConnection
.
prototype
.
setRemoteDescription
;
window
.
RTCPeerConnection
.
prototype
.
setRemoteDescription
=
function
()
{
var
pc
=
this
;
pc
.
_sctp
=
null
;
if
(
sctpInDescription
(
arguments
[
0
]))
{
// Check if the remote is FF.
var
isFirefox
=
getRemoteFirefoxVersion
(
arguments
[
0
]);
// Get the maximum message size the local peer is capable of sending
var
canSendMMS
=
getCanSendMaxMessageSize
(
isFirefox
);
// Get the maximum message size of the remote peer.
var
remoteMMS
=
getMaxMessageSize
(
arguments
[
0
],
isFirefox
);
// Determine final maximum message size
var
maxMessageSize
;
if
(
canSendMMS
===
0
&&
remoteMMS
===
0
)
{
maxMessageSize
=
Number
.
POSITIVE_INFINITY
;
}
else
if
(
canSendMMS
===
0
||
remoteMMS
===
0
)
{
maxMessageSize
=
Math
.
max
(
canSendMMS
,
remoteMMS
);
}
else
{
maxMessageSize
=
Math
.
min
(
canSendMMS
,
remoteMMS
);
}
// Create a dummy RTCSctpTransport object and the 'maxMessageSize'
// attribute.
var
sctp
=
{};
Object
.
defineProperty
(
sctp
,
'maxMessageSize'
,
{
get
:
function
()
{
return
maxMessageSize
;
}
});
pc
.
_sctp
=
sctp
;
}
return
origSetRemoteDescription
.
apply
(
pc
,
arguments
);
};
},
shimSendThrowTypeError
:
function
(
window
)
{
// Note: Although Firefox >= 57 has a native implementation, the maximum
// message size can be reset for all data channels at a later stage.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
var
origCreateDataChannel
=
window
.
RTCPeerConnection
.
prototype
.
createDataChannel
;
window
.
RTCPeerConnection
.
prototype
.
createDataChannel
=
function
()
{
var
pc
=
this
;
var
dataChannel
=
origCreateDataChannel
.
apply
(
pc
,
arguments
);
var
origDataChannelSend
=
dataChannel
.
send
;
// Patch 'send' method
dataChannel
.
send
=
function
()
{
var
dc
=
this
;
var
data
=
arguments
[
0
];
var
length
=
data
.
length
||
data
.
size
||
data
.
byteLength
;
if
(
length
>
pc
.
sctp
.
maxMessageSize
)
{
throw
new
DOMException
(
'Message too large (can send a maximum of '
+
pc
.
sctp
.
maxMessageSize
+
' bytes)'
,
'TypeError'
);
}
return
origDataChannelSend
.
apply
(
dc
,
arguments
);
};
return
dataChannel
;
};
}
};
...
...
@@ -3584,7 +3868,8 @@ module.exports = function(window) {
var
utils
=
require
(
'../utils'
);
var
firefoxShim
=
{
module
.
exports
=
{
shimGetUserMedia
:
require
(
'./getusermedia'
),
shimOnTrack
:
function
(
window
)
{
if
(
typeof
window
===
'object'
&&
window
.
RTCPeerConnection
&&
!
(
'ontrack'
in
window
.
RTCPeerConnection
.
prototype
))
{
...
...
@@ -3789,15 +4074,6 @@ var firefoxShim = {
}
};
// Expose public methods.
module
.
exports
=
{
shimOnTrack
:
firefoxShim
.
shimOnTrack
,
shimSourceObject
:
firefoxShim
.
shimSourceObject
,
shimPeerConnection
:
firefoxShim
.
shimPeerConnection
,
shimRemoveStream
:
firefoxShim
.
shimRemoveStream
,
shimGetUserMedia
:
require
(
'./getusermedia'
)
};
},{
"../utils"
:
13
,
"./getusermedia"
:
11
}],
11
:[
function
(
require
,
module
,
exports
){
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
...
...
@@ -4020,13 +4296,7 @@ module.exports = function(window) {
'use strict'
;
var
utils
=
require
(
'../utils'
);
var
safariShim
=
{
// TODO: DrAlex, should be here, double check against LayoutTests
// TODO: once the back-end for the mac port is done, add.
// TODO: check for webkitGTK+
// shimPeerConnection: function() { },
module
.
exports
=
{
shimLocalStreamsAPI
:
function
(
window
)
{
if
(
typeof
window
!==
'object'
||
!
window
.
RTCPeerConnection
)
{
return
;
...
...
@@ -4068,9 +4338,9 @@ var safariShim = {
if
(
this
.
_localStreams
.
indexOf
(
stream
)
===
-
1
)
{
this
.
_localStreams
.
push
(
stream
);
}
var
self
=
this
;
var
pc
=
this
;
stream
.
getTracks
().
forEach
(
function
(
track
)
{
_addTrack
.
call
(
self
,
track
,
stream
);
_addTrack
.
call
(
pc
,
track
,
stream
);
});
};
...
...
@@ -4095,11 +4365,11 @@ var safariShim = {
return
;
}
this
.
_localStreams
.
splice
(
index
,
1
);
var
self
=
this
;
var
pc
=
this
;
var
tracks
=
stream
.
getTracks
();
this
.
getSenders
().
forEach
(
function
(
sender
)
{
if
(
tracks
.
indexOf
(
sender
.
track
)
!==
-
1
)
{
self
.
removeTrack
(
sender
);
pc
.
removeTrack
(
sender
);
}
});
};
...
...
@@ -4120,24 +4390,26 @@ var safariShim = {
return
this
.
_onaddstream
;
},
set
:
function
(
f
)
{
var
pc
=
this
;
if
(
this
.
_onaddstream
)
{
this
.
removeEventListener
(
'addstream'
,
this
.
_onaddstream
);
this
.
removeEventListener
(
'track'
,
this
.
_onaddstreampoly
);
}
this
.
addEventListener
(
'addstream'
,
this
.
_onaddstream
=
f
);
this
.
addEventListener
(
'track'
,
this
.
_onaddstreampoly
=
function
(
e
)
{
var
stream
=
e
.
streams
[
0
];
if
(
!
this
.
_remoteStreams
)
{
this
.
_remoteStreams
=
[];
}
if
(
this
.
_remoteStreams
.
indexOf
(
stream
)
>=
0
)
{
return
;
}
this
.
_remoteStreams
.
push
(
stream
);
var
event
=
new
Event
(
'addstream'
);
event
.
stream
=
e
.
streams
[
0
];
this
.
dispatchEvent
(
event
);
}.
bind
(
this
));
e
.
streams
.
forEach
(
function
(
stream
)
{
if
(
!
pc
.
_remoteStreams
)
{
pc
.
_remoteStreams
=
[];
}
if
(
pc
.
_remoteStreams
.
indexOf
(
stream
)
>=
0
)
{
return
;
}
pc
.
_remoteStreams
.
push
(
stream
);
var
event
=
new
Event
(
'addstream'
);
event
.
stream
=
stream
;
pc
.
dispatchEvent
(
event
);
});
});
}
});
}
...
...
@@ -4277,9 +4549,17 @@ var safariShim = {
});
if
(
offerOptions
.
offerToReceiveAudio
===
false
&&
audioTransceiver
)
{
if
(
audioTransceiver
.
direction
===
'sendrecv'
)
{
audioTransceiver
.
setDirection
(
'sendonly'
);
if
(
audioTransceiver
.
setDirection
)
{
audioTransceiver
.
setDirection
(
'sendonly'
);
}
else
{
audioTransceiver
.
direction
=
'sendonly'
;
}
}
else
if
(
audioTransceiver
.
direction
===
'recvonly'
)
{
audioTransceiver
.
setDirection
(
'inactive'
);
if
(
audioTransceiver
.
setDirection
)
{
audioTransceiver
.
setDirection
(
'inactive'
);
}
else
{
audioTransceiver
.
direction
=
'inactive'
;
}
}
}
else
if
(
offerOptions
.
offerToReceiveAudio
===
true
&&
!
audioTransceiver
)
{
...
...
@@ -4306,19 +4586,6 @@ var safariShim = {
}
};
// Expose public methods.
module
.
exports
=
{
shimCallbacksAPI
:
safariShim
.
shimCallbacksAPI
,
shimLocalStreamsAPI
:
safariShim
.
shimLocalStreamsAPI
,
shimRemoteStreamsAPI
:
safariShim
.
shimRemoteStreamsAPI
,
shimGetUserMedia
:
safariShim
.
shimGetUserMedia
,
shimRTCIceServerUrls
:
safariShim
.
shimRTCIceServerUrls
,
shimTrackEventTransceiver
:
safariShim
.
shimTrackEventTransceiver
,
shimCreateOfferLegacy
:
safariShim
.
shimCreateOfferLegacy
// TODO
// shimPeerConnection: safariShim.shimPeerConnection
};
},{
"../utils"
:
13
}],
13
:[
function
(
require
,
module
,
exports
){
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
...
...
@@ -4333,8 +4600,74 @@ module.exports = {
var
logDisabled_
=
true
;
var
deprecationWarnings_
=
true
;
/**
* Extract browser version out of the provided user agent string.
*
* @param {!string} uastring userAgent string.
* @param {!string} expr Regular expression used as match criteria.
* @param {!number} pos position in the version string to be returned.
* @return {!number} browser version.
*/
function
extractVersion
(
uastring
,
expr
,
pos
)
{
var
match
=
uastring
.
match
(
expr
);
return
match
&&
match
.
length
>=
pos
&&
parseInt
(
match
[
pos
],
10
);
}
// Wraps the peerconnection event eventNameToWrap in a function
// which returns the modified event object.
function
wrapPeerConnectionEvent
(
window
,
eventNameToWrap
,
wrapper
)
{
if
(
!
window
.
RTCPeerConnection
)
{
return
;
}
var
proto
=
window
.
RTCPeerConnection
.
prototype
;
var
nativeAddEventListener
=
proto
.
addEventListener
;
proto
.
addEventListener
=
function
(
nativeEventName
,
cb
)
{
if
(
nativeEventName
!==
eventNameToWrap
)
{
return
nativeAddEventListener
.
apply
(
this
,
arguments
);
}
var
wrappedCallback
=
function
(
e
)
{
cb
(
wrapper
(
e
));
};
this
.
_eventMap
=
this
.
_eventMap
||
{};
this
.
_eventMap
[
cb
]
=
wrappedCallback
;
return
nativeAddEventListener
.
apply
(
this
,
[
nativeEventName
,
wrappedCallback
]);
};
var
nativeRemoveEventListener
=
proto
.
removeEventListener
;
proto
.
removeEventListener
=
function
(
nativeEventName
,
cb
)
{
if
(
nativeEventName
!==
eventNameToWrap
||
!
this
.
_eventMap
||
!
this
.
_eventMap
[
cb
])
{
return
nativeRemoveEventListener
.
apply
(
this
,
arguments
);
}
var
unwrappedCb
=
this
.
_eventMap
[
cb
];
delete
this
.
_eventMap
[
cb
];
return
nativeRemoveEventListener
.
apply
(
this
,
[
nativeEventName
,
unwrappedCb
]);
};
Object
.
defineProperty
(
proto
,
'on'
+
eventNameToWrap
,
{
get
:
function
()
{
return
this
[
'_on'
+
eventNameToWrap
];
},
set
:
function
(
cb
)
{
if
(
this
[
'_on'
+
eventNameToWrap
])
{
this
.
removeEventListener
(
eventNameToWrap
,
this
[
'_on'
+
eventNameToWrap
]);
delete
this
[
'_on'
+
eventNameToWrap
];
}
if
(
cb
)
{
this
.
addEventListener
(
eventNameToWrap
,
this
[
'_on'
+
eventNameToWrap
]
=
cb
);
}
}
});
}
// Utility methods.
var
utils
=
{
module
.
exports
=
{
extractVersion
:
extractVersion
,
wrapPeerConnectionEvent
:
wrapPeerConnectionEvent
,
disableLog
:
function
(
bool
)
{
if
(
typeof
bool
!==
'boolean'
)
{
return
new
Error
(
'Argument type: '
+
typeof
bool
+
...
...
@@ -4380,19 +4713,6 @@ var utils = {
' instead.'
);
},
/**
* Extract browser version out of the provided user agent string.
*
* @param {!string} uastring userAgent string.
* @param {!string} expr Regular expression used as match criteria.
* @param {!number} pos position in the version string to be returned.
* @return {!number} browser version.
*/
extractVersion
:
function
(
uastring
,
expr
,
pos
)
{
var
match
=
uastring
.
match
(
expr
);
return
match
&&
match
.
length
>=
pos
&&
parseInt
(
match
[
pos
],
10
);
},
/**
* Browser detector.
*
...
...
@@ -4413,38 +4733,25 @@ var utils = {
return
result
;
}
// Firefox.
if
(
navigator
.
mozGetUserMedia
)
{
if
(
navigator
.
mozGetUserMedia
)
{
// Firefox.
result
.
browser
=
'firefox'
;
result
.
version
=
this
.
extractVersion
(
navigator
.
userAgent
,
result
.
version
=
extractVersion
(
navigator
.
userAgent
,
/Firefox
\/(\d
+
)\.
/
,
1
);
}
else
if
(
navigator
.
webkitGetUserMedia
)
{
// Chrome, Chromium, Webview, Opera
, all use the chrome shim for now
if
(
window
.
webkitRTCPeerConnection
)
{
result
.
browser
=
'chrome'
;
result
.
version
=
this
.
extractVersion
(
navigator
.
userAgent
,
// Chrome, Chromium, Webview, Opera
.
// Version matches Chrome/WebRTC version.
result
.
browser
=
'chrome'
;
result
.
version
=
extractVersion
(
navigator
.
userAgent
,
/Chrom
(
e|ium
)\/(\d
+
)\.
/
,
2
);
}
else
{
// Safari (in an unpublished version) or unknown webkit-based.
if
(
navigator
.
userAgent
.
match
(
/Version
\/(\d
+
)
.
(\d
+
)
/
))
{
result
.
browser
=
'safari'
;
result
.
version
=
this
.
extractVersion
(
navigator
.
userAgent
,
/AppleWebKit
\/(\d
+
)\.
/
,
1
);
}
else
{
// unknown webkit-based browser.
result
.
browser
=
'Unsupported webkit-based browser '
+
'with GUM support but no WebRTC support.'
;
return
result
;
}
}
}
else
if
(
navigator
.
mediaDevices
&&
navigator
.
userAgent
.
match
(
/Edge
\/(\d
+
)
.
(\d
+
)
$/
))
{
// Edge.
result
.
browser
=
'edge'
;
result
.
version
=
this
.
extractVersion
(
navigator
.
userAgent
,
result
.
version
=
extractVersion
(
navigator
.
userAgent
,
/Edge
\/(\d
+
)
.
(\d
+
)
$/
,
2
);
}
else
if
(
navigator
.
mediaDevices
&&
navigator
.
userAgent
.
match
(
/AppleWebKit
\/(\d
+
)\.
/
))
{
// Safari, with webkitGetUserMedia removed.
navigator
.
userAgent
.
match
(
/AppleWebKit
\/(\d
+
)\.
/
))
{
// Safari.
result
.
browser
=
'safari'
;
result
.
version
=
this
.
extractVersion
(
navigator
.
userAgent
,
result
.
version
=
extractVersion
(
navigator
.
userAgent
,
/AppleWebKit
\/(\d
+
)\.
/
,
1
);
}
else
{
// Default fallthrough: not supported.
result
.
browser
=
'Not a supported browser.'
;
...
...
@@ -4452,19 +4759,7 @@ var utils = {
}
return
result
;
},
};
// Export.
module
.
exports
=
{
log
:
utils
.
log
,
deprecated
:
utils
.
deprecated
,
disableLog
:
utils
.
disableLog
,
disableWarnings
:
utils
.
disableWarnings
,
extractVersion
:
utils
.
extractVersion
,
shimCreateObjectURL
:
utils
.
shimCreateObjectURL
,
detectBrowser
:
utils
.
detectBrowser
.
bind
(
utils
)
}
};
},{}]},{},[
3
])(
3
)
...
...
html5/verto/video_demo-live_canvas/js/verto-min.js
浏览文件 @
5fa0a04b
This diff was suppressed by a .gitattributes entry.
html5/verto/video_demo/js/verto-min.js
浏览文件 @
5fa0a04b
This diff was suppressed by a .gitattributes entry.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论