blob: 8ad0e0070b85b579b3f29ddd16fbbe62fe0dec51 [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,
Niels Möllerc35b6e62019-04-25 16:31:18 +020025 size_t payloadSize) {
Niels Möllerbf474952019-02-18 12:00:06 +010026 RTPHeader rtp_header;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000027 int32_t status;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000028 size_t payloadDataSize = payloadSize;
niklase@google.com470e71d2011-07-07 08:21:25 +000029
Niels Möllerbf474952019-02-18 12:00:06 +010030 rtp_header.markerBit = false;
31 rtp_header.ssrc = 0;
32 rtp_header.sequenceNumber =
Yves Gerey665174f2018-06-19 15:03:05 +020033 (external_sequence_number_ < 0)
34 ? _seqNo++
35 : static_cast<uint16_t>(external_sequence_number_);
Niels Möllerbf474952019-02-18 12:00:06 +010036 rtp_header.payloadType = payloadType;
37 rtp_header.timestamp = (external_send_timestamp_ < 0)
38 ? timeStamp
39 : static_cast<uint32_t>(external_send_timestamp_);
turaj@webrtc.orga305e962013-06-06 19:00:09 +000040
Niels Möllerc936cb62019-03-19 14:10:16 +010041 if (frameType == AudioFrameType::kEmptyFrame) {
minyue@webrtc.org05617162015-03-03 12:02:30 +000042 // When frame is empty, we should not transmit it. The frame size of the
43 // next non-empty frame will be based on the previous frame size.
44 _useLastFrameSize = _lastFrameSizeSample > 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000045 return 0;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000046 }
niklase@google.com470e71d2011-07-07 08:21:25 +000047
Niels Möllerc35b6e62019-04-25 16:31:18 +020048 memcpy(_payloadData, payloadData, payloadDataSize);
49 if (_isStereo) {
50 if (_leftChannel) {
51 _rtp_header = rtp_header;
52 _leftChannel = false;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000053 } else {
Niels Möllerc35b6e62019-04-25 16:31:18 +020054 rtp_header = _rtp_header;
55 _leftChannel = true;
niklase@google.com470e71d2011-07-07 08:21:25 +000056 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000057 }
niklase@google.com470e71d2011-07-07 08:21:25 +000058
Tommi9090e0b2016-01-20 13:39:36 +010059 _channelCritSect.Enter();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000060 if (_saveBitStream) {
Yves Gerey665174f2018-06-19 15:03:05 +020061 // fwrite(payloadData, sizeof(uint8_t), payloadSize, _bitStreamFile);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000062 }
niklase@google.com470e71d2011-07-07 08:21:25 +000063
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000064 if (!_isStereo) {
Niels Möllerbf474952019-02-18 12:00:06 +010065 CalcStatistics(rtp_header, payloadSize);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000066 }
minyue@webrtc.org05617162015-03-03 12:02:30 +000067 _useLastFrameSize = false;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000068 _lastInTimestamp = timeStamp;
69 _totalBytes += payloadDataSize;
Tommi9090e0b2016-01-20 13:39:36 +010070 _channelCritSect.Leave();
niklase@google.com470e71d2011-07-07 08:21:25 +000071
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000072 if (_useFECTestWithPacketLoss) {
73 _packetLoss += 1;
74 if (_packetLoss == 3) {
75 _packetLoss = 0;
76 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000077 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000078 }
niklase@google.com470e71d2011-07-07 08:21:25 +000079
turaj@webrtc.orga305e962013-06-06 19:00:09 +000080 if (num_packets_to_drop_ > 0) {
81 num_packets_to_drop_--;
82 return 0;
83 }
84
Niels Möllerbf474952019-02-18 12:00:06 +010085 status =
86 _receiverACM->IncomingPacket(_payloadData, payloadDataSize, rtp_header);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000087
88 return status;
89}
90
turaj@webrtc.orgc2d69d32014-02-19 20:31:17 +000091// TODO(turajs): rewite this method.
Niels Möllerbf474952019-02-18 12:00:06 +010092void Channel::CalcStatistics(const RTPHeader& rtp_header, size_t payloadSize) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000093 int n;
Niels Möllerbf474952019-02-18 12:00:06 +010094 if ((rtp_header.payloadType != _lastPayloadType) &&
Yves Gerey665174f2018-06-19 15:03:05 +020095 (_lastPayloadType != -1)) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000096 // payload-type is changed.
97 // we have to terminate the calculations on the previous payload type
98 // we ignore the last packet in that payload type just to make things
99 // easier.
100 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
101 if (_lastPayloadType == _payloadStats[n].payloadType) {
102 _payloadStats[n].newPacket = true;
103 break;
104 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000105 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000106 }
Niels Möllerbf474952019-02-18 12:00:06 +0100107 _lastPayloadType = rtp_header.payloadType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000108
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000109 bool newPayload = true;
110 ACMTestPayloadStats* currentPayloadStr = NULL;
111 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
Niels Möllerbf474952019-02-18 12:00:06 +0100112 if (rtp_header.payloadType == _payloadStats[n].payloadType) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000113 newPayload = false;
114 currentPayloadStr = &_payloadStats[n];
115 break;
116 }
117 }
118
119 if (!newPayload) {
120 if (!currentPayloadStr->newPacket) {
minyue@webrtc.org05617162015-03-03 12:02:30 +0000121 if (!_useLastFrameSize) {
Yves Gerey665174f2018-06-19 15:03:05 +0200122 _lastFrameSizeSample =
Niels Möllerbf474952019-02-18 12:00:06 +0100123 (uint32_t)((uint32_t)rtp_header.timestamp -
Yves Gerey665174f2018-06-19 15:03:05 +0200124 (uint32_t)currentPayloadStr->lastTimestamp);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000125 }
126 assert(_lastFrameSizeSample > 0);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000127 int k = 0;
minyue@webrtc.org05617162015-03-03 12:02:30 +0000128 for (; k < MAX_NUM_FRAMESIZES; ++k) {
129 if ((currentPayloadStr->frameSizeStats[k].frameSizeSample ==
Yves Gerey665174f2018-06-19 15:03:05 +0200130 _lastFrameSizeSample) ||
minyue@webrtc.org05617162015-03-03 12:02:30 +0000131 (currentPayloadStr->frameSizeStats[k].frameSizeSample == 0)) {
132 break;
133 }
134 }
135 if (k == MAX_NUM_FRAMESIZES) {
136 // New frame size found but no space to count statistics on it. Skip it.
137 printf("No memory to store statistics for payload %d : frame size %d\n",
138 _lastPayloadType, _lastFrameSizeSample);
139 return;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000140 }
Yves Gerey665174f2018-06-19 15:03:05 +0200141 ACMTestFrameSizeStats* currentFrameSizeStats =
142 &(currentPayloadStr->frameSizeStats[k]);
143 currentFrameSizeStats->frameSizeSample = (int16_t)_lastFrameSizeSample;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000144
145 // increment the number of encoded samples.
minyue@webrtc.org05617162015-03-03 12:02:30 +0000146 currentFrameSizeStats->totalEncodedSamples += _lastFrameSizeSample;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000147 // increment the number of recveived packets
148 currentFrameSizeStats->numPackets++;
149 // increment the total number of bytes (this is based on
150 // the previous payload we don't know the frame-size of
151 // the current payload.
Yves Gerey665174f2018-06-19 15:03:05 +0200152 currentFrameSizeStats->totalPayloadLenByte +=
153 currentPayloadStr->lastPayloadLenByte;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000154 // store the maximum payload-size (this is based on
155 // the previous payload we don't know the frame-size of
156 // the current payload.
Yves Gerey665174f2018-06-19 15:03:05 +0200157 if (currentFrameSizeStats->maxPayloadLen <
158 currentPayloadStr->lastPayloadLenByte) {
159 currentFrameSizeStats->maxPayloadLen =
160 currentPayloadStr->lastPayloadLenByte;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000161 }
162 // store the current values for the next time
Niels Möllerbf474952019-02-18 12:00:06 +0100163 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000164 currentPayloadStr->lastPayloadLenByte = payloadSize;
165 } else {
166 currentPayloadStr->newPacket = false;
167 currentPayloadStr->lastPayloadLenByte = payloadSize;
Niels Möllerbf474952019-02-18 12:00:06 +0100168 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
169 currentPayloadStr->payloadType = rtp_header.payloadType;
Yves Gerey665174f2018-06-19 15:03:05 +0200170 memset(currentPayloadStr->frameSizeStats, 0,
171 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000172 }
173 } else {
174 n = 0;
175 while (_payloadStats[n].payloadType != -1) {
176 n++;
177 }
178 // first packet
179 _payloadStats[n].newPacket = false;
180 _payloadStats[n].lastPayloadLenByte = payloadSize;
Niels Möllerbf474952019-02-18 12:00:06 +0100181 _payloadStats[n].lastTimestamp = rtp_header.timestamp;
182 _payloadStats[n].payloadType = rtp_header.payloadType;
Yves Gerey665174f2018-06-19 15:03:05 +0200183 memset(_payloadStats[n].frameSizeStats, 0,
184 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000185 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000186}
187
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000188Channel::Channel(int16_t chID)
189 : _receiverACM(NULL),
190 _seqNo(0),
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000191 _bitStreamFile(NULL),
192 _saveBitStream(false),
193 _lastPayloadType(-1),
194 _isStereo(false),
195 _leftChannel(true),
196 _lastInTimestamp(0),
minyue@webrtc.org05617162015-03-03 12:02:30 +0000197 _useLastFrameSize(false),
198 _lastFrameSizeSample(0),
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000199 _packetLoss(0),
200 _useFECTestWithPacketLoss(false),
Niels Möllerd28db7f2016-05-10 16:31:47 +0200201 _beginTime(rtc::TimeMillis()),
turaj@webrtc.orga305e962013-06-06 19:00:09 +0000202 _totalBytes(0),
203 external_send_timestamp_(-1),
204 external_sequence_number_(-1),
205 num_packets_to_drop_(0) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000206 int n;
207 int k;
208 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
209 _payloadStats[n].payloadType = -1;
210 _payloadStats[n].newPacket = true;
211 for (k = 0; k < MAX_NUM_FRAMESIZES; k++) {
212 _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
213 _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
214 _payloadStats[n].frameSizeStats[k].numPackets = 0;
215 _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
216 _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
217 }
218 }
219 if (chID >= 0) {
220 _saveBitStream = true;
221 char bitStreamFileName[500];
222 sprintf(bitStreamFileName, "bitStream_%d.dat", chID);
223 _bitStreamFile = fopen(bitStreamFileName, "wb");
224 } else {
225 _saveBitStream = false;
226 }
227}
228
Yves Gerey665174f2018-06-19 15:03:05 +0200229Channel::~Channel() {}
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000230
231void Channel::RegisterReceiverACM(AudioCodingModule* acm) {
232 _receiverACM = acm;
233 return;
234}
235
236void Channel::ResetStats() {
237 int n;
238 int k;
Tommi9090e0b2016-01-20 13:39:36 +0100239 _channelCritSect.Enter();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000240 _lastPayloadType = -1;
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 }
Niels Möllerd28db7f2016-05-10 16:31:47 +0200252 _beginTime = rtc::TimeMillis();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000253 _totalBytes = 0;
Tommi9090e0b2016-01-20 13:39:36 +0100254 _channelCritSect.Leave();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000255}
256
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000257uint32_t Channel::LastInTimestamp() {
258 uint32_t timestamp;
Tommi9090e0b2016-01-20 13:39:36 +0100259 _channelCritSect.Enter();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000260 timestamp = _lastInTimestamp;
Tommi9090e0b2016-01-20 13:39:36 +0100261 _channelCritSect.Leave();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000262 return timestamp;
263}
264
265double Channel::BitRate() {
266 double rate;
Niels Möllerd28db7f2016-05-10 16:31:47 +0200267 uint64_t currTime = rtc::TimeMillis();
Tommi9090e0b2016-01-20 13:39:36 +0100268 _channelCritSect.Enter();
Yves Gerey665174f2018-06-19 15:03:05 +0200269 rate = ((double)_totalBytes * 8.0) / (double)(currTime - _beginTime);
Tommi9090e0b2016-01-20 13:39:36 +0100270 _channelCritSect.Leave();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000271 return rate;
272}
273
274} // namespace webrtc