1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
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
11 #include "modules/audio_coding/test/Channel.h"
12
13 #include <iostream>
14
15 #include "rtc_base/strings/string_builder.h"
16 #include "rtc_base/time_utils.h"
17
18 namespace webrtc {
19
SendData(AudioFrameType frameType,uint8_t payloadType,uint32_t timeStamp,const uint8_t * payloadData,size_t payloadSize,int64_t absolute_capture_timestamp_ms)20 int32_t Channel::SendData(AudioFrameType frameType,
21 uint8_t payloadType,
22 uint32_t timeStamp,
23 const uint8_t* payloadData,
24 size_t payloadSize,
25 int64_t absolute_capture_timestamp_ms) {
26 RTPHeader rtp_header;
27 int32_t status;
28 size_t payloadDataSize = payloadSize;
29
30 rtp_header.markerBit = false;
31 rtp_header.ssrc = 0;
32 rtp_header.sequenceNumber =
33 (external_sequence_number_ < 0)
34 ? _seqNo++
35 : static_cast<uint16_t>(external_sequence_number_);
36 rtp_header.payloadType = payloadType;
37 rtp_header.timestamp = (external_send_timestamp_ < 0)
38 ? timeStamp
39 : static_cast<uint32_t>(external_send_timestamp_);
40
41 if (frameType == AudioFrameType::kEmptyFrame) {
42 // 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;
45 return 0;
46 }
47
48 memcpy(_payloadData, payloadData, payloadDataSize);
49 if (_isStereo) {
50 if (_leftChannel) {
51 _rtp_header = rtp_header;
52 _leftChannel = false;
53 } else {
54 rtp_header = _rtp_header;
55 _leftChannel = true;
56 }
57 }
58
59 _channelCritSect.Lock();
60 if (_saveBitStream) {
61 // fwrite(payloadData, sizeof(uint8_t), payloadSize, _bitStreamFile);
62 }
63
64 if (!_isStereo) {
65 CalcStatistics(rtp_header, payloadSize);
66 }
67 _useLastFrameSize = false;
68 _lastInTimestamp = timeStamp;
69 _totalBytes += payloadDataSize;
70 _channelCritSect.Unlock();
71
72 if (_useFECTestWithPacketLoss) {
73 _packetLoss += 1;
74 if (_packetLoss == 3) {
75 _packetLoss = 0;
76 return 0;
77 }
78 }
79
80 if (num_packets_to_drop_ > 0) {
81 num_packets_to_drop_--;
82 return 0;
83 }
84
85 status =
86 _receiverACM->IncomingPacket(_payloadData, payloadDataSize, rtp_header);
87
88 return status;
89 }
90
91 // TODO(turajs): rewite this method.
CalcStatistics(const RTPHeader & rtp_header,size_t payloadSize)92 void Channel::CalcStatistics(const RTPHeader& rtp_header, size_t payloadSize) {
93 int n;
94 if ((rtp_header.payloadType != _lastPayloadType) &&
95 (_lastPayloadType != -1)) {
96 // 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 }
105 }
106 }
107 _lastPayloadType = rtp_header.payloadType;
108
109 bool newPayload = true;
110 ACMTestPayloadStats* currentPayloadStr = NULL;
111 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
112 if (rtp_header.payloadType == _payloadStats[n].payloadType) {
113 newPayload = false;
114 currentPayloadStr = &_payloadStats[n];
115 break;
116 }
117 }
118
119 if (!newPayload) {
120 if (!currentPayloadStr->newPacket) {
121 if (!_useLastFrameSize) {
122 _lastFrameSizeSample =
123 (uint32_t)((uint32_t)rtp_header.timestamp -
124 (uint32_t)currentPayloadStr->lastTimestamp);
125 }
126 RTC_DCHECK_GT(_lastFrameSizeSample, 0);
127 int k = 0;
128 for (; k < MAX_NUM_FRAMESIZES; ++k) {
129 if ((currentPayloadStr->frameSizeStats[k].frameSizeSample ==
130 _lastFrameSizeSample) ||
131 (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;
140 }
141 ACMTestFrameSizeStats* currentFrameSizeStats =
142 &(currentPayloadStr->frameSizeStats[k]);
143 currentFrameSizeStats->frameSizeSample = (int16_t)_lastFrameSizeSample;
144
145 // increment the number of encoded samples.
146 currentFrameSizeStats->totalEncodedSamples += _lastFrameSizeSample;
147 // 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.
152 currentFrameSizeStats->totalPayloadLenByte +=
153 currentPayloadStr->lastPayloadLenByte;
154 // 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.
157 if (currentFrameSizeStats->maxPayloadLen <
158 currentPayloadStr->lastPayloadLenByte) {
159 currentFrameSizeStats->maxPayloadLen =
160 currentPayloadStr->lastPayloadLenByte;
161 }
162 // store the current values for the next time
163 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
164 currentPayloadStr->lastPayloadLenByte = payloadSize;
165 } else {
166 currentPayloadStr->newPacket = false;
167 currentPayloadStr->lastPayloadLenByte = payloadSize;
168 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
169 currentPayloadStr->payloadType = rtp_header.payloadType;
170 memset(currentPayloadStr->frameSizeStats, 0,
171 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
172 }
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;
181 _payloadStats[n].lastTimestamp = rtp_header.timestamp;
182 _payloadStats[n].payloadType = rtp_header.payloadType;
183 memset(_payloadStats[n].frameSizeStats, 0,
184 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
185 }
186 }
187
Channel(int16_t chID)188 Channel::Channel(int16_t chID)
189 : _receiverACM(NULL),
190 _seqNo(0),
191 _bitStreamFile(NULL),
192 _saveBitStream(false),
193 _lastPayloadType(-1),
194 _isStereo(false),
195 _leftChannel(true),
196 _lastInTimestamp(0),
197 _useLastFrameSize(false),
198 _lastFrameSizeSample(0),
199 _packetLoss(0),
200 _useFECTestWithPacketLoss(false),
201 _beginTime(rtc::TimeMillis()),
202 _totalBytes(0),
203 external_send_timestamp_(-1),
204 external_sequence_number_(-1),
205 num_packets_to_drop_(0) {
206 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 rtc::StringBuilder ss;
222 ss.AppendFormat("bitStream_%d.dat", chID);
223 _bitStreamFile = fopen(ss.str().c_str(), "wb");
224 } else {
225 _saveBitStream = false;
226 }
227 }
228
~Channel()229 Channel::~Channel() {}
230
RegisterReceiverACM(AudioCodingModule * acm)231 void Channel::RegisterReceiverACM(AudioCodingModule* acm) {
232 _receiverACM = acm;
233 return;
234 }
235
ResetStats()236 void Channel::ResetStats() {
237 int n;
238 int k;
239 _channelCritSect.Lock();
240 _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 }
252 _beginTime = rtc::TimeMillis();
253 _totalBytes = 0;
254 _channelCritSect.Unlock();
255 }
256
LastInTimestamp()257 uint32_t Channel::LastInTimestamp() {
258 uint32_t timestamp;
259 _channelCritSect.Lock();
260 timestamp = _lastInTimestamp;
261 _channelCritSect.Unlock();
262 return timestamp;
263 }
264
BitRate()265 double Channel::BitRate() {
266 double rate;
267 uint64_t currTime = rtc::TimeMillis();
268 _channelCritSect.Lock();
269 rate = ((double)_totalBytes * 8.0) / (double)(currTime - _beginTime);
270 _channelCritSect.Unlock();
271 return rate;
272 }
273
274 } // namespace webrtc
275