mediasoup 3.15.4 → 3.15.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -4
- package/node/lib/test/test-DirectTransport.js +3 -1
- package/node/lib/test/test-Worker.js +7 -7
- package/node/lib/test/test-mediasoup.js +2 -2
- package/npm-scripts.mjs +25 -9
- package/package.json +11 -10
- package/worker/include/Channel/ChannelSocket.hpp +3 -1
- package/worker/include/RTC/ActiveSpeakerObserver.hpp +0 -1
- package/worker/include/RTC/Codecs/PayloadDescriptorHandler.hpp +110 -0
- package/worker/include/RTC/Consumer.hpp +0 -4
- package/worker/include/RTC/DataProducer.hpp +0 -1
- package/worker/include/RTC/RTCP/Feedback.hpp +0 -1
- package/worker/include/RTC/RTCP/FeedbackItem.hpp +1 -1
- package/worker/include/RTC/RTCP/FeedbackPs.hpp +1 -0
- package/worker/include/RTC/RTCP/FeedbackRtp.hpp +1 -0
- package/worker/include/RTC/Router.hpp +0 -1
- package/worker/include/RTC/RtpDictionaries.hpp +1 -1
- package/worker/include/RTC/Transport.hpp +0 -1
- package/worker/meson.build +1 -0
- package/worker/src/Channel/ChannelSocket.cpp +8 -1
- package/worker/src/RTC/Codecs/VP9.cpp +63 -55
- package/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp +1 -1
- package/worker/src/RTC/RtpPacket.cpp +2 -0
- package/worker/src/RTC/SimpleConsumer.cpp +10 -2
- package/worker/src/RTC/SimulcastConsumer.cpp +26 -13
- package/worker/src/RTC/SvcConsumer.cpp +19 -10
- package/worker/src/RTC/Transport.cpp +0 -1
- package/worker/src/Worker.cpp +1 -14
- package/worker/test/src/RTC/Codecs/TestVP9.cpp +108 -2
- package/worker/test/src/RTC/TestRtpStreamSend.cpp +3 -3
- package/worker/test/src/RTC/TestSimpleConsumer.cpp +281 -0
package/README.md
CHANGED
|
@@ -4,11 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
[![][npm-shield-mediasoup]][npm-mediasoup]
|
|
6
6
|
[![][crates-shield-mediasoup]][crates-mediasoup]
|
|
7
|
+
[![][opencollective-shield-mediasoup]][opencollective-mediasoup]
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
7
11
|
[![][github-actions-shield-mediasoup-node]][github-actions-mediasoup-node]
|
|
8
12
|
[![][github-actions-shield-mediasoup-worker]][github-actions-mediasoup-worker]
|
|
9
13
|
[![][github-actions-shield-mediasoup-rust]][github-actions-mediasoup-rust]
|
|
14
|
+
[![][github-actions-shield-mediasoup-worker-fuzzer]][github-actions-mediasoup-worker-fuzzer]
|
|
15
|
+
[![][github-actions-shield-mediasoup-worker-prebuild]][github-actions-mediasoup-worker-prebuild]
|
|
10
16
|
[![][codeql-shield-mediasoup]][codeql-mediasoup]
|
|
11
|
-
[![][opencollective-shield-mediasoup]][opencollective-mediasoup]
|
|
12
17
|
|
|
13
18
|
## Website and Documentation
|
|
14
19
|
|
|
@@ -87,17 +92,21 @@ You can support mediasoup by [sponsoring][sponsor] it. Thanks!
|
|
|
87
92
|
[npm-mediasoup]: https://npmjs.org/package/mediasoup
|
|
88
93
|
[crates-shield-mediasoup]: https://img.shields.io/crates/v/mediasoup.svg
|
|
89
94
|
[crates-mediasoup]: https://crates.io/crates/mediasoup
|
|
95
|
+
[opencollective-shield-mediasoup]: https://img.shields.io/opencollective/all/mediasoup.svg
|
|
96
|
+
[opencollective-mediasoup]: https://opencollective.com/mediasoup
|
|
90
97
|
[github-actions-shield-mediasoup-node]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-node.yaml/badge.svg
|
|
91
98
|
[github-actions-mediasoup-node]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-node.yaml
|
|
92
99
|
[github-actions-shield-mediasoup-worker]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-worker.yaml/badge.svg
|
|
93
100
|
[github-actions-mediasoup-worker]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-worker.yaml
|
|
94
101
|
[github-actions-shield-mediasoup-rust]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-rust.yaml/badge.svg
|
|
95
102
|
[github-actions-mediasoup-rust]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-rust.yaml
|
|
103
|
+
[github-actions-shield-mediasoup-worker-fuzzer]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-worker-fuzzer.yaml/badge.svg
|
|
104
|
+
[github-actions-mediasoup-worker-fuzzer]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-worker-fuzzer.yaml
|
|
105
|
+
[github-actions-shield-mediasoup-worker-prebuild]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-worker-prebuild.yaml/badge.svg
|
|
106
|
+
[github-actions-mediasoup-worker-prebuild]: https://github.com/versatica/mediasoup/actions/workflows/mediasoup-worker-prebuild.yaml
|
|
96
107
|
[codeql-shield-mediasoup]: https://github.com/versatica/mediasoup/actions/workflows/codeql.yml/badge.svg
|
|
97
108
|
[codeql-mediasoup]: https://github.com/versatica/mediasoup/actions/workflows/codeql.yml
|
|
98
|
-
[
|
|
99
|
-
[opencollective-mediasoup]: https://opencollective.com/mediasoup/
|
|
100
|
-
[sponsor]: https://mediasoup.org/sponsor/
|
|
109
|
+
[sponsor]: https://mediasoup.org/sponsor
|
|
101
110
|
[mediasoup-architecture]: /art/mediasoup-v3-architecture-01.svg
|
|
102
111
|
[mediasoup-demo-screenshot]: /art/mediasoup-v3.png
|
|
103
112
|
[mediasoup-demo]: https://v3demo.mediasoup.org
|
|
@@ -111,16 +111,18 @@ test('dataProducer.send() succeeds', async () => {
|
|
|
111
111
|
else if (id === resumeReceivingAtMessage) {
|
|
112
112
|
await dataConsumer.resume();
|
|
113
113
|
}
|
|
114
|
+
let messageSize;
|
|
114
115
|
// Send string (WebRTC DataChannel string).
|
|
115
116
|
if (id < numMessages / 2) {
|
|
116
117
|
message = String(id);
|
|
118
|
+
messageSize = Buffer.from(message).byteLength;
|
|
117
119
|
}
|
|
118
120
|
// Send string (WebRTC DataChannel binary).
|
|
119
121
|
else {
|
|
120
122
|
message = Buffer.from(String(id));
|
|
123
|
+
messageSize = message.byteLength;
|
|
121
124
|
}
|
|
122
125
|
dataProducer.send(message);
|
|
123
|
-
const messageSize = Buffer.from(message).byteLength;
|
|
124
126
|
sentMessageBytes += messageSize;
|
|
125
127
|
if (!dataProducer.paused && !dataConsumer.paused) {
|
|
126
128
|
effectivelySentMessageBytes += messageSize;
|
|
@@ -6,7 +6,7 @@ const path = require("node:path");
|
|
|
6
6
|
const mediasoup = require("../");
|
|
7
7
|
const enhancedEvents_1 = require("../enhancedEvents");
|
|
8
8
|
const errors_1 = require("../errors");
|
|
9
|
-
test('
|
|
9
|
+
test('mediasoup.workerBin matches mediasoup-worker absolute path', () => {
|
|
10
10
|
const workerBin = process.env.MEDIASOUP_WORKER_BIN
|
|
11
11
|
? process.env.MEDIASOUP_WORKER_BIN
|
|
12
12
|
: process.env.MEDIASOUP_BUILDTYPE === 'Debug'
|
|
@@ -14,7 +14,7 @@ test('Worker.workerBin matches mediasoup-worker absolute path', () => {
|
|
|
14
14
|
: path.join(__dirname, '..', '..', '..', 'worker', 'out', 'Release', 'mediasoup-worker');
|
|
15
15
|
expect(mediasoup.workerBin).toBe(workerBin);
|
|
16
16
|
});
|
|
17
|
-
test('createWorker() succeeds', async () => {
|
|
17
|
+
test('mediasoup.createWorker() succeeds', async () => {
|
|
18
18
|
const onObserverNewWorker = jest.fn();
|
|
19
19
|
mediasoup.observer.once('newworker', onObserverNewWorker);
|
|
20
20
|
const worker1 = await mediasoup.createWorker();
|
|
@@ -49,7 +49,7 @@ test('createWorker() succeeds', async () => {
|
|
|
49
49
|
expect(worker2.closed).toBe(true);
|
|
50
50
|
expect(worker2.died).toBe(false);
|
|
51
51
|
}, 2000);
|
|
52
|
-
test('createWorker() with wrong settings rejects with TypeError', async () => {
|
|
52
|
+
test('mediasoup.createWorker() with wrong settings rejects with TypeError', async () => {
|
|
53
53
|
// @ts-expect-error --- Testing purposes.
|
|
54
54
|
await expect(mediasoup.createWorker({ logLevel: 'chicken' })).rejects.toThrow(TypeError);
|
|
55
55
|
await expect(mediasoup.createWorker({ rtcMinPort: 1000, rtcMaxPort: 999 })).rejects.toThrow(TypeError);
|
|
@@ -115,7 +115,7 @@ test('worker.close() succeeds', async () => {
|
|
|
115
115
|
expect(worker.closed).toBe(true);
|
|
116
116
|
expect(worker.died).toBe(false);
|
|
117
117
|
}, 2000);
|
|
118
|
-
test('Worker emits "died" if worker process died unexpectedly', async () => {
|
|
118
|
+
test('Worker emits "died" if mediasoup-worker process died unexpectedly', async () => {
|
|
119
119
|
let onDied;
|
|
120
120
|
let onObserverClose;
|
|
121
121
|
const worker1 = await mediasoup.createWorker({ logLevel: 'warn' });
|
|
@@ -200,7 +200,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => {
|
|
|
200
200
|
// Windows doesn't have some signals such as SIGPIPE, SIGALRM, SIGUSR1, SIGUSR2
|
|
201
201
|
// so we just skip this test in Windows.
|
|
202
202
|
if (os.platform() !== 'win32') {
|
|
203
|
-
test('worker process ignores PIPE, HUP, ALRM, USR1 and USR2 signals', async () => {
|
|
203
|
+
test('mediasoup-worker process ignores PIPE, HUP, ALRM, USR1 and USR2 signals', async () => {
|
|
204
204
|
const worker = await mediasoup.createWorker({ logLevel: 'warn' });
|
|
205
205
|
await new Promise((resolve, reject) => {
|
|
206
206
|
worker.on('died', reject);
|
|
@@ -211,9 +211,9 @@ if (os.platform() !== 'win32') {
|
|
|
211
211
|
process.kill(worker.pid, 'SIGUSR2');
|
|
212
212
|
setTimeout(() => {
|
|
213
213
|
expect(worker.closed).toBe(false);
|
|
214
|
-
worker.close();
|
|
215
214
|
worker.on('subprocessclose', resolve);
|
|
215
|
+
worker.close();
|
|
216
216
|
}, 2000);
|
|
217
217
|
});
|
|
218
|
-
},
|
|
218
|
+
}, 4000);
|
|
219
219
|
}
|
|
@@ -11,7 +11,7 @@ const { version, getSupportedRtpCapabilities, parseScalabilityMode } = mediasoup
|
|
|
11
11
|
test('mediasoup.version matches version field in package.json', () => {
|
|
12
12
|
expect(version).toBe(PKG.version);
|
|
13
13
|
});
|
|
14
|
-
test('setLoggerEventListeners()
|
|
14
|
+
test('mediasoup.setLoggerEventListeners() succeeds', async () => {
|
|
15
15
|
const onDebug = jest.fn();
|
|
16
16
|
mediasoup.setLogEventListeners({
|
|
17
17
|
ondebug: onDebug,
|
|
@@ -35,7 +35,7 @@ test('mediasoup.getSupportedRtpCapabilities() returns the mediasoup RTP capabili
|
|
|
35
35
|
const rtpCapabilities2 = getSupportedRtpCapabilities();
|
|
36
36
|
expect(rtpCapabilities2).not.toEqual(rtpCapabilities);
|
|
37
37
|
});
|
|
38
|
-
test('parseScalabilityMode()
|
|
38
|
+
test('mediasoup.parseScalabilityMode() succeeds', () => {
|
|
39
39
|
expect(parseScalabilityMode('L1T3')).toEqual({
|
|
40
40
|
spatialLayers: 1,
|
|
41
41
|
temporalLayers: 3,
|
package/npm-scripts.mjs
CHANGED
|
@@ -20,8 +20,6 @@ const WORKER_RELEASE_BIN = IS_WINDOWS
|
|
|
20
20
|
: 'mediasoup-worker';
|
|
21
21
|
const WORKER_RELEASE_BIN_PATH = `${WORKER_RELEASE_DIR}/${WORKER_RELEASE_BIN}`;
|
|
22
22
|
const WORKER_PREBUILD_DIR = 'worker/prebuild';
|
|
23
|
-
const WORKER_PREBUILD_TAR = getWorkerPrebuildTarName();
|
|
24
|
-
const WORKER_PREBUILD_TAR_PATH = `${WORKER_PREBUILD_DIR}/${WORKER_PREBUILD_TAR}`;
|
|
25
23
|
const GH_OWNER = 'versatica';
|
|
26
24
|
const GH_REPO = 'mediasoup';
|
|
27
25
|
|
|
@@ -154,6 +152,12 @@ async function run() {
|
|
|
154
152
|
break;
|
|
155
153
|
}
|
|
156
154
|
|
|
155
|
+
case 'worker:prebuild-name': {
|
|
156
|
+
getWorkerPrebuildTarName();
|
|
157
|
+
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
|
|
157
161
|
case 'worker:prebuild': {
|
|
158
162
|
await prebuildWorker();
|
|
159
163
|
|
|
@@ -284,17 +288,23 @@ function getPython() {
|
|
|
284
288
|
}
|
|
285
289
|
|
|
286
290
|
function getWorkerPrebuildTarName() {
|
|
287
|
-
let
|
|
291
|
+
let workerPrebuildTarName = `mediasoup-worker-${PKG.version}-${os.platform()}-${os.arch()}`;
|
|
288
292
|
|
|
289
293
|
// In Linux we want to know about kernel version since kernel >= 6 supports
|
|
290
294
|
// io-uring.
|
|
291
295
|
if (os.platform() === 'linux') {
|
|
292
296
|
const kernelMajorVersion = Number(os.release().split('.')[0]);
|
|
293
297
|
|
|
294
|
-
|
|
298
|
+
workerPrebuildTarName += `-kernel${kernelMajorVersion}`;
|
|
295
299
|
}
|
|
296
300
|
|
|
297
|
-
|
|
301
|
+
workerPrebuildTarName = `${workerPrebuildTarName}.tgz`;
|
|
302
|
+
|
|
303
|
+
logInfo(
|
|
304
|
+
`getWorkerPrebuildTarName() [workerPrebuildTarName:${workerPrebuildTarName}]`
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
return workerPrebuildTarName;
|
|
298
308
|
}
|
|
299
309
|
|
|
300
310
|
function installInvoke() {
|
|
@@ -490,6 +500,9 @@ async function prebuildWorker() {
|
|
|
490
500
|
|
|
491
501
|
ensureDir(WORKER_PREBUILD_DIR);
|
|
492
502
|
|
|
503
|
+
const workerPrebuildTar = getWorkerPrebuildTarName();
|
|
504
|
+
const workerPrebuildTarPath = `${WORKER_PREBUILD_DIR}/${workerPrebuildTar}`;
|
|
505
|
+
|
|
493
506
|
return new Promise((resolve, reject) => {
|
|
494
507
|
// Generate a gzip file which just contains mediasoup-worker binary without
|
|
495
508
|
// any folder.
|
|
@@ -501,7 +514,7 @@ async function prebuildWorker() {
|
|
|
501
514
|
},
|
|
502
515
|
[WORKER_RELEASE_BIN]
|
|
503
516
|
)
|
|
504
|
-
.pipe(fs.createWriteStream(
|
|
517
|
+
.pipe(fs.createWriteStream(workerPrebuildTarPath))
|
|
505
518
|
.on('finish', resolve)
|
|
506
519
|
.on('error', reject);
|
|
507
520
|
});
|
|
@@ -516,16 +529,19 @@ async function downloadPrebuiltWorker() {
|
|
|
516
529
|
.replace(/^git\+/, '')
|
|
517
530
|
.replace(/\.git$/, '')}/releases/download`;
|
|
518
531
|
|
|
519
|
-
const
|
|
532
|
+
const workerPrebuildTar = getWorkerPrebuildTarName();
|
|
533
|
+
const workerPrebuildTarUrl = `${releaseBase}/${PKG.version}/${workerPrebuildTar}`;
|
|
520
534
|
|
|
521
|
-
logInfo(
|
|
535
|
+
logInfo(
|
|
536
|
+
`downloadPrebuiltWorker() [workerPrebuildTarUrl:${workerPrebuildTarUrl}]`
|
|
537
|
+
);
|
|
522
538
|
|
|
523
539
|
ensureDir(WORKER_PREBUILD_DIR);
|
|
524
540
|
|
|
525
541
|
let res;
|
|
526
542
|
|
|
527
543
|
try {
|
|
528
|
-
res = await fetch(
|
|
544
|
+
res = await fetch(workerPrebuildTarUrl);
|
|
529
545
|
|
|
530
546
|
if (res.status === 404) {
|
|
531
547
|
logInfo(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mediasoup",
|
|
3
|
-
"version": "3.15.
|
|
3
|
+
"version": "3.15.6",
|
|
4
4
|
"description": "Cutting Edge WebRTC Video Conferencing",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"typescript:build": "node npm-scripts.mjs typescript:build",
|
|
55
55
|
"typescript:watch": "node npm-scripts.mjs typescript:watch",
|
|
56
56
|
"worker:build": "node npm-scripts.mjs worker:build",
|
|
57
|
+
"worker:prebuild-name": "node npm-scripts.mjs worker:prebuild-name",
|
|
57
58
|
"worker:prebuild": "node npm-scripts.mjs worker:prebuild",
|
|
58
59
|
"lint": "npm run lint:node && npm run lint:worker",
|
|
59
60
|
"lint:node": "node npm-scripts.mjs lint:node",
|
|
@@ -102,20 +103,20 @@
|
|
|
102
103
|
"@types/ini": "^4.1.1",
|
|
103
104
|
"debug": "^4.4.0",
|
|
104
105
|
"flatbuffers": "^25.2.10",
|
|
105
|
-
"h264-profile-level-id": "^2.
|
|
106
|
+
"h264-profile-level-id": "^2.2.0",
|
|
106
107
|
"ini": "^5.0.0",
|
|
107
108
|
"node-fetch": "^3.3.2",
|
|
108
109
|
"supports-color": "^10.0.0",
|
|
109
110
|
"tar": "^7.4.3"
|
|
110
111
|
},
|
|
111
112
|
"devDependencies": {
|
|
112
|
-
"@eslint/js": "^9.
|
|
113
|
+
"@eslint/js": "^9.22.0",
|
|
113
114
|
"@octokit/rest": "^21.1.1",
|
|
114
115
|
"@types/debug": "^4.1.12",
|
|
115
116
|
"@types/jest": "^29.5.14",
|
|
116
|
-
"@types/node": "^22.13.
|
|
117
|
-
"eslint": "^9.
|
|
118
|
-
"eslint-config-prettier": "^10.
|
|
117
|
+
"@types/node": "^22.13.10",
|
|
118
|
+
"eslint": "^9.22.0",
|
|
119
|
+
"eslint-config-prettier": "^10.1.1",
|
|
119
120
|
"eslint-plugin-jest": "^28.11.0",
|
|
120
121
|
"eslint-plugin-prettier": "^5.2.3",
|
|
121
122
|
"globals": "^16.0.0",
|
|
@@ -123,10 +124,10 @@
|
|
|
123
124
|
"marked": "^15.0.7",
|
|
124
125
|
"open-cli": "^8.0.0",
|
|
125
126
|
"pick-port": "^2.1.0",
|
|
126
|
-
"prettier": "^3.5.
|
|
127
|
+
"prettier": "^3.5.3",
|
|
127
128
|
"sctp": "^1.0.0",
|
|
128
|
-
"ts-jest": "^29.2.
|
|
129
|
-
"typescript": "^5.
|
|
130
|
-
"typescript-eslint": "^8.
|
|
129
|
+
"ts-jest": "^29.2.6",
|
|
130
|
+
"typescript": "^5.8.2",
|
|
131
|
+
"typescript-eslint": "^8.26.1"
|
|
131
132
|
}
|
|
132
133
|
}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
#include "Channel/ChannelNotification.hpp"
|
|
6
6
|
#include "Channel/ChannelRequest.hpp"
|
|
7
7
|
#include "handles/UnixStreamSocketHandle.hpp"
|
|
8
|
-
#include <string>
|
|
9
8
|
|
|
10
9
|
namespace Channel
|
|
11
10
|
{
|
|
@@ -82,6 +81,9 @@ namespace Channel
|
|
|
82
81
|
};
|
|
83
82
|
|
|
84
83
|
public:
|
|
84
|
+
#ifdef MS_TEST
|
|
85
|
+
explicit ChannelSocket();
|
|
86
|
+
#endif
|
|
85
87
|
explicit ChannelSocket(int consumerFd, int producerFd);
|
|
86
88
|
explicit ChannelSocket(
|
|
87
89
|
ChannelReadFn channelReadFn,
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
#define MS_RTC_CODECS_PAYLOAD_DESCRIPTOR_HANDLER_HPP
|
|
3
3
|
|
|
4
4
|
#include "common.hpp"
|
|
5
|
+
#include "RTC/SeqManager.hpp"
|
|
6
|
+
#include <deque>
|
|
5
7
|
|
|
6
8
|
namespace RTC
|
|
7
9
|
{
|
|
@@ -14,6 +16,67 @@ namespace RTC
|
|
|
14
16
|
virtual void Dump() const = 0;
|
|
15
17
|
};
|
|
16
18
|
|
|
19
|
+
class PictureIdList
|
|
20
|
+
{
|
|
21
|
+
static constexpr uint16_t MaxCurrentLayerPictureIdNum{ 1000u };
|
|
22
|
+
|
|
23
|
+
public:
|
|
24
|
+
explicit PictureIdList()
|
|
25
|
+
{
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
~PictureIdList()
|
|
29
|
+
{
|
|
30
|
+
this->layerChanges.clear();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
void Push(uint16_t pictureId, int16_t layer)
|
|
34
|
+
{
|
|
35
|
+
for (const auto& it : this->layerChanges)
|
|
36
|
+
{
|
|
37
|
+
// Layers can be changed only with ordered pictureId values.
|
|
38
|
+
// If pictureId is lower than the previous one, then it has rolled over the max value.
|
|
39
|
+
uint16_t diff = pictureId > it.first
|
|
40
|
+
? pictureId - it.first
|
|
41
|
+
: pictureId + RTC::SeqManager<uint16_t, 15>::MaxValue - it.first;
|
|
42
|
+
|
|
43
|
+
if (diff > MaxCurrentLayerPictureIdNum)
|
|
44
|
+
{
|
|
45
|
+
this->layerChanges.pop_front();
|
|
46
|
+
}
|
|
47
|
+
else
|
|
48
|
+
{
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this->layerChanges.push_back({ pictureId, layer });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
int16_t GetLayer(uint16_t pictureId) const
|
|
57
|
+
{
|
|
58
|
+
if (this->layerChanges.size() <= 1)
|
|
59
|
+
{
|
|
60
|
+
return -1;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
for (auto it = std::next(this->layerChanges.begin()); it != this->layerChanges.end(); ++it)
|
|
64
|
+
{
|
|
65
|
+
if (RTC::SeqManager<uint16_t, 15>::IsSeqHigherThan(it->first, pictureId))
|
|
66
|
+
{
|
|
67
|
+
return std::prev(it)->second;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return -1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private:
|
|
75
|
+
// List populated with the spatial/temporal layer changes
|
|
76
|
+
// indexed by the corresponding pictureId.
|
|
77
|
+
std::deque<std::pair<uint16_t, int16_t>> layerChanges;
|
|
78
|
+
};
|
|
79
|
+
|
|
17
80
|
// Encoding context used by PayloadDescriptorHandler to properly rewrite the
|
|
18
81
|
// PayloadDescriptor.
|
|
19
82
|
class EncodingContext
|
|
@@ -86,6 +149,48 @@ namespace RTC
|
|
|
86
149
|
this->ignoreDtx = ignoreDtx;
|
|
87
150
|
}
|
|
88
151
|
virtual void SyncRequired() = 0;
|
|
152
|
+
void SetCurrentSpatialLayer(int16_t spatialLayer, uint16_t pictureId)
|
|
153
|
+
{
|
|
154
|
+
if (this->currentSpatialLayer == spatialLayer)
|
|
155
|
+
{
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this->spatialLayerPictureIdList.Push(pictureId, spatialLayer);
|
|
160
|
+
this->currentSpatialLayer = spatialLayer;
|
|
161
|
+
}
|
|
162
|
+
void SetCurrentTemporalLayer(int16_t temporalLayer, uint16_t pictureId)
|
|
163
|
+
{
|
|
164
|
+
if (this->currentTemporalLayer == temporalLayer)
|
|
165
|
+
{
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
this->temporalLayerPictureIdList.Push(pictureId, temporalLayer);
|
|
170
|
+
this->currentTemporalLayer = temporalLayer;
|
|
171
|
+
}
|
|
172
|
+
int16_t GetSpatialLayerForPictureId(uint16_t pictureId) const
|
|
173
|
+
{
|
|
174
|
+
int16_t layer = this->spatialLayerPictureIdList.GetLayer(pictureId);
|
|
175
|
+
|
|
176
|
+
if (layer > -1)
|
|
177
|
+
{
|
|
178
|
+
return layer;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return this->currentSpatialLayer;
|
|
182
|
+
}
|
|
183
|
+
int16_t GetTemporalLayerForPictureId(uint16_t pictureId) const
|
|
184
|
+
{
|
|
185
|
+
int16_t layer = this->temporalLayerPictureIdList.GetLayer(pictureId);
|
|
186
|
+
|
|
187
|
+
if (layer > -1)
|
|
188
|
+
{
|
|
189
|
+
return layer;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return this->currentTemporalLayer;
|
|
193
|
+
}
|
|
89
194
|
|
|
90
195
|
private:
|
|
91
196
|
Params params;
|
|
@@ -94,6 +199,11 @@ namespace RTC
|
|
|
94
199
|
int16_t currentSpatialLayer{ -1 };
|
|
95
200
|
int16_t currentTemporalLayer{ -1 };
|
|
96
201
|
bool ignoreDtx{ false };
|
|
202
|
+
|
|
203
|
+
private:
|
|
204
|
+
// List of spatial/temporal layer changes indexed by the corresponding pictureId.
|
|
205
|
+
PictureIdList spatialLayerPictureIdList;
|
|
206
|
+
PictureIdList temporalLayerPictureIdList;
|
|
97
207
|
};
|
|
98
208
|
|
|
99
209
|
class PayloadDescriptorHandler
|
|
@@ -6,15 +6,11 @@
|
|
|
6
6
|
#include "Channel/ChannelSocket.hpp"
|
|
7
7
|
#include "FBS/consumer.h"
|
|
8
8
|
#include "RTC/RTCP/CompoundPacket.hpp"
|
|
9
|
-
#include "RTC/RTCP/FeedbackPs.hpp"
|
|
10
|
-
#include "RTC/RTCP/FeedbackPsFir.hpp"
|
|
11
|
-
#include "RTC/RTCP/FeedbackPsPli.hpp"
|
|
12
9
|
#include "RTC/RTCP/FeedbackRtpNack.hpp"
|
|
13
10
|
#include "RTC/RTCP/ReceiverReport.hpp"
|
|
14
11
|
#include "RTC/RtpDictionaries.hpp"
|
|
15
12
|
#include "RTC/RtpHeaderExtensionIds.hpp"
|
|
16
13
|
#include "RTC/RtpPacket.hpp"
|
|
17
|
-
#include "RTC/RtpStream.hpp"
|
|
18
14
|
#include "RTC/RtpStreamRecv.hpp"
|
|
19
15
|
#include "RTC/RtpStreamSend.hpp"
|
|
20
16
|
#include "RTC/Shared.hpp"
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
#include "RTC/Producer.hpp"
|
|
15
15
|
#include "RTC/RTCP/CompoundPacket.hpp"
|
|
16
16
|
#include "RTC/RTCP/Packet.hpp"
|
|
17
|
-
#include "RTC/RTCP/ReceiverReport.hpp"
|
|
18
17
|
#include "RTC/RateCalculator.hpp"
|
|
19
18
|
#include "RTC/RtpHeaderExtensionIds.hpp"
|
|
20
19
|
#include "RTC/RtpListener.hpp"
|
package/worker/meson.build
CHANGED
|
@@ -333,6 +333,7 @@ test_sources = [
|
|
|
333
333
|
'test/src/RTC/TestRtpStreamSend.cpp',
|
|
334
334
|
'test/src/RTC/TestRtpStreamRecv.cpp',
|
|
335
335
|
'test/src/RTC/TestSeqManager.cpp',
|
|
336
|
+
'test/src/RTC/TestSimpleConsumer.cpp',
|
|
336
337
|
'test/src/RTC/TestTrendCalculator.cpp',
|
|
337
338
|
'test/src/RTC/TestRtpEncodingParameters.cpp',
|
|
338
339
|
'test/src/RTC/TestTransportCongestionControlServer.cpp',
|
|
@@ -30,6 +30,13 @@ namespace Channel
|
|
|
30
30
|
|
|
31
31
|
/* Instance methods. */
|
|
32
32
|
|
|
33
|
+
#ifdef MS_TEST
|
|
34
|
+
ChannelSocket::ChannelSocket()
|
|
35
|
+
{
|
|
36
|
+
MS_TRACE_STD();
|
|
37
|
+
}
|
|
38
|
+
#endif
|
|
39
|
+
|
|
33
40
|
ChannelSocket::ChannelSocket(int consumerFd, int producerFd)
|
|
34
41
|
: consumerSocket(new ConsumerSocket(consumerFd, MessageMaxLen, this)),
|
|
35
42
|
producerSocket(new ProducerSocket(producerFd, MessageMaxLen))
|
|
@@ -256,7 +263,7 @@ namespace Channel
|
|
|
256
263
|
{
|
|
257
264
|
this->channelWriteFn(payload, payloadLen, this->channelWriteCtx);
|
|
258
265
|
}
|
|
259
|
-
else
|
|
266
|
+
else if (this->producerSocket)
|
|
260
267
|
{
|
|
261
268
|
this->producerSocket->Write(payload, payloadLen);
|
|
262
269
|
}
|