您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

SendVideoController.js 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
  2. import RTCEvents from '../../service/RTC/RTCEvents';
  3. import FeatureFlags from '../flags/FeatureFlags';
  4. import MediaSessionEvents from '../xmpp/MediaSessionEvents';
  5. /**
  6. * The class manages send video constraints across media sessions({@link JingleSessionPC}) which belong to
  7. * {@link JitsiConference}. It finds the lowest common value, between the local user's send preference and
  8. * the remote party's receive preference. Also this module will consider only the active session's receive value,
  9. * because local tracks are shared and while JVB may have no preference, the remote p2p may have and they may be totally
  10. * different.
  11. */
  12. export default class SendVideoController {
  13. /**
  14. * Creates new instance for a given conference.
  15. *
  16. * @param {JitsiConference} conference - the conference instance for which the new instance will be managing
  17. * the send video quality constraints.
  18. * @param {RTC} rtc - the rtc instance that is responsible for sending the messages on the bridge channel.
  19. */
  20. constructor(conference, rtc) {
  21. this._conference = conference;
  22. this._rtc = rtc;
  23. /**
  24. * Source name based sender constraints.
  25. * @type {Map<string, number>};
  26. */
  27. this._sourceSenderConstraints = new Map();
  28. this._conference.on(
  29. JitsiConferenceEvents._MEDIA_SESSION_STARTED,
  30. session => this._onMediaSessionStarted(session));
  31. this._conference.on(
  32. JitsiConferenceEvents._MEDIA_SESSION_ACTIVE_CHANGED,
  33. () => this._propagateSendMaxFrameHeight());
  34. this._rtc.on(
  35. RTCEvents.SENDER_VIDEO_CONSTRAINTS_CHANGED,
  36. videoConstraints => this._onSenderConstraintsReceived(videoConstraints));
  37. }
  38. /**
  39. * Handles the {@link JitsiConferenceEvents.MEDIA_SESSION_STARTED}, that is when the conference creates new media
  40. * session. It doesn't mean it's already active though. For example the JVB connection may be created after
  41. * the conference has entered the p2p mode already.
  42. *
  43. * @param {JingleSessionPC} mediaSession - the started media session.
  44. * @private
  45. */
  46. _onMediaSessionStarted(mediaSession) {
  47. mediaSession.addListener(
  48. MediaSessionEvents.REMOTE_VIDEO_CONSTRAINTS_CHANGED,
  49. session => {
  50. if (session === this._conference.getActiveMediaSession()) {
  51. this._propagateSendMaxFrameHeight();
  52. }
  53. });
  54. }
  55. /**
  56. * Propagates the video constraints if they have changed.
  57. *
  58. * @param {Object} videoConstraints - The sender video constraints received from the bridge.
  59. */
  60. _onSenderConstraintsReceived(videoConstraints) {
  61. if (FeatureFlags.isSourceNameSignalingEnabled()) {
  62. const { idealHeight, sourceName } = videoConstraints;
  63. const localVideoTracks = this._conference.getLocalVideoTracks() ?? [];
  64. for (const track of localVideoTracks) {
  65. // Propagate the sender constraint only if it has changed.
  66. if (track.getSourceName() === sourceName
  67. && (!this._sourceSenderConstraints.has(sourceName)
  68. || this._sourceSenderConstraints.get(sourceName) !== idealHeight)) {
  69. this._sourceSenderConstraints.set(sourceName, idealHeight);
  70. this._propagateSendMaxFrameHeight(sourceName);
  71. }
  72. }
  73. } else if (this._senderVideoConstraints?.idealHeight !== videoConstraints.idealHeight) {
  74. this._senderVideoConstraints = videoConstraints;
  75. this._propagateSendMaxFrameHeight();
  76. }
  77. }
  78. /**
  79. * Figures out the send video constraint as specified by {@link selectSendMaxFrameHeight} and sets it on all media
  80. * sessions for the reasons mentioned in this class description.
  81. *
  82. * @param {string} sourceName - The source for which sender constraints have changed.
  83. * @returns {Promise<void[]>}
  84. * @private
  85. */
  86. _propagateSendMaxFrameHeight(sourceName = null) {
  87. const sendMaxFrameHeight = this.selectSendMaxFrameHeight(sourceName);
  88. const promises = [];
  89. if (sendMaxFrameHeight >= 0) {
  90. for (const session of this._conference.getMediaSessions()) {
  91. promises.push(session.setSenderVideoConstraint(sendMaxFrameHeight, sourceName));
  92. }
  93. }
  94. return Promise.all(promises);
  95. }
  96. /**
  97. * Selects the lowest common value for the local video send constraint by looking at local user's preference and
  98. * the active media session's receive preference set by the remote party.
  99. *
  100. * @param {string} sourceName - The source for which sender constraints have changed.
  101. * @returns {number|undefined}
  102. */
  103. selectSendMaxFrameHeight(sourceName = null) {
  104. const activeMediaSession = this._conference.getActiveMediaSession();
  105. const remoteRecvMaxFrameHeight = activeMediaSession
  106. ? activeMediaSession.isP2P
  107. ? activeMediaSession.getRemoteRecvMaxFrameHeight()
  108. : sourceName ? this._sourceSenderConstraints.get(sourceName) : this._senderVideoConstraints?.idealHeight
  109. : undefined;
  110. if (this._preferredSendMaxFrameHeight >= 0 && remoteRecvMaxFrameHeight >= 0) {
  111. return Math.min(this._preferredSendMaxFrameHeight, remoteRecvMaxFrameHeight);
  112. } else if (remoteRecvMaxFrameHeight >= 0) {
  113. return remoteRecvMaxFrameHeight;
  114. }
  115. return this._preferredSendMaxFrameHeight;
  116. }
  117. /**
  118. * Sets local preference for max send video frame height.
  119. *
  120. * @param {number} maxFrameHeight - the new value to set.
  121. * @returns {Promise<void[]>} - resolved when the operation is complete.
  122. */
  123. setPreferredSendMaxFrameHeight(maxFrameHeight) {
  124. this._preferredSendMaxFrameHeight = maxFrameHeight;
  125. return this._propagateSendMaxFrameHeight();
  126. }
  127. }