|
@@ -6,7 +6,12 @@ import transform from 'sdp-transform';
|
6
|
6
|
|
7
|
7
|
import * as GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
|
8
|
8
|
import JitsiRemoteTrack from './JitsiRemoteTrack';
|
|
9
|
+import {
|
|
10
|
+ TRACK_ADDED,
|
|
11
|
+ TRACK_MUTE_CHANGED
|
|
12
|
+} from '../../JitsiConferenceEvents';
|
9
|
13
|
import * as MediaType from '../../service/RTC/MediaType';
|
|
14
|
+import * as VideoType from '../../service/RTC/VideoType';
|
10
|
15
|
import LocalSdpMunger from './LocalSdpMunger';
|
11
|
16
|
import RTC from './RTC';
|
12
|
17
|
import RTCUtils from './RTCUtils';
|
|
@@ -335,6 +340,29 @@ export default function TraceablePeerConnection(
|
335
|
340
|
}, 1000);
|
336
|
341
|
}
|
337
|
342
|
|
|
343
|
+ // Set sender video constraints when a new local video track is added
|
|
344
|
+ // to the conference or when it is unmuted.
|
|
345
|
+ this.senderVideoMaxHeight = null;
|
|
346
|
+ const maybeSetSenderVideoConstraints = track => {
|
|
347
|
+ if (track.isLocal()
|
|
348
|
+ && !track.isMuted()
|
|
349
|
+ && track.isVideoTrack()
|
|
350
|
+ && track.videoType === VideoType.CAMERA
|
|
351
|
+ && this.senderVideoMaxHeight) {
|
|
352
|
+ this.setSenderVideoConstraint(this.senderVideoMaxHeight)
|
|
353
|
+ .catch(err => {
|
|
354
|
+ logger.error(`Settings sender video constraints failed: ${err}`);
|
|
355
|
+ });
|
|
356
|
+ }
|
|
357
|
+ };
|
|
358
|
+
|
|
359
|
+ this.rtc.conference.on(
|
|
360
|
+ TRACK_ADDED,
|
|
361
|
+ maybeSetSenderVideoConstraints);
|
|
362
|
+ this.rtc.conference.on(
|
|
363
|
+ TRACK_MUTE_CHANGED,
|
|
364
|
+ maybeSetSenderVideoConstraints);
|
|
365
|
+
|
338
|
366
|
logger.info(`Create new ${this}`);
|
339
|
367
|
}
|
340
|
368
|
|
|
@@ -1469,6 +1497,11 @@ TraceablePeerConnection.prototype.addTrack = function(track, isInitiator = false
|
1469
|
1497
|
if (browser.usesUnifiedPlan() && !browser.usesSdpMungingForSimulcast()) {
|
1470
|
1498
|
this.tpcUtils.setEncodings(track);
|
1471
|
1499
|
}
|
|
1500
|
+
|
|
1501
|
+ // Construct the simulcast stream constraints for the newly added track.
|
|
1502
|
+ if (track.isVideoTrack() && track.videoType === VideoType.CAMERA && this.isSimulcastOn()) {
|
|
1503
|
+ this.tpcUtils._setSimulcastStreamConstraints(track.getTrack());
|
|
1504
|
+ }
|
1472
|
1505
|
};
|
1473
|
1506
|
|
1474
|
1507
|
/**
|
|
@@ -2042,6 +2075,79 @@ TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
|
2042
|
2075
|
});
|
2043
|
2076
|
};
|
2044
|
2077
|
|
|
2078
|
+/**
|
|
2079
|
+ * Changes the resolution of the video stream that is sent to the peer based on
|
|
2080
|
+ * the user preferred value. If simulcast is enabled on the peerconection, all the
|
|
2081
|
+ * simulcast encodings that have a resolution height lower or equal to the value
|
|
2082
|
+ * provided will remain active. For the non-simulcast case, video constraint is
|
|
2083
|
+ * applied on the track.
|
|
2084
|
+ * @param {number} frameHeight - The user preferred max frame height.
|
|
2085
|
+ * @returns {Promise} promise that will be resolved when the operation is
|
|
2086
|
+ * successful and rejected otherwise.
|
|
2087
|
+ */
|
|
2088
|
+TraceablePeerConnection.prototype.setSenderVideoConstraint = function(frameHeight) {
|
|
2089
|
+ this.senderVideoMaxHeight = frameHeight;
|
|
2090
|
+ const localVideoTrack = Array.from(this.localTracks.values()).find(t => t.isVideoTrack());
|
|
2091
|
+
|
|
2092
|
+ if (!localVideoTrack || localVideoTrack.isMuted() || localVideoTrack.videoType !== VideoType.CAMERA) {
|
|
2093
|
+ return Promise.resolve();
|
|
2094
|
+ }
|
|
2095
|
+ const track = localVideoTrack.getTrack();
|
|
2096
|
+
|
|
2097
|
+ if (this.isSimulcastOn()) {
|
|
2098
|
+ let promise = Promise.resolve();
|
|
2099
|
+
|
|
2100
|
+ // Check if the track constraints have been modified in p2p mode, apply
|
|
2101
|
+ // the constraints that were used for creating the track if that is the case.
|
|
2102
|
+ const height = localVideoTrack._constraints.height.ideal
|
|
2103
|
+ ? localVideoTrack._constraints.height.ideal
|
|
2104
|
+ : localVideoTrack._constraints.height;
|
|
2105
|
+
|
|
2106
|
+ if (track.getSettings().height !== height) {
|
|
2107
|
+ promise = track.applyConstraints(localVideoTrack._constraints);
|
|
2108
|
+ }
|
|
2109
|
+
|
|
2110
|
+ return promise
|
|
2111
|
+ .then(() => {
|
|
2112
|
+ // Determine the encodings that need to stay enabled based on the
|
|
2113
|
+ // new frameHeight provided.
|
|
2114
|
+ const encodingsEnabledState = this.tpcUtils.simulcastStreamConstraints
|
|
2115
|
+ .map(constraint => constraint.height <= frameHeight);
|
|
2116
|
+ const videoSender = this.findSenderByKind(MediaType.VIDEO);
|
|
2117
|
+
|
|
2118
|
+ if (!videoSender) {
|
|
2119
|
+ return Promise.reject(new Error('RTCRtpSender not found for local video'));
|
|
2120
|
+ }
|
|
2121
|
+ const parameters = videoSender.getParameters();
|
|
2122
|
+
|
|
2123
|
+ if (!parameters || !parameters.encodings || !parameters.encodings.length) {
|
|
2124
|
+ return Promise.reject(new Error('RTCRtpSendParameters not found for local video track'));
|
|
2125
|
+ }
|
|
2126
|
+ logger.debug(`Setting max height of ${frameHeight} on local video`);
|
|
2127
|
+ for (const encoding in parameters.encodings) {
|
|
2128
|
+ if (parameters.encodings.hasOwnProperty(encoding)) {
|
|
2129
|
+ parameters.encodings[encoding].active = encodingsEnabledState[encoding];
|
|
2130
|
+ }
|
|
2131
|
+ }
|
|
2132
|
+
|
|
2133
|
+ return videoSender.setParameters(parameters);
|
|
2134
|
+ });
|
|
2135
|
+ }
|
|
2136
|
+
|
|
2137
|
+ // Apply the height constraint on the local camera track
|
|
2138
|
+ const aspectRatio = (track.getSettings().width / track.getSettings().height).toPrecision(4);
|
|
2139
|
+
|
|
2140
|
+ logger.debug(`Setting max height of ${frameHeight} on local video`);
|
|
2141
|
+
|
|
2142
|
+ return track.applyConstraints(
|
|
2143
|
+ {
|
|
2144
|
+ aspectRatio,
|
|
2145
|
+ height: {
|
|
2146
|
+ ideal: frameHeight
|
|
2147
|
+ }
|
|
2148
|
+ });
|
|
2149
|
+};
|
|
2150
|
+
|
2045
|
2151
|
/**
|
2046
|
2152
|
* Enables/disables video media transmission on this peer connection. When
|
2047
|
2153
|
* disabled the SDP video media direction in the local SDP will be adjusted to
|