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ů.

LocalSdpMunger.js 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /* global __filename */
  2. import { getLogger } from 'jitsi-meet-logger';
  3. import * as MediaType from '../../service/RTC/MediaType';
  4. import { SdpTransformWrap } from '../xmpp/SdpTransformUtil';
  5. const logger = getLogger(__filename);
  6. /**
  7. * Fakes local SDP exposed to {@link JingleSessionPC} through the local
  8. * description getter. Modifies the SDP, so that it will contain muted local
  9. * video tracks description, even though their underlying {MediaStreamTrack}s
  10. * are no longer in the WebRTC peerconnection. That prevents from SSRC updates
  11. * being sent to Jicofo/remote peer and prevents sRD/sLD cycle on the remote
  12. * side.
  13. */
  14. export default class LocalSdpMunger {
  15. /**
  16. * Creates new <tt>LocalSdpMunger</tt> instance.
  17. *
  18. * @param {TraceablePeerConnection} tpc
  19. */
  20. constructor(tpc) {
  21. this.tpc = tpc;
  22. }
  23. /**
  24. * Makes sure that muted local video tracks associated with the parent
  25. * {@link TraceablePeerConnection} are described in the local SDP. It's done
  26. * in order to prevent from sending 'source-remove'/'source-add' Jingle
  27. * notifications when local video track is muted (<tt>MediaStream</tt> is
  28. * removed from the peerconnection).
  29. *
  30. * NOTE 1 video track is assumed
  31. *
  32. * @param {SdpTransformWrap} transformer the transformer instance which will
  33. * be used to process the SDP.
  34. * @return {boolean} <tt>true</tt> if there were any modifications to
  35. * the SDP wrapped by <tt>transformer</tt>.
  36. * @private
  37. */
  38. _addMutedLocalVideoTracksToSDP(transformer) {
  39. // Go over each video tracks and check if the SDP has to be changed
  40. const localVideos = this.tpc.getLocalTracks(MediaType.VIDEO);
  41. if (!localVideos.length) {
  42. return false;
  43. } else if (localVideos.length !== 1) {
  44. logger.error(
  45. `${this.tpc} there is more than 1 video track ! `
  46. + 'Strange things may happen !', localVideos);
  47. }
  48. const videoMLine = transformer.selectMedia('video');
  49. if (!videoMLine) {
  50. logger.error(
  51. `${this.tpc} unable to hack local video track SDP`
  52. + '- no "video" media');
  53. return false;
  54. }
  55. let modified = false;
  56. for (const videoTrack of localVideos) {
  57. const isMuted = videoTrack.isMuted();
  58. const muteInProgress = videoTrack.inMuteOrUnmuteProgress;
  59. const shouldFakeSdp = isMuted || muteInProgress;
  60. logger.debug(
  61. `${this.tpc} ${videoTrack
  62. } isMuted: ${isMuted
  63. }, is mute in progress: ${muteInProgress
  64. } => should fake sdp ? : ${shouldFakeSdp}`);
  65. if (!shouldFakeSdp) {
  66. // eslint-disable-next-line no-continue
  67. continue;
  68. }
  69. // Inject removed SSRCs
  70. const requiredSSRCs
  71. = this.tpc.isSimulcastOn()
  72. ? this.tpc.simulcast.ssrcCache
  73. : [ this.tpc.sdpConsistency.cachedPrimarySsrc ];
  74. if (!requiredSSRCs.length) {
  75. logger.error(
  76. `No SSRCs stored for: ${videoTrack} in ${this.tpc}`);
  77. // eslint-disable-next-line no-continue
  78. continue;
  79. }
  80. if (!videoMLine.getSSRCCount()) {
  81. logger.error(
  82. `${this.tpc} - no video SSRCs found`
  83. + '(should be at least the recv-only one)');
  84. // eslint-disable-next-line no-continue
  85. continue;
  86. }
  87. modified = true;
  88. // We need to fake sendrecv.
  89. // NOTE the SDP produced here goes only to Jicofo and is never set
  90. // as localDescription. That's why
  91. // {@link TraceablePeerConnection.mediaTransferActive} is ignored
  92. // here.
  93. videoMLine.direction = 'sendrecv';
  94. // Check if the recvonly has MSID
  95. const primarySSRC = requiredSSRCs[0];
  96. // FIXME the cname could come from the stream, but may
  97. // turn out to be too complex. It is fine to come up
  98. // with any value, as long as we only care about
  99. // the actual SSRC values when deciding whether or not
  100. // an update should be sent
  101. const primaryCname = `injected-${primarySSRC}`;
  102. for (const ssrcNum of requiredSSRCs) {
  103. // Remove old attributes
  104. videoMLine.removeSSRC(ssrcNum);
  105. // Inject
  106. logger.debug(
  107. `${this.tpc} injecting video SSRC: `
  108. + `${ssrcNum} for ${videoTrack}`);
  109. videoMLine.addSSRCAttribute({
  110. id: ssrcNum,
  111. attribute: 'cname',
  112. value: primaryCname
  113. });
  114. videoMLine.addSSRCAttribute({
  115. id: ssrcNum,
  116. attribute: 'msid',
  117. value: videoTrack.storedMSID
  118. });
  119. }
  120. if (requiredSSRCs.length > 1) {
  121. const group = {
  122. ssrcs: requiredSSRCs.join(' '),
  123. semantics: 'SIM'
  124. };
  125. if (!videoMLine.findGroup(group.semantics, group.ssrcs)) {
  126. // Inject the group
  127. logger.debug(
  128. `${this.tpc} injecting SIM group for ${videoTrack}`,
  129. group);
  130. videoMLine.addSSRCGroup(group);
  131. }
  132. }
  133. // Insert RTX
  134. // FIXME in P2P RTX is used by Chrome regardless of config option
  135. // status. Because of that 'source-remove'/'source-add'
  136. // notifications are still sent to remove/add RTX SSRC and FID group
  137. if (!this.tpc.options.disableRtx) {
  138. this.tpc.rtxModifier.modifyRtxSsrcs2(videoMLine);
  139. }
  140. }
  141. return modified;
  142. }
  143. /**
  144. * Maybe modifies local description to fake local video tracks SDP when
  145. * those are muted.
  146. *
  147. * @param {object} desc the WebRTC SDP object instance for the local
  148. * description.
  149. */
  150. maybeMungeLocalSdp(desc) {
  151. // Nothing to be done in early stage when localDescription
  152. // is not available yet
  153. if (!desc || !desc.sdp) {
  154. return;
  155. }
  156. const transformer = new SdpTransformWrap(desc.sdp);
  157. if (this._addMutedLocalVideoTracksToSDP(transformer)) {
  158. // Write
  159. desc.sdp = transformer.toRawSDP();
  160. // logger.info("Post TRANSFORM: ", desc.sdp);
  161. }
  162. }
  163. }