webrtc/modules/audio_coding/test/Channel.cc
Niels Möller 87e2d785a0 Prepare for splitting FrameType into AudioFrameType and VideoFrameType
This cl deprecates the FrameType enum, and adds aliases AudioFrameType
and VideoFrameType.

After downstream usage is updated, the enums will be separated
and be moved out of common_types.h.

Bug: webrtc:6883
Change-Id: I2aaf660169da45f22574b4cbb16aea8522cc07a6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/123184
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27011}
2019-03-07 10:12:57 +00:00

307 lines
10 KiB
C++

/*
* 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 <assert.h>
#include <iostream>
#include "rtc_base/format_macros.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,
const RTPFragmentationHeader* fragmentation) {
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 == 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;
}
// Treat fragmentation separately
if (fragmentation != NULL) {
// If silence for too long, send only new data.
if ((fragmentation->fragmentationVectorSize == 2) &&
(fragmentation->fragmentationTimeDiff[1] <= 0x3fff)) {
// only 0x80 if we have multiple blocks
_payloadData[0] = 0x80 + fragmentation->fragmentationPlType[1];
size_t REDheader = (fragmentation->fragmentationTimeDiff[1] << 10) +
fragmentation->fragmentationLength[1];
_payloadData[1] = uint8_t((REDheader >> 16) & 0x000000FF);
_payloadData[2] = uint8_t((REDheader >> 8) & 0x000000FF);
_payloadData[3] = uint8_t(REDheader & 0x000000FF);
_payloadData[4] = fragmentation->fragmentationPlType[0];
// copy the RED data
memcpy(_payloadData + 5,
payloadData + fragmentation->fragmentationOffset[1],
fragmentation->fragmentationLength[1]);
// copy the normal data
memcpy(_payloadData + 5 + fragmentation->fragmentationLength[1],
payloadData + fragmentation->fragmentationOffset[0],
fragmentation->fragmentationLength[0]);
payloadDataSize += 5;
} else {
// single block (newest one)
memcpy(_payloadData, payloadData + fragmentation->fragmentationOffset[0],
fragmentation->fragmentationLength[0]);
payloadDataSize = fragmentation->fragmentationLength[0];
rtp_header.payloadType = fragmentation->fragmentationPlType[0];
}
} else {
memcpy(_payloadData, payloadData, payloadDataSize);
if (_isStereo) {
if (_leftChannel) {
_rtp_header = rtp_header;
_leftChannel = false;
} else {
rtp_header = _rtp_header;
_leftChannel = true;
}
}
}
_channelCritSect.Enter();
if (_saveBitStream) {
// fwrite(payloadData, sizeof(uint8_t), payloadSize, _bitStreamFile);
}
if (!_isStereo) {
CalcStatistics(rtp_header, payloadSize);
}
_useLastFrameSize = false;
_lastInTimestamp = timeStamp;
_totalBytes += payloadDataSize;
_channelCritSect.Leave();
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);
}
assert(_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;
char bitStreamFileName[500];
sprintf(bitStreamFileName, "bitStream_%d.dat", chID);
_bitStreamFile = fopen(bitStreamFileName, "wb");
} else {
_saveBitStream = false;
}
}
Channel::~Channel() {}
void Channel::RegisterReceiverACM(AudioCodingModule* acm) {
_receiverACM = acm;
return;
}
void Channel::ResetStats() {
int n;
int k;
_channelCritSect.Enter();
_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.Leave();
}
uint32_t Channel::LastInTimestamp() {
uint32_t timestamp;
_channelCritSect.Enter();
timestamp = _lastInTimestamp;
_channelCritSect.Leave();
return timestamp;
}
double Channel::BitRate() {
double rate;
uint64_t currTime = rtc::TimeMillis();
_channelCritSect.Enter();
rate = ((double)_totalBytes * 8.0) / (double)(currTime - _beginTime);
_channelCritSect.Leave();
return rate;
}
} // namespace webrtc