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

LocalSdpMunger.spec.js 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import * as transform from 'sdp-transform';
  2. import { MockPeerConnection } from '../RTC/MockClasses';
  3. import FeatureFlags from '../flags/FeatureFlags';
  4. import LocalSdpMunger from './LocalSdpMunger';
  5. import { default as SampleSdpStrings } from './SampleSdpStrings.js';
  6. /**
  7. * Returns the associated ssrc lines for a given media type.
  8. *
  9. * @param {RTCSessionDescription} desc
  10. * @param {string} mediaType
  11. * @returns
  12. */
  13. function getSsrcLines(desc, mediaType) {
  14. const mline = desc.media.find(m => m.type === mediaType);
  15. return mline.ssrcs ?? [];
  16. }
  17. describe('TransformSdpsForUnifiedPlan', () => {
  18. let localSdpMunger;
  19. const tpc = new MockPeerConnection('1', true);
  20. const localEndpointId = 'sRdpsdg';
  21. beforeEach(() => {
  22. FeatureFlags.init({ });
  23. localSdpMunger = new LocalSdpMunger(tpc, localEndpointId);
  24. });
  25. describe('stripSsrcs', () => {
  26. it('should strip ssrcs from an sdp with no msid', () => {
  27. localSdpMunger.tpc.isP2P = false;
  28. const sdpStr = transform.write(SampleSdpStrings.recvOnlySdp);
  29. const desc = new RTCSessionDescription({
  30. type: 'offer',
  31. sdp: sdpStr
  32. });
  33. const transformedDesc = localSdpMunger.transformStreamIdentifiers(desc);
  34. const newSdp = transform.parse(transformedDesc.sdp);
  35. const audioSsrcs = getSsrcLines(newSdp, 'audio');
  36. const videoSsrcs = getSsrcLines(newSdp, 'video');
  37. expect(audioSsrcs.length).toEqual(0);
  38. expect(videoSsrcs.length).toEqual(0);
  39. });
  40. describe('should do nothing to an sdp with msid', () => {
  41. let audioSsrcs, videoSsrcs;
  42. const transformStreamIdentifiers = () => {
  43. const sdpStr = transform.write(SampleSdpStrings.simulcastSdp);
  44. const desc = new RTCSessionDescription({
  45. type: 'offer',
  46. sdp: sdpStr
  47. });
  48. const transformedDesc = localSdpMunger.transformStreamIdentifiers(desc);
  49. const newSdp = transform.parse(transformedDesc.sdp);
  50. audioSsrcs = getSsrcLines(newSdp, 'audio');
  51. videoSsrcs = getSsrcLines(newSdp, 'video');
  52. };
  53. it('without source name signaling enabled (no injected source name)', () => {
  54. transformStreamIdentifiers();
  55. expect(audioSsrcs.length).toEqual(4);
  56. expect(videoSsrcs.length).toEqual(6);
  57. });
  58. it('with source name signaling enabled (injected source name)', () => {
  59. FeatureFlags.init({ sourceNameSignaling: true });
  60. transformStreamIdentifiers();
  61. expect(audioSsrcs.length).toEqual(4 + 1 /* injected source name */);
  62. expect(videoSsrcs.length).toEqual(6 + 3 /* injected source name into each ssrc */);
  63. });
  64. });
  65. });
  66. describe('addMsids', () => {
  67. it('should add endpointId to msid', () => {
  68. const sdpStr = transform.write(SampleSdpStrings.firefoxSdp);
  69. const desc = new RTCSessionDescription({
  70. type: 'offer',
  71. sdp: sdpStr
  72. });
  73. const transformedDesc = localSdpMunger.transformStreamIdentifiers(desc);
  74. const newSdp = transform.parse(transformedDesc.sdp);
  75. const videoSsrcs = getSsrcLines(newSdp, 'video');
  76. for (const ssrcLine of videoSsrcs) {
  77. if (ssrcLine.attribute === 'msid') {
  78. const msid = ssrcLine.value.split(' ')[0];
  79. expect(msid).toBe(`${localEndpointId}-video-${tpc.id}`);
  80. }
  81. }
  82. });
  83. it('should add missing msid', () => {
  84. // P2P case only.
  85. localSdpMunger.tpc.isP2P = true;
  86. const sdpStr = transform.write(SampleSdpStrings.firefoxP2pSdp);
  87. const desc = new RTCSessionDescription({
  88. type: 'offer',
  89. sdp: sdpStr
  90. });
  91. const transformedDesc = localSdpMunger.transformStreamIdentifiers(desc);
  92. const newSdp = transform.parse(transformedDesc.sdp);
  93. const videoSsrcs = getSsrcLines(newSdp, 'video');
  94. const msidExists = videoSsrcs.find(s => s.attribute === 'msid');
  95. expect(msidExists).toBeDefined();
  96. });
  97. });
  98. });
  99. describe('DoNotTransformSdpForPlanB', () => {
  100. let localSdpMunger;
  101. const tpc = new MockPeerConnection('1', false);
  102. const localEndpointId = 'sRdpsdg';
  103. beforeEach(() => {
  104. FeatureFlags.init({ });
  105. localSdpMunger = new LocalSdpMunger(tpc, localEndpointId);
  106. });
  107. describe('stripSsrcs', () => {
  108. describe('should not strip ssrcs from an sdp with no msid', () => {
  109. let audioSsrcs, videoSsrcs;
  110. const transformStreamIdentifiers = () => {
  111. localSdpMunger.tpc.isP2P = false;
  112. const sdpStr = transform.write(SampleSdpStrings.recvOnlySdp);
  113. const desc = new RTCSessionDescription({
  114. type: 'offer',
  115. sdp: sdpStr
  116. });
  117. const transformedDesc = localSdpMunger.transformStreamIdentifiers(desc);
  118. const newSdp = transform.parse(transformedDesc.sdp);
  119. audioSsrcs = getSsrcLines(newSdp, 'audio');
  120. videoSsrcs = getSsrcLines(newSdp, 'video');
  121. };
  122. it('without source name signaling', () => {
  123. transformStreamIdentifiers();
  124. expect(audioSsrcs.length).toEqual(1);
  125. expect(videoSsrcs.length).toEqual(1);
  126. });
  127. it('with source name signaling', () => {
  128. FeatureFlags.init({ sourceNameSignaling: true });
  129. transformStreamIdentifiers();
  130. expect(audioSsrcs.length).toEqual(1 + 1 /* injected source name */);
  131. expect(videoSsrcs.length).toEqual(1 + 1 /* injected source name */);
  132. });
  133. });
  134. });
  135. });