Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

SdpConsistency.js 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /* global __filename */
  2. import { getLogger } from 'jitsi-meet-logger';
  3. import {
  4. parsePrimarySSRC,
  5. parseSecondarySSRC,
  6. SdpTransformWrap
  7. } from './SdpTransformUtil';
  8. const logger = getLogger(__filename);
  9. /**
  10. * Handles the work of keeping video ssrcs consistent across multiple
  11. * o/a cycles, making it such that all stream operations can be
  12. * kept local and do not need to be signaled.
  13. * NOTE: This only keeps the 'primary' video ssrc consistent: meaning
  14. * the primary video stream
  15. */
  16. export default class SdpConsistency {
  17. /**
  18. * Constructor
  19. */
  20. constructor() {
  21. this.clearSsrcCache();
  22. }
  23. /**
  24. * Clear the cached primary and primary rtx ssrcs so that
  25. * they will not be used for the next call to
  26. * makeVideoPrimarySsrcsConsistent
  27. */
  28. clearSsrcCache() {
  29. this.cachedPrimarySsrc = null;
  30. }
  31. /**
  32. * Explicitly set the primary ssrc to be used in
  33. * makeVideoPrimarySsrcsConsistent
  34. * @param {number} primarySsrc the primarySsrc to be used
  35. * in future calls to makeVideoPrimarySsrcsConsistent
  36. * @throws Error if <tt>primarySsrc</tt> is not a number
  37. */
  38. setPrimarySsrc(primarySsrc) {
  39. if (typeof primarySsrc !== 'number') {
  40. throw new Error('Primary SSRC must be a number!');
  41. }
  42. this.cachedPrimarySsrc = primarySsrc;
  43. }
  44. /**
  45. * Given an sdp string, either:
  46. * 1) record the primary video and primary rtx ssrcs to be
  47. * used in future calls to makeVideoPrimarySsrcsConsistent or
  48. * 2) change the primary and primary rtx ssrcs in the given sdp
  49. * to match the ones previously cached
  50. * @param {string} sdpStr the sdp string to (potentially)
  51. * change to make the video ssrcs consistent
  52. * @returns {string} a (potentially) modified sdp string
  53. * with ssrcs consistent with this class' cache
  54. */
  55. makeVideoPrimarySsrcsConsistent(sdpStr) {
  56. const sdpTransformer = new SdpTransformWrap(sdpStr);
  57. const videoMLine = sdpTransformer.selectMedia('video');
  58. if (!videoMLine) {
  59. logger.error(`No 'video' media found in the sdp: ${sdpStr}`);
  60. return sdpStr;
  61. }
  62. if (videoMLine.direction === 'inactive') {
  63. logger.info(
  64. 'Sdp-consistency doing nothing, video mline is inactive');
  65. return sdpStr;
  66. }
  67. if (videoMLine.direction === 'recvonly') {
  68. // If the mline is recvonly, we'll add the primary
  69. // ssrc as a recvonly ssrc
  70. if (this.cachedPrimarySsrc) {
  71. videoMLine.addSSRCAttribute({
  72. id: this.cachedPrimarySsrc,
  73. attribute: 'cname',
  74. value: `recvonly-${this.cachedPrimarySsrc}`
  75. });
  76. } else {
  77. logger.error('No SSRC found for the recvonly video stream!');
  78. }
  79. } else {
  80. const newPrimarySsrc = videoMLine.getPrimaryVideoSsrc();
  81. if (!newPrimarySsrc) {
  82. logger.info('Sdp-consistency couldn\'t parse new primary ssrc');
  83. return sdpStr;
  84. }
  85. if (this.cachedPrimarySsrc) {
  86. logger.info(
  87. `Sdp-consistency replacing new ssrc ${newPrimarySsrc
  88. } with cached ${this.cachedPrimarySsrc}`);
  89. videoMLine.replaceSSRC(newPrimarySsrc, this.cachedPrimarySsrc);
  90. for (const group of videoMLine.ssrcGroups) {
  91. if (group.semantics === 'FID') {
  92. const primarySsrc = parsePrimarySSRC(group);
  93. const rtxSsrc = parseSecondarySSRC(group);
  94. // eslint-disable-next-line max-depth
  95. if (primarySsrc === newPrimarySsrc) {
  96. group.ssrcs
  97. = `${this.cachedPrimarySsrc} ${rtxSsrc}`;
  98. }
  99. }
  100. }
  101. } else {
  102. this.cachedPrimarySsrc = newPrimarySsrc;
  103. logger.info(
  104. `Sdp-consistency caching primary ssrc ${
  105. this.cachedPrimarySsrc}`);
  106. }
  107. }
  108. return sdpTransformer.toRawSDP();
  109. }
  110. }