blob: e76bacb59393a6855a213e66179092d0515a4fcd [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>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
niklase@google.com470e71d2011-07-07 08:21:25 +000015#include <iostream>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/format_macros.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "rtc_base/time_utils.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019
tina.legrand@webrtc.org554ae1a2011-12-16 10:09:04 +000020namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000021
Niels Möller87e2d782019-03-07 10:18:23 +010022int32_t Channel::SendData(AudioFrameType frameType,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000023 uint8_t payloadType,
24 uint32_t timeStamp,
25 const uint8_t* payloadData,
Niels Möllerc35b6e62019-04-25 16:31:18 +020026 size_t payloadSize) {
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
Niels Möllerc936cb62019-03-19 14:10:16 +010042 if (frameType == AudioFrameType::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
Niels Möllerc35b6e62019-04-25 16:31:18 +020049 memcpy(_payloadData, payloadData, payloadDataSize);
50 if (_isStereo) {
51 if (_leftChannel) {
52 _rtp_header = rtp_header;
53 _leftChannel = false;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000054 } else {
Niels Möllerc35b6e62019-04-25 16:31:18 +020055 rtp_header = _rtp_header;
56 _leftChannel = true;
niklase@google.com470e71d2011-07-07 08:21:25 +000057 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000058 }
niklase@google.com470e71d2011-07-07 08:21:25 +000059
Tommi9090e0b2016-01-20 13:39:36 +010060 _channelCritSect.Enter();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000061 if (_saveBitStream) {
Yves Gerey665174f2018-06-19 15:03:05 +020062 // fwrite(payloadData, sizeof(uint8_t), payloadSize, _bitStreamFile);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000063 }
niklase@google.com470e71d2011-07-07 08:21:25 +000064
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000065 if (!_isStereo) {
Niels Möllerbf474952019-02-18 12:00:06 +010066 CalcStatistics(rtp_header, payloadSize);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000067 }
minyue@webrtc.org05617162015-03-03 12:02:30 +000068 _useLastFrameSize = false;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000069 _lastInTimestamp = timeStamp;
70 _totalBytes += payloadDataSize;
Tommi9090e0b2016-01-20 13:39:36 +010071 _channelCritSect.Leave();
niklase@google.com470e71d2011-07-07 08:21:25 +000072
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000073 if (_useFECTestWithPacketLoss) {
74 _packetLoss += 1;
75 if (_packetLoss == 3) {
76 _packetLoss = 0;
77 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000078 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000079 }
niklase@google.com470e71d2011-07-07 08:21:25 +000080
turaj@webrtc.orga305e962013-06-06 19:00:09 +000081 if (num_packets_to_drop_ > 0) {
82 num_packets_to_drop_--;
83 return 0;
84 }
85
Niels Möllerbf474952019-02-18 12:00:06 +010086 status =
87 _receiverACM->IncomingPacket(_payloadData, payloadDataSize, rtp_header);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000088
89 return status;
90}
91
turaj@webrtc.orgc2d69d32014-02-19 20:31:17 +000092// TODO(turajs): rewite this method.
Niels Möllerbf474952019-02-18 12:00:06 +010093void Channel::CalcStatistics(const RTPHeader& rtp_header, size_t payloadSize) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000094 int n;
Niels Möllerbf474952019-02-18 12:00:06 +010095 if ((rtp_header.payloadType != _lastPayloadType) &&
Yves Gerey665174f2018-06-19 15:03:05 +020096 (_lastPayloadType != -1)) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +000097 // payload-type is changed.
98 // we have to terminate the calculations on the previous payload type
99 // we ignore the last packet in that payload type just to make things
100 // easier.
101 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
102 if (_lastPayloadType == _payloadStats[n].payloadType) {
103 _payloadStats[n].newPacket = true;
104 break;
105 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000106 }
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000107 }
Niels Möllerbf474952019-02-18 12:00:06 +0100108 _lastPayloadType = rtp_header.payloadType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000109
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000110 bool newPayload = true;
111 ACMTestPayloadStats* currentPayloadStr = NULL;
112 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
Niels Möllerbf474952019-02-18 12:00:06 +0100113 if (rtp_header.payloadType == _payloadStats[n].payloadType) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000114 newPayload = false;
115 currentPayloadStr = &_payloadStats[n];
116 break;
117 }
118 }
119
120 if (!newPayload) {
121 if (!currentPayloadStr->newPacket) {
minyue@webrtc.org05617162015-03-03 12:02:30 +0000122 if (!_useLastFrameSize) {
Yves Gerey665174f2018-06-19 15:03:05 +0200123 _lastFrameSizeSample =
Niels Möllerbf474952019-02-18 12:00:06 +0100124 (uint32_t)((uint32_t)rtp_header.timestamp -
Yves Gerey665174f2018-06-19 15:03:05 +0200125 (uint32_t)currentPayloadStr->lastTimestamp);
minyue@webrtc.org05617162015-03-03 12:02:30 +0000126 }
127 assert(_lastFrameSizeSample > 0);
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000128 int k = 0;
minyue@webrtc.org05617162015-03-03 12:02:30 +0000129 for (; k < MAX_NUM_FRAMESIZES; ++k) {
130 if ((currentPayloadStr->frameSizeStats[k].frameSizeSample ==
Yves Gerey665174f2018-06-19 15:03:05 +0200131 _lastFrameSizeSample) ||
minyue@webrtc.org05617162015-03-03 12:02:30 +0000132 (currentPayloadStr->frameSizeStats[k].frameSizeSample == 0)) {
133 break;
134 }
135 }
136 if (k == MAX_NUM_FRAMESIZES) {
137 // New frame size found but no space to count statistics on it. Skip it.
138 printf("No memory to store statistics for payload %d : frame size %d\n",
139 _lastPayloadType, _lastFrameSizeSample);
140 return;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000141 }
Yves Gerey665174f2018-06-19 15:03:05 +0200142 ACMTestFrameSizeStats* currentFrameSizeStats =
143 &(currentPayloadStr->frameSizeStats[k]);
144 currentFrameSizeStats->frameSizeSample = (int16_t)_lastFrameSizeSample;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000145
146 // increment the number of encoded samples.
minyue@webrtc.org05617162015-03-03 12:02:30 +0000147 currentFrameSizeStats->totalEncodedSamples += _lastFrameSizeSample;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000148 // increment the number of recveived packets
149 currentFrameSizeStats->numPackets++;
150 // increment the total number of bytes (this is based on
151 // the previous payload we don't know the frame-size of
152 // the current payload.
Yves Gerey665174f2018-06-19 15:03:05 +0200153 currentFrameSizeStats->totalPayloadLenByte +=
154 currentPayloadStr->lastPayloadLenByte;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000155 // store the maximum payload-size (this is based on
156 // the previous payload we don't know the frame-size of
157 // the current payload.
Yves Gerey665174f2018-06-19 15:03:05 +0200158 if (currentFrameSizeStats->maxPayloadLen <
159 currentPayloadStr->lastPayloadLenByte) {
160 currentFrameSizeStats->maxPayloadLen =
161 currentPayloadStr->lastPayloadLenByte;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000162 }
163 // store the current values for the next time
Niels Möllerbf474952019-02-18 12:00:06 +0100164 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000165 currentPayloadStr->lastPayloadLenByte = payloadSize;
166 } else {
167 currentPayloadStr->newPacket = false;
168 currentPayloadStr->lastPayloadLenByte = payloadSize;
Niels Möllerbf474952019-02-18 12:00:06 +0100169 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
170 currentPayloadStr->payloadType = rtp_header.payloadType;
Yves Gerey665174f2018-06-19 15:03:05 +0200171 memset(currentPayloadStr->frameSizeStats, 0,
172 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000173 }
174 } else {
175 n = 0;
176 while (_payloadStats[n].payloadType != -1) {
177 n++;
178 }
179 // first packet
180 _payloadStats[n].newPacket = false;
181 _payloadStats[n].lastPayloadLenByte = payloadSize;
Niels Möllerbf474952019-02-18 12:00:06 +0100182 _payloadStats[n].lastTimestamp = rtp_header.timestamp;
183 _payloadStats[n].payloadType = rtp_header.payloadType;
Yves Gerey665174f2018-06-19 15:03:05 +0200184 memset(_payloadStats[n].frameSizeStats, 0,
185 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000186 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000187}
188
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000189Channel::Channel(int16_t chID)
190 : _receiverACM(NULL),
191 _seqNo(0),
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000192 _bitStreamFile(NULL),
193 _saveBitStream(false),
194 _lastPayloadType(-1),
195 _isStereo(false),
196 _leftChannel(true),
197 _lastInTimestamp(0),
minyue@webrtc.org05617162015-03-03 12:02:30 +0000198 _useLastFrameSize(false),
199 _lastFrameSizeSample(0),
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000200 _packetLoss(0),
201 _useFECTestWithPacketLoss(false),
Niels Möllerd28db7f2016-05-10 16:31:47 +0200202 _beginTime(rtc::TimeMillis()),
turaj@webrtc.orga305e962013-06-06 19:00:09 +0000203 _totalBytes(0),
204 external_send_timestamp_(-1),
205 external_sequence_number_(-1),
206 num_packets_to_drop_(0) {
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000207 int n;
208 int k;
209 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
210 _payloadStats[n].payloadType = -1;
211 _payloadStats[n].newPacket = true;
212 for (k = 0; k < MAX_NUM_FRAMESIZES; k++) {
213 _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
214 _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
215 _payloadStats[n].frameSizeStats[k].numPackets = 0;
216 _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
217 _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
218 }
219 }
220 if (chID >= 0) {
221 _saveBitStream = true;
222 char bitStreamFileName[500];
223 sprintf(bitStreamFileName, "bitStream_%d.dat", chID);
224 _bitStreamFile = fopen(bitStreamFileName, "wb");
225 } else {
226 _saveBitStream = false;
227 }
228}
229
Yves Gerey665174f2018-06-19 15:03:05 +0200230Channel::~Channel() {}
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000231
232void Channel::RegisterReceiverACM(AudioCodingModule* acm) {
233 _receiverACM = acm;
234 return;
235}
236
237void Channel::ResetStats() {
238 int n;
239 int k;
Tommi9090e0b2016-01-20 13:39:36 +0100240 _channelCritSect.Enter();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000241 _lastPayloadType = -1;
242 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
243 _payloadStats[n].payloadType = -1;
244 _payloadStats[n].newPacket = true;
245 for (k = 0; k < MAX_NUM_FRAMESIZES; k++) {
246 _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
247 _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
248 _payloadStats[n].frameSizeStats[k].numPackets = 0;
249 _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
250 _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
251 }
252 }
Niels Möllerd28db7f2016-05-10 16:31:47 +0200253 _beginTime = rtc::TimeMillis();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000254 _totalBytes = 0;
Tommi9090e0b2016-01-20 13:39:36 +0100255 _channelCritSect.Leave();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000256}
257
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000258uint32_t Channel::LastInTimestamp() {
259 uint32_t timestamp;
Tommi9090e0b2016-01-20 13:39:36 +0100260 _channelCritSect.Enter();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000261 timestamp = _lastInTimestamp;
Tommi9090e0b2016-01-20 13:39:36 +0100262 _channelCritSect.Leave();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000263 return timestamp;
264}
265
266double Channel::BitRate() {
267 double rate;
Niels Möllerd28db7f2016-05-10 16:31:47 +0200268 uint64_t currTime = rtc::TimeMillis();
Tommi9090e0b2016-01-20 13:39:36 +0100269 _channelCritSect.Enter();
Yves Gerey665174f2018-06-19 15:03:05 +0200270 rate = ((double)_totalBytes * 8.0) / (double)(currTime - _beginTime);
Tommi9090e0b2016-01-20 13:39:36 +0100271 _channelCritSect.Leave();
tina.legrand@webrtc.orgd5726a12013-05-03 07:34:12 +0000272 return rate;
273}
274
275} // namespace webrtc