Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix PeerConnection.addStream|addTrack by using UUID().uuidString preffix for PluginMediaStream and PluginMediaStreamTrack only for Janus #467 #467

Merged
merged 4 commits into from
Feb 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 15 additions & 14 deletions js/RTCPeerConnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module.exports = RTCPeerConnection;
/**
* Dependencies.
*/
var
var
debug = require('debug')('iosrtc:RTCPeerConnection'),
debugerror = require('debug')('iosrtc:ERROR:RTCPeerConnection'),
exec = require('cordova/exec'),
Expand All @@ -29,7 +29,7 @@ function deprecateWarning(method, newMethod) {
if (!newMethod) {
console.warn(method + ' is deprecated.');
} else {
console.warn(method + ' method is deprecated, use ' + newMethod + ' instead.');
console.warn(method + ' method is deprecated, use ' + newMethod + ' instead.');
}
}

Expand All @@ -46,10 +46,11 @@ function RTCPeerConnection(pcConfig, pcConstraints) {
// Object.defineProperties(this, RTCPeerConnection.prototype_descriptor);

// Fix webrtc-adapter bad SHIM on addTrack causing error when original does support multiple streams.
// NotSupportedError: The adapter.js addTrack polyfill only supports a single stream which is associated with the specified track.
// NotSupportedError: The adapter.js addTrack, addStream polyfill only supports a single stream which is associated with the specified track.
Object.defineProperty(this, 'addTrack', RTCPeerConnection.prototype_descriptor.addTrack);
Object.defineProperty(this, 'addStream', RTCPeerConnection.prototype_descriptor.addStream);
Object.defineProperty(this, 'getLocalStreams', RTCPeerConnection.prototype_descriptor.getLocalStreams);

// Public atributes.
this._localDescription = null;
this.remoteDescription = null;
Expand All @@ -74,17 +75,17 @@ RTCPeerConnection.prototype = Object.create(EventTarget.prototype);
RTCPeerConnection.prototype.constructor = RTCPeerConnection;

Object.defineProperties(RTCPeerConnection.prototype, {
'localDescription': {
'localDescription': {
// Fix webrtc-adapter TypeError: Attempting to change the getter of an unconfigurable property.
configurable: true,
get: function() {
get: function() {
return this._localDescription;
}
},
'connectionState': {
get: function() {
'connectionState': {
get: function() {
return this.iceConnectionState;
}
}
},
'onicecandidate': {
// Fix webrtc-adapter TypeError: Attempting to change the getter of an unconfigurable property.
Expand Down Expand Up @@ -209,8 +210,8 @@ RTCPeerConnection.prototype.setLocalDescription = function (desc) {
});
}

// "This is no longer necessary, however; RTCPeerConnection.setLocalDescription() and other
// methods which take SDP as input now directly accept an object conforming to the RTCSessionDescriptionInit dictionary,
// "This is no longer necessary, however; RTCPeerConnection.setLocalDescription() and other
// methods which take SDP as input now directly accept an object conforming to the RTCSessionDescriptionInit dictionary,
// so you don't have to instantiate an RTCSessionDescription yourself.""
// Source: https://developer.mozilla.org/en-US/docs/Web/API/RTCSessionDescription/RTCSessionDescription#Example
// Still we do instnanciate RTCSessionDescription, so internal object is used properly.
Expand Down Expand Up @@ -260,8 +261,8 @@ RTCPeerConnection.prototype.setRemoteDescription = function (desc) {

debug('setRemoteDescription() [desc:%o]', desc);

// "This is no longer necessary, however; RTCPeerConnection.setLocalDescription() and other
// methods which take SDP as input now directly accept an object conforming to the RTCSessionDescriptionInit dictionary,
// "This is no longer necessary, however; RTCPeerConnection.setLocalDescription() and other
// methods which take SDP as input now directly accept an object conforming to the RTCSessionDescriptionInit dictionary,
// so you don't have to instantiate an RTCSessionDescription yourself.""
// Source: https://developer.mozilla.org/en-US/docs/Web/API/RTCSessionDescription/RTCSessionDescription#Example
// Still we do instnanciate RTCSessionDescription so internal object is used properly.
Expand Down Expand Up @@ -439,7 +440,7 @@ RTCPeerConnection.prototype.addTrack = function (track, stream) {
for (id in this.localStreams) {
if (this.localStreams.hasOwnProperty(id)) {
// Target provided stream argument or first added stream to group track
if (!stream || (stream && stream.id === id)) {
if (!stream || (stream && stream.id === id)) {
stream = this.localStreams[id];
stream.addTrack(track);
exec(null, null, 'iosrtcPlugin', 'RTCPeerConnection_addTrack', [this.pcId, track.id, id]);
Expand Down
9 changes: 8 additions & 1 deletion src/PluginMediaStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ class PluginMediaStream : NSObject {
NSLog("PluginMediaStream#init()")

self.rtcMediaStream = rtcMediaStream
self.id = rtcMediaStream.streamId + "_" + UUID().uuidString;

// Handle possible duplicate remote streamId with janus name
// See: https://github.com/cordova-rtc/cordova-plugin-iosrtc/issues/432
if (rtcMediaStream.streamId.starts(with: "janus")) {
self.id = rtcMediaStream.streamId + "_" + UUID().uuidString;
} else {
self.id = rtcMediaStream.streamId;
}

for track: RTCMediaStreamTrack in (self.rtcMediaStream.audioTracks as Array<RTCMediaStreamTrack>) {
let pluginMediaStreamTrack = PluginMediaStreamTrack(rtcMediaStreamTrack: track, streamId: id)
Expand Down
10 changes: 9 additions & 1 deletion src/PluginMediaStreamTrack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@ class PluginMediaStreamTrack : NSObject {
NSLog("PluginMediaStreamTrack#init()")

self.rtcMediaStreamTrack = rtcMediaStreamTrack
self.id = rtcMediaStreamTrack.trackId + "_" + UUID().uuidString;

// Handle possible duplicate remote trackId with janus name
// See: https://github.com/cordova-rtc/cordova-plugin-iosrtc/issues/432
if (rtcMediaStreamTrack.trackId.starts(with: "janus")) {
self.id = rtcMediaStreamTrack.trackId + "_" + UUID().uuidString;
} else {
self.id = rtcMediaStreamTrack.trackId;
}

self.kind = rtcMediaStreamTrack.kind
self.renders = [:]
self.streamId = streamId;
Expand Down
67 changes: 35 additions & 32 deletions src/iosrtcPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class iosrtcPlugin : CDVPlugin {
// This is just called if <param name="onload" value="true" /> in plugin.xml.
@objc(pluginInitialize) override func pluginInitialize() {
NSLog("iosrtcPlugin#pluginInitialize()")

// Make the web view transparent
self.webView!.isOpaque = false
self.webView!.backgroundColor = UIColor.clear
Expand All @@ -42,7 +42,7 @@ class iosrtcPlugin : CDVPlugin {

// Create a RTCPeerConnectionFactory.
self.initPeerConnectionFactory();

// Create a PluginGetUserMedia instance.
self.pluginGetUserMedia = PluginGetUserMedia(
rtcPeerConnectionFactory: rtcPeerConnectionFactory
Expand All @@ -51,7 +51,7 @@ class iosrtcPlugin : CDVPlugin {
// Create a PluginRTCAudioController instance.
self.audioOutputController = PluginRTCAudioController()
}

private func initPeerConnectionFactory() {
let encoderFactory = RTCDefaultVideoEncoderFactory()
let decoderFactory = RTCDefaultVideoDecoderFactory()
Expand All @@ -62,7 +62,7 @@ class iosrtcPlugin : CDVPlugin {
decoderFactory: decoderFactory
)
}

private func getSupportedVideoEncoder(factory: RTCDefaultVideoEncoderFactory) -> RTCVideoCodecInfo {
let supportedCodecs: [RTCVideoCodecInfo] = RTCDefaultVideoEncoderFactory.supportedCodecs()
if supportedCodecs.contains(RTCVideoCodecInfo.init(name: kRTCH264CodecName)){
Expand Down Expand Up @@ -334,69 +334,69 @@ class iosrtcPlugin : CDVPlugin {
pluginRTCPeerConnection?.removeStream(pluginMediaStream!)
}
}

@objc(RTCPeerConnection_addTrack:) func RTCPeerConnection_addTrack(_ command: CDVInvokedUrlCommand) {

let pcId = command.argument(at: 0) as! Int
let trackId = command.argument(at: 1) as! String
var streamIds : [String] = [];
let pluginRTCPeerConnection = self.pluginRTCPeerConnections[pcId]
let pluginMediaStreamTrack = self.pluginMediaStreamTracks[trackId]

if pluginRTCPeerConnection == nil {
NSLog("iosrtcPlugin#RTCPeerConnection_addTrack() | ERROR: pluginRTCPeerConnection with pcId=%@ does not exist", String(pcId))
return;
}

if command.argument(at: 2) != nil {
let id = command.argument(at: 2) as! String
let pluginMediaStream = self.pluginMediaStreams[id]

if pluginMediaStream == nil {
NSLog("iosrtcPlugin#RTCPeerConnection_addTrack() | ERROR: pluginMediaStream with id=%@ does not exist", String(id))
return;
}

let streamId = pluginMediaStream!.rtcMediaStream.streamId;
streamIds.append(streamId)
self.saveMediaStream(pluginMediaStream!)
}

if pluginMediaStreamTrack == nil {
NSLog("iosrtcPlugin#RTCPeerConnection_addTrack() | ERROR: pluginMediaStreamTrack with id=\(trackId) does not exist")
return;
}

self.queue.async { [weak pluginRTCPeerConnection, weak pluginMediaStreamTrack] in
if pluginRTCPeerConnection?.addTrack(pluginMediaStreamTrack!, streamIds) == true {
self.saveMediaStreamTrack(pluginMediaStreamTrack!)
}
}
}

@objc(RTCPeerConnection_removeTrack:) func RTCPeerConnection_removeTrack(_ command: CDVInvokedUrlCommand) {
let pcId = command.argument(at: 0) as! Int
let trackId = command.argument(at: 1) as! String
let streamId = command.argument(at: 2) as! String
let pluginRTCPeerConnection = self.pluginRTCPeerConnections[pcId]
let pluginMediaStream = self.pluginMediaStreams[streamId]
let pluginMediaStreamTrack = self.pluginMediaStreamTracks[trackId]

if pluginRTCPeerConnection == nil {
NSLog("iosrtcPlugin#RTCPeerConnection_removeTrack() | ERROR: pluginRTCPeerConnection with pcId=%@ does not exist", String(pcId))
return;
}

if pluginMediaStream == nil {
NSLog("iosrtcPlugin#RTCPeerConnection_removeTrack() | ERROR: pluginMediaStream with id=%@ does not exist", String(streamId))
return;
}

if pluginMediaStreamTrack == nil {
NSLog("iosrtcPlugin#RTCPeerConnection_removeTrack() | ERROR: pluginMediaStreamTrack with id=\(trackId) does not exist")
return;
}

self.queue.async { [weak pluginRTCPeerConnection, weak pluginMediaStreamTrack] in
pluginRTCPeerConnection?.removeTrack(pluginMediaStreamTrack!)
// TODO remove only if not used by other stream
Expand Down Expand Up @@ -684,15 +684,18 @@ class iosrtcPlugin : CDVPlugin {
}

@objc(MediaStream_init:) func MediaStream_init(_ command: CDVInvokedUrlCommand) {

NSLog("iosrtcPlugin#MediaStream_init()")

let streamId = command.argument(at: 0) as! String

if self.pluginMediaStreams[streamId] == nil {
let rtcMediaStream : RTCMediaStream = self.rtcPeerConnectionFactory.mediaStream(withStreamId: streamId)
let pluginMediaStream = PluginMediaStream(rtcMediaStream: rtcMediaStream)
pluginMediaStream.run()

self.saveMediaStream(pluginMediaStream)
} else {
NSLog("iosrtcPlugin#MediaStream_init() | ERROR: pluginMediaStream with id=%@ already exist", String(streamId))
}
}

Expand Down Expand Up @@ -769,7 +772,7 @@ class iosrtcPlugin : CDVPlugin {

self.queue.async { [weak pluginMediaStream, weak pluginMediaStreamTrack] in
pluginMediaStream?.removeTrack(pluginMediaStreamTrack!)

// TODO only stop if no more pluginMediaStream attached only
// currently pluginMediaStreamTrack can be attached to more than one pluginMediaStream
// use track.stop() or stream.stop() to stop tracks
Expand Down Expand Up @@ -856,7 +859,7 @@ class iosrtcPlugin : CDVPlugin {
pluginMediaStreamTrack?.stop()
}
}

@objc(new_MediaStreamRenderer:) func new_MediaStreamRenderer(_ command: CDVInvokedUrlCommand) {
NSLog("iosrtcPlugin#new_MediaStreamRenderer()")

Expand Down Expand Up @@ -935,15 +938,15 @@ class iosrtcPlugin : CDVPlugin {

@objc(MediaStreamRenderer_save:) func MediaStreamRenderer_save(_ command: CDVInvokedUrlCommand) {
NSLog("iosrtcPlugin#MediaStreamRenderer_save()")

let id = command.argument(at: 0) as! Int
let pluginMediaStreamRenderer = self.pluginMediaStreamRenderers[id]

if pluginMediaStreamRenderer == nil {
NSLog("iosrtcPlugin#MediaStreamRenderer_save() | ERROR: pluginMediaStreamRenderer with id=%@ does not exist", String(id))
return;
}

let based64 = pluginMediaStreamRenderer!.save()
self.emit(command.callbackId,
result: CDVPluginResult(
Expand Down Expand Up @@ -1009,29 +1012,29 @@ class iosrtcPlugin : CDVPlugin {
)
}
}

@objc(RTCRequestPermission:) func RTCRequestPermission(_ command: CDVInvokedUrlCommand) {
DispatchQueue.main.async {
let audioRequested: Bool = CBool(command.arguments[0] as! Bool)
let videoRequested: Bool = CBool(command.arguments[1] as! Bool)
var status: Bool = true

if videoRequested == true {
switch AVCaptureDevice.authorizationStatus(for: AVMediaType.video) {
case AVAuthorizationStatus.notDetermined:
NSLog("PluginGetUserMedia#call() | video authorization: not determined")
case AVAuthorizationStatus.authorized:
NSLog("PluginGetUserMedia#call() | video authorization: authorized")
case AVAuthorizationStatus.denied:

NSLog("PluginGetUserMedia#call() | video authorization: denied")
status = false
case AVAuthorizationStatus.restricted:
NSLog("PluginGetUserMedia#call() | video authorization: restricted")
status = false
}
}

if audioRequested == true {
switch AVCaptureDevice.authorizationStatus(for: AVMediaType.audio) {
case AVAuthorizationStatus.notDetermined:
Expand All @@ -1046,7 +1049,7 @@ class iosrtcPlugin : CDVPlugin {
status = false
}
}

if (status) {
self.emit(command.callbackId,result: CDVPluginResult(status: CDVCommandStatus_OK))
} else {
Expand All @@ -1062,7 +1065,7 @@ class iosrtcPlugin : CDVPlugin {
self.emit(command.callbackId, result: CDVPluginResult(status: CDVCommandStatus_OK))
}
}

@objc(selectAudioOutputEarpiece:) func selectAudioOutputEarpiece(_ command: CDVInvokedUrlCommand) {
NSLog("iosrtcPlugin#selectAudioOutputEarpiece()")

Expand All @@ -1071,7 +1074,7 @@ class iosrtcPlugin : CDVPlugin {

@objc(selectAudioOutputSpeaker:) func selectAudioOutputSpeaker(_ command: CDVInvokedUrlCommand) {
NSLog("iosrtcPlugin#selectAudioOutputSpeaker()")

PluginRTCAudioController.selectAudioOutputSpeaker()
}

Expand Down