openvidu-browser: Safari video attributes. iOS Ionic bug fix (setRemoteDescription delayed)

pull/173/head
pabloFuente 2018-12-05 11:19:40 +01:00
parent 0e80c9b626
commit b0bc3d40d2
6 changed files with 43 additions and 11 deletions

View File

@ -202,7 +202,7 @@ export class LocalRecorder {
this.videoPreview.id = this.id; this.videoPreview.id = this.id;
this.videoPreview.autoplay = true; this.videoPreview.autoplay = true;
if (platform.name === 'Safari' && platform.product === 'iPhone') { if (platform.name === 'Safari') {
this.videoPreview.setAttribute('playsinline', 'true'); this.videoPreview.setAttribute('playsinline', 'true');
} }

View File

@ -293,7 +293,7 @@ export class Publisher extends StreamManager {
this.videoReference = document.createElement('video'); this.videoReference = document.createElement('video');
if (platform.name === 'Safari' && platform.product === 'iPhone') { if (platform.name === 'Safari') {
this.videoReference.setAttribute('playsinline', 'true'); this.videoReference.setAttribute('playsinline', 'true');
} }
@ -314,8 +314,8 @@ export class Publisher extends StreamManager {
if (this.stream.isSendVideo()) { if (this.stream.isSendVideo()) {
if (!this.stream.isSendScreen()) { if (!this.stream.isSendScreen()) {
if (platform['isIonicIos']) { if (platform['isIonicIos'] || platform.name === 'Safari') {
// iOS Ionic. Limitation: cannot set videoDimensions directly, as the videoReference is not loaded // iOS Ionic or Safari. Limitation: cannot set videoDimensions directly, as the videoReference is not loaded
// if not added to DOM. Must add it to DOM and wait for videoWidth and videoHeight properties to be defined // if not added to DOM. Must add it to DOM and wait for videoWidth and videoHeight properties to be defined
this.videoReference.style.display = 'none'; this.videoReference.style.display = 'none';

View File

@ -77,6 +77,15 @@ export class Session implements EventDispatcher {
*/ */
remoteStreamsCreated: ObjMap<boolean> = {}; remoteStreamsCreated: ObjMap<boolean> = {};
/**
* @hidden
*/
isFirstIonicIosSubscriber: boolean = true;
/**
* @hidden
*/
countDownForIonicIosSubscribers: boolean = true;
/** /**
* @hidden * @hidden
*/ */
@ -658,6 +667,10 @@ export class Session implements EventDispatcher {
streamEvent.callDefaultBehavior(); streamEvent.callDefaultBehavior();
delete this.remoteStreamsCreated[stream.streamId]; delete this.remoteStreamsCreated[stream.streamId];
if (Object.keys(this.remoteStreamsCreated).length === 0) {
this.isFirstIonicIosSubscriber = true;
this.countDownForIonicIosSubscribers = true;
}
} }
delete this.remoteConnections[connection.connectionId]; delete this.remoteConnections[connection.connectionId];
this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent(false, this, 'connectionDestroyed', connection, msg.reason)]); this.ee.emitEvent('connectionDestroyed', [new ConnectionEvent(false, this, 'connectionDestroyed', connection, msg.reason)]);
@ -727,6 +740,10 @@ export class Session implements EventDispatcher {
// Deleting the remote stream // Deleting the remote stream
const streamId: string = connection.stream.streamId; const streamId: string = connection.stream.streamId;
delete this.remoteStreamsCreated[streamId]; delete this.remoteStreamsCreated[streamId];
if (Object.keys(this.remoteStreamsCreated).length === 0) {
this.isFirstIonicIosSubscriber = true;
this.countDownForIonicIosSubscribers = true;
}
connection.removeStream(streamId); connection.removeStream(streamId);
}) })
.catch(openViduError => { .catch(openViduError => {

View File

@ -623,7 +623,7 @@ export class Stream implements EventDispatcher {
reject('Error on publishVideo: ' + JSON.stringify(error)); reject('Error on publishVideo: ' + JSON.stringify(error));
} }
} else { } else {
this.webRtcPeer.processAnswer(response.sdpAnswer) this.webRtcPeer.processAnswer(response.sdpAnswer, false)
.then(() => { .then(() => {
this.streamId = response.id; this.streamId = response.id;
this.isLocalStreamPublished = true; this.isLocalStreamPublished = true;
@ -682,7 +682,16 @@ export class Stream implements EventDispatcher {
if (error) { if (error) {
reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error))); reject(new Error('Error on recvVideoFrom: ' + JSON.stringify(error)));
} else { } else {
this.webRtcPeer.processAnswer(response.sdpAnswer).then(() => { // Ios Ionic. Limitation: some bug in iosrtc cordova plugin makes
// it necessary to add a timeout before processAnswer method
if (this.session.isFirstIonicIosSubscriber) {
this.session.isFirstIonicIosSubscriber = false;
this.session['iosInterval'] = setTimeout(() => {
this.session.countDownForIonicIosSubscribers = false;
}, 400);
}
const needsTimeoutOnProcessAswer = this.session.countDownForIonicIosSubscribers;
this.webRtcPeer.processAnswer(response.sdpAnswer, needsTimeoutOnProcessAswer).then(() => {
this.remotePeerSuccessfullyEstablished(); this.remotePeerSuccessfullyEstablished();
this.initWebRtcStats(); this.initWebRtcStats();
resolve(); resolve();

View File

@ -113,7 +113,7 @@ export class StreamManager implements EventDispatcher {
video: document.createElement('video'), video: document.createElement('video'),
id: '' id: ''
}; };
if (platform.name === 'Safari' && platform.product === 'iPhone') { if (platform.name === 'Safari') {
this.firstVideoElement.video.setAttribute('playsinline', 'true'); this.firstVideoElement.video.setAttribute('playsinline', 'true');
} }
this.targetElement = targEl; this.targetElement = targEl;
@ -334,7 +334,7 @@ export class StreamManager implements EventDispatcher {
video.autoplay = true; video.autoplay = true;
video.controls = false; video.controls = false;
if (platform.name === 'Safari' && platform.product === 'iPhone') { if (platform.name === 'Safari') {
video.setAttribute('playsinline', 'true'); video.setAttribute('playsinline', 'true');
} }

View File

@ -266,7 +266,7 @@ export class WebRtcPeer {
* 3) Function invoked when a SDP answer is received. Final step in SDP negotiation, the peer * 3) Function invoked when a SDP answer is received. Final step in SDP negotiation, the peer
* just needs to set the answer as its remote description * just needs to set the answer as its remote description
*/ */
processAnswer(sdpAnswer: string): Promise<string> { processAnswer(sdpAnswer: string, needsTimeoutOnProcessAswer: boolean): Promise<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const answer: RTCSessionDescriptionInit = { const answer: RTCSessionDescriptionInit = {
@ -279,8 +279,14 @@ export class WebRtcPeer {
if (this.pc.signalingState === 'closed') { if (this.pc.signalingState === 'closed') {
reject('RTCPeerConnection is closed'); reject('RTCPeerConnection is closed');
} }
if (needsTimeoutOnProcessAswer && platform['isIonicIos']) {
setTimeout(() => {
console.info('setRemoteDescription run after timout for iOS device');
this.pc.setRemoteDescription(answer).then(() => resolve()).catch(error => reject(error)); this.pc.setRemoteDescription(answer).then(() => resolve()).catch(error => reject(error));
}, 250);
} else {
this.pc.setRemoteDescription(answer).then(() => resolve()).catch(error => reject(error));
}
}); });
} }