You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SDPDiffer.js 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import { isEqual } from 'lodash-es';
  2. import { XEP } from '../../service/xmpp/XMPPExtensioProtocols';
  3. import SDPUtil from './SDPUtil';
  4. /**
  5. * A class that provides methods for comparing the source information present in two different SDPs so that the delta
  6. * can be signaled to Jicofo via 'source-remove' or 'source-add'.
  7. */
  8. export class SDPDiffer {
  9. /**
  10. * Constructor.
  11. *
  12. * @param {SDP} mySdp - the new SDP.
  13. * @param {SDP} othersSdp - the old SDP.
  14. * @param {boolean} isP2P - Whether the SDPs belong to a p2p peerconnection.
  15. */
  16. constructor(mySdp, othersSdp, isP2P = false) {
  17. this.isP2P = isP2P;
  18. this.mySdp = mySdp;
  19. this.othersSdp = othersSdp;
  20. }
  21. /**
  22. * Returns a map of the sources that are present in 'othersSdp' but not in 'mySdp'.
  23. *
  24. * @returns {*}
  25. */
  26. getNewMedia() {
  27. const mySources = this.mySdp.getMediaSsrcMap();
  28. const othersSources = this.othersSdp.getMediaSsrcMap();
  29. const diff = {};
  30. for (const [ index, othersSource ] of othersSources.entries()) {
  31. const mySource = mySources.get(index);
  32. if (!mySource) {
  33. diff[index] = othersSource;
  34. continue; // eslint-disable-line no-continue
  35. }
  36. const othersSsrcs = Object.keys(othersSource.ssrcs);
  37. if (othersSsrcs.length && !isEqual(Object.keys(mySource.ssrcs).sort(), [ ...othersSsrcs ].sort())) {
  38. diff[index] = othersSource;
  39. }
  40. }
  41. return diff;
  42. }
  43. /**
  44. * Adds the diff source info to the provided IQ stanza.
  45. *
  46. * @param {*} modify - Stanza IQ.
  47. * @returns {boolean}
  48. */
  49. toJingle(modify) {
  50. let modified = false;
  51. const diffSourceInfo = this.getNewMedia();
  52. for (const media of Object.values(diffSourceInfo)) {
  53. modified = true;
  54. modify.c('content', { name: this.isP2P ? media.mid : media.mediaType });
  55. modify.c('description', {
  56. xmlns: XEP.RTP_MEDIA,
  57. media: media.mediaType
  58. });
  59. Object.keys(media.ssrcs).forEach(ssrcNum => {
  60. const mediaSsrc = media.ssrcs[ssrcNum];
  61. const ssrcLines = mediaSsrc.lines;
  62. const sourceName = SDPUtil.parseSourceNameLine(ssrcLines);
  63. const videoType = SDPUtil.parseVideoTypeLine(ssrcLines);
  64. modify.c('source', { xmlns: XEP.SOURCE_ATTRIBUTES });
  65. modify.attrs({
  66. name: sourceName,
  67. videoType,
  68. ssrc: mediaSsrc.ssrc
  69. });
  70. // Only MSID attribute is sent
  71. const msid = SDPUtil.parseMSIDAttribute(ssrcLines);
  72. if (msid) {
  73. modify.c('parameter');
  74. modify.attrs({ name: 'msid' });
  75. modify.attrs({ value: msid });
  76. modify.up();
  77. }
  78. modify.up(); // end of source
  79. });
  80. // generate source groups from lines
  81. media.ssrcGroups.forEach(ssrcGroup => {
  82. if (ssrcGroup.ssrcs.length) {
  83. modify.c('ssrc-group', {
  84. semantics: ssrcGroup.semantics,
  85. xmlns: XEP.SOURCE_ATTRIBUTES
  86. });
  87. ssrcGroup.ssrcs.forEach(ssrc => {
  88. modify.c('source', { ssrc })
  89. .up(); // end of source
  90. });
  91. modify.up(); // end of ssrc-group
  92. }
  93. });
  94. modify.up(); // end of description
  95. modify.up(); // end of content
  96. }
  97. return modified;
  98. }
  99. }