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

SDPDiffer.js 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. var SDPUtil = require("./SDPUtil");
  2. function SDPDiffer(mySDP, otherSDP)
  3. {
  4. this.mySDP = mySDP;
  5. this.otherSDP = otherSDP;
  6. }
  7. /**
  8. * Returns map of MediaChannel that contains media contained in
  9. * 'mySDP', but not contained in 'otherSdp'. Mapped by channel idx.
  10. */
  11. SDPDiffer.prototype.getNewMedia = function() {
  12. // this could be useful in Array.prototype.
  13. function arrayEquals(array) {
  14. // if the other array is a falsy value, return
  15. if (!array)
  16. return false;
  17. // compare lengths - can save a lot of time
  18. if (this.length != array.length)
  19. return false;
  20. for (var i = 0, l=this.length; i < l; i++) {
  21. // Check if we have nested arrays
  22. if (this[i] instanceof Array && array[i] instanceof Array) {
  23. // recurse into the nested arrays
  24. if (!this[i].equals(array[i]))
  25. return false;
  26. }
  27. else if (this[i] != array[i]) {
  28. // Warning - two different object instances will never be
  29. // equal: {x:20} != {x:20}
  30. return false;
  31. }
  32. }
  33. return true;
  34. }
  35. var myMedias = this.mySDP.getMediaSsrcMap();
  36. var othersMedias = this.otherSDP.getMediaSsrcMap();
  37. var newMedia = {};
  38. Object.keys(othersMedias).forEach(function(othersMediaIdx) {
  39. var myMedia = myMedias[othersMediaIdx];
  40. var othersMedia = othersMedias[othersMediaIdx];
  41. if(!myMedia && othersMedia) {
  42. // Add whole channel
  43. newMedia[othersMediaIdx] = othersMedia;
  44. return;
  45. }
  46. // Look for new ssrcs across the channel
  47. Object.keys(othersMedia.ssrcs).forEach(function(ssrc) {
  48. if(Object.keys(myMedia.ssrcs).indexOf(ssrc) === -1) {
  49. // Allocate channel if we've found ssrc that doesn't exist in
  50. // our channel
  51. if(!newMedia[othersMediaIdx]){
  52. newMedia[othersMediaIdx] = {
  53. mediaindex: othersMedia.mediaindex,
  54. mid: othersMedia.mid,
  55. ssrcs: {},
  56. ssrcGroups: []
  57. };
  58. }
  59. newMedia[othersMediaIdx].ssrcs[ssrc] = othersMedia.ssrcs[ssrc];
  60. }
  61. });
  62. // Look for new ssrc groups across the channels
  63. othersMedia.ssrcGroups.forEach(function(otherSsrcGroup){
  64. // try to match the other ssrc-group with an ssrc-group of ours
  65. var matched = false;
  66. for (var i = 0; i < myMedia.ssrcGroups.length; i++) {
  67. var mySsrcGroup = myMedia.ssrcGroups[i];
  68. if (otherSsrcGroup.semantics == mySsrcGroup.semantics &&
  69. arrayEquals.apply(otherSsrcGroup.ssrcs,
  70. [mySsrcGroup.ssrcs])) {
  71. matched = true;
  72. break;
  73. }
  74. }
  75. if (!matched) {
  76. // Allocate channel if we've found an ssrc-group that doesn't
  77. // exist in our channel
  78. if(!newMedia[othersMediaIdx]){
  79. newMedia[othersMediaIdx] = {
  80. mediaindex: othersMedia.mediaindex,
  81. mid: othersMedia.mid,
  82. ssrcs: {},
  83. ssrcGroups: []
  84. };
  85. }
  86. newMedia[othersMediaIdx].ssrcGroups.push(otherSsrcGroup);
  87. }
  88. });
  89. });
  90. return newMedia;
  91. };
  92. /**
  93. * TODO: document!
  94. */
  95. SDPDiffer.prototype.toJingle = function(modify) {
  96. var sdpMediaSsrcs = this.getNewMedia();
  97. var modified = false;
  98. Object.keys(sdpMediaSsrcs).forEach(function(mediaindex){
  99. modified = true;
  100. var media = sdpMediaSsrcs[mediaindex];
  101. modify.c('content', {name: media.mid});
  102. modify.c('description',
  103. {xmlns:'urn:xmpp:jingle:apps:rtp:1', media: media.mid});
  104. // FIXME: not completely sure this operates on blocks and / or handles
  105. // different ssrcs correctly
  106. // generate sources from lines
  107. Object.keys(media.ssrcs).forEach(function(ssrcNum) {
  108. var mediaSsrc = media.ssrcs[ssrcNum];
  109. modify.c('source', { xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
  110. modify.attrs({ssrc: mediaSsrc.ssrc});
  111. // iterate over ssrc lines
  112. mediaSsrc.lines.forEach(function (line) {
  113. var idx = line.indexOf(' ');
  114. var kv = line.substr(idx + 1);
  115. modify.c('parameter');
  116. if (kv.indexOf(':') == -1) {
  117. modify.attrs({ name: kv });
  118. } else {
  119. var nv = kv.split(':', 2);
  120. var name = nv[0];
  121. var value = SDPUtil.filter_special_chars(nv[1]);
  122. modify.attrs({ name: name });
  123. modify.attrs({ value: value });
  124. }
  125. modify.up(); // end of parameter
  126. });
  127. modify.up(); // end of source
  128. });
  129. // generate source groups from lines
  130. media.ssrcGroups.forEach(function(ssrcGroup) {
  131. if (ssrcGroup.ssrcs.length) {
  132. modify.c('ssrc-group', {
  133. semantics: ssrcGroup.semantics,
  134. xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0'
  135. });
  136. ssrcGroup.ssrcs.forEach(function (ssrc) {
  137. modify.c('source', { ssrc: ssrc })
  138. .up(); // end of source
  139. });
  140. modify.up(); // end of ssrc-group
  141. }
  142. });
  143. modify.up(); // end of description
  144. modify.up(); // end of content
  145. });
  146. return modified;
  147. };
  148. module.exports = SDPDiffer;