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

SDPDiffer.spec.js 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. import { $iq } from 'strophe.js';
  2. import FeatureFlags from '../flags/FeatureFlags';
  3. import SDP from './SDP';
  4. import { SDPDiffer } from './SDPDiffer';
  5. import SampleSdpStrings from './SampleSdpStrings';
  6. /* eslint-disable max-len*/
  7. describe('SDPDiffer', () => {
  8. beforeEach(() => {
  9. FeatureFlags.init({ });
  10. });
  11. describe('toJingle', () => {
  12. it('should include source names in added/removed sources', () => {
  13. FeatureFlags.init({ });
  14. const testSdpOld = [
  15. 'v=0\r\n',
  16. 'o=thisisadapterortc 2719486166053431 0 IN IP4 127.0.0.1\r\n',
  17. 's=-\r\n',
  18. 't=0 0\r\n',
  19. 'a=group:BUNDLE audio video\r\n',
  20. 'm=audio 9 UDP/TLS/RTP/SAVPF 111 126\r\n',
  21. 'a=mid:audio\r\n',
  22. 'a=ssrc:2002 msid:26D16D51-503A-420B-8274-3DD1174E498F 8205D1FC-50B4-407C-87D5-9C45F1B779F0\r\n',
  23. 'a=ssrc:2002 cname:juejgy8a01\r\n',
  24. 'a=ssrc:2002 name:a8f7g30-a0\r\n',
  25. 'm=video 9 UDP/TLS/RTP/SAVPF 107 100 99 96\r\n',
  26. 'a=mid:video\r\n'
  27. ].join('');
  28. const testSdpNew = [
  29. 'v=0\r\n',
  30. 'o=thisisadapterortc 2719486166053431 0 IN IP4 127.0.0.1\r\n',
  31. 's=-\r\n',
  32. 't=0 0\r\n',
  33. 'a=group:BUNDLE audio video\r\n',
  34. 'm=audio 9 UDP/TLS/RTP/SAVPF 111 126\r\n',
  35. 'a=mid:audio\r\n',
  36. 'm=video 9 UDP/TLS/RTP/SAVPF 107 100 99 96\r\n',
  37. 'a=mid:video\r\n',
  38. 'a=ssrc:4004 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  39. 'a=ssrc:4005 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  40. 'a=ssrc:4004 cname:juejgy8a01\r\n',
  41. 'a=ssrc:4005 cname:juejgy8a01\r\n',
  42. 'a=ssrc:4004 name:a8f7g30-v0\r\n',
  43. 'a=ssrc:4005 name:a8f7g30-v0\r\n',
  44. 'a=ssrc-group:FID 4004 4005\r\n'
  45. ].join('');
  46. const newToOldDiff = new SDPDiffer(new SDP(testSdpNew), new SDP(testSdpOld));
  47. const sourceRemoveIq = $iq({})
  48. .c('jingle', { action: 'source-remove' });
  49. newToOldDiff.toJingle(sourceRemoveIq);
  50. const removedAudioSources = sourceRemoveIq.nodeTree.querySelectorAll('description[media=\'audio\']>source');
  51. expect(removedAudioSources[0].getAttribute('name')).toBe('a8f7g30-a0');
  52. const oldToNewDiff = new SDPDiffer(new SDP(testSdpOld), new SDP(testSdpNew));
  53. const sourceAddIq = $iq({})
  54. .c('jingle', { action: 'source-add' });
  55. oldToNewDiff.toJingle(sourceAddIq);
  56. const addedVideoSources = sourceAddIq.nodeTree.querySelectorAll('description[media=\'video\']>source');
  57. const addedVideoSourceGroups = sourceAddIq.nodeTree.querySelectorAll('description[media=\'video\']>ssrc-group');
  58. expect(addedVideoSources.length).toBe(2);
  59. expect(addedVideoSources[0].getAttribute('name')).toBe('a8f7g30-v0');
  60. expect(addedVideoSources[1].getAttribute('name')).toBe('a8f7g30-v0');
  61. expect(addedVideoSourceGroups.length).toBe(1);
  62. });
  63. it('should send source-remove/source-add when ssrc changes', () => {
  64. FeatureFlags.init({ });
  65. const testSdpOld = [
  66. 'v=0\r\n',
  67. 'o=thisisadapterortc 2719486166053431 0 IN IP4 127.0.0.1\r\n',
  68. 's=-\r\n',
  69. 't=0 0\r\n',
  70. 'a=group:BUNDLE audio video\r\n',
  71. 'm=audio 9 UDP/TLS/RTP/SAVPF 111 126\r\n',
  72. 'a=mid:audio\r\n',
  73. 'a=ssrc:2002 msid:26D16D51-503A-420B-8274-3DD1174E498F 8205D1FC-50B4-407C-87D5-9C45F1B779F0\r\n',
  74. 'a=ssrc:2002 cname:juejgy8a01\r\n',
  75. 'a=ssrc:2002 name:a8f7g30-a0\r\n',
  76. 'm=video 9 UDP/TLS/RTP/SAVPF 107 100 99 96\r\n',
  77. 'a=mid:video\r\n',
  78. 'a=ssrc:4004 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  79. 'a=ssrc:4005 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  80. 'a=ssrc:4004 cname:juejgy8a01\r\n',
  81. 'a=ssrc:4005 cname:juejgy8a01\r\n',
  82. 'a=ssrc:4004 name:a8f7g30-v0\r\n',
  83. 'a=ssrc:4005 name:a8f7g30-v0\r\n',
  84. 'a=ssrc-group:FID 4004 4005\r\n'
  85. ].join('');
  86. const testSdpNew = [
  87. 'v=0\r\n',
  88. 'o=thisisadapterortc 2719486166053431 0 IN IP4 127.0.0.1\r\n',
  89. 's=-\r\n',
  90. 't=0 0\r\n',
  91. 'a=group:BUNDLE audio video\r\n',
  92. 'm=audio 9 UDP/TLS/RTP/SAVPF 111 126\r\n',
  93. 'a=mid:audio\r\n',
  94. 'a=ssrc:2003 msid:26D16D51-503A-420B-8274-3DD1174E498F 8205D1FC-50B4-407C-87D5-9C45F1B779F0\r\n',
  95. 'a=ssrc:2003 cname:juejgy8a01\r\n',
  96. 'a=ssrc:2003 name:a8f7g30-a0\r\n',
  97. 'm=video 9 UDP/TLS/RTP/SAVPF 107 100 99 96\r\n',
  98. 'a=mid:video\r\n',
  99. 'a=ssrc:4004 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  100. 'a=ssrc:4005 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  101. 'a=ssrc:4004 cname:juejgy8a01\r\n',
  102. 'a=ssrc:4005 cname:juejgy8a01\r\n',
  103. 'a=ssrc:4004 name:a8f7g30-v0\r\n',
  104. 'a=ssrc:4005 name:a8f7g30-v0\r\n',
  105. 'a=ssrc-group:FID 4004 4005\r\n'
  106. ].join('');
  107. const newToOldDiff = new SDPDiffer(new SDP(testSdpNew), new SDP(testSdpOld));
  108. const sourceRemoveIq = $iq({})
  109. .c('jingle', { action: 'source-remove' });
  110. newToOldDiff.toJingle(sourceRemoveIq);
  111. const removedAudioSources = sourceRemoveIq.nodeTree.querySelectorAll('description[media=\'audio\']>source');
  112. const removedVideoSources = sourceRemoveIq.nodeTree.querySelectorAll('description[media=\'video\']>source');
  113. expect(removedAudioSources.length).toBe(1);
  114. expect(removedAudioSources[0].getAttribute('name')).toBe('a8f7g30-a0');
  115. expect(removedAudioSources[0].getAttribute('ssrc')).toBe('2002');
  116. expect(removedVideoSources.length).toBe(0);
  117. const oldToNewDiff = new SDPDiffer(new SDP(testSdpOld), new SDP(testSdpNew));
  118. const sourceAddIq = $iq({})
  119. .c('jingle', { action: 'source-add' });
  120. oldToNewDiff.toJingle(sourceAddIq);
  121. const addedAudioSources = sourceAddIq.nodeTree.querySelectorAll('description[media=\'audio\']>source');
  122. const addedVideoSources = sourceAddIq.nodeTree.querySelectorAll('description[media=\'video\']>source');
  123. expect(addedAudioSources.length).toBe(1);
  124. expect(addedAudioSources[0].getAttribute('name')).toBe('a8f7g30-a0');
  125. expect(addedAudioSources[0].getAttribute('ssrc')).toBe('2003');
  126. expect(addedVideoSources.length).toBe(0);
  127. });
  128. it('should not send source-remove/source-add when nothing changes', () => {
  129. FeatureFlags.init({ });
  130. const testSdpOld = [
  131. 'v=0\r\n',
  132. 'o=thisisadapterortc 2719486166053431 0 IN IP4 127.0.0.1\r\n',
  133. 's=-\r\n',
  134. 't=0 0\r\n',
  135. 'a=group:BUNDLE audio video\r\n',
  136. 'm=audio 9 UDP/TLS/RTP/SAVPF 111 126\r\n',
  137. 'a=mid:audio\r\n',
  138. 'a=ssrc:2002 msid:26D16D51-503A-420B-8274-3DD1174E498F 8205D1FC-50B4-407C-87D5-9C45F1B779F0\r\n',
  139. 'a=ssrc:2002 cname:juejgy8a01\r\n',
  140. 'a=ssrc:2002 name:a8f7g30-a0\r\n',
  141. 'm=video 9 UDP/TLS/RTP/SAVPF 107 100 99 96\r\n',
  142. 'a=mid:video\r\n',
  143. 'a=ssrc:4004 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  144. 'a=ssrc:4005 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  145. 'a=ssrc:4004 cname:juejgy8a01\r\n',
  146. 'a=ssrc:4005 cname:juejgy8a01\r\n',
  147. 'a=ssrc:4004 name:a8f7g30-v0\r\n',
  148. 'a=ssrc:4005 name:a8f7g30-v0\r\n',
  149. 'a=ssrc-group:FID 4004 4005\r\n'
  150. ].join('');
  151. const testSdpNew = [
  152. 'v=0\r\n',
  153. 'o=thisisadapterortc 2719486166053431 0 IN IP4 127.0.0.1\r\n',
  154. 's=-\r\n',
  155. 't=0 0\r\n',
  156. 'a=group:BUNDLE audio video\r\n',
  157. 'm=audio 9 UDP/TLS/RTP/SAVPF 111 126\r\n',
  158. 'a=mid:audio\r\n',
  159. 'a=ssrc:2002 msid:26D16D51-503A-420B-8274-3DD1174E498F 8205D1FC-50B4-407C-87D5-9C45F1B779F0\r\n',
  160. 'a=ssrc:2002 cname:juejgy8a01\r\n',
  161. 'a=ssrc:2002 name:a8f7g30-a0\r\n',
  162. 'm=video 9 UDP/TLS/RTP/SAVPF 107 100 99 96\r\n',
  163. 'a=mid:video\r\n',
  164. 'a=ssrc:4004 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  165. 'a=ssrc:4005 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  166. 'a=ssrc:4004 cname:juejgy8a01\r\n',
  167. 'a=ssrc:4005 cname:juejgy8a01\r\n',
  168. 'a=ssrc:4004 name:a8f7g30-v0\r\n',
  169. 'a=ssrc:4005 name:a8f7g30-v0\r\n',
  170. 'a=ssrc-group:FID 4004 4005\r\n'
  171. ].join('');
  172. const newToOldDiff = new SDPDiffer(new SDP(testSdpNew), new SDP(testSdpOld));
  173. const sourceRemoveIq = $iq({})
  174. .c('jingle', { action: 'source-remove' });
  175. newToOldDiff.toJingle(sourceRemoveIq);
  176. const removedAudioSources = sourceRemoveIq.nodeTree.querySelectorAll('description[media=\'audio\']>source');
  177. const removedVideoSources = sourceRemoveIq.nodeTree.querySelectorAll('description[media=\'video\']>source');
  178. expect(removedAudioSources.length).toBe(0);
  179. expect(removedVideoSources.length).toBe(0);
  180. const oldToNewDiff = new SDPDiffer(new SDP(testSdpOld), new SDP(testSdpNew));
  181. const sourceAddIq = $iq({})
  182. .c('jingle', { action: 'source-add' });
  183. oldToNewDiff.toJingle(sourceAddIq);
  184. const addedAudioSources = sourceAddIq.nodeTree.querySelectorAll('description[media=\'audio\']>source');
  185. const addedVideoSources = sourceAddIq.nodeTree.querySelectorAll('description[media=\'video\']>source');
  186. expect(addedAudioSources.length).toBe(0);
  187. expect(addedVideoSources.length).toBe(0);
  188. });
  189. it('should send source-adds for 2 sources', () => {
  190. FeatureFlags.init({ });
  191. const testSdpOld = [
  192. 'v=0\r\n',
  193. 'o=thisisadapterortc 2719486166053431 0 IN IP4 127.0.0.1\r\n',
  194. 's=-\r\n',
  195. 't=0 0\r\n',
  196. 'a=group:BUNDLE audio video\r\n',
  197. 'm=audio 9 UDP/TLS/RTP/SAVPF 111 126\r\n',
  198. 'a=mid:audio\r\n',
  199. 'm=video 9 UDP/TLS/RTP/SAVPF 107 100 99 96\r\n',
  200. 'a=mid:video\r\n'
  201. ].join('');
  202. const testSdpNew = [
  203. 'v=0\r\n',
  204. 'o=thisisadapterortc 2719486166053431 0 IN IP4 127.0.0.1\r\n',
  205. 's=-\r\n',
  206. 't=0 0\r\n',
  207. 'a=group:BUNDLE audio video\r\n',
  208. 'm=audio 9 UDP/TLS/RTP/SAVPF 111 126\r\n',
  209. 'a=mid:audio\r\n',
  210. 'a=ssrc:2002 msid:26D16D51-503A-420B-8274-3DD1174E498F 8205D1FC-50B4-407C-87D5-9C45F1B779F0\r\n',
  211. 'a=ssrc:2002 cname:juejgy8a01\r\n',
  212. 'a=ssrc:2002 name:a8f7g30-a0\r\n',
  213. 'm=video 9 UDP/TLS/RTP/SAVPF 107 100 99 96\r\n',
  214. 'a=mid:video\r\n',
  215. 'a=ssrc:4004 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  216. 'a=ssrc:4005 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  217. 'a=ssrc:4004 cname:juejgy8a01\r\n',
  218. 'a=ssrc:4005 cname:juejgy8a01\r\n',
  219. 'a=ssrc:4004 name:a8f7g30-v0\r\n',
  220. 'a=ssrc:4005 name:a8f7g30-v0\r\n',
  221. 'a=ssrc-group:FID 4004 4005\r\n'
  222. ].join('');
  223. const newToOldDiff = new SDPDiffer(new SDP(testSdpNew), new SDP(testSdpOld));
  224. const sourceRemoveIq = $iq({})
  225. .c('jingle', { action: 'source-remove' });
  226. newToOldDiff.toJingle(sourceRemoveIq);
  227. const removedAudioSources = sourceRemoveIq.nodeTree.querySelectorAll('description[media=\'audio\']>source');
  228. const removedVideoSources = sourceRemoveIq.nodeTree.querySelectorAll('description[media=\'video\']>source');
  229. expect(removedAudioSources.length).toBe(0);
  230. expect(removedVideoSources.length).toBe(0);
  231. const oldToNewDiff = new SDPDiffer(new SDP(testSdpOld), new SDP(testSdpNew));
  232. const sourceAddIq = $iq({})
  233. .c('jingle', { action: 'source-add' });
  234. oldToNewDiff.toJingle(sourceAddIq);
  235. const addedAudioSources = sourceAddIq.nodeTree.querySelectorAll('description[media=\'audio\']>source');
  236. const addedVideoSources = sourceAddIq.nodeTree.querySelectorAll('description[media=\'video\']>source');
  237. const addedVideoSourceGroups = sourceAddIq.nodeTree.querySelectorAll('description[media=\'video\']>ssrc-group');
  238. expect(addedAudioSources.length).toBe(1);
  239. expect(addedVideoSources.length).toBe(2);
  240. expect(addedVideoSourceGroups.length).toBe(1);
  241. });
  242. });
  243. describe('getNewMedia', () => {
  244. it(' should generate sources for source-remove when SSCRs are missing from the new SDP', () => {
  245. const oldSdp = new SDP(SampleSdpStrings.simulcastSdpStr);
  246. const newSdp = new SDP(SampleSdpStrings.recvOnlySdpStrChrome);
  247. let sdpDiffer = new SDPDiffer(newSdp, oldSdp, false);
  248. let diff = sdpDiffer.getNewMedia();
  249. // There should be 2 sources for source-remove.
  250. expect(Object.keys(diff).length).toBe(2);
  251. sdpDiffer = new SDPDiffer(oldSdp, newSdp, false);
  252. diff = sdpDiffer.getNewMedia();
  253. // There should zero sources for source-add.
  254. expect(Object.keys(diff).length).toBe(0);
  255. });
  256. it(' should not generate sources for source-remove or source-add if the SDP does not change', () => {
  257. const oldSdp = new SDP(SampleSdpStrings.simulcastSdpStr);
  258. const newSdp = new SDP(SampleSdpStrings.simulcastSdpStr);
  259. const sdpDiffer = new SDPDiffer(newSdp, oldSdp, false);
  260. const diff = sdpDiffer.getNewMedia();
  261. // There should be zero sources in diff.
  262. expect(Object.keys(diff).length).toBe(0);
  263. });
  264. it(' should generate sources for source-remove and source-add when SSRC changes', () => {
  265. const oldSdp = new SDP(SampleSdpStrings.simulcastSdpStr);
  266. const newSdp = new SDP(SampleSdpStrings.simulcastDifferentSsrcSdpStr);
  267. let sdpDiffer = new SDPDiffer(newSdp, oldSdp, false);
  268. let diff = sdpDiffer.getNewMedia();
  269. // There should be 1 source for source-remove.
  270. expect(Object.keys(diff).length).toBe(1);
  271. sdpDiffer = new SDPDiffer(oldSdp, newSdp, false);
  272. diff = sdpDiffer.getNewMedia();
  273. // There should 1 source for source-add.
  274. expect(Object.keys(diff).length).toBe(1);
  275. });
  276. });
  277. });