blob: d54faa7c07edb0fede4877446d36c0530a09bc75 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
tina.legrand@webrtc.org16b6b902012-04-12 11:02:38 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/test/Channel.h"
turaj@webrtc.orga305e962013-06-06 19:00:09 +000012
niklase@google.com470e71d2011-07-07 08:21:25 +000013#include <assert.h>
14#include <iostream>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "rtc_base/format_macros.h"
Steve Anton10542f22019-01-11 09:11:00 -080017#include "rtc_base/time_utils.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000018
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000019namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000020
Niels Möller87e2d782019-03-07 10:18:23 +010021int32_t Channel::SendData(AudioFrameType frameType,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000022 uint8_t payloadType,
23 uint32_t timeStamp,
24 const uint8_t* payloadData,
25 size_t payloadSize,
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000026 const RTPFragmentationHeader* fragmentation) {
Niels Möllerbf474952019-02-18 12:00:06 +010027 RTPHeader rtp_header;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000028 int32_t status;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000029 size_t payloadDataSize = payloadSize;
niklase@google.com470e71d2011-07-07 08:21:25 +000030
Niels Möllerbf474952019-02-18 12:00:06 +010031 rtp_header.markerBit = false;
32 rtp_header.ssrc = 0;
33 rtp_header.sequenceNumber =
Yves Gerey665174f2018-06-19 15:03:05 +020034 (external_sequence_number_ < 0)
35 ? _seqNo++
36 : static_cast<uint16_t>(external_sequence_number_);
Niels Möllerbf474952019-02-18 12:00:06 +010037 rtp_header.payloadType = payloadType;
38 rtp_header.timestamp = (external_send_timestamp_ < 0)
39 ? timeStamp
40 : static_cast<uint32_t>(external_send_timestamp_);
turaj@webrtc.orga305e962013-06-06 19:00:09 +000041
pbos22993e12015-10-19 02:39:06 -070042 if (frameType == kEmptyFrame) {
minyue@webrtc.org05617162015-03-03 12:02:30 +000043 // When frame is empty, we should not transmit it. The frame size of the
44 // next non-empty frame will be based on the previous frame size.
45 _useLastFrameSize = _lastFrameSizeSample > 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000046 return 0;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000047 }
niklase@google.com470e71d2011-07-07 08:21:25 +000048
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000049 // Treat fragmentation separately
50 if (fragmentation != NULL) {
51 // If silence for too long, send only new data.
henrik.lundin@webrtc.org05db3522015-01-30 13:03:45 +000052 if ((fragmentation->fragmentationVectorSize == 2) &&
53 (fragmentation->fragmentationTimeDiff[1] <= 0x3fff)) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000054 // only 0x80 if we have multiple blocks
55 _payloadData[0] = 0x80 + fragmentation->fragmentationPlType[1];
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000056 size_t REDheader = (fragmentation->fragmentationTimeDiff[1] << 10) +
Yves Gerey665174f2018-06-19 15:03:05 +020057 fragmentation->fragmentationLength[1];
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000058 _payloadData[1] = uint8_t((REDheader >> 16) & 0x000000FF);
59 _payloadData[2] = uint8_t((REDheader >> 8) & 0x000000FF);
60 _payloadData[3] = uint8_t(REDheader & 0x000000FF);
61
62 _payloadData[4] = fragmentation->fragmentationPlType[0];
63 // copy the RED data
64 memcpy(_payloadData + 5,
65 payloadData + fragmentation->fragmentationOffset[1],
66 fragmentation->fragmentationLength[1]);
67 // copy the normal data
68 memcpy(_payloadData + 5 + fragmentation->fragmentationLength[1],
69 payloadData + fragmentation->fragmentationOffset[0],
70 fragmentation->fragmentationLength[0]);
71 payloadDataSize += 5;
72 } else {
73 // single block (newest one)
74 memcpy(_payloadData, payloadData + fragmentation->fragmentationOffset[0],
75 fragmentation->fragmentationLength[0]);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000076 payloadDataSize = fragmentation->fragmentationLength[0];
Niels Möllerbf474952019-02-18 12:00:06 +010077 rtp_header.payloadType = fragmentation->fragmentationPlType[0];
niklase@google.com470e71d2011-07-07 08:21:25 +000078 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000079 } else {
80 memcpy(_payloadData, payloadData, payloadDataSize);
81 if (_isStereo) {
82 if (_leftChannel) {
Niels Möllerbf474952019-02-18 12:00:06 +010083 _rtp_header = rtp_header;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000084 _leftChannel = false;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000085 } else {
Niels Möllerbf474952019-02-18 12:00:06 +010086 rtp_header = _rtp_header;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000087 _leftChannel = true;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000088 }
niklase@google.com470e71d2011-07-07 08:21:25 +000089 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000090 }
niklase@google.com470e71d2011-07-07 08:21:25 +000091
Tommi9090e0b2016-01-20 13:39:36 +010092 _channelCritSect.Enter();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000093 if (_saveBitStream) {
Yves Gerey665174f2018-06-19 15:03:05 +020094 // fwrite(payloadData, sizeof(uint8_t), payloadSize, _bitStreamFile);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000095 }
niklase@google.com470e71d2011-07-07 08:21:25 +000096
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000097 if (!_isStereo) {
Niels Möllerbf474952019-02-18 12:00:06 +010098 CalcStatistics(rtp_header, payloadSize);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000099 }
minyue@webrtc.org05617162015-03-03 12:02:30 +0000100 _useLastFrameSize = false;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000101 _lastInTimestamp = timeStamp;
102 _totalBytes += payloadDataSize;
Tommi9090e0b2016-01-20 13:39:36 +0100103 _channelCritSect.Leave();
niklase@google.com470e71d2011-07-07 08:21:25 +0000104
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000105 if (_useFECTestWithPacketLoss) {
106 _packetLoss += 1;
107 if (_packetLoss == 3) {
108 _packetLoss = 0;
109 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000110 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000111 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000112
turaj@webrtc.orga305e962013-06-06 19:00:09 +0000113 if (num_packets_to_drop_ > 0) {
114 num_packets_to_drop_--;
115 return 0;
116 }
117
Niels Möllerbf474952019-02-18 12:00:06 +0100118 status =
119 _receiverACM->IncomingPacket(_payloadData, payloadDataSize, rtp_header);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000120
121 return status;
122}
123
turaj@webrtc.orgc2d69d32014-02-19 20:31:17 +0000124// TODO(turajs): rewite this method.
Niels Möllerbf474952019-02-18 12:00:06 +0100125void Channel::CalcStatistics(const RTPHeader& rtp_header, size_t payloadSize) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000126 int n;
Niels Möllerbf474952019-02-18 12:00:06 +0100127 if ((rtp_header.payloadType != _lastPayloadType) &&
Yves Gerey665174f2018-06-19 15:03:05 +0200128 (_lastPayloadType != -1)) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000129 // payload-type is changed.
130 // we have to terminate the calculations on the previous payload type
131 // we ignore the last packet in that payload type just to make things
132 // easier.
133 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
134 if (_lastPayloadType == _payloadStats[n].payloadType) {
135 _payloadStats[n].newPacket = true;
136 break;
137 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000138 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000139 }
Niels Möllerbf474952019-02-18 12:00:06 +0100140 _lastPayloadType = rtp_header.payloadType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000141
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000142 bool newPayload = true;
143 ACMTestPayloadStats* currentPayloadStr = NULL;
144 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
Niels Möllerbf474952019-02-18 12:00:06 +0100145 if (rtp_header.payloadType == _payloadStats[n].payloadType) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000146 newPayload = false;
147 currentPayloadStr = &_payloadStats[n];
148 break;
149 }
150 }
151
152 if (!newPayload) {
153 if (!currentPayloadStr->newPacket) {
minyue@webrtc.org05617162015-03-03 12:02:30 +0000154 if (!_useLastFrameSize) {
Yves Gerey665174f2018-06-19 15:03:05 +0200155 _lastFrameSizeSample =
Niels Möllerbf474952019-02-18 12:00:06 +0100156 (uint32_t)((uint32_t)rtp_header.timestamp -
Yves Gerey665174f2018-06-19 15:03:05 +0200157 (uint32_t)currentPayloadStr->lastTimestamp);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000158 }
159 assert(_lastFrameSizeSample > 0);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000160 int k = 0;
minyue@webrtc.org05617162015-03-03 12:02:30 +0000161 for (; k < MAX_NUM_FRAMESIZES; ++k) {
162 if ((currentPayloadStr->frameSizeStats[k].frameSizeSample ==
Yves Gerey665174f2018-06-19 15:03:05 +0200163 _lastFrameSizeSample) ||
minyue@webrtc.org05617162015-03-03 12:02:30 +0000164 (currentPayloadStr->frameSizeStats[k].frameSizeSample == 0)) {
165 break;
166 }
167 }
168 if (k == MAX_NUM_FRAMESIZES) {
169 // New frame size found but no space to count statistics on it. Skip it.
170 printf("No memory to store statistics for payload %d : frame size %d\n",
171 _lastPayloadType, _lastFrameSizeSample);
172 return;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000173 }
Yves Gerey665174f2018-06-19 15:03:05 +0200174 ACMTestFrameSizeStats* currentFrameSizeStats =
175 &(currentPayloadStr->frameSizeStats[k]);
176 currentFrameSizeStats->frameSizeSample = (int16_t)_lastFrameSizeSample;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000177
178 // increment the number of encoded samples.
minyue@webrtc.org05617162015-03-03 12:02:30 +0000179 currentFrameSizeStats->totalEncodedSamples += _lastFrameSizeSample;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000180 // increment the number of recveived packets
181 currentFrameSizeStats->numPackets++;
182 // increment the total number of bytes (this is based on
183 // the previous payload we don't know the frame-size of
184 // the current payload.
Yves Gerey665174f2018-06-19 15:03:05 +0200185 currentFrameSizeStats->totalPayloadLenByte +=
186 currentPayloadStr->lastPayloadLenByte;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000187 // store the maximum payload-size (this is based on
188 // the previous payload we don't know the frame-size of
189 // the current payload.
Yves Gerey665174f2018-06-19 15:03:05 +0200190 if (currentFrameSizeStats->maxPayloadLen <
191 currentPayloadStr->lastPayloadLenByte) {
192 currentFrameSizeStats->maxPayloadLen =
193 currentPayloadStr->lastPayloadLenByte;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000194 }
195 // store the current values for the next time
Niels Möllerbf474952019-02-18 12:00:06 +0100196 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000197 currentPayloadStr->lastPayloadLenByte = payloadSize;
198 } else {
199 currentPayloadStr->newPacket = false;
200 currentPayloadStr->lastPayloadLenByte = payloadSize;
Niels Möllerbf474952019-02-18 12:00:06 +0100201 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
202 currentPayloadStr->payloadType = rtp_header.payloadType;
Yves Gerey665174f2018-06-19 15:03:05 +0200203 memset(currentPayloadStr->frameSizeStats, 0,
204 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000205 }
206 } else {
207 n = 0;
208 while (_payloadStats[n].payloadType != -1) {
209 n++;
210 }
211 // first packet
212 _payloadStats[n].newPacket = false;
213 _payloadStats[n].lastPayloadLenByte = payloadSize;
Niels Möllerbf474952019-02-18 12:00:06 +0100214 _payloadStats[n].lastTimestamp = rtp_header.timestamp;
215 _payloadStats[n].payloadType = rtp_header.payloadType;
Yves Gerey665174f2018-06-19 15:03:05 +0200216 memset(_payloadStats[n].frameSizeStats, 0,
217 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000218 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000221Channel::Channel(int16_t chID)
222 : _receiverACM(NULL),
223 _seqNo(0),
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000224 _bitStreamFile(NULL),
225 _saveBitStream(false),
226 _lastPayloadType(-1),
227 _isStereo(false),
228 _leftChannel(true),
229 _lastInTimestamp(0),
minyue@webrtc.org05617162015-03-03 12:02:30 +0000230 _useLastFrameSize(false),
231 _lastFrameSizeSample(0),
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000232 _packetLoss(0),
233 _useFECTestWithPacketLoss(false),
Niels Möllerd28db7f2016-05-10 16:31:47 +0200234 _beginTime(rtc::TimeMillis()),
turaj@webrtc.orga305e962013-06-06 19:00:09 +0000235 _totalBytes(0),
236 external_send_timestamp_(-1),
237 external_sequence_number_(-1),
238 num_packets_to_drop_(0) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000239 int n;
240 int k;
241 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
242 _payloadStats[n].payloadType = -1;
243 _payloadStats[n].newPacket = true;
244 for (k = 0; k < MAX_NUM_FRAMESIZES; k++) {
245 _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
246 _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
247 _payloadStats[n].frameSizeStats[k].numPackets = 0;
248 _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
249 _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
250 }
251 }
252 if (chID >= 0) {
253 _saveBitStream = true;
254 char bitStreamFileName[500];
255 sprintf(bitStreamFileName, "bitStream_%d.dat", chID);
256 _bitStreamFile = fopen(bitStreamFileName, "wb");
257 } else {
258 _saveBitStream = false;
259 }
260}
261
Yves Gerey665174f2018-06-19 15:03:05 +0200262Channel::~Channel() {}
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000263
264void Channel::RegisterReceiverACM(AudioCodingModule* acm) {
265 _receiverACM = acm;
266 return;
267}
268
269void Channel::ResetStats() {
270 int n;
271 int k;
Tommi9090e0b2016-01-20 13:39:36 +0100272 _channelCritSect.Enter();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000273 _lastPayloadType = -1;
274 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
275 _payloadStats[n].payloadType = -1;
276 _payloadStats[n].newPacket = true;
277 for (k = 0; k < MAX_NUM_FRAMESIZES; k++) {
278 _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
279 _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
280 _payloadStats[n].frameSizeStats[k].numPackets = 0;
281 _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
282 _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
283 }
284 }
Niels Möllerd28db7f2016-05-10 16:31:47 +0200285 _beginTime = rtc::TimeMillis();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000286 _totalBytes = 0;
Tommi9090e0b2016-01-20 13:39:36 +0100287 _channelCritSect.Leave();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000288}
289
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000290uint32_t Channel::LastInTimestamp() {
291 uint32_t timestamp;
Tommi9090e0b2016-01-20 13:39:36 +0100292 _channelCritSect.Enter();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000293 timestamp = _lastInTimestamp;
Tommi9090e0b2016-01-20 13:39:36 +0100294 _channelCritSect.Leave();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000295 return timestamp;
296}
297
298double Channel::BitRate() {
299 double rate;
Niels Möllerd28db7f2016-05-10 16:31:47 +0200300 uint64_t currTime = rtc::TimeMillis();
Tommi9090e0b2016-01-20 13:39:36 +0100301 _channelCritSect.Enter();
Yves Gerey665174f2018-06-19 15:03:05 +0200302 rate = ((double)_totalBytes * 8.0) / (double)(currTime - _beginTime);
Tommi9090e0b2016-01-20 13:39:36 +0100303 _channelCritSect.Leave();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000304 return rate;
305}
306
307} // namespace webrtc