diff --git a/meet/server/test/fakeParameters.js b/meet/server/test/fakeParameters.js index dd747213..c7ccb1c9 100644 --- a/meet/server/test/fakeParameters.js +++ b/meet/server/test/fakeParameters.js @@ -1,619 +1,609 @@ const uuidv4 = require('uuid/v4'); -exports.generateRouterRtpCapabilities = function() -{ - return { - codecs : - [ - { - mimeType : 'audio/opus', - kind : 'audio', - preferredPayloadType : 100, - clockRate : 48000, - channels : 2, - rtcpFeedback : - [ - { type: 'transport-cc' } - ], - parameters : - { - useinbandfec : 1, - foo : 'bar' - } - }, - { - mimeType : 'video/VP8', - kind : 'video', - preferredPayloadType : 101, - clockRate : 90000, - rtcpFeedback : - [ - { type: 'nack' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb' }, - { type: 'transport-cc' } - ], - parameters : - { - 'x-google-start-bitrate' : 1500 - } - }, - { - mimeType : 'video/rtx', - kind : 'video', - preferredPayloadType : 102, - clockRate : 90000, - rtcpFeedback : [], - parameters : - { - apt : 101 - } - }, - { - mimeType : 'video/H264', - kind : 'video', - preferredPayloadType : 103, - clockRate : 90000, - rtcpFeedback : - [ - { type: 'nack' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb' }, - { type: 'transport-cc' } - ], - parameters : - { - 'level-asymmetry-allowed' : 1, - 'packetization-mode' : 1, - 'profile-level-id' : '42e01f' - } - }, - { - mimeType : 'video/rtx', - kind : 'video', - preferredPayloadType : 104, - clockRate : 90000, - rtcpFeedback : [], - parameters : - { - apt : 103 - } - } - ], - headerExtensions : - [ - { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false, - direction : 'sendrecv' - }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1, - preferredEncrypt : false, - direction : 'sendrecv' - }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', - preferredId : 2, - preferredEncrypt : false, - direction : 'recvonly' - }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id', - preferredId : 3, - preferredEncrypt : false, - direction : 'recvonly' - }, - { - kind : 'audio', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId : 4, - preferredEncrypt : false, - direction : 'sendrecv' - }, - { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId : 4, - preferredEncrypt : false, - direction : 'sendrecv' - }, - { - kind : 'audio', - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - preferredId : 5, - preferredEncrypt : false, - direction : 'recvonly' - }, - { - kind : 'video', - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - preferredId : 5, - preferredEncrypt : false, - direction : 'sendrecv' - }, - { - kind : 'video', - uri : 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07', - preferredId : 6, - preferredEncrypt : false, - direction : 'sendrecv' - }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:framemarking', - preferredId : 7, - preferredEncrypt : false, - direction : 'sendrecv' - }, - { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId : 10, - preferredEncrypt : false, - direction : 'sendrecv' - }, - { - kind : 'video', - uri : 'urn:3gpp:video-orientation', - preferredId : 11, - preferredEncrypt : false, - direction : 'sendrecv' - }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:toffset', - preferredId : 12, - preferredEncrypt : false, - direction : 'sendrecv' - } - ], - fecMechanisms : [] - }; +exports.generateRouterRtpCapabilities = function() { + return { + codecs : + [ + { + mimeType : 'audio/opus', + kind : 'audio', + preferredPayloadType : 100, + clockRate : 48000, + channels : 2, + rtcpFeedback : + [ + { type: 'transport-cc' } + ], + parameters : + { + useinbandfec : 1, + foo : 'bar' + } + }, + { + mimeType : 'video/VP8', + kind : 'video', + preferredPayloadType : 101, + clockRate : 90000, + rtcpFeedback : + [ + { type: 'nack' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb' }, + { type: 'transport-cc' } + ], + parameters : + { + 'x-google-start-bitrate' : 1500 + } + }, + { + mimeType : 'video/rtx', + kind : 'video', + preferredPayloadType : 102, + clockRate : 90000, + rtcpFeedback : [], + parameters : + { + apt : 101 + } + }, + { + mimeType : 'video/H264', + kind : 'video', + preferredPayloadType : 103, + clockRate : 90000, + rtcpFeedback : + [ + { type: 'nack' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb' }, + { type: 'transport-cc' } + ], + parameters : + { + 'level-asymmetry-allowed' : 1, + 'packetization-mode' : 1, + 'profile-level-id' : '42e01f' + } + }, + { + mimeType : 'video/rtx', + kind : 'video', + preferredPayloadType : 104, + clockRate : 90000, + rtcpFeedback : [], + parameters : + { + apt : 103 + } + } + ], + headerExtensions : + [ + { + kind : 'audio', + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId : 1, + preferredEncrypt : false, + direction : 'sendrecv' + }, + { + kind : 'video', + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId : 1, + preferredEncrypt : false, + direction : 'sendrecv' + }, + { + kind : 'video', + uri : 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', + preferredId : 2, + preferredEncrypt : false, + direction : 'recvonly' + }, + { + kind : 'video', + uri : 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id', + preferredId : 3, + preferredEncrypt : false, + direction : 'recvonly' + }, + { + kind : 'audio', + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + preferredId : 4, + preferredEncrypt : false, + direction : 'sendrecv' + }, + { + kind : 'video', + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + preferredId : 4, + preferredEncrypt : false, + direction : 'sendrecv' + }, + { + kind : 'audio', + uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + preferredId : 5, + preferredEncrypt : false, + direction : 'recvonly' + }, + { + kind : 'video', + uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + preferredId : 5, + preferredEncrypt : false, + direction : 'sendrecv' + }, + { + kind : 'video', + uri : 'http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07', + preferredId : 6, + preferredEncrypt : false, + direction : 'sendrecv' + }, + { + kind : 'video', + uri : 'urn:ietf:params:rtp-hdrext:framemarking', + preferredId : 7, + preferredEncrypt : false, + direction : 'sendrecv' + }, + { + kind : 'audio', + uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId : 10, + preferredEncrypt : false, + direction : 'sendrecv' + }, + { + kind : 'video', + uri : 'urn:3gpp:video-orientation', + preferredId : 11, + preferredEncrypt : false, + direction : 'sendrecv' + }, + { + kind : 'video', + uri : 'urn:ietf:params:rtp-hdrext:toffset', + preferredId : 12, + preferredEncrypt : false, + direction : 'sendrecv' + } + ], + fecMechanisms : [] + }; }; -exports.generateNativeRtpCapabilities = function() -{ - return { - codecs : - [ - { - mimeType : 'audio/opus', - kind : 'audio', - preferredPayloadType : 111, - clockRate : 48000, - channels : 2, - rtcpFeedback : - [ - { type: 'transport-cc' } - ], - parameters : - { - minptime : 10, - useinbandfec : 1 - } - }, - { - mimeType : 'audio/ISAC', - kind : 'audio', - preferredPayloadType : 103, - clockRate : 16000, - channels : 1, - rtcpFeedback : - [ - { type: 'transport-cc' } - ], - parameters : {} - }, - { - mimeType : 'audio/CN', - kind : 'audio', - preferredPayloadType : 106, - clockRate : 32000, - channels : 1, - rtcpFeedback : - [ - { type: 'transport-cc' } - ], - parameters : {} - }, - { - mimeType : 'video/VP8', - kind : 'video', - preferredPayloadType : 96, - clockRate : 90000, - rtcpFeedback : - [ - { type: 'goog-remb' }, - { type: 'transport-cc' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'nack' }, - { type: 'nack', parameter: 'pli' } - ], - parameters : - { - baz : '1234abcd' - } - }, - { - mimeType : 'video/rtx', - kind : 'video', - preferredPayloadType : 97, - clockRate : 90000, - rtcpFeedback : [], - parameters : - { - apt : 96 - } - } - ], - headerExtensions : - [ - { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1 - }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId : 1 - }, - { - kind : 'video', - uri : 'urn:ietf:params:rtp-hdrext:toffset', - preferredId : 2 - }, - { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId : 3 - }, - { - kind : 'video', - uri : 'urn:3gpp:video-orientation', - preferredId : 4 - }, - { - kind : 'video', - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - preferredId : 5 - }, - { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay', - preferredId : 6 - }, - { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/video-content-type', - preferredId : 7 - }, - { - kind : 'video', - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/video-timing', - preferredId : 8 - }, - { - kind : 'audio', - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId : 10 - } - ], - fecMechanisms : [] - }; +exports.generateNativeRtpCapabilities = function() { + return { + codecs : + [ + { + mimeType : 'audio/opus', + kind : 'audio', + preferredPayloadType : 111, + clockRate : 48000, + channels : 2, + rtcpFeedback : + [ + { type: 'transport-cc' } + ], + parameters : + { + minptime : 10, + useinbandfec : 1 + } + }, + { + mimeType : 'audio/ISAC', + kind : 'audio', + preferredPayloadType : 103, + clockRate : 16000, + channels : 1, + rtcpFeedback : + [ + { type: 'transport-cc' } + ], + parameters : {} + }, + { + mimeType : 'audio/CN', + kind : 'audio', + preferredPayloadType : 106, + clockRate : 32000, + channels : 1, + rtcpFeedback : + [ + { type: 'transport-cc' } + ], + parameters : {} + }, + { + mimeType : 'video/VP8', + kind : 'video', + preferredPayloadType : 96, + clockRate : 90000, + rtcpFeedback : + [ + { type: 'goog-remb' }, + { type: 'transport-cc' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'nack' }, + { type: 'nack', parameter: 'pli' } + ], + parameters : + { + baz : '1234abcd' + } + }, + { + mimeType : 'video/rtx', + kind : 'video', + preferredPayloadType : 97, + clockRate : 90000, + rtcpFeedback : [], + parameters : + { + apt : 96 + } + } + ], + headerExtensions : + [ + { + kind : 'audio', + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId : 1 + }, + { + kind : 'video', + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId : 1 + }, + { + kind : 'video', + uri : 'urn:ietf:params:rtp-hdrext:toffset', + preferredId : 2 + }, + { + kind : 'video', + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + preferredId : 3 + }, + { + kind : 'video', + uri : 'urn:3gpp:video-orientation', + preferredId : 4 + }, + { + kind : 'video', + uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + preferredId : 5 + }, + { + kind : 'video', + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/playout-delay', + preferredId : 6 + }, + { + kind : 'video', + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/video-content-type', + preferredId : 7 + }, + { + kind : 'video', + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/video-timing', + preferredId : 8 + }, + { + kind : 'audio', + uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId : 10 + } + ], + fecMechanisms : [] + }; }; -exports.generateNativeSctpCapabilities = function() -{ - return { - numStreams : { OS: 2048, MIS: 2048 } - }; +exports.generateNativeSctpCapabilities = function() { + return { + numStreams : { OS: 2048, MIS: 2048 } + }; }; -exports.generateLocalDtlsParameters = function() -{ - return { - fingerprints : - [ - { - algorithm : 'sha-256', - value : '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD' - } - ], - role : 'auto' - }; +exports.generateLocalDtlsParameters = function() { + return { + fingerprints : + [ + { + algorithm : 'sha-256', + value : '82:5A:68:3D:36:C3:0A:DE:AF:E7:32:43:D2:88:83:57:AC:2D:65:E5:80:C4:B6:FB:AF:1A:A0:21:9F:6D:0C:AD' + } + ], + role : 'auto' + }; }; -exports.generateTransportRemoteParameters = function() -{ - return { - id : uuidv4(), - iceParameters : - { - iceLite : true, - password : 'yku5ej8nvfaor28lvtrabcx0wkrpkztz', - usernameFragment : 'h3hk1iz6qqlnqlne' - }, - iceCandidates : - [ - { - family : 'ipv4', - foundation : 'udpcandidate', - ip : '9.9.9.9', - port : 40533, - priority : 1078862079, - protocol : 'udp', - type : 'host' - }, - { - family : 'ipv6', - foundation : 'udpcandidate', - ip : '9:9:9:9:9:9', - port : 41333, - priority : 1078862089, - protocol : 'udp', - type : 'host' - } - ], - dtlsParameters : - { - fingerprints : - [ - { - algorithm : 'sha-256', - value : 'A9:F4:E0:D2:74:D3:0F:D9:CA:A5:2F:9F:7F:47:FA:F0:C4:72:DD:73:49:D0:3B:14:90:20:51:30:1B:90:8E:71' - }, - { - algorithm : 'sha-384', - value : '03:D9:0B:87:13:98:F6:6D:BC:FC:92:2E:39:D4:E1:97:32:61:30:56:84:70:81:6E:D1:82:97:EA:D9:C1:21:0F:6B:C5:E7:7F:E1:97:0C:17:97:6E:CF:B3:EF:2E:74:B0' - }, - { - algorithm : 'sha-512', - value : '84:27:A4:28:A4:73:AF:43:02:2A:44:68:FF:2F:29:5C:3B:11:9A:60:F4:A8:F0:F5:AC:A0:E3:49:3E:B1:34:53:A9:85:CE:51:9B:ED:87:5E:B8:F4:8E:3D:FA:20:51:B8:96:EE:DA:56:DC:2F:5C:62:79:15:23:E0:21:82:2B:2C' - } - ], - role : 'auto' - }, - sctpParameters : - { - port : 5000, - numStreams : 2048, - maxMessageSize : 2000000 - } - }; +exports.generateTransportRemoteParameters = function() { + return { + id : uuidv4(), + iceParameters : + { + iceLite : true, + password : 'yku5ej8nvfaor28lvtrabcx0wkrpkztz', + usernameFragment : 'h3hk1iz6qqlnqlne' + }, + iceCandidates : + [ + { + family : 'ipv4', + foundation : 'udpcandidate', + ip : '9.9.9.9', + port : 40533, + priority : 1078862079, + protocol : 'udp', + type : 'host' + }, + { + family : 'ipv6', + foundation : 'udpcandidate', + ip : '9:9:9:9:9:9', + port : 41333, + priority : 1078862089, + protocol : 'udp', + type : 'host' + } + ], + dtlsParameters : + { + fingerprints : + [ + { + algorithm : 'sha-256', + value : 'A9:F4:E0:D2:74:D3:0F:D9:CA:A5:2F:9F:7F:47:FA:F0:C4:72:DD:73:49:D0:3B:14:90:20:51:30:1B:90:8E:71' + }, + { + algorithm : 'sha-384', + value : '03:D9:0B:87:13:98:F6:6D:BC:FC:92:2E:39:D4:E1:97:32:61:30:56:84:70:81:6E:D1:82:97:EA:D9:C1:21:0F:6B:C5:E7:7F:E1:97:0C:17:97:6E:CF:B3:EF:2E:74:B0' + }, + { + algorithm : 'sha-512', + value : '84:27:A4:28:A4:73:AF:43:02:2A:44:68:FF:2F:29:5C:3B:11:9A:60:F4:A8:F0:F5:AC:A0:E3:49:3E:B1:34:53:A9:85:CE:51:9B:ED:87:5E:B8:F4:8E:3D:FA:20:51:B8:96:EE:DA:56:DC:2F:5C:62:79:15:23:E0:21:82:2B:2C' + } + ], + role : 'auto' + }, + sctpParameters : + { + port : 5000, + numStreams : 2048, + maxMessageSize : 2000000 + } + }; }; -exports.generateProducerRemoteParameters = function() -{ - return { - id : uuidv4() - }; +exports.generateProducerRemoteParameters = function() { + return { + id : uuidv4() + }; }; -exports.generateConsumerRemoteParameters = function({ id, codecMimeType } = {}) -{ - switch (codecMimeType) - { - case 'audio/opus': - { - return { - id : id || uuidv4(), - producerId : uuidv4(), - kind : 'audio', - rtpParameters : - { - codecs : - [ - { - mimeType : 'audio/opus', - payloadType : 100, - clockRate : 48000, - channels : 2, - rtcpFeedback : - [ - { type: 'transport-cc' } - ], - parameters : - { - useinbandfec : 1, - foo : 'bar' - } - } - ], - encodings : - [ - { - ssrc : 46687003 - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 1 - }, - { - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - id : 5 - }, - { - uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - id : 10 - } - ], - rtcp : - { - cname : 'wB4Ql4lrsxYLjzuN', - reducedSize : true, - mux : true - } - } - }; - } +exports.generateConsumerRemoteParameters = function({ id, codecMimeType } = {}) { + switch (codecMimeType) { + case 'audio/opus': + { + return { + id : id || uuidv4(), + producerId : uuidv4(), + kind : 'audio', + rtpParameters : + { + codecs : + [ + { + mimeType : 'audio/opus', + payloadType : 100, + clockRate : 48000, + channels : 2, + rtcpFeedback : + [ + { type: 'transport-cc' } + ], + parameters : + { + useinbandfec : 1, + foo : 'bar' + } + } + ], + encodings : + [ + { + ssrc : 46687003 + } + ], + headerExtensions : + [ + { + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + id : 1 + }, + { + uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + id : 5 + }, + { + uri : 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + id : 10 + } + ], + rtcp : + { + cname : 'wB4Ql4lrsxYLjzuN', + reducedSize : true, + mux : true + } + } + }; + } - case 'audio/ISAC': - { - return { - id : id || uuidv4(), - producerId : uuidv4(), - kind : 'audio', - rtpParameters : - { - codecs : - [ - { - mimeType : 'audio/ISAC', - payloadType : 111, - clockRate : 16000, - channels : 1, - rtcpFeedback : - [ - { type: 'transport-cc' } - ], - parameters : {} - } - ], - encodings : - [ - { - ssrc : 46687004 - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 1 - }, - { - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - id : 5 - } - ], - rtcp : - { - cname : 'wB4Ql4lrsxYLjzuN', - reducedSize : true, - mux : true - } - } - }; - } + case 'audio/ISAC': + { + return { + id : id || uuidv4(), + producerId : uuidv4(), + kind : 'audio', + rtpParameters : + { + codecs : + [ + { + mimeType : 'audio/ISAC', + payloadType : 111, + clockRate : 16000, + channels : 1, + rtcpFeedback : + [ + { type: 'transport-cc' } + ], + parameters : {} + } + ], + encodings : + [ + { + ssrc : 46687004 + } + ], + headerExtensions : + [ + { + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + id : 1 + }, + { + uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + id : 5 + } + ], + rtcp : + { + cname : 'wB4Ql4lrsxYLjzuN', + reducedSize : true, + mux : true + } + } + }; + } - case 'video/VP8': - { - return { - id : id || uuidv4(), - producerId : uuidv4(), - kind : 'video', - rtpParameters : - { - codecs : - [ - { - mimeType : 'video/VP8', - payloadType : 101, - clockRate : 90000, - rtcpFeedback : - [ - { type: 'nack' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb' }, - { type: 'transport-cc' } - ], - parameters : - { - 'x-google-start-bitrate' : 1500 - } - }, - { - mimeType : 'video/rtx', - payloadType : 102, - clockRate : 90000, - rtcpFeedback : [], - parameters : - { - apt : 101 - } - } - ], - encodings : - [ - { - ssrc : 99991111, - rtx : - { - ssrc : 99991112 - } - } - ], - headerExtensions : - [ - { - uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', - id : 1 - }, - { - uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - id : 4 - }, - { - uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - id : 5 - }, - { - uri : 'urn:3gpp:video-orientation', - id : 11 - }, - { - uri : 'urn:ietf:params:rtp-hdrext:toffset', - id : 12 - } - ], - rtcp : - { - cname : 'wB4Ql4lrsxYLjzuN', - reducedSize : true, - mux : true - } - } - }; - } + case 'video/VP8': + { + return { + id : id || uuidv4(), + producerId : uuidv4(), + kind : 'video', + rtpParameters : + { + codecs : + [ + { + mimeType : 'video/VP8', + payloadType : 101, + clockRate : 90000, + rtcpFeedback : + [ + { type: 'nack' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb' }, + { type: 'transport-cc' } + ], + parameters : + { + 'x-google-start-bitrate' : 1500 + } + }, + { + mimeType : 'video/rtx', + payloadType : 102, + clockRate : 90000, + rtcpFeedback : [], + parameters : + { + apt : 101 + } + } + ], + encodings : + [ + { + ssrc : 99991111, + rtx : + { + ssrc : 99991112 + } + } + ], + headerExtensions : + [ + { + uri : 'urn:ietf:params:rtp-hdrext:sdes:mid', + id : 1 + }, + { + uri : 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + id : 4 + }, + { + uri : 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + id : 5 + }, + { + uri : 'urn:3gpp:video-orientation', + id : 11 + }, + { + uri : 'urn:ietf:params:rtp-hdrext:toffset', + id : 12 + } + ], + rtcp : + { + cname : 'wB4Ql4lrsxYLjzuN', + reducedSize : true, + mux : true + } + } + }; + } - default: - { - throw new TypeError(`unknown codecMimeType "${codecMimeType}"`); - } - } + default: + { + throw new TypeError(`unknown codecMimeType "${codecMimeType}"`); + } + } }; -exports.generateDataProducerRemoteParameters = function() -{ - return { - id : uuidv4() - }; +exports.generateDataProducerRemoteParameters = function() { + return { + id : uuidv4() + }; }; -exports.generateDataConsumerRemoteParameters = function({ id } = {}) -{ - return { - id : id || uuidv4(), - dataProducerId : uuidv4(), - sctpStreamParameters : - { - streamId : 666, - maxPacketLifeTime : 5000, - maxRetransmits : undefined - } - }; +exports.generateDataConsumerRemoteParameters = function({ id } = {}) { + return { + id : id || uuidv4(), + dataProducerId : uuidv4(), + sctpStreamParameters : + { + streamId : 666, + maxPacketLifeTime : 5000, + maxRetransmits : undefined + } + }; }; diff --git a/meet/server/test/performancetestbench.js b/meet/server/test/performancetestbench.js index 20b74752..26021ae3 100644 --- a/meet/server/test/performancetestbench.js +++ b/meet/server/test/performancetestbench.js @@ -1,235 +1,237 @@ process.env.DEBUG = '' const assert = require('assert'); let request = require('supertest') const io = require("socket.io-client"); const child_process = require("child_process"); const udp = require('dgram'); const Roles = require('../lib/userRoles'); let recvUdpSocket let recvRtcpUdpSocket let app let processes = []; let rtpParameters = { codecs: [ { mimeType: "video/H264", payloadType: 125, clockRate: 90000, parameters: { "level-asymmetry-allowed": 1, "packetization-mode": 1, "profile-level-id": "42e01f", }, }, ], } function startFFMPEGStream(peers, ssrc) { const cmdProgram = "ffmpeg"; //Build a video stream per producer const streams = peers.map((peer) => `[select=v:f=rtp:ssrc=${ssrc}:payload_type=125]rtp://127.0.0.1:${peer.senderTransportInfo.port}?rtcpport=${peer.senderTransportInfo.rtcpPort}`); const cmdArgStr = [ "-i /dev/video0", //We are streaming from the webcam (a looping videofile would be an alternative) `-c:v h264`, //The codec "-map 0:v:0", "-f tee", //This option allows us to read the source once, encode once, and then output multiple streams streams.join('|').trim() ].join(" ").trim(); console.log(`Run command: ${cmdProgram} ${cmdArgStr}`); let recProcess = child_process.spawn(cmdProgram, cmdArgStr.split(/\s+/)); recProcess.on("error", (err) => { console.error("Recording process error:", err); }); recProcess.on("exit", (code, signal) => { console.log("Recording process exit, code: %d, signal: %s", code, signal); recProcess = null; }); // FFmpeg writes its logs to stderr recProcess.stderr.on("data", (chunk) => { chunk .toString() .split(/\r?\n/g) .filter(Boolean) // Filter out empty strings .forEach((line) => { // console.log(line); }); }); return recProcess; } async function sendRequest(socket, method, data = null) { return await new Promise((resolve, /*reject*/) => { socket.emit( 'request', {method: method, data: data}, (error, response) => { assert(!error) resolve(response) } ) }) } async function createPeer(roomId, request, receiverPort, receiverRtcpPort) { let signalingSocket await request .post(`/meetmedia/api/sessions/${roomId}/connection`) .send({role: Roles.PUBLISHER | Roles.SUBSCRIBER | Roles.MODERATOR}) .expect(200) .then(async (res) => { let data = res.body; const signalingUrl = data['token']; signalingSocket = io(signalingUrl, { path: '/meetmedia/signaling', transports: ["websocket"], rejectUnauthorized: false }); let roomReady = new Promise((resolve, /*reject*/) => { signalingSocket.once('notification', (reason) => { // console.warn("Received notification", reason) if (reason['method'] == 'roomReady') { resolve(); } }); }) signalingSocket.connect(); await roomReady }) - .catch(err => { console.warn(err); throw err }) + .catch(err => { + console.warn(err); throw err + }) //Necessary later for the server to resume the consumer, //once we join with another peer signalingSocket.on('request', async (reason, cb) => { // console.warn("Received request", reason) if (reason['method'] == 'newConsumer') { cb(); } }); //Join await sendRequest(signalingSocket, 'join', { nickname: "nickname", rtpCapabilities: rtpParameters }) //Create sending transport const senderTransportInfo = await sendRequest(signalingSocket, 'createPlainTransport', { producing: true, consuming: false, }) //Create consuming transport const consumerTransportInfo = await sendRequest(signalingSocket, 'createPlainTransport', { producing: false, consuming: true, }) await sendRequest(signalingSocket, 'connectPlainTransport', { transportId: consumerTransportInfo.id, ip: '127.0.0.1', port: receiverPort, rtcpPort: receiverRtcpPort, }) //Create sending producer await sendRequest(signalingSocket, 'produce', { transportId: senderTransportInfo.id, kind: 'video', rtpParameters: { codecs: [ { mimeType: "video/H264", payloadType: 125, clockRate: 90000, parameters: { "level-asymmetry-allowed": 1, "packetization-mode": 1, "profile-level-id": "42e01f", }, }, ], encodings: [{ ssrc: 2222 }] }, appData: { source: 'webcam' } }) return {senderTransportInfo, consumerTransportInfo, signalingSocket}; } before(function (done) { process.env.SSL_CERT = "../../docker/certs/kolab.hosted.com.cert" process.env.SSL_KEY = "../../docker/certs/kolab.hosted.com.key" process.env.REDIS_IP = "none" process.env.MEDIASOUP_NUM_WORKERS = 3 process.env.ROUTER_SCALE_SIZE = 3 app = require('../server.js') request = request(app); recvUdpSocket = udp.createSocket('udp4'); recvUdpSocket.on('message',function(msg,info){ // console.warn("Received message", msg, info) }); recvRtcpUdpSocket = udp.createSocket('udp4'); recvRtcpUdpSocket.on('message',function(msg,info){ // console.warn("Received RTCP message", msg, info) }); app.on("ready", function(){ done(); }); }); describe('Testbench', function() { const roomId = "room1"; let peers = []; it('prepare udp sockets', async () => { await new Promise(resolve => recvUdpSocket.bind(22222, '127.0.0.1', resolve)); await new Promise(resolve => recvRtcpUdpSocket.bind(22223, '127.0.0.1', resolve)); }); it('create peers', async () => { for (var i = 0; i < 20; i++) { peers.push(await createPeer(roomId, request, recvUdpSocket.address().port, recvRtcpUdpSocket.address().port)) } }); it('start ffmpg stream', async () => { processes.push(startFFMPEGStream(peers, 2222)) }); it('wait forever', async () => { setInterval(function(){ sendRequest(peers[0].signalingSocket, 'dumpStats', {}) }, 5000) const promise = new Promise((res, _rej) => {}); return promise; }) }); after(function () { for (const process of processes) { process.kill() } process.exit(); }) diff --git a/meet/server/test/test.js b/meet/server/test/test.js index c042ced3..7be88236 100644 --- a/meet/server/test/test.js +++ b/meet/server/test/test.js @@ -1,202 +1,206 @@ const assert = require('assert'); let request = require('supertest') const io = require("socket.io-client"); const Roles = require('../lib/userRoles'); const mediasoupClient = require('mediasoup-client'); const { FakeHandler } = require('mediasoup-client/lib/handlers/FakeHandler'); const fakeParameters = require('./fakeParameters'); let app before(function (done) { process.env.SSL_CERT = "../../docker/certs/kolab.hosted.com.cert" process.env.SSL_KEY = "../../docker/certs/kolab.hosted.com.key" process.env.REDIS_IP = "none" // process.env.DEBUG = '*' app = require('../server.js') request = request(app); app.on("ready", function(){ done(); }); }); describe('GET /ping', function() { - it('responds', function(done) { - request - .get('/meetmedia/api/ping') - .expect(200, done); - }); + it('responds', function(done) { + request + .get('/meetmedia/api/ping') + .expect(200, done); + }); }); describe('Join room', function() { const roomId = "room1"; let signalingSocket let peerId async function sendRequest(socket, method, data = null) { return await new Promise((resolve, /*reject*/) => { socket.emit( 'request', {method: method, - data: data}, + data: data}, (error, response) => { assert(!error) resolve(response) } ) }) } it('create room', async () => { return request .post(`/meetmedia/api/sessions/${roomId}/connection`) .send({role: Roles.PUBLISHER | Roles.SUBSCRIBER | Roles.MODERATOR}) .expect(200) .then(async (res) => { let data = res.body; peerId = data['id']; const signalingUrl = data['token']; assert(signalingUrl.includes(peerId)) assert(signalingUrl.includes(roomId)) console.info(signalingUrl); signalingSocket = io(signalingUrl, { path: '/meetmedia/signaling', transports: ["websocket"], rejectUnauthorized: false }); let roomReady = new Promise((resolve, /*reject*/) => { signalingSocket.on('notification', (reason) => { if (reason['method'] == 'roomReady') { resolve(); } }); }) signalingSocket.connect(); await roomReady }) - .catch(err => { console.warn(err); throw err }) + .catch(err => { + console.warn(err); throw err + }) }); it('getRtpCapabilities', async () => { const routerRtpCapabilities = await sendRequest(signalingSocket, 'getRouterRtpCapabilities') assert(Object.keys(routerRtpCapabilities).length != 0) }); it('join', async () => { const { id, role, peers } = await sendRequest(signalingSocket, 'join', { nickname: "nickname", rtpCapabilities: fakeParameters.generateNativeRtpCapabilities() }) assert.equal(id, peerId) assert.equal(role, Roles.PUBLISHER | Roles.SUBSCRIBER | Roles.MODERATOR) assert.equal(peers.length, 0) }) it('second peer joining', async () => { return request .post(`/meetmedia/api/sessions/${roomId}/connection`) .expect(200) .then(async (res) => { let data = res.body; const newId = data['id']; const signalingUrl = data['token']; let signalingSocket2 = io(signalingUrl, { path: '/meetmedia/signaling', transports: ["websocket"], rejectUnauthorized: false }); let roomReady = new Promise((resolve, /*reject*/) => { signalingSocket2.on('notification', async (reason) => { if (reason['method'] == 'roomReady') { resolve(reason); } }); }) let newPeer = new Promise((resolve, /*reject*/) => { signalingSocket.on('notification', (reason) => { if (reason.method == 'newPeer') { resolve(reason); } }); }) signalingSocket.connect(); let reason = await roomReady; const { peers } = await sendRequest(signalingSocket2, 'join', { nickname: "nickname", rtpCapabilities: fakeParameters.generateNativeRtpCapabilities() }) assert.equal(peers.length, 1) assert.equal(peers[0].id, peerId) reason = await newPeer; assert(reason.data.id == newId); }) - .catch(err => { console.warn(err); throw err }) + .catch(err => { + console.warn(err); throw err + }) }); let transportInfo; it('createWebRtcTransport', async () => { transportInfo = await sendRequest(signalingSocket, 'createWebRtcTransport', { forceTcp: false, producing: true, consuming: false }) const { id, iceParameters, iceCandidates, dtlsParameters } = transportInfo console.warn(id); }); it('createDevice', async () => { let device; try{ device = new mediasoupClient.Device({ handlerFactory: FakeHandler.createFactory(fakeParameters) }); let caps = fakeParameters.generateRouterRtpCapabilities(); await device.load({routerRtpCapabilities: caps}) assert(device.canProduce('video')) console.info(transportInfo) const { id, iceParameters, iceCandidates, dtlsParameters } = transportInfo //FIXME it doesn't look like this device can actually connect let sendTransport = device.createSendTransport({ id, iceParameters, iceCandidates, dtlsParameters, // iceServers: turnServers, // iceTransportPolicy: iceTransportPolicy, proprietaryConstraints: { optional: [{ googDscp: true }] } }) sendTransport.on('connect', ({ dtlsParameters }, callback, errback) => { console.warn("on connect"); // done(); // socket.sendRequest('connectWebRtcTransport', // { transportId: sendTransport.id, dtlsParameters }) // .then(callback) // .catch(errback) }) //TODO we should get it to connected // assert.equal(sendTransport.connectionState, 'new'); } catch (error) { console.warn(error) } }); after(function () { signalingSocket.close(); }) }); after(function () { process.exit(); })