Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

SendVideoController.js 4.9KB

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