mediasoup 3.13.3 → 3.13.5
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/node/lib/ortc.js +1 -1
- package/node/lib/tests/test-Consumer.js +2 -2
- package/node/lib/tests/test-multiopus.js +1 -1
- package/node/lib/tests/test-node-sctp.js +6 -6
- package/node/lib/tests/test-ortc.js +4 -4
- package/package.json +7 -7
- package/worker/Makefile +3 -3
- package/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc +4 -0
- package/worker/include/RTC/RTCP/CompoundPacket.hpp +13 -4
- package/worker/include/RTC/RTCP/Sdes.hpp +1 -1
- package/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp +13 -0
- package/worker/include/RTC/RtpStreamSend.hpp +1 -1
- package/worker/scripts/clang-format.mjs +89 -0
- package/worker/src/RTC/PipeConsumer.cpp +5 -8
- package/worker/src/RTC/RTCP/CompoundPacket.cpp +28 -26
- package/worker/src/RTC/RTCP/XrDelaySinceLastRr.cpp +1 -3
- package/worker/src/RTC/RtpStreamSend.cpp +1 -1
- package/worker/src/RTC/SimpleConsumer.cpp +2 -10
- package/worker/src/RTC/SimulcastConsumer.cpp +2 -10
- package/worker/src/RTC/SvcConsumer.cpp +2 -10
- package/worker/test/src/RTC/Codecs/TestVP8.cpp +1 -1
- package/worker/test/src/RTC/RTCP/TestSdes.cpp +88 -8
- package/worker/test/src/RTC/RTCP/TestXr.cpp +123 -1
package/node/lib/ortc.js
CHANGED
|
@@ -656,7 +656,7 @@ function getConsumableRtpParameters(kind, params, caps, rtpMapping) {
|
|
|
656
656
|
payloadType: matchedCapCodec.preferredPayloadType,
|
|
657
657
|
clockRate: matchedCapCodec.clockRate,
|
|
658
658
|
channels: matchedCapCodec.channels,
|
|
659
|
-
parameters: codec.parameters,
|
|
659
|
+
parameters: codec.parameters, // Keep the Producer codec parameters.
|
|
660
660
|
rtcpFeedback: matchedCapCodec.rtcpFeedback
|
|
661
661
|
};
|
|
662
662
|
consumableParams.codecs.push(consumableCodec);
|
|
@@ -185,13 +185,13 @@ const consumerDeviceCapabilities = {
|
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
187
|
kind: 'audio',
|
|
188
|
-
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time',
|
|
188
|
+
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len
|
|
189
189
|
preferredId: 4,
|
|
190
190
|
preferredEncrypt: false
|
|
191
191
|
},
|
|
192
192
|
{
|
|
193
193
|
kind: 'video',
|
|
194
|
-
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time',
|
|
194
|
+
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len
|
|
195
195
|
preferredId: 4,
|
|
196
196
|
preferredEncrypt: false
|
|
197
197
|
},
|
|
@@ -73,7 +73,7 @@ const consumerDeviceCapabilities = {
|
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
kind: 'audio',
|
|
76
|
-
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time',
|
|
76
|
+
uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len
|
|
77
77
|
preferredId: 4,
|
|
78
78
|
preferredEncrypt: false
|
|
79
79
|
},
|
|
@@ -19,8 +19,8 @@ beforeAll(async () => {
|
|
|
19
19
|
worker = await mediasoup.createWorker();
|
|
20
20
|
router = await worker.createRouter();
|
|
21
21
|
transport = await router.createPlainTransport({
|
|
22
|
-
listenIp: '127.0.0.1',
|
|
23
|
-
comedia: true,
|
|
22
|
+
listenIp: '127.0.0.1', // https://github.com/nodejs/node/issues/14900
|
|
23
|
+
comedia: true, // So we don't need to call transport.connect().
|
|
24
24
|
enableSctp: true,
|
|
25
25
|
numSctpStreams: { OS: 256, MIS: 256 }
|
|
26
26
|
});
|
|
@@ -40,8 +40,8 @@ beforeAll(async () => {
|
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
sctpSocket = sctp.connect({
|
|
43
|
-
localPort: 5000,
|
|
44
|
-
port: 5000,
|
|
43
|
+
localPort: 5000, // Required for SCTP over UDP in mediasoup.
|
|
44
|
+
port: 5000, // Required for SCTP over UDP in mediasoup.
|
|
45
45
|
OS: OS,
|
|
46
46
|
MIS: MIS,
|
|
47
47
|
udpTransport: udpSocket
|
|
@@ -53,8 +53,8 @@ beforeAll(async () => {
|
|
|
53
53
|
// Use UDP disconnected socket if Node < 12.
|
|
54
54
|
else {
|
|
55
55
|
sctpSocket = sctp.connect({
|
|
56
|
-
localPort: 5000,
|
|
57
|
-
port: 5000,
|
|
56
|
+
localPort: 5000, // Required for SCTP over UDP in mediasoup.
|
|
57
|
+
port: 5000, // Required for SCTP over UDP in mediasoup.
|
|
58
58
|
OS: OS,
|
|
59
59
|
MIS: MIS,
|
|
60
60
|
udpTransport: udpSocket,
|
|
@@ -17,7 +17,7 @@ test('generateRouterRtpCapabilities() succeeds', () => {
|
|
|
17
17
|
{
|
|
18
18
|
kind: 'video',
|
|
19
19
|
mimeType: 'video/VP8',
|
|
20
|
-
preferredPayloadType: 125,
|
|
20
|
+
preferredPayloadType: 125, // Let's force it.
|
|
21
21
|
clockRate: 90000
|
|
22
22
|
},
|
|
23
23
|
{
|
|
@@ -38,7 +38,7 @@ test('generateRouterRtpCapabilities() succeeds', () => {
|
|
|
38
38
|
expect(rtpCapabilities.codecs?.[0]).toEqual({
|
|
39
39
|
kind: 'audio',
|
|
40
40
|
mimeType: 'audio/opus',
|
|
41
|
-
preferredPayloadType: 100,
|
|
41
|
+
preferredPayloadType: 100, // 100 is the first available dynamic PT.
|
|
42
42
|
clockRate: 48000,
|
|
43
43
|
channels: 2,
|
|
44
44
|
parameters: {
|
|
@@ -69,7 +69,7 @@ test('generateRouterRtpCapabilities() succeeds', () => {
|
|
|
69
69
|
expect(rtpCapabilities.codecs?.[2]).toEqual({
|
|
70
70
|
kind: 'video',
|
|
71
71
|
mimeType: 'video/rtx',
|
|
72
|
-
preferredPayloadType: 101,
|
|
72
|
+
preferredPayloadType: 101, // 101 is the second available dynamic PT.
|
|
73
73
|
clockRate: 90000,
|
|
74
74
|
parameters: {
|
|
75
75
|
apt: 125
|
|
@@ -80,7 +80,7 @@ test('generateRouterRtpCapabilities() succeeds', () => {
|
|
|
80
80
|
expect(rtpCapabilities.codecs?.[3]).toEqual({
|
|
81
81
|
kind: 'video',
|
|
82
82
|
mimeType: 'video/H264',
|
|
83
|
-
preferredPayloadType: 102,
|
|
83
|
+
preferredPayloadType: 102, // 102 is the third available dynamic PT.
|
|
84
84
|
clockRate: 90000,
|
|
85
85
|
parameters: {
|
|
86
86
|
// Since packetization-mode param was not included in the H264 codec
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mediasoup",
|
|
3
|
-
"version": "3.13.
|
|
3
|
+
"version": "3.13.5",
|
|
4
4
|
"description": "Cutting Edge WebRTC Video Conferencing",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Iñaki Baz Castillo <ibc@aliax.net> (https://inakibaz.me)",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"worker/fuzzer/include",
|
|
27
27
|
"worker/fuzzer/src",
|
|
28
28
|
"worker/include",
|
|
29
|
-
"worker/scripts/*.
|
|
29
|
+
"worker/scripts/*.mjs",
|
|
30
30
|
"worker/scripts/*.json",
|
|
31
31
|
"worker/scripts/*.py",
|
|
32
32
|
"worker/scripts/*.sh",
|
|
@@ -105,10 +105,10 @@
|
|
|
105
105
|
"devDependencies": {
|
|
106
106
|
"@octokit/rest": "^20.0.2",
|
|
107
107
|
"@types/debug": "^4.1.12",
|
|
108
|
-
"@types/jest": "^29.5.
|
|
109
|
-
"@types/node": "^20.9.
|
|
110
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
111
|
-
"@typescript-eslint/parser": "^6.
|
|
108
|
+
"@types/jest": "^29.5.10",
|
|
109
|
+
"@types/node": "^20.9.4",
|
|
110
|
+
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
|
111
|
+
"@typescript-eslint/parser": "^6.12.0",
|
|
112
112
|
"eslint": "^8.54.0",
|
|
113
113
|
"eslint-plugin-jest": "^27.6.0",
|
|
114
114
|
"jest": "^29.7.0",
|
|
@@ -117,6 +117,6 @@
|
|
|
117
117
|
"pick-port": "^1.0.1",
|
|
118
118
|
"sctp": "^1.0.0",
|
|
119
119
|
"ts-jest": "^29.1.1",
|
|
120
|
-
"typescript": "^5.
|
|
120
|
+
"typescript": "^5.3.2"
|
|
121
121
|
}
|
|
122
122
|
}
|
package/worker/Makefile
CHANGED
|
@@ -213,7 +213,7 @@ libmediasoup-worker: setup flatc
|
|
|
213
213
|
flatc: setup
|
|
214
214
|
$(MESON) compile -C $(BUILD_DIR) flatbuffers-generator
|
|
215
215
|
|
|
216
|
-
xcode: setup
|
|
216
|
+
xcode: setup flatc
|
|
217
217
|
$(MESON) setup --buildtype debug --backend xcode $(MEDIASOUP_OUT_DIR)/xcode
|
|
218
218
|
|
|
219
219
|
lint:
|
|
@@ -234,7 +234,7 @@ else
|
|
|
234
234
|
$(BUILD_DIR)/mediasoup-worker-test --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS)
|
|
235
235
|
endif
|
|
236
236
|
|
|
237
|
-
test-asan: setup
|
|
237
|
+
test-asan: setup flatc
|
|
238
238
|
$(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-test-asan
|
|
239
239
|
$(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-test-asan
|
|
240
240
|
ASAN_OPTIONS=detect_leaks=1 $(BUILD_DIR)/mediasoup-worker-test-asan --invisibles --use-colour=yes $(MEDIASOUP_TEST_TAGS)
|
|
@@ -249,7 +249,7 @@ tidy:
|
|
|
249
249
|
-checks=$(MEDIASOUP_TIDY_CHECKS) \
|
|
250
250
|
-quiet
|
|
251
251
|
|
|
252
|
-
fuzzer: setup
|
|
252
|
+
fuzzer: setup flatc
|
|
253
253
|
$(MESON) compile -C $(BUILD_DIR) -j $(CORES) mediasoup-worker-fuzzer
|
|
254
254
|
$(MESON) install -C $(BUILD_DIR) --no-rebuild --tags mediasoup-worker-fuzzer
|
|
255
255
|
|
|
@@ -289,6 +289,8 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo(
|
|
|
289
289
|
if (payload_size > kMinProbePacketSize &&
|
|
290
290
|
(!remote_rate_.ValidEstimate() ||
|
|
291
291
|
now_ms - first_packet_time_ms_ < kInitialProbingIntervalMs)) {
|
|
292
|
+
|
|
293
|
+
#if MS_LOG_DEV_LEVEL == 3
|
|
292
294
|
// TODO(holmer): Use a map instead to get correct order?
|
|
293
295
|
if (total_probes_received_ < kMaxProbePackets) {
|
|
294
296
|
int send_delta_ms = -1;
|
|
@@ -306,6 +308,8 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo(
|
|
|
306
308
|
send_delta_ms,
|
|
307
309
|
recv_delta_ms);
|
|
308
310
|
}
|
|
311
|
+
#endif
|
|
312
|
+
|
|
309
313
|
probes_.push_back(Probe(send_time_ms, arrival_time_ms, payload_size));
|
|
310
314
|
++total_probes_received_;
|
|
311
315
|
// Make sure that a probe which updated the bitrate immediately has an
|
|
@@ -48,14 +48,16 @@ namespace RTC
|
|
|
48
48
|
// Adds the given data and returns true if there is enough space to hold it,
|
|
49
49
|
// false otherwise.
|
|
50
50
|
bool Add(
|
|
51
|
-
SenderReport* senderReport,
|
|
51
|
+
SenderReport* senderReport,
|
|
52
|
+
SdesChunk* sdesChunk,
|
|
53
|
+
DelaySinceLastRr::SsrcInfo* delaySinceLastRrSsrcInfo);
|
|
52
54
|
// RTCP additions per Consumer (pipe).
|
|
53
55
|
// Adds the given data and returns true if there is enough space to hold it,
|
|
54
56
|
// false otherwise.
|
|
55
57
|
bool Add(
|
|
56
58
|
std::vector<SenderReport*>& senderReports,
|
|
57
59
|
std::vector<SdesChunk*>& sdesChunks,
|
|
58
|
-
std::vector<DelaySinceLastRr*>&
|
|
60
|
+
std::vector<DelaySinceLastRr::SsrcInfo*>& delaySinceLastRrSsrcInfos);
|
|
59
61
|
// RTCP additions per Producer.
|
|
60
62
|
// Adds the given data and returns true if there is enough space to hold it,
|
|
61
63
|
// false otherwise.
|
|
@@ -63,8 +65,6 @@ namespace RTC
|
|
|
63
65
|
void AddSenderReport(SenderReport* report);
|
|
64
66
|
void AddReceiverReport(ReceiverReport* report);
|
|
65
67
|
void AddSdesChunk(SdesChunk* chunk);
|
|
66
|
-
void AddReceiverReferenceTime(ReceiverReferenceTime* report);
|
|
67
|
-
void AddDelaySinceLastRr(DelaySinceLastRr* report);
|
|
68
68
|
bool HasSenderReport()
|
|
69
69
|
{
|
|
70
70
|
return this->senderReportPacket.Begin() != this->senderReportPacket.End();
|
|
@@ -77,6 +77,14 @@ namespace RTC
|
|
|
77
77
|
[](const ExtendedReportBlock* report)
|
|
78
78
|
{ return report->GetType() == ExtendedReportBlock::Type::RRT; });
|
|
79
79
|
}
|
|
80
|
+
bool HasDelaySinceLastRr()
|
|
81
|
+
{
|
|
82
|
+
return std::any_of(
|
|
83
|
+
this->xrPacket.Begin(),
|
|
84
|
+
this->xrPacket.End(),
|
|
85
|
+
[](const ExtendedReportBlock* report)
|
|
86
|
+
{ return report->GetType() == ExtendedReportBlock::Type::DLRR; });
|
|
87
|
+
}
|
|
80
88
|
void Serialize(uint8_t* data);
|
|
81
89
|
|
|
82
90
|
private:
|
|
@@ -85,6 +93,7 @@ namespace RTC
|
|
|
85
93
|
ReceiverReportPacket receiverReportPacket;
|
|
86
94
|
SdesPacket sdesPacket;
|
|
87
95
|
ExtendedReportPacket xrPacket;
|
|
96
|
+
DelaySinceLastRr* delaySinceLastRr{ nullptr };
|
|
88
97
|
};
|
|
89
98
|
} // namespace RTCP
|
|
90
99
|
} // namespace RTC
|
|
@@ -214,7 +214,7 @@ namespace RTC
|
|
|
214
214
|
// A serialized packet can contain a maximum of 31 chunks.
|
|
215
215
|
// If number of chunks exceeds 31 then the required number of packets
|
|
216
216
|
// will be serialized which will take the size calculated below.
|
|
217
|
-
size_t size = Packet::CommonHeaderSize * ((this->GetCount() / MaxChunksPerPacket) + 1);
|
|
217
|
+
size_t size = Packet::CommonHeaderSize * ((this->GetCount() / (MaxChunksPerPacket + 1)) + 1);
|
|
218
218
|
|
|
219
219
|
for (auto* chunk : this->chunks)
|
|
220
220
|
{
|
|
@@ -119,6 +119,19 @@ namespace RTC
|
|
|
119
119
|
{
|
|
120
120
|
this->ssrcInfos.push_back(ssrcInfo);
|
|
121
121
|
}
|
|
122
|
+
// NOTE: This method not only removes given number of ssrc info sub-blocks
|
|
123
|
+
// but also deletes their SsrcInfo instances.
|
|
124
|
+
void RemoveLastSsrcInfos(size_t number)
|
|
125
|
+
{
|
|
126
|
+
while (!this->ssrcInfos.empty() && number-- > 0)
|
|
127
|
+
{
|
|
128
|
+
auto* ssrcInfo = this->ssrcInfos.back();
|
|
129
|
+
|
|
130
|
+
this->ssrcInfos.pop_back();
|
|
131
|
+
|
|
132
|
+
delete ssrcInfo;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
122
135
|
Iterator Begin()
|
|
123
136
|
{
|
|
124
137
|
return this->ssrcInfos.begin();
|
|
@@ -37,7 +37,7 @@ namespace RTC
|
|
|
37
37
|
void ReceiveRtcpReceiverReport(RTC::RTCP::ReceiverReport* report);
|
|
38
38
|
void ReceiveRtcpXrReceiverReferenceTime(RTC::RTCP::ReceiverReferenceTime* report);
|
|
39
39
|
RTC::RTCP::SenderReport* GetRtcpSenderReport(uint64_t nowMs);
|
|
40
|
-
RTC::RTCP::DelaySinceLastRr::SsrcInfo*
|
|
40
|
+
RTC::RTCP::DelaySinceLastRr::SsrcInfo* GetRtcpXrDelaySinceLastRrSsrcInfo(uint64_t nowMs);
|
|
41
41
|
RTC::RTCP::SdesChunk* GetRtcpSdesChunk();
|
|
42
42
|
void Pause() override;
|
|
43
43
|
void Resume() override;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { glob } from 'glob';
|
|
3
|
+
import clangFormat from 'clang-format';
|
|
4
|
+
|
|
5
|
+
const task = process.argv.slice(2).join(' ');
|
|
6
|
+
|
|
7
|
+
run();
|
|
8
|
+
|
|
9
|
+
async function run()
|
|
10
|
+
{
|
|
11
|
+
const clangFormatNativeBinary = clangFormat.getNativeBinary();
|
|
12
|
+
const workerFiles = await glob(
|
|
13
|
+
[
|
|
14
|
+
'../src/**/*.cpp',
|
|
15
|
+
'../include/**/*.hpp',
|
|
16
|
+
'../test/src/**/*.cpp',
|
|
17
|
+
'../test/include/helpers.hpp',
|
|
18
|
+
'../fuzzer/src/**/*.cpp',
|
|
19
|
+
'../fuzzer/include/**/*.hpp'
|
|
20
|
+
]
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
switch (task)
|
|
24
|
+
{
|
|
25
|
+
case 'lint':
|
|
26
|
+
{
|
|
27
|
+
executeCmd(
|
|
28
|
+
`${clangFormatNativeBinary} --Werror --dry-run ${workerFiles.join(' ')}`
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
case 'format':
|
|
35
|
+
{
|
|
36
|
+
executeCmd(
|
|
37
|
+
`${clangFormatNativeBinary} --Werror -i ${workerFiles.join(' ')}`
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
default:
|
|
44
|
+
{
|
|
45
|
+
logError('unknown task');
|
|
46
|
+
|
|
47
|
+
exitWithError();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function executeCmd(command)
|
|
53
|
+
{
|
|
54
|
+
try
|
|
55
|
+
{
|
|
56
|
+
execSync(command, { stdio: [ 'ignore', process.stdout, process.stderr ] });
|
|
57
|
+
}
|
|
58
|
+
catch (error)
|
|
59
|
+
{
|
|
60
|
+
logError('executeCmd() failed');
|
|
61
|
+
|
|
62
|
+
exitWithError();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// eslint-disable-next-line no-unused-vars
|
|
67
|
+
function logInfo(message)
|
|
68
|
+
{
|
|
69
|
+
// eslint-disable-next-line no-console
|
|
70
|
+
console.log(`clang-format.mjs \x1b[36m[INFO] [${task}]\x1b\[0m`, message);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// eslint-disable-next-line no-unused-vars
|
|
74
|
+
function logWarn(message)
|
|
75
|
+
{
|
|
76
|
+
// eslint-disable-next-line no-console
|
|
77
|
+
console.warn(`clang-format.mjs \x1b[33m[WARN] [${task}]\x1b\[0m`, message);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function logError(message)
|
|
81
|
+
{
|
|
82
|
+
// eslint-disable-next-line no-console
|
|
83
|
+
console.error(`clang-format.mjs \x1b[31m[ERROR] [${task}]\x1b\[0m`, message);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function exitWithError()
|
|
87
|
+
{
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
@@ -345,7 +345,7 @@ namespace RTC
|
|
|
345
345
|
|
|
346
346
|
std::vector<RTCP::SenderReport*> senderReports;
|
|
347
347
|
std::vector<RTCP::SdesChunk*> sdesChunks;
|
|
348
|
-
std::vector<RTCP::DelaySinceLastRr*>
|
|
348
|
+
std::vector<RTCP::DelaySinceLastRr::SsrcInfo*> delaySinceLastRrSsrcInfos;
|
|
349
349
|
|
|
350
350
|
for (auto* rtpStream : this->rtpStreams)
|
|
351
351
|
{
|
|
@@ -362,19 +362,16 @@ namespace RTC
|
|
|
362
362
|
auto* sdesChunk = rtpStream->GetRtcpSdesChunk();
|
|
363
363
|
sdesChunks.push_back(sdesChunk);
|
|
364
364
|
|
|
365
|
-
auto*
|
|
365
|
+
auto* delaySinceLastRrSsrcInfo = rtpStream->GetRtcpXrDelaySinceLastRrSsrcInfo(nowMs);
|
|
366
366
|
|
|
367
|
-
if (
|
|
367
|
+
if (delaySinceLastRrSsrcInfo)
|
|
368
368
|
{
|
|
369
|
-
|
|
370
|
-
report->AddSsrcInfo(dlrr);
|
|
371
|
-
|
|
372
|
-
xrReports.push_back(report);
|
|
369
|
+
delaySinceLastRrSsrcInfos.push_back(delaySinceLastRrSsrcInfo);
|
|
373
370
|
}
|
|
374
371
|
}
|
|
375
372
|
|
|
376
373
|
// RTCP Compound packet buffer cannot hold the data.
|
|
377
|
-
if (!packet->Add(senderReports, sdesChunks,
|
|
374
|
+
if (!packet->Add(senderReports, sdesChunks, delaySinceLastRrSsrcInfos))
|
|
378
375
|
{
|
|
379
376
|
return false;
|
|
380
377
|
}
|
|
@@ -72,7 +72,9 @@ namespace RTC
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
bool CompoundPacket::Add(
|
|
75
|
-
SenderReport* senderReport,
|
|
75
|
+
SenderReport* senderReport,
|
|
76
|
+
SdesChunk* sdesChunk,
|
|
77
|
+
DelaySinceLastRr::SsrcInfo* delaySinceLastRrSsrcInfo)
|
|
76
78
|
{
|
|
77
79
|
// Add the items into the packet.
|
|
78
80
|
|
|
@@ -86,9 +88,16 @@ namespace RTC
|
|
|
86
88
|
this->sdesPacket.AddChunk(sdesChunk);
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
if (
|
|
91
|
+
if (delaySinceLastRrSsrcInfo)
|
|
90
92
|
{
|
|
91
|
-
|
|
93
|
+
// Add a DLRR block into the XR packet if no present.
|
|
94
|
+
if (!this->delaySinceLastRr)
|
|
95
|
+
{
|
|
96
|
+
this->delaySinceLastRr = new RTC::RTCP::DelaySinceLastRr();
|
|
97
|
+
this->xrPacket.AddReport(this->delaySinceLastRr);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this->delaySinceLastRr->AddSsrcInfo(delaySinceLastRrSsrcInfo);
|
|
92
101
|
}
|
|
93
102
|
|
|
94
103
|
// New items can hold in the packet, report it.
|
|
@@ -112,10 +121,10 @@ namespace RTC
|
|
|
112
121
|
delete sdesChunk;
|
|
113
122
|
}
|
|
114
123
|
|
|
115
|
-
if (
|
|
124
|
+
if (delaySinceLastRrSsrcInfo)
|
|
116
125
|
{
|
|
117
|
-
|
|
118
|
-
|
|
126
|
+
// NOTE: This method deletes the removed instances in place.
|
|
127
|
+
this->delaySinceLastRr->RemoveLastSsrcInfos(1);
|
|
119
128
|
}
|
|
120
129
|
|
|
121
130
|
return false;
|
|
@@ -124,7 +133,7 @@ namespace RTC
|
|
|
124
133
|
bool CompoundPacket::Add(
|
|
125
134
|
std::vector<SenderReport*>& senderReports,
|
|
126
135
|
std::vector<SdesChunk*>& sdesChunks,
|
|
127
|
-
std::vector<DelaySinceLastRr*>&
|
|
136
|
+
std::vector<DelaySinceLastRr::SsrcInfo*>& delaySinceLastRrSsrcInfos)
|
|
128
137
|
{
|
|
129
138
|
// Add the items into the packet.
|
|
130
139
|
|
|
@@ -138,9 +147,16 @@ namespace RTC
|
|
|
138
147
|
this->sdesPacket.AddChunk(chunk);
|
|
139
148
|
}
|
|
140
149
|
|
|
141
|
-
|
|
150
|
+
// Add a DLRR block into the XR packet if no present.
|
|
151
|
+
if (!delaySinceLastRrSsrcInfos.empty() && !this->delaySinceLastRr)
|
|
142
152
|
{
|
|
143
|
-
this->
|
|
153
|
+
this->delaySinceLastRr = new RTC::RTCP::DelaySinceLastRr();
|
|
154
|
+
this->xrPacket.AddReport(this->delaySinceLastRr);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
for (auto* ssrcInfo : delaySinceLastRrSsrcInfos)
|
|
158
|
+
{
|
|
159
|
+
this->delaySinceLastRr->AddSsrcInfo(ssrcInfo);
|
|
144
160
|
}
|
|
145
161
|
|
|
146
162
|
// New items can hold in the packet, report it.
|
|
@@ -164,10 +180,10 @@ namespace RTC
|
|
|
164
180
|
delete chunk;
|
|
165
181
|
}
|
|
166
182
|
|
|
167
|
-
|
|
183
|
+
if (!delaySinceLastRrSsrcInfos.empty())
|
|
168
184
|
{
|
|
169
|
-
|
|
170
|
-
|
|
185
|
+
// NOTE: This method deletes the instances in place.
|
|
186
|
+
this->delaySinceLastRr->RemoveLastSsrcInfos(delaySinceLastRrSsrcInfos.size());
|
|
171
187
|
}
|
|
172
188
|
|
|
173
189
|
return false;
|
|
@@ -266,19 +282,5 @@ namespace RTC
|
|
|
266
282
|
|
|
267
283
|
this->sdesPacket.AddChunk(chunk);
|
|
268
284
|
}
|
|
269
|
-
|
|
270
|
-
void CompoundPacket::AddReceiverReferenceTime(ReceiverReferenceTime* report)
|
|
271
|
-
{
|
|
272
|
-
MS_TRACE();
|
|
273
|
-
|
|
274
|
-
this->xrPacket.AddReport(report);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
void CompoundPacket::AddDelaySinceLastRr(DelaySinceLastRr* report)
|
|
278
|
-
{
|
|
279
|
-
MS_TRACE();
|
|
280
|
-
|
|
281
|
-
this->xrPacket.AddReport(report);
|
|
282
|
-
}
|
|
283
285
|
} // namespace RTCP
|
|
284
286
|
} // namespace RTC
|
|
@@ -75,14 +75,12 @@ namespace RTC
|
|
|
75
75
|
{
|
|
76
76
|
report->AddSsrcInfo(ssrcInfo);
|
|
77
77
|
offset += ssrcInfo->GetSize();
|
|
78
|
+
reportLength -= ssrcInfo->GetSize();
|
|
78
79
|
}
|
|
79
80
|
else
|
|
80
81
|
{
|
|
81
82
|
return report.release();
|
|
82
83
|
}
|
|
83
|
-
|
|
84
|
-
offset += ssrcInfo->GetSize();
|
|
85
|
-
reportLength -= DelaySinceLastRr::SsrcInfo::BodySize;
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
return report.release();
|
|
@@ -274,7 +274,7 @@ namespace RTC
|
|
|
274
274
|
return report;
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
-
RTC::RTCP::DelaySinceLastRr::SsrcInfo* RtpStreamSend::
|
|
277
|
+
RTC::RTCP::DelaySinceLastRr::SsrcInfo* RtpStreamSend::GetRtcpXrDelaySinceLastRrSsrcInfo(uint64_t nowMs)
|
|
278
278
|
{
|
|
279
279
|
MS_TRACE();
|
|
280
280
|
|
|
@@ -439,18 +439,10 @@ namespace RTC
|
|
|
439
439
|
// Build SDES chunk for this sender.
|
|
440
440
|
auto* sdesChunk = this->rtpStream->GetRtcpSdesChunk();
|
|
441
441
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
auto* dlrr = this->rtpStream->GetRtcpXrDelaySinceLastRr(nowMs);
|
|
445
|
-
|
|
446
|
-
if (dlrr)
|
|
447
|
-
{
|
|
448
|
-
delaySinceLastRrReport = new RTC::RTCP::DelaySinceLastRr();
|
|
449
|
-
delaySinceLastRrReport->AddSsrcInfo(dlrr);
|
|
450
|
-
}
|
|
442
|
+
auto* delaySinceLastRrSsrcInfo = this->rtpStream->GetRtcpXrDelaySinceLastRrSsrcInfo(nowMs);
|
|
451
443
|
|
|
452
444
|
// RTCP Compound packet buffer cannot hold the data.
|
|
453
|
-
if (!packet->Add(senderReport, sdesChunk,
|
|
445
|
+
if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrSsrcInfo))
|
|
454
446
|
{
|
|
455
447
|
return false;
|
|
456
448
|
}
|
|
@@ -1081,18 +1081,10 @@ namespace RTC
|
|
|
1081
1081
|
// Build SDES chunk for this sender.
|
|
1082
1082
|
auto* sdesChunk = this->rtpStream->GetRtcpSdesChunk();
|
|
1083
1083
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
auto* dlrr = this->rtpStream->GetRtcpXrDelaySinceLastRr(nowMs);
|
|
1087
|
-
|
|
1088
|
-
if (dlrr)
|
|
1089
|
-
{
|
|
1090
|
-
delaySinceLastRrReport = new RTC::RTCP::DelaySinceLastRr();
|
|
1091
|
-
delaySinceLastRrReport->AddSsrcInfo(dlrr);
|
|
1092
|
-
}
|
|
1084
|
+
auto* delaySinceLastRrSsrcInfo = this->rtpStream->GetRtcpXrDelaySinceLastRrSsrcInfo(nowMs);
|
|
1093
1085
|
|
|
1094
1086
|
// RTCP Compound packet buffer cannot hold the data.
|
|
1095
|
-
if (!packet->Add(senderReport, sdesChunk,
|
|
1087
|
+
if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrSsrcInfo))
|
|
1096
1088
|
{
|
|
1097
1089
|
return false;
|
|
1098
1090
|
}
|
|
@@ -795,18 +795,10 @@ namespace RTC
|
|
|
795
795
|
// Build SDES chunk for this sender.
|
|
796
796
|
auto* sdesChunk = this->rtpStream->GetRtcpSdesChunk();
|
|
797
797
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
auto* dlrr = this->rtpStream->GetRtcpXrDelaySinceLastRr(nowMs);
|
|
801
|
-
|
|
802
|
-
if (dlrr)
|
|
803
|
-
{
|
|
804
|
-
delaySinceLastRrReport = new RTC::RTCP::DelaySinceLastRr();
|
|
805
|
-
delaySinceLastRrReport->AddSsrcInfo(dlrr);
|
|
806
|
-
}
|
|
798
|
+
auto* delaySinceLastRrSsrcInfo = this->rtpStream->GetRtcpXrDelaySinceLastRrSsrcInfo(nowMs);
|
|
807
799
|
|
|
808
800
|
// RTCP Compound packet buffer cannot hold the data.
|
|
809
|
-
if (!packet->Add(senderReport, sdesChunk,
|
|
801
|
+
if (!packet->Add(senderReport, sdesChunk, delaySinceLastRrSsrcInfo))
|
|
810
802
|
{
|
|
811
803
|
return false;
|
|
812
804
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include "common.hpp"
|
|
2
|
+
#include "RTC/RTCP/Packet.hpp"
|
|
2
3
|
#include "RTC/RTCP/Sdes.hpp"
|
|
3
4
|
#include <catch2/catch.hpp>
|
|
4
5
|
#include <cstring> // std::memcmp()
|
|
@@ -383,40 +384,118 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]")
|
|
|
383
384
|
REQUIRE(!packet);
|
|
384
385
|
}
|
|
385
386
|
|
|
387
|
+
SECTION("create SDES packet with 31 chunks")
|
|
388
|
+
{
|
|
389
|
+
const size_t count = 31;
|
|
390
|
+
|
|
391
|
+
SdesPacket packet;
|
|
392
|
+
// Create a chunk and an item to obtain their size.
|
|
393
|
+
SdesChunk* chunk = new SdesChunk(1234 /*ssrc*/);
|
|
394
|
+
auto* item1 =
|
|
395
|
+
new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str());
|
|
396
|
+
|
|
397
|
+
chunk->AddItem(item1);
|
|
398
|
+
|
|
399
|
+
auto chunkSize = chunk->GetSize();
|
|
400
|
+
|
|
401
|
+
delete chunk;
|
|
402
|
+
|
|
403
|
+
for (auto i{ 1 }; i <= count; ++i)
|
|
404
|
+
{
|
|
405
|
+
// Create chunk and add to packet.
|
|
406
|
+
SdesChunk* chunk = new SdesChunk(i /*ssrc*/);
|
|
407
|
+
|
|
408
|
+
auto* item1 =
|
|
409
|
+
new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str());
|
|
410
|
+
|
|
411
|
+
chunk->AddItem(item1);
|
|
412
|
+
|
|
413
|
+
packet.AddChunk(chunk);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
REQUIRE(packet.GetCount() == count);
|
|
417
|
+
REQUIRE(packet.GetSize() == Packet::CommonHeaderSize + (count * chunkSize));
|
|
418
|
+
|
|
419
|
+
uint8_t buffer1[1500] = { 0 };
|
|
420
|
+
|
|
421
|
+
// Serialization must contain 1 SDES packet since report count doesn't
|
|
422
|
+
// exceed 31.
|
|
423
|
+
packet.Serialize(buffer1);
|
|
424
|
+
|
|
425
|
+
auto* packet2 = static_cast<SdesPacket*>(Packet::Parse(buffer1, sizeof(buffer1)));
|
|
426
|
+
|
|
427
|
+
REQUIRE(packet2 != nullptr);
|
|
428
|
+
REQUIRE(packet2->GetCount() == count);
|
|
429
|
+
REQUIRE(packet2->GetSize() == Packet::CommonHeaderSize + (count * chunkSize));
|
|
430
|
+
|
|
431
|
+
auto reportIt = packet2->Begin();
|
|
432
|
+
|
|
433
|
+
for (auto i{ 1 }; i <= 31; ++i, reportIt++)
|
|
434
|
+
{
|
|
435
|
+
auto* chunk = *reportIt;
|
|
436
|
+
|
|
437
|
+
REQUIRE(chunk->GetSsrc() == i);
|
|
438
|
+
|
|
439
|
+
auto* item = *(chunk->Begin());
|
|
440
|
+
|
|
441
|
+
REQUIRE(item->GetType() == SdesItem::Type::CNAME);
|
|
442
|
+
REQUIRE(item->GetSize() == 2 + item1Value.size());
|
|
443
|
+
REQUIRE(std::string(item->GetValue()) == item1Value);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
SdesPacket* packet3 = static_cast<SdesPacket*>(packet2->GetNext());
|
|
447
|
+
|
|
448
|
+
REQUIRE(packet3 == nullptr);
|
|
449
|
+
|
|
450
|
+
delete packet3;
|
|
451
|
+
}
|
|
452
|
+
|
|
386
453
|
SECTION("create SDES packet with more than 31 chunks")
|
|
387
454
|
{
|
|
388
455
|
const size_t count = 33;
|
|
389
456
|
|
|
390
457
|
SdesPacket packet;
|
|
458
|
+
// Create a chunk and an item to obtain their size.
|
|
459
|
+
SdesChunk* chunk = new SdesChunk(1234 /*ssrc*/);
|
|
460
|
+
auto* item1 =
|
|
461
|
+
new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str());
|
|
462
|
+
|
|
463
|
+
chunk->AddItem(item1);
|
|
464
|
+
|
|
465
|
+
auto chunkSize = chunk->GetSize();
|
|
466
|
+
|
|
467
|
+
delete chunk;
|
|
391
468
|
|
|
392
|
-
for (auto i
|
|
469
|
+
for (auto i{ 1 }; i <= count; ++i)
|
|
393
470
|
{
|
|
394
471
|
// Create chunk and add to packet.
|
|
395
|
-
SdesChunk*
|
|
472
|
+
SdesChunk* chunk = new SdesChunk(i /*ssrc*/);
|
|
396
473
|
|
|
397
474
|
auto* item1 =
|
|
398
475
|
new RTC::RTCP::SdesItem(SdesItem::Type::CNAME, item1Value.size(), item1Value.c_str());
|
|
399
476
|
|
|
400
|
-
|
|
477
|
+
chunk->AddItem(item1);
|
|
401
478
|
|
|
402
|
-
packet.AddChunk(
|
|
479
|
+
packet.AddChunk(chunk);
|
|
403
480
|
}
|
|
404
481
|
|
|
405
482
|
REQUIRE(packet.GetCount() == count);
|
|
483
|
+
REQUIRE(packet.GetSize() == Packet::CommonHeaderSize + (31 * chunkSize) + Packet::CommonHeaderSize + ((count - 31) * chunkSize));
|
|
406
484
|
|
|
407
485
|
uint8_t buffer1[1500] = { 0 };
|
|
408
486
|
|
|
409
|
-
// Serialization must contain 2
|
|
487
|
+
// Serialization must contain 2 SDES packets since report count exceeds 31.
|
|
410
488
|
packet.Serialize(buffer1);
|
|
411
489
|
|
|
412
490
|
auto* packet2 = static_cast<SdesPacket*>(Packet::Parse(buffer1, sizeof(buffer1)));
|
|
413
491
|
|
|
414
492
|
REQUIRE(packet2 != nullptr);
|
|
415
493
|
REQUIRE(packet2->GetCount() == 31);
|
|
494
|
+
REQUIRE(packet2->GetSize() == Packet::CommonHeaderSize + (31 * chunkSize));
|
|
416
495
|
|
|
417
496
|
auto reportIt = packet2->Begin();
|
|
418
497
|
|
|
419
|
-
for (auto i
|
|
498
|
+
for (auto i{ 1 }; i <= 31; ++i, reportIt++)
|
|
420
499
|
{
|
|
421
500
|
auto* chunk = *reportIt;
|
|
422
501
|
|
|
@@ -432,11 +511,12 @@ SCENARIO("RTCP SDES parsing", "[parser][rtcp][sdes]")
|
|
|
432
511
|
SdesPacket* packet3 = static_cast<SdesPacket*>(packet2->GetNext());
|
|
433
512
|
|
|
434
513
|
REQUIRE(packet3 != nullptr);
|
|
435
|
-
REQUIRE(packet3->GetCount() ==
|
|
514
|
+
REQUIRE(packet3->GetCount() == count - 31);
|
|
515
|
+
REQUIRE(packet3->GetSize() == Packet::CommonHeaderSize + ((count - 31) * chunkSize));
|
|
436
516
|
|
|
437
517
|
reportIt = packet3->Begin();
|
|
438
518
|
|
|
439
|
-
for (auto i
|
|
519
|
+
for (auto i{ 1 }; i <= 2; ++i, reportIt++)
|
|
440
520
|
{
|
|
441
521
|
auto* chunk = *reportIt;
|
|
442
522
|
|
|
@@ -1,11 +1,133 @@
|
|
|
1
1
|
#include "common.hpp"
|
|
2
|
+
#include "RTC/RTCP/XR.hpp"
|
|
2
3
|
#include "RTC/RTCP/XrDelaySinceLastRr.hpp"
|
|
3
4
|
#include "RTC/RTCP/XrReceiverReferenceTime.hpp"
|
|
4
5
|
#include <catch2/catch.hpp>
|
|
5
|
-
#include <cstring> // std::memcmp
|
|
6
|
+
#include <cstring> // std::memcmp(), std::memcpy()
|
|
6
7
|
|
|
7
8
|
using namespace RTC::RTCP;
|
|
8
9
|
|
|
10
|
+
SCENARIO("RTCP XR parsing", "[parser][rtcp][xr]")
|
|
11
|
+
{
|
|
12
|
+
// clang-format off
|
|
13
|
+
uint8_t buffer[] =
|
|
14
|
+
{
|
|
15
|
+
0xa0, 0xcf, 0x00, 0x09, // Padding, Type: 207 (XR), Length: 9
|
|
16
|
+
0x5d, 0x93, 0x15, 0x34, // Sender SSRC: 0x5d931534
|
|
17
|
+
// Extended Report DLRR
|
|
18
|
+
0x05, 0x00, 0x00, 0x06, // BT: 5 (DLRR), Block Length: 6
|
|
19
|
+
0x11, 0x12, 0x13, 0x14, // SSRC 1
|
|
20
|
+
0x00, 0x11, 0x00, 0x11, // LRR 1
|
|
21
|
+
0x11, 0x00, 0x11, 0x00, // DLRR 1
|
|
22
|
+
0x21, 0x22, 0x23, 0x24, // SSRC 2
|
|
23
|
+
0x00, 0x22, 0x00, 0x22, // LRR 2
|
|
24
|
+
0x22, 0x00, 0x22, 0x00, // DLRR 2
|
|
25
|
+
0x00, 0x00, 0x00, 0x04 // Padding (4 bytes)
|
|
26
|
+
};
|
|
27
|
+
// clang-format on
|
|
28
|
+
|
|
29
|
+
SECTION("parse XR packet")
|
|
30
|
+
{
|
|
31
|
+
auto* packet = ExtendedReportPacket::Parse(buffer, sizeof(buffer));
|
|
32
|
+
|
|
33
|
+
REQUIRE(packet);
|
|
34
|
+
// Despite total buffer size is 40 bytes, our GetSize() method doesn't not
|
|
35
|
+
// consider RTCP padding (4 bytes in this case).
|
|
36
|
+
// https://github.com/versatica/mediasoup/issues/1233
|
|
37
|
+
REQUIRE(packet->GetSize() == 36);
|
|
38
|
+
REQUIRE(packet->GetCount() == 0);
|
|
39
|
+
REQUIRE(packet->GetSsrc() == 0x5d931534);
|
|
40
|
+
|
|
41
|
+
size_t blockIdx{ 0u };
|
|
42
|
+
|
|
43
|
+
for (auto it = packet->Begin(); it != packet->End(); ++it, ++blockIdx)
|
|
44
|
+
{
|
|
45
|
+
auto* block = *it;
|
|
46
|
+
|
|
47
|
+
switch (blockIdx)
|
|
48
|
+
{
|
|
49
|
+
case 0:
|
|
50
|
+
{
|
|
51
|
+
REQUIRE(block->GetSize() == 28);
|
|
52
|
+
|
|
53
|
+
size_t ssrcInfoIdx{ 0u };
|
|
54
|
+
auto* dlrrBlock = reinterpret_cast<DelaySinceLastRr*>(block);
|
|
55
|
+
|
|
56
|
+
for (auto it2 = dlrrBlock->Begin(); it2 != dlrrBlock->End(); ++it2, ++ssrcInfoIdx)
|
|
57
|
+
{
|
|
58
|
+
auto* ssrcInfo = *it2;
|
|
59
|
+
|
|
60
|
+
switch (ssrcInfoIdx)
|
|
61
|
+
{
|
|
62
|
+
case 0:
|
|
63
|
+
{
|
|
64
|
+
REQUIRE(ssrcInfo->GetSsrc() == 0x11121314);
|
|
65
|
+
REQUIRE(ssrcInfo->GetLastReceiverReport() == 0x00110011);
|
|
66
|
+
REQUIRE(ssrcInfo->GetDelaySinceLastReceiverReport() == 0x11001100);
|
|
67
|
+
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
case 1:
|
|
72
|
+
{
|
|
73
|
+
REQUIRE(ssrcInfo->GetSsrc() == 0x21222324);
|
|
74
|
+
REQUIRE(ssrcInfo->GetLastReceiverReport() == 0x00220022);
|
|
75
|
+
REQUIRE(ssrcInfo->GetDelaySinceLastReceiverReport() == 0x22002200);
|
|
76
|
+
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// There are 2 SSRC infos.
|
|
83
|
+
REQUIRE(ssrcInfoIdx == 2);
|
|
84
|
+
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// There are 1 block (the DLRR block).
|
|
91
|
+
REQUIRE(blockIdx == 1);
|
|
92
|
+
|
|
93
|
+
SECTION("serialize packet instance")
|
|
94
|
+
{
|
|
95
|
+
// NOTE: Padding in RTCP is removed (if not needed) when serializing the
|
|
96
|
+
// packet, so we must mangle the buffer content (padding bit) and the
|
|
97
|
+
// buffer length before comparing the serialized packet with and original
|
|
98
|
+
// buffer.
|
|
99
|
+
|
|
100
|
+
const size_t paddingBytes{ 4 };
|
|
101
|
+
const size_t serializedBufferLength = sizeof(buffer) - paddingBytes;
|
|
102
|
+
uint8_t serialized[serializedBufferLength] = { 0 };
|
|
103
|
+
|
|
104
|
+
// Clone the original buffer into a new buffer without padding.
|
|
105
|
+
uint8_t clonedBuffer[serializedBufferLength] = { 0 };
|
|
106
|
+
std::memcpy(clonedBuffer, buffer, serializedBufferLength);
|
|
107
|
+
|
|
108
|
+
// Remove the padding bit in the first byte of the cloned buffer.
|
|
109
|
+
clonedBuffer[0] = 0x80;
|
|
110
|
+
|
|
111
|
+
// Change RTCP length field in the cloned buffer.
|
|
112
|
+
clonedBuffer[3] = clonedBuffer[3] - 1;
|
|
113
|
+
|
|
114
|
+
packet->Serialize(serialized);
|
|
115
|
+
|
|
116
|
+
auto* packet2 = ExtendedReportPacket::Parse(serialized, serializedBufferLength);
|
|
117
|
+
|
|
118
|
+
REQUIRE(packet2->GetType() == Type::XR);
|
|
119
|
+
REQUIRE(packet2->GetCount() == 0);
|
|
120
|
+
REQUIRE(packet2->GetSize() == 36);
|
|
121
|
+
|
|
122
|
+
REQUIRE(std::memcmp(clonedBuffer, serialized, serializedBufferLength) == 0);
|
|
123
|
+
|
|
124
|
+
delete packet2;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
delete packet;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
9
131
|
SCENARIO("RTCP XrDelaySinceLastRt parsing", "[parser][rtcp][xr-dlrr]")
|
|
10
132
|
{
|
|
11
133
|
SECTION("create RRT")
|