diff options
Diffstat (limited to 'third_party/libwebrtc/modules/audio_coding/test/Channel.cc')
-rw-r--r-- | third_party/libwebrtc/modules/audio_coding/test/Channel.cc | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/audio_coding/test/Channel.cc b/third_party/libwebrtc/modules/audio_coding/test/Channel.cc new file mode 100644 index 0000000000..35aa6cb6b4 --- /dev/null +++ b/third_party/libwebrtc/modules/audio_coding/test/Channel.cc @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "modules/audio_coding/test/Channel.h" + +#include <iostream> + +#include "rtc_base/strings/string_builder.h" +#include "rtc_base/time_utils.h" + +namespace webrtc { + +int32_t Channel::SendData(AudioFrameType frameType, + uint8_t payloadType, + uint32_t timeStamp, + const uint8_t* payloadData, + size_t payloadSize, + int64_t absolute_capture_timestamp_ms) { + RTPHeader rtp_header; + int32_t status; + size_t payloadDataSize = payloadSize; + + rtp_header.markerBit = false; + rtp_header.ssrc = 0; + rtp_header.sequenceNumber = + (external_sequence_number_ < 0) + ? _seqNo++ + : static_cast<uint16_t>(external_sequence_number_); + rtp_header.payloadType = payloadType; + rtp_header.timestamp = (external_send_timestamp_ < 0) + ? timeStamp + : static_cast<uint32_t>(external_send_timestamp_); + + if (frameType == AudioFrameType::kEmptyFrame) { + // When frame is empty, we should not transmit it. The frame size of the + // next non-empty frame will be based on the previous frame size. + _useLastFrameSize = _lastFrameSizeSample > 0; + return 0; + } + + memcpy(_payloadData, payloadData, payloadDataSize); + if (_isStereo) { + if (_leftChannel) { + _rtp_header = rtp_header; + _leftChannel = false; + } else { + rtp_header = _rtp_header; + _leftChannel = true; + } + } + + _channelCritSect.Lock(); + if (_saveBitStream) { + // fwrite(payloadData, sizeof(uint8_t), payloadSize, _bitStreamFile); + } + + if (!_isStereo) { + CalcStatistics(rtp_header, payloadSize); + } + _useLastFrameSize = false; + _lastInTimestamp = timeStamp; + _totalBytes += payloadDataSize; + _channelCritSect.Unlock(); + + if (_useFECTestWithPacketLoss) { + _packetLoss += 1; + if (_packetLoss == 3) { + _packetLoss = 0; + return 0; + } + } + + if (num_packets_to_drop_ > 0) { + num_packets_to_drop_--; + return 0; + } + + status = + _receiverACM->IncomingPacket(_payloadData, payloadDataSize, rtp_header); + + return status; +} + +// TODO(turajs): rewite this method. +void Channel::CalcStatistics(const RTPHeader& rtp_header, size_t payloadSize) { + int n; + if ((rtp_header.payloadType != _lastPayloadType) && + (_lastPayloadType != -1)) { + // payload-type is changed. + // we have to terminate the calculations on the previous payload type + // we ignore the last packet in that payload type just to make things + // easier. + for (n = 0; n < MAX_NUM_PAYLOADS; n++) { + if (_lastPayloadType == _payloadStats[n].payloadType) { + _payloadStats[n].newPacket = true; + break; + } + } + } + _lastPayloadType = rtp_header.payloadType; + + bool newPayload = true; + ACMTestPayloadStats* currentPayloadStr = NULL; + for (n = 0; n < MAX_NUM_PAYLOADS; n++) { + if (rtp_header.payloadType == _payloadStats[n].payloadType) { + newPayload = false; + currentPayloadStr = &_payloadStats[n]; + break; + } + } + + if (!newPayload) { + if (!currentPayloadStr->newPacket) { + if (!_useLastFrameSize) { + _lastFrameSizeSample = + (uint32_t)((uint32_t)rtp_header.timestamp - + (uint32_t)currentPayloadStr->lastTimestamp); + } + RTC_DCHECK_GT(_lastFrameSizeSample, 0); + int k = 0; + for (; k < MAX_NUM_FRAMESIZES; ++k) { + if ((currentPayloadStr->frameSizeStats[k].frameSizeSample == + _lastFrameSizeSample) || + (currentPayloadStr->frameSizeStats[k].frameSizeSample == 0)) { + break; + } + } + if (k == MAX_NUM_FRAMESIZES) { + // New frame size found but no space to count statistics on it. Skip it. + printf("No memory to store statistics for payload %d : frame size %d\n", + _lastPayloadType, _lastFrameSizeSample); + return; + } + ACMTestFrameSizeStats* currentFrameSizeStats = + &(currentPayloadStr->frameSizeStats[k]); + currentFrameSizeStats->frameSizeSample = (int16_t)_lastFrameSizeSample; + + // increment the number of encoded samples. + currentFrameSizeStats->totalEncodedSamples += _lastFrameSizeSample; + // increment the number of recveived packets + currentFrameSizeStats->numPackets++; + // increment the total number of bytes (this is based on + // the previous payload we don't know the frame-size of + // the current payload. + currentFrameSizeStats->totalPayloadLenByte += + currentPayloadStr->lastPayloadLenByte; + // store the maximum payload-size (this is based on + // the previous payload we don't know the frame-size of + // the current payload. + if (currentFrameSizeStats->maxPayloadLen < + currentPayloadStr->lastPayloadLenByte) { + currentFrameSizeStats->maxPayloadLen = + currentPayloadStr->lastPayloadLenByte; + } + // store the current values for the next time + currentPayloadStr->lastTimestamp = rtp_header.timestamp; + currentPayloadStr->lastPayloadLenByte = payloadSize; + } else { + currentPayloadStr->newPacket = false; + currentPayloadStr->lastPayloadLenByte = payloadSize; + currentPayloadStr->lastTimestamp = rtp_header.timestamp; + currentPayloadStr->payloadType = rtp_header.payloadType; + memset(currentPayloadStr->frameSizeStats, 0, + MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats)); + } + } else { + n = 0; + while (_payloadStats[n].payloadType != -1) { + n++; + } + // first packet + _payloadStats[n].newPacket = false; + _payloadStats[n].lastPayloadLenByte = payloadSize; + _payloadStats[n].lastTimestamp = rtp_header.timestamp; + _payloadStats[n].payloadType = rtp_header.payloadType; + memset(_payloadStats[n].frameSizeStats, 0, + MAX_NUM_FRAMESIZES * sizeof(ACMTestFrameSizeStats)); + } +} + +Channel::Channel(int16_t chID) + : _receiverACM(NULL), + _seqNo(0), + _bitStreamFile(NULL), + _saveBitStream(false), + _lastPayloadType(-1), + _isStereo(false), + _leftChannel(true), + _lastInTimestamp(0), + _useLastFrameSize(false), + _lastFrameSizeSample(0), + _packetLoss(0), + _useFECTestWithPacketLoss(false), + _beginTime(rtc::TimeMillis()), + _totalBytes(0), + external_send_timestamp_(-1), + external_sequence_number_(-1), + num_packets_to_drop_(0) { + int n; + int k; + for (n = 0; n < MAX_NUM_PAYLOADS; n++) { + _payloadStats[n].payloadType = -1; + _payloadStats[n].newPacket = true; + for (k = 0; k < MAX_NUM_FRAMESIZES; k++) { + _payloadStats[n].frameSizeStats[k].frameSizeSample = 0; + _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0; + _payloadStats[n].frameSizeStats[k].numPackets = 0; + _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0; + _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0; + } + } + if (chID >= 0) { + _saveBitStream = true; + rtc::StringBuilder ss; + ss.AppendFormat("bitStream_%d.dat", chID); + _bitStreamFile = fopen(ss.str().c_str(), "wb"); + } else { + _saveBitStream = false; + } +} + +Channel::~Channel() {} + +void Channel::RegisterReceiverACM(AudioCodingModule* acm) { + _receiverACM = acm; + return; +} + +void Channel::ResetStats() { + int n; + int k; + _channelCritSect.Lock(); + _lastPayloadType = -1; + for (n = 0; n < MAX_NUM_PAYLOADS; n++) { + _payloadStats[n].payloadType = -1; + _payloadStats[n].newPacket = true; + for (k = 0; k < MAX_NUM_FRAMESIZES; k++) { + _payloadStats[n].frameSizeStats[k].frameSizeSample = 0; + _payloadStats[n].frameSizeStats[k].maxPayloadLen = 0; + _payloadStats[n].frameSizeStats[k].numPackets = 0; + _payloadStats[n].frameSizeStats[k].totalPayloadLenByte = 0; + _payloadStats[n].frameSizeStats[k].totalEncodedSamples = 0; + } + } + _beginTime = rtc::TimeMillis(); + _totalBytes = 0; + _channelCritSect.Unlock(); +} + +uint32_t Channel::LastInTimestamp() { + uint32_t timestamp; + _channelCritSect.Lock(); + timestamp = _lastInTimestamp; + _channelCritSect.Unlock(); + return timestamp; +} + +double Channel::BitRate() { + double rate; + uint64_t currTime = rtc::TimeMillis(); + _channelCritSect.Lock(); + rate = ((double)_totalBytes * 8.0) / (double)(currTime - _beginTime); + _channelCritSect.Unlock(); + return rate; +} + +} // namespace webrtc |