選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

MockClasses.ts 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. import transform from 'sdp-transform';
  2. import { MediaType } from '../../service/RTC/MediaType';
  3. import { VideoType } from '../../service/RTC/VideoType';
  4. import Listenable from '../util/Listenable';
  5. /* eslint-disable @typescript-eslint/no-empty-function */
  6. /* eslint-disable max-len */
  7. /**
  8. * MockRTCPeerConnection that return the local description sdp.
  9. */
  10. class MockRTCPeerConnection {
  11. /**
  12. * local description SDP.
  13. * * @private
  14. */
  15. private _localDescription: { sdp: string; };
  16. /**
  17. * Gets the local description containing the SDP.
  18. * @returns {{ sdp: string }} The local SDP description.
  19. */
  20. get localDescription(): { sdp: string; } {
  21. return this._localDescription;
  22. }
  23. /**
  24. * Creates an instance of MockRTCPeerConnection and initializes the local SDP description.
  25. */
  26. constructor() {
  27. this._localDescription = { sdp: [
  28. 'v=0\r\n',
  29. 'o=- 2074571967553371465 5 IN IP4 127.0.0.1\r\n',
  30. 's=-\r\n',
  31. 't=0 0\r\n',
  32. 'a=msid-semantic: WMS 2a9e4328-59f4-4af5-883f-4b265ac854d6\r\n',
  33. 'a=group:BUNDLE 0 1\r\n',
  34. 'a=extmap-allow-mixed\r\n',
  35. 'm=audio 9 UDP/TLS/RTP/SAVPF 111 126\r\n',
  36. 'c=IN IP4 0.0.0.0\r\n',
  37. 'a=rtpmap:111 opus/48000/2\r\n',
  38. 'a=rtpmap:126 telephone-event/8000\r\n',
  39. 'a=fmtp:126 0-15\r\n',
  40. 'a=fmtp:111 minptime=10;useinbandfec=1\r\n',
  41. 'a=rtcp:9 IN IP4 0.0.0.0\r\n',
  42. 'a=setup:active\r\n',
  43. 'a=mid:0\r\n',
  44. 'a=msid:26D16D51-503A-420B-8274-3DD1174E498F 8205D1FC-50B4-407C-87D5-9C45F1B779F0\r\n',
  45. 'a=sendrecv\r\n',
  46. 'a=ice-ufrag:tOQd\r\n',
  47. 'a=ice-pwd:3sAozs7hw6+2O6DBp2pt9fvY\r\n',
  48. 'a=fingerprint:sha-256 A9:00:CC:F9:81:33:EA:E9:E3:B4:01:E9:9E:18:B3:9B:F8:49:25:A0:5D:12:20:70:D5:6F:34:5A:2A:39:19:0A\r\n',
  49. 'a=ssrc:2002 msid:26D16D51-503A-420B-8274-3DD1174E498F 8205D1FC-50B4-407C-87D5-9C45F1B779F0\r\n',
  50. 'a=ssrc:2002 cname:juejgy8a01\r\n',
  51. 'a=ssrc:2002 name:a8f7g30-a0\r\n',
  52. 'a=rtcp-mux\r\n',
  53. 'a=extmap-allow-mixed\r\n',
  54. 'm=video 9 UDP/TLS/RTP/SAVPF 100 98 96 45\r\n',
  55. 'c=IN IP4 0.0.0.0\r\n',
  56. 'a=rtpmap:100 VP9/90000\r\n',
  57. 'a=rtpmap:98 VP9/90000\r\n',
  58. 'a=rtpmap:96 VP8/90000\r\n',
  59. 'a=rtpmap:45 AV1/90000\r\n',
  60. 'a=fmtp:100 profile-id=2\r\n',
  61. 'a=fmtp:98 profile-id=0\r\n',
  62. 'a=rtcp:9 IN IP4 0.0.0.0\r\n',
  63. 'a=rtcp-fb:100 goog-remb\r\n',
  64. 'a=rtcp-fb:100 transport-cc\r\n',
  65. 'a=rtcp-fb:100 ccm fir\r\n',
  66. 'a=rtcp-fb:100 nack\r\n',
  67. 'a=rtcp-fb:100 nack pli\r\n',
  68. 'a=rtcp-fb:98 goog-remb\r\n',
  69. 'a=rtcp-fb:98 transport-cc\r\n',
  70. 'a=rtcp-fb:98 ccm fir\r\n',
  71. 'a=rtcp-fb:98 nack\r\n',
  72. 'a=rtcp-fb:98 nack pli\r\n',
  73. 'a=rtcp-fb:96 goog-remb\r\n',
  74. 'a=rtcp-fb:96 transport-cc\r\n',
  75. 'a=rtcp-fb:96 ccm fir\r\n',
  76. 'a=rtcp-fb:96 nack\r\n',
  77. 'a=rtcp-fb:96 nack pli\r\n',
  78. 'a=rtcp-fb:45 goog-remb\r\n',
  79. 'a=rtcp-fb:45 transport-cc\r\n',
  80. 'a=rtcp-fb:45 ccm fir\r\n',
  81. 'a=rtcp-fb:45 nack\r\n',
  82. 'a=rtcp-fb:45 nack pli\r\n',
  83. 'a=extmap:14 urn:ietf:params:rtp-hdrext:toffset\r\n',
  84. 'a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n',
  85. 'a=extmap:13 urn:3gpp:video-orientation\r\n',
  86. 'a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n',
  87. 'a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\n',
  88. 'a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\r\n',
  89. 'a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\r\n',
  90. 'a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space\r\n',
  91. 'a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\n',
  92. 'a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\n',
  93. 'a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\r\n',
  94. 'a=setup:actpass\r\n',
  95. 'a=mid:1\r\n',
  96. 'a=msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  97. 'a=sendrecv\r\n',
  98. 'a=ice-ufrag:tOQd\r\n',
  99. 'a=ice-pwd:3sAozs7hw6+2O6DBp2pt9fvY\r\n',
  100. 'a=fingerprint:sha-256 A9:00:CC:F9:81:33:EA:E9:E3:B4:01:E9:9E:18:B3:9B:F8:49:25:A0:5D:12:20:70:D5:6F:34:5A:2A:39:19:0A\r\n',
  101. 'a=ssrc:4004 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  102. 'a=ssrc:4005 msid:7C0035E5-2DA1-4AEA-804A-9E75BF9B3768 225E9CDA-0384-4C92-92DD-E74C1153EC68\r\n',
  103. 'a=ssrc:4004 cname:juejgy8a01\r\n',
  104. 'a=ssrc:4005 cname:juejgy8a01\r\n',
  105. 'a=ssrc:4004 name:a8f7g30-v0\r\n',
  106. 'a=ssrc:4005 name:a8f7g30-v0\r\n',
  107. 'a=ssrc-group:FID 4004 4005\r\n',
  108. 'a=rtcp-mux\r\n'
  109. ].join('') };
  110. }
  111. }
  112. /**
  113. * Mock {@link TraceablePeerConnection} - add things as needed, but only things useful for all tests.
  114. */
  115. export class MockPeerConnection {
  116. private id: string;
  117. private _usesUnifiedPlan: boolean;
  118. private peerconnection: MockRTCPeerConnection;
  119. private _simulcast: boolean;
  120. /**
  121. * Constructor.
  122. *
  123. * @param {string} id RTC id
  124. * @param {boolean} usesUnifiedPlan
  125. * @param {boolean} simulcast
  126. */
  127. constructor(id: string, usesUnifiedPlan: boolean, simulcast: boolean) {
  128. this.id = id;
  129. this._usesUnifiedPlan = usesUnifiedPlan;
  130. this.peerconnection = new MockRTCPeerConnection();
  131. this._simulcast = simulcast;
  132. }
  133. /**
  134. * {@link TraceablePeerConnection.localDescription}.
  135. *
  136. * @returns {Object}
  137. */
  138. get localDescription(): { sdp: string; } {
  139. return {
  140. sdp: ''
  141. };
  142. }
  143. /**
  144. * {@link TraceablePeerConnection.remoteDescription}.
  145. *
  146. * @returns {Object}
  147. */
  148. get remoteDescription(): { sdp: string; } {
  149. return {
  150. sdp: ''
  151. };
  152. }
  153. /**
  154. * {@link TracablePeerConnection.calculateExpectedSendResolution}.
  155. * @param {JitsiLocalTrack} localTrack
  156. * @returns {number}
  157. */
  158. calculateExpectedSendResolution(localTrack: MockJitsiLocalTrack): number {
  159. return localTrack.getCaptureResolution();
  160. }
  161. /**
  162. * {@link TraceablePeerConnection.createAnswer}.
  163. *
  164. * @returns {Promise<Object>}
  165. */
  166. createAnswer(): Promise<object> {
  167. return Promise.resolve(/* answer */{});
  168. }
  169. /**
  170. * {@link TraceablePeerConnection.doesTrueSimulcast}.
  171. * @returns {boolean}
  172. */
  173. doesTrueSimulcast(): boolean {
  174. return false;
  175. }
  176. /**
  177. * Returns the list of the codecs negotiated.
  178. * @returns {Array<string>}
  179. */
  180. getConfiguredVideoCodecs(): string[] {
  181. const sdp = this.peerconnection.localDescription?.sdp;
  182. if (!sdp) {
  183. return [];
  184. }
  185. const parsedSdp = transform.parse(sdp);
  186. const mLine = parsedSdp.media.find(m => m.type === 'video');
  187. const codecs = new Set(mLine.rtp.map(pt => pt.codec.toLowerCase()));
  188. return Array.from(codecs);
  189. }
  190. /**
  191. * {@link TraceablePeerConnection.getDesiredMediaDirection}.
  192. */
  193. getDesiredMediaDirection(): string {
  194. return 'sendrecv';
  195. }
  196. /**
  197. * {@link TraceablePeerConnection.isSpatialScalabilityOn}.
  198. *
  199. * @returns {boolean}
  200. */
  201. isSpatialScalabilityOn(): boolean {
  202. return this._simulcast;
  203. }
  204. /**
  205. * {@link TraceablePeerConnection.processLocalSdpForTransceiverInfo}.
  206. *
  207. * @returns {void}
  208. */
  209. processLocalSdpForTransceiverInfo(): void {
  210. }
  211. /**
  212. * {@link TraceablePeerConnection.setLocalDescription}.
  213. *
  214. * @returns {Promise<void>}
  215. */
  216. setLocalDescription(): Promise<void> {
  217. return Promise.resolve();
  218. }
  219. /**
  220. * {@link TraceablePeerConnection.setRemoteDescription}.
  221. *
  222. * @returns {Promise<void>}
  223. */
  224. setRemoteDescription(): Promise<void> {
  225. return Promise.resolve();
  226. }
  227. /**
  228. * {@link TraceablePeerConnection.setSenderVideoConstraints}.
  229. *
  230. * Sets the sender video constraints.
  231. * @returns {void}
  232. */
  233. setSenderVideoConstraints(): void {
  234. }
  235. /**
  236. * {@link TraceablePeerConnection.setVideoTransferActive}.
  237. */
  238. setVideoTransferActive(): boolean {
  239. return false;
  240. }
  241. /**
  242. * {@link TraceablePeerConnection.updateRemoteSources}.
  243. *
  244. * Updates the remote sources.
  245. * @returns {void}
  246. */
  247. updateRemoteSources(): void {
  248. }
  249. /**
  250. * {@link TraceablePeerConnection.usesUnifiedPlan}.
  251. */
  252. usesUnifiedPlan() {
  253. return this._usesUnifiedPlan;
  254. }
  255. /**
  256. * {@link TraceablePeerConnection.getLocalVideoTracks}.
  257. */
  258. getLocalVideoTracks(): any[] {
  259. return [];
  260. }
  261. }
  262. /**
  263. * Mock {@link RTC} - add things as needed, but only things useful for all tests.
  264. */
  265. export class MockRTC extends Listenable {
  266. private pc: MockPeerConnection;
  267. private forwardedSources: string[];
  268. /**
  269. * {@link RTC.createPeerConnection}.
  270. *
  271. * @returns {MockPeerConnection}
  272. */
  273. createPeerConnection(id: string, usesUnifiedPlan: boolean, simulcast: boolean): MockPeerConnection {
  274. this.pc = new MockPeerConnection(id, usesUnifiedPlan, simulcast);
  275. this.forwardedSources = [];
  276. return this.pc;
  277. }
  278. /**
  279. * Returns the list of sources that the bridge is forwarding to the client.
  280. * @returns {Array<string>}
  281. */
  282. getForwardedSources(): string[] {
  283. return this.forwardedSources;
  284. }
  285. }
  286. /**
  287. * MockSignalingLayerImpl
  288. */
  289. export class MockSignalingLayerImpl {
  290. private _remoteSourceState: { [key: string]: any; };
  291. /**
  292. * A constructor
  293. */
  294. constructor() {
  295. this._remoteSourceState = {};
  296. }
  297. /**
  298. * Returns the muted state, videoType and codec info received in presence.
  299. * @param {string} endpointId
  300. * @returns Object
  301. */
  302. getPeerMediaInfo(endpointId: string): object | undefined {
  303. return this._remoteSourceState[endpointId];
  304. }
  305. /**
  306. * Updates the media info for peer on join/leave.
  307. * @param {boolean} isJoin - whether endpoint is joining or leaving the call
  308. * @param {string} endpointId - endpoint id
  309. * @param {Array<string>} codecList - new codec list published in presence
  310. * @param {string} codecType - legacy codec setting published in presence
  311. */
  312. setPeerMediaInfo(isJoin: boolean, endpointId: string, codecList: string[], codecType: string): void {
  313. if (isJoin) {
  314. this._remoteSourceState[endpointId] = {
  315. muted: true, // muted by default
  316. videoType: 'camera',
  317. codecList,
  318. codecType
  319. };
  320. } else {
  321. this._remoteSourceState[endpointId] = undefined;
  322. }
  323. }
  324. }
  325. /**
  326. * MockTrack
  327. */
  328. export class MockTrack {
  329. private height: number;
  330. /**
  331. * A constructor
  332. */
  333. constructor(height: number) {
  334. this.height = height;
  335. }
  336. /**
  337. * Returns height.
  338. * @returns {object}
  339. */
  340. getSettings(): { height: number; } {
  341. return {
  342. height: this.height
  343. };
  344. }
  345. /**
  346. * Gets the height value.
  347. * @returns {number} The height.
  348. */
  349. public getHeight(): number {
  350. return this.height;
  351. }
  352. }
  353. /**
  354. * MockJitsiLocalTrack
  355. */
  356. export class MockJitsiLocalTrack {
  357. private resolution: number;
  358. private track: MockTrack;
  359. private type: MediaType;
  360. private videoType: VideoType;
  361. /**
  362. * A constructor
  363. */
  364. constructor(height: number, mediaType: MediaType, videoType: VideoType) {
  365. this.resolution = height;
  366. this.track = new MockTrack(height);
  367. this.type = mediaType;
  368. this.videoType = videoType;
  369. }
  370. /**
  371. * Returns the height.
  372. * @returns {number}
  373. */
  374. getHeight(): number {
  375. return this.track.getHeight();
  376. }
  377. /**
  378. * Returns the capture resolution.
  379. * @returns {number}
  380. */
  381. getCaptureResolution(): number {
  382. return this.getHeight();
  383. }
  384. /**
  385. * Returns track.
  386. * @returns {MockTrack}
  387. */
  388. getTrack(): MockTrack {
  389. return this.track;
  390. }
  391. /**
  392. * Returns media type.
  393. * @returns {MediaType}
  394. */
  395. getType(): MediaType {
  396. return this.type;
  397. }
  398. /**
  399. * Returns video type.
  400. * @returns {VideoType}
  401. */
  402. getVideoType(): VideoType {
  403. return this.videoType;
  404. }
  405. }