blob: b85f9f416addd8a42d4a5c70443059e6ec09934e [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 <iostream>
14
Steve Anton10542f22019-01-11 09:11:00 -080015#include "rtc_base/time_utils.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000016
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000017namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000018
Niels Möller87e2d782019-03-07 10:18:23 +010019int32_t Channel::SendData(AudioFrameType frameType,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000020 uint8_t payloadType,
21 uint32_t timeStamp,
22 const uint8_t* payloadData,
Minyue Liff0e4db2020-01-23 13:45:50 +010023 size_t payloadSize,
24 int64_t absolute_capture_timestamp_ms) {
Niels Möllerbf474952019-02-18 12:00:06 +010025 RTPHeader rtp_header;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000026 int32_t status;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000027 size_t payloadDataSize = payloadSize;
niklase@google.com470e71d2011-07-07 08:21:25 +000028
Niels Möllerbf474952019-02-18 12:00:06 +010029 rtp_header.markerBit = false;
30 rtp_header.ssrc = 0;
31 rtp_header.sequenceNumber =
Yves Gerey665174f2018-06-19 15:03:05 +020032 (external_sequence_number_ < 0)
33 ? _seqNo++
34 : static_cast<uint16_t>(external_sequence_number_);
Niels Möllerbf474952019-02-18 12:00:06 +010035 rtp_header.payloadType = payloadType;
36 rtp_header.timestamp = (external_send_timestamp_ < 0)
37 ? timeStamp
38 : static_cast<uint32_t>(external_send_timestamp_);
turaj@webrtc.orga305e962013-06-06 19:00:09 +000039
Niels Möllerc936cb62019-03-19 14:10:16 +010040 if (frameType == AudioFrameType::kEmptyFrame) {
minyue@webrtc.org05617162015-03-03 12:02:30 +000041 // When frame is empty, we should not transmit it. The frame size of the
42 // next non-empty frame will be based on the previous frame size.
43 _useLastFrameSize = _lastFrameSizeSample > 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000044 return 0;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000045 }
niklase@google.com470e71d2011-07-07 08:21:25 +000046
Niels Möllerc35b6e62019-04-25 16:31:18 +020047 memcpy(_payloadData, payloadData, payloadDataSize);
48 if (_isStereo) {
49 if (_leftChannel) {
50 _rtp_header = rtp_header;
51 _leftChannel = false;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000052 } else {
Niels Möllerc35b6e62019-04-25 16:31:18 +020053 rtp_header = _rtp_header;
54 _leftChannel = true;
niklase@google.com470e71d2011-07-07 08:21:25 +000055 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000056 }
niklase@google.com470e71d2011-07-07 08:21:25 +000057
Markus Handell0df0fae2020-07-07 15:53:34 +020058 _channelCritSect.Lock();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000059 if (_saveBitStream) {
Yves Gerey665174f2018-06-19 15:03:05 +020060 // fwrite(payloadData, sizeof(uint8_t), payloadSize, _bitStreamFile);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000061 }
niklase@google.com470e71d2011-07-07 08:21:25 +000062
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000063 if (!_isStereo) {
Niels Möllerbf474952019-02-18 12:00:06 +010064 CalcStatistics(rtp_header, payloadSize);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000065 }
minyue@webrtc.org05617162015-03-03 12:02:30 +000066 _useLastFrameSize = false;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000067 _lastInTimestamp = timeStamp;
68 _totalBytes += payloadDataSize;
Markus Handell0df0fae2020-07-07 15:53:34 +020069 _channelCritSect.Unlock();
niklase@google.com470e71d2011-07-07 08:21:25 +000070
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000071 if (_useFECTestWithPacketLoss) {
72 _packetLoss += 1;
73 if (_packetLoss == 3) {
74 _packetLoss = 0;
75 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000076 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000077 }
niklase@google.com470e71d2011-07-07 08:21:25 +000078
turaj@webrtc.orga305e962013-06-06 19:00:09 +000079 if (num_packets_to_drop_ > 0) {
80 num_packets_to_drop_--;
81 return 0;
82 }
83
Niels Möllerbf474952019-02-18 12:00:06 +010084 status =
85 _receiverACM->IncomingPacket(_payloadData, payloadDataSize, rtp_header);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000086
87 return status;
88}
89
turaj@webrtc.orgc2d69d32014-02-19 20:31:17 +000090// TODO(turajs): rewite this method.
Niels Möllerbf474952019-02-18 12:00:06 +010091void Channel::CalcStatistics(const RTPHeader& rtp_header, size_t payloadSize) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000092 int n;
Niels Möllerbf474952019-02-18 12:00:06 +010093 if ((rtp_header.payloadType != _lastPayloadType) &&
Yves Gerey665174f2018-06-19 15:03:05 +020094 (_lastPayloadType != -1)) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000095 // payload-type is changed.
96 // we have to terminate the calculations on the previous payload type
97 // we ignore the last packet in that payload type just to make things
98 // easier.
99 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
100 if (_lastPayloadType == _payloadStats[n].payloadType) {
101 _payloadStats[n].newPacket = true;
102 break;
103 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000104 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000105 }
Niels Möllerbf474952019-02-18 12:00:06 +0100106 _lastPayloadType = rtp_header.payloadType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000107
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000108 bool newPayload = true;
109 ACMTestPayloadStats* currentPayloadStr = NULL;
110 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
Niels Möllerbf474952019-02-18 12:00:06 +0100111 if (rtp_header.payloadType == _payloadStats[n].payloadType) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000112 newPayload = false;
113 currentPayloadStr = &_payloadStats[n];
114 break;
115 }
116 }
117
118 if (!newPayload) {
119 if (!currentPayloadStr->newPacket) {
minyue@webrtc.org05617162015-03-03 12:02:30 +0000120 if (!_useLastFrameSize) {
Yves Gerey665174f2018-06-19 15:03:05 +0200121 _lastFrameSizeSample =
Niels Möllerbf474952019-02-18 12:00:06 +0100122 (uint32_t)((uint32_t)rtp_header.timestamp -
Yves Gerey665174f2018-06-19 15:03:05 +0200123 (uint32_t)currentPayloadStr->lastTimestamp);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000124 }
Mirko Bonadei25ab3222021-07-08 20:08:20 +0200125 RTC_DCHECK_GT(_lastFrameSizeSample, 0);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000126 int k = 0;
minyue@webrtc.org05617162015-03-03 12:02:30 +0000127 for (; k < MAX_NUM_FRAMESIZES; ++k) {
128 if ((currentPayloadStr->frameSizeStats[k].frameSizeSample ==
Yves Gerey665174f2018-06-19 15:03:05 +0200129 _lastFrameSizeSample) ||
minyue@webrtc.org05617162015-03-03 12:02:30 +0000130 (currentPayloadStr->frameSizeStats[k].frameSizeSample == 0)) {
131 break;
132 }
133 }
134 if (k == MAX_NUM_FRAMESIZES) {
135 // New frame size found but no space to count statistics on it. Skip it.
136 printf("No memory to store statistics for payload %d : frame size %d\n",
137 _lastPayloadType, _lastFrameSizeSample);
138 return;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000139 }
Yves Gerey665174f2018-06-19 15:03:05 +0200140 ACMTestFrameSizeStats* currentFrameSizeStats =
141 &(currentPayloadStr->frameSizeStats[k]);
142 currentFrameSizeStats->frameSizeSample = (int16_t)_lastFrameSizeSample;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000143
144 // increment the number of encoded samples.
minyue@webrtc.org05617162015-03-03 12:02:30 +0000145 currentFrameSizeStats->totalEncodedSamples += _lastFrameSizeSample;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000146 // increment the number of recveived packets
147 currentFrameSizeStats->numPackets++;
148 // increment the total number of bytes (this is based on
149 // the previous payload we don't know the frame-size of
150 // the current payload.
Yves Gerey665174f2018-06-19 15:03:05 +0200151 currentFrameSizeStats->totalPayloadLenByte +=
152 currentPayloadStr->lastPayloadLenByte;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000153 // store the maximum payload-size (this is based on
154 // the previous payload we don't know the frame-size of
155 // the current payload.
Yves Gerey665174f2018-06-19 15:03:05 +0200156 if (currentFrameSizeStats->maxPayloadLen <
157 currentPayloadStr->lastPayloadLenByte) {
158 currentFrameSizeStats->maxPayloadLen =
159 currentPayloadStr->lastPayloadLenByte;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000160 }
161 // store the current values for the next time
Niels Möllerbf474952019-02-18 12:00:06 +0100162 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000163 currentPayloadStr->lastPayloadLenByte = payloadSize;
164 } else {
165 currentPayloadStr->newPacket = false;
166 currentPayloadStr->lastPayloadLenByte = payloadSize;
Niels Möllerbf474952019-02-18 12:00:06 +0100167 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
168 currentPayloadStr->payloadType = rtp_header.payloadType;
Yves Gerey665174f2018-06-19 15:03:05 +0200169 memset(currentPayloadStr->frameSizeStats, 0,
170 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000171 }
172 } else {
173 n = 0;
174 while (_payloadStats[n].payloadType != -1) {
175 n++;
176 }
177 // first packet
178 _payloadStats[n].newPacket = false;
179 _payloadStats[n].lastPayloadLenByte = payloadSize;
Niels Möllerbf474952019-02-18 12:00:06 +0100180 _payloadStats[n].lastTimestamp = rtp_header.timestamp;
181 _payloadStats[n].payloadType = rtp_header.payloadType;
Yves Gerey665174f2018-06-19 15:03:05 +0200182 memset(_payloadStats[n].frameSizeStats, 0,
183 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000184 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000185}
186
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000187Channel::Channel(int16_t chID)
188 : _receiverACM(NULL),
189 _seqNo(0),
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000190 _bitStreamFile(NULL),
191 _saveBitStream(false),
192 _lastPayloadType(-1),
193 _isStereo(false),
194 _leftChannel(true),
195 _lastInTimestamp(0),
minyue@webrtc.org05617162015-03-03 12:02:30 +0000196 _useLastFrameSize(false),
197 _lastFrameSizeSample(0),
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000198 _packetLoss(0),
199 _useFECTestWithPacketLoss(false),
Niels Möllerd28db7f2016-05-10 16:31:47 +0200200 _beginTime(rtc::TimeMillis()),
turaj@webrtc.orga305e962013-06-06 19:00:09 +0000201 _totalBytes(0),
202 external_send_timestamp_(-1),
203 external_sequence_number_(-1),
204 num_packets_to_drop_(0) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000205 int n;
206 int k;
207 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
208 _payloadStats[n].payloadType = -1;
209 _payloadStats[n].newPacket = true;
210 for (k = 0; k < MAX_NUM_FRAMESIZES; k++) {
211 _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
212 _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
213 _payloadStats[n].frameSizeStats[k].numPackets = 0;
214 _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
215 _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
216 }
217 }
218 if (chID >= 0) {
219 _saveBitStream = true;
220 char bitStreamFileName[500];
221 sprintf(bitStreamFileName, "bitStream_%d.dat", chID);
222 _bitStreamFile = fopen(bitStreamFileName, "wb");
223 } else {
224 _saveBitStream = false;
225 }
226}
227
Yves Gerey665174f2018-06-19 15:03:05 +0200228Channel::~Channel() {}
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000229
230void Channel::RegisterReceiverACM(AudioCodingModule* acm) {
231 _receiverACM = acm;
232 return;
233}
234
235void Channel::ResetStats() {
236 int n;
237 int k;
Markus Handell0df0fae2020-07-07 15:53:34 +0200238 _channelCritSect.Lock();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000239 _lastPayloadType = -1;
240 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
241 _payloadStats[n].payloadType = -1;
242 _payloadStats[n].newPacket = true;
243 for (k = 0; k < MAX_NUM_FRAMESIZES; k++) {
244 _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
245 _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
246 _payloadStats[n].frameSizeStats[k].numPackets = 0;
247 _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
248 _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
249 }
250 }
Niels Möllerd28db7f2016-05-10 16:31:47 +0200251 _beginTime = rtc::TimeMillis();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000252 _totalBytes = 0;
Markus Handell0df0fae2020-07-07 15:53:34 +0200253 _channelCritSect.Unlock();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000254}
255
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000256uint32_t Channel::LastInTimestamp() {
257 uint32_t timestamp;
Markus Handell0df0fae2020-07-07 15:53:34 +0200258 _channelCritSect.Lock();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000259 timestamp = _lastInTimestamp;
Markus Handell0df0fae2020-07-07 15:53:34 +0200260 _channelCritSect.Unlock();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000261 return timestamp;
262}
263
264double Channel::BitRate() {
265 double rate;
Niels Möllerd28db7f2016-05-10 16:31:47 +0200266 uint64_t currTime = rtc::TimeMillis();
Markus Handell0df0fae2020-07-07 15:53:34 +0200267 _channelCritSect.Lock();
Yves Gerey665174f2018-06-19 15:03:05 +0200268 rate = ((double)_totalBytes * 8.0) / (double)(currTime - _beginTime);
Markus Handell0df0fae2020-07-07 15:53:34 +0200269 _channelCritSect.Unlock();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000270 return rate;
271}
272
273} // namespace webrtc