• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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