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 <assert.h>
14
15 #include <iostream>
16
17 #include "rtc_base/format_macros.h"
18 #include "rtc_base/time_utils.h"
19
20 namespace webrtc {
21
SendData(AudioFrameType frameType,uint8_t payloadType,uint32_t timeStamp,const uint8_t * payloadData,size_t payloadSize,int64_t absolute_capture_timestamp_ms)22 int32_t Channel::SendData(AudioFrameType frameType,
23 uint8_t payloadType,
24 uint32_t timeStamp,
25 const uint8_t* payloadData,
26 size_t payloadSize,
27 int64_t absolute_capture_timestamp_ms) {
28 RTPHeader rtp_header;
29 int32_t status;
30 size_t payloadDataSize = payloadSize;
31
32 rtp_header.markerBit = false;
33 rtp_header.ssrc = 0;
34 rtp_header.sequenceNumber =
35 (external_sequence_number_ < 0)
36 ? _seqNo++
37 : static_cast<uint16_t>(external_sequence_number_);
38 rtp_header.payloadType = payloadType;
39 rtp_header.timestamp = (external_send_timestamp_ < 0)
40 ? timeStamp
41 : static_cast<uint32_t>(external_send_timestamp_);
42
43 if (frameType == AudioFrameType::kEmptyFrame) {
44 // When frame is empty, we should not transmit it. The frame size of the
45 // next non-empty frame will be based on the previous frame size.
46 _useLastFrameSize = _lastFrameSizeSample > 0;
47 return 0;
48 }
49
50 memcpy(_payloadData, payloadData, payloadDataSize);
51 if (_isStereo) {
52 if (_leftChannel) {
53 _rtp_header = rtp_header;
54 _leftChannel = false;
55 } else {
56 rtp_header = _rtp_header;
57 _leftChannel = true;
58 }
59 }
60
61 _channelCritSect.Lock();
62 if (_saveBitStream) {
63 // fwrite(payloadData, sizeof(uint8_t), payloadSize, _bitStreamFile);
64 }
65
66 if (!_isStereo) {
67 CalcStatistics(rtp_header, payloadSize);
68 }
69 _useLastFrameSize = false;
70 _lastInTimestamp = timeStamp;
71 _totalBytes += payloadDataSize;
72 _channelCritSect.Unlock();
73
74 if (_useFECTestWithPacketLoss) {
75 _packetLoss += 1;
76 if (_packetLoss == 3) {
77 _packetLoss = 0;
78 return 0;
79 }
80 }
81
82 if (num_packets_to_drop_ > 0) {
83 num_packets_to_drop_--;
84 return 0;
85 }
86
87 status =
88 _receiverACM->IncomingPacket(_payloadData, payloadDataSize, rtp_header);
89
90 return status;
91 }
92
93 // TODO(turajs): rewite this method.
CalcStatistics(const RTPHeader & rtp_header,size_t payloadSize)94 void Channel::CalcStatistics(const RTPHeader& rtp_header, size_t payloadSize) {
95 int n;
96 if ((rtp_header.payloadType != _lastPayloadType) &&
97 (_lastPayloadType != -1)) {
98 // payload-type is changed.
99 // we have to terminate the calculations on the previous payload type
100 // we ignore the last packet in that payload type just to make things
101 // easier.
102 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
103 if (_lastPayloadType == _payloadStats[n].payloadType) {
104 _payloadStats[n].newPacket = true;
105 break;
106 }
107 }
108 }
109 _lastPayloadType = rtp_header.payloadType;
110
111 bool newPayload = true;
112 ACMTestPayloadStats* currentPayloadStr = NULL;
113 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
114 if (rtp_header.payloadType == _payloadStats[n].payloadType) {
115 newPayload = false;
116 currentPayloadStr = &_payloadStats[n];
117 break;
118 }
119 }
120
121 if (!newPayload) {
122 if (!currentPayloadStr->newPacket) {
123 if (!_useLastFrameSize) {
124 _lastFrameSizeSample =
125 (uint32_t)((uint32_t)rtp_header.timestamp -
126 (uint32_t)currentPayloadStr->lastTimestamp);
127 }
128 assert(_lastFrameSizeSample > 0);
129 int k = 0;
130 for (; k < MAX_NUM_FRAMESIZES; ++k) {
131 if ((currentPayloadStr->frameSizeStats[k].frameSizeSample ==
132 _lastFrameSizeSample) ||
133 (currentPayloadStr->frameSizeStats[k].frameSizeSample == 0)) {
134 break;
135 }
136 }
137 if (k == MAX_NUM_FRAMESIZES) {
138 // New frame size found but no space to count statistics on it. Skip it.
139 printf("No memory to store statistics for payload %d : frame size %d\n",
140 _lastPayloadType, _lastFrameSizeSample);
141 return;
142 }
143 ACMTestFrameSizeStats* currentFrameSizeStats =
144 &(currentPayloadStr->frameSizeStats[k]);
145 currentFrameSizeStats->frameSizeSample = (int16_t)_lastFrameSizeSample;
146
147 // increment the number of encoded samples.
148 currentFrameSizeStats->totalEncodedSamples += _lastFrameSizeSample;
149 // increment the number of recveived packets
150 currentFrameSizeStats->numPackets++;
151 // increment the total number of bytes (this is based on
152 // the previous payload we don't know the frame-size of
153 // the current payload.
154 currentFrameSizeStats->totalPayloadLenByte +=
155 currentPayloadStr->lastPayloadLenByte;
156 // store the maximum payload-size (this is based on
157 // the previous payload we don't know the frame-size of
158 // the current payload.
159 if (currentFrameSizeStats->maxPayloadLen <
160 currentPayloadStr->lastPayloadLenByte) {
161 currentFrameSizeStats->maxPayloadLen =
162 currentPayloadStr->lastPayloadLenByte;
163 }
164 // store the current values for the next time
165 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
166 currentPayloadStr->lastPayloadLenByte = payloadSize;
167 } else {
168 currentPayloadStr->newPacket = false;
169 currentPayloadStr->lastPayloadLenByte = payloadSize;
170 currentPayloadStr->lastTimestamp = rtp_header.timestamp;
171 currentPayloadStr->payloadType = rtp_header.payloadType;
172 memset(currentPayloadStr->frameSizeStats, 0,
173 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
174 }
175 } else {
176 n = 0;
177 while (_payloadStats[n].payloadType != -1) {
178 n++;
179 }
180 // first packet
181 _payloadStats[n].newPacket = false;
182 _payloadStats[n].lastPayloadLenByte = payloadSize;
183 _payloadStats[n].lastTimestamp = rtp_header.timestamp;
184 _payloadStats[n].payloadType = rtp_header.payloadType;
185 memset(_payloadStats[n].frameSizeStats, 0,
186 MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats));
187 }
188 }
189
Channel(int16_t chID)190 Channel::Channel(int16_t chID)
191 : _receiverACM(NULL),
192 _seqNo(0),
193 _bitStreamFile(NULL),
194 _saveBitStream(false),
195 _lastPayloadType(-1),
196 _isStereo(false),
197 _leftChannel(true),
198 _lastInTimestamp(0),
199 _useLastFrameSize(false),
200 _lastFrameSizeSample(0),
201 _packetLoss(0),
202 _useFECTestWithPacketLoss(false),
203 _beginTime(rtc::TimeMillis()),
204 _totalBytes(0),
205 external_send_timestamp_(-1),
206 external_sequence_number_(-1),
207 num_packets_to_drop_(0) {
208 int n;
209 int k;
210 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
211 _payloadStats[n].payloadType = -1;
212 _payloadStats[n].newPacket = true;
213 for (k = 0; k < MAX_NUM_FRAMESIZES; k++) {
214 _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
215 _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
216 _payloadStats[n].frameSizeStats[k].numPackets = 0;
217 _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
218 _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
219 }
220 }
221 if (chID >= 0) {
222 _saveBitStream = true;
223 char bitStreamFileName[500];
224 sprintf(bitStreamFileName, "bitStream_%d.dat", chID);
225 _bitStreamFile = fopen(bitStreamFileName, "wb");
226 } else {
227 _saveBitStream = false;
228 }
229 }
230
~Channel()231 Channel::~Channel() {}
232
RegisterReceiverACM(AudioCodingModule * acm)233 void Channel::RegisterReceiverACM(AudioCodingModule* acm) {
234 _receiverACM = acm;
235 return;
236 }
237
ResetStats()238 void Channel::ResetStats() {
239 int n;
240 int k;
241 _channelCritSect.Lock();
242 _lastPayloadType = -1;
243 for (n = 0; n < MAX_NUM_PAYLOADS; n++) {
244 _payloadStats[n].payloadType = -1;
245 _payloadStats[n].newPacket = true;
246 for (k = 0; k < MAX_NUM_FRAMESIZES; k++) {
247 _payloadStats[n].frameSizeStats[k].frameSizeSample = 0;
248 _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0;
249 _payloadStats[n].frameSizeStats[k].numPackets = 0;
250 _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0;
251 _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0;
252 }
253 }
254 _beginTime = rtc::TimeMillis();
255 _totalBytes = 0;
256 _channelCritSect.Unlock();
257 }
258
LastInTimestamp()259 uint32_t Channel::LastInTimestamp() {
260 uint32_t timestamp;
261 _channelCritSect.Lock();
262 timestamp = _lastInTimestamp;
263 _channelCritSect.Unlock();
264 return timestamp;
265 }
266
BitRate()267 double Channel::BitRate() {
268 double rate;
269 uint64_t currTime = rtc::TimeMillis();
270 _channelCritSect.Lock();
271 rate = ((double)_totalBytes * 8.0) / (double)(currTime - _beginTime);
272 _channelCritSect.Unlock();
273 return rate;
274 }
275
276 } // namespace webrtc
277