blob: 4ba280b5bb2f1af54ddf4ce9a0ddd84dbee83fba [file] [log] [blame]
/*
* Copyright (c) 2011 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 "transmission_bucket.h"
#include <assert.h>
#include "critical_section_wrapper.h"
namespace webrtc {
TransmissionBucket::TransmissionBucket()
: critsect_(CriticalSectionWrapper::CreateCriticalSection()),
accumulator_(0),
bytes_rem_total_(0),
bytes_rem_interval_(0),
packets_(),
first_(true) {
}
TransmissionBucket::~TransmissionBucket() {
packets_.clear();
delete critsect_;
}
void TransmissionBucket::Reset() {
webrtc::CriticalSectionScoped cs(*critsect_);
accumulator_ = 0;
bytes_rem_total_ = 0;
bytes_rem_interval_ = 0;
packets_.clear();
first_ = true;
}
void TransmissionBucket::Fill(const uint16_t seq_num,
const uint32_t num_bytes) {
webrtc::CriticalSectionScoped cs(*critsect_);
accumulator_ += num_bytes;
Packet p(seq_num, num_bytes);
packets_.push_back(p);
}
bool TransmissionBucket::Empty() {
webrtc::CriticalSectionScoped cs(*critsect_);
return packets_.empty();
}
void TransmissionBucket::UpdateBytesPerInterval(
const uint32_t delta_time_ms,
const uint16_t target_bitrate_kbps) {
webrtc::CriticalSectionScoped cs(*critsect_);
const float kMargin = 1.05;
uint32_t bytes_per_interval =
kMargin * (target_bitrate_kbps * delta_time_ms / 8);
if (bytes_rem_interval_ < 0) {
bytes_rem_interval_ += bytes_per_interval;
} else {
bytes_rem_interval_ = bytes_per_interval;
}
if (accumulator_) {
bytes_rem_total_ += bytes_per_interval;
return;
}
bytes_rem_total_ = bytes_per_interval;
}
int32_t TransmissionBucket::GetNextPacket() {
webrtc::CriticalSectionScoped cs(*critsect_);
if (accumulator_ == 0) {
// Empty.
return -1;
}
std::vector<Packet>::const_iterator it_begin = packets_.begin();
const uint16_t num_bytes = (*it_begin).length_;
const uint16_t seq_num = (*it_begin).sequence_number_;
if (first_) {
// Ok to transmit first packet.
first_ = false;
packets_.erase(packets_.begin());
return seq_num;
}
const float kFrameComplete = 0.80;
if (num_bytes * kFrameComplete > bytes_rem_total_) {
// Packet does not fit.
return -1;
}
if (bytes_rem_interval_ <= 0) {
// All bytes consumed for this interval.
return -1;
}
// Ok to transmit packet.
bytes_rem_total_ -= num_bytes;
bytes_rem_interval_ -= num_bytes;
assert(accumulator_ >= num_bytes);
accumulator_ -= num_bytes;
packets_.erase(packets_.begin());
return seq_num;
}
} // namespace webrtc