2012-01-16 11:06:31 +00:00
|
|
|
/*
|
2012-07-03 10:41:54 +00:00
|
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
2012-01-16 11:06:31 +00:00
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2013-05-29 14:27:38 +00:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h"
|
2012-01-16 11:06:31 +00:00
|
|
|
|
2015-12-10 05:05:27 -08:00
|
|
|
#include <algorithm>
|
2013-12-04 10:24:26 +00:00
|
|
|
#include <limits>
|
2017-03-24 03:22:49 -07:00
|
|
|
#include <utility>
|
2012-01-16 11:06:31 +00:00
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
2017-07-06 19:44:34 +02:00
|
|
|
#include "webrtc/rtc_base/checks.h"
|
|
|
|
|
#include "webrtc/rtc_base/logging.h"
|
2016-08-03 18:27:40 +02:00
|
|
|
#include "webrtc/system_wrappers/include/clock.h"
|
2012-01-16 11:06:31 +00:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
2016-08-03 18:27:40 +02:00
|
|
|
namespace {
|
|
|
|
|
constexpr size_t kMinPacketRequestBytes = 50;
|
|
|
|
|
} // namespace
|
|
|
|
|
constexpr size_t RtpPacketHistory::kMaxCapacity;
|
2012-01-16 11:06:31 +00:00
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
RtpPacketHistory::RtpPacketHistory(Clock* clock)
|
|
|
|
|
: clock_(clock), store_(false), prev_index_(0) {}
|
2012-01-16 11:06:31 +00:00
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
RtpPacketHistory::~RtpPacketHistory() {}
|
2012-01-16 11:06:31 +00:00
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
void RtpPacketHistory::SetStorePacketsStatus(bool enable,
|
2012-01-16 11:06:31 +00:00
|
|
|
uint16_t number_to_store) {
|
2016-04-14 03:05:31 -07:00
|
|
|
rtc::CritScope cs(&critsect_);
|
2012-01-16 11:06:31 +00:00
|
|
|
if (enable) {
|
2014-04-08 11:06:12 +00:00
|
|
|
if (store_) {
|
|
|
|
|
LOG(LS_WARNING) << "Purging packet history in order to re-set status.";
|
|
|
|
|
Free();
|
|
|
|
|
}
|
2016-08-03 18:27:40 +02:00
|
|
|
RTC_DCHECK(!store_);
|
2012-01-16 11:06:31 +00:00
|
|
|
Allocate(number_to_store);
|
|
|
|
|
} else {
|
|
|
|
|
Free();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
void RtpPacketHistory::Allocate(size_t number_to_store) {
|
2016-11-28 15:21:39 -08:00
|
|
|
RTC_DCHECK_GT(number_to_store, 0);
|
2016-08-03 18:27:40 +02:00
|
|
|
RTC_DCHECK_LE(number_to_store, kMaxCapacity);
|
2012-01-16 11:06:31 +00:00
|
|
|
store_ = true;
|
|
|
|
|
stored_packets_.resize(number_to_store);
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
void RtpPacketHistory::Free() {
|
2012-01-16 11:06:31 +00:00
|
|
|
if (!store_) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stored_packets_.clear();
|
|
|
|
|
|
|
|
|
|
store_ = false;
|
|
|
|
|
prev_index_ = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
bool RtpPacketHistory::StorePackets() const {
|
2016-04-14 03:05:31 -07:00
|
|
|
rtc::CritScope cs(&critsect_);
|
2012-01-16 11:06:31 +00:00
|
|
|
return store_;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
void RtpPacketHistory::PutRtpPacket(std::unique_ptr<RtpPacketToSend> packet,
|
|
|
|
|
StorageType type,
|
|
|
|
|
bool sent) {
|
|
|
|
|
RTC_DCHECK(packet);
|
2016-04-14 03:05:31 -07:00
|
|
|
rtc::CritScope cs(&critsect_);
|
2012-01-16 11:06:31 +00:00
|
|
|
if (!store_) {
|
2016-08-03 18:27:40 +02:00
|
|
|
return;
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
2015-01-29 09:09:17 +00:00
|
|
|
// If index we're about to overwrite contains a packet that has not
|
|
|
|
|
// yet been sent (probably pending in paced sender), we need to expand
|
|
|
|
|
// the buffer.
|
2016-08-03 18:27:40 +02:00
|
|
|
if (stored_packets_[prev_index_].packet &&
|
2015-09-11 08:33:35 -07:00
|
|
|
stored_packets_[prev_index_].send_time == 0) {
|
2015-01-29 09:09:17 +00:00
|
|
|
size_t current_size = static_cast<uint16_t>(stored_packets_.size());
|
2016-08-03 18:27:40 +02:00
|
|
|
if (current_size < kMaxCapacity) {
|
2015-02-02 13:08:02 +00:00
|
|
|
size_t expanded_size = std::max(current_size * 3 / 2, current_size + 1);
|
2016-08-03 18:27:40 +02:00
|
|
|
expanded_size = std::min(expanded_size, kMaxCapacity);
|
2015-02-02 13:08:02 +00:00
|
|
|
Allocate(expanded_size);
|
|
|
|
|
// Causes discontinuity, but that's OK-ish. FindSeqNum() will still work,
|
|
|
|
|
// but may be slower - at least until buffer has wrapped around once.
|
|
|
|
|
prev_index_ = current_size;
|
|
|
|
|
}
|
2015-01-29 09:09:17 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
// Store packet.
|
|
|
|
|
if (packet->capture_time_ms() <= 0)
|
|
|
|
|
packet->set_capture_time_ms(clock_->TimeInMilliseconds());
|
|
|
|
|
stored_packets_[prev_index_].sequence_number = packet->SequenceNumber();
|
|
|
|
|
stored_packets_[prev_index_].send_time =
|
|
|
|
|
(sent ? clock_->TimeInMilliseconds() : 0);
|
2015-09-11 08:33:35 -07:00
|
|
|
stored_packets_[prev_index_].storage_type = type;
|
2015-10-21 13:46:33 -07:00
|
|
|
stored_packets_[prev_index_].has_been_retransmitted = false;
|
2016-08-03 18:27:40 +02:00
|
|
|
stored_packets_[prev_index_].packet = std::move(packet);
|
2012-01-16 11:06:31 +00:00
|
|
|
|
|
|
|
|
++prev_index_;
|
2015-09-11 08:33:35 -07:00
|
|
|
if (prev_index_ >= stored_packets_.size()) {
|
2012-01-16 11:06:31 +00:00
|
|
|
prev_index_ = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
bool RtpPacketHistory::HasRtpPacket(uint16_t sequence_number) const {
|
2016-04-14 03:05:31 -07:00
|
|
|
rtc::CritScope cs(&critsect_);
|
2012-01-16 11:06:31 +00:00
|
|
|
if (!store_) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
int unused_index = 0;
|
|
|
|
|
return FindSeqNum(sequence_number, &unused_index);
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetPacketAndSetSendTime(
|
|
|
|
|
uint16_t sequence_number,
|
|
|
|
|
int64_t min_elapsed_time_ms,
|
|
|
|
|
bool retransmit) {
|
2016-04-14 03:05:31 -07:00
|
|
|
rtc::CritScope cs(&critsect_);
|
2015-01-29 09:09:17 +00:00
|
|
|
if (!store_) {
|
2016-08-03 18:27:40 +02:00
|
|
|
return nullptr;
|
2015-01-29 09:09:17 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
int index = 0;
|
|
|
|
|
if (!FindSeqNum(sequence_number, &index)) {
|
2014-04-08 11:06:12 +00:00
|
|
|
LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number;
|
2016-08-03 18:27:40 +02:00
|
|
|
return nullptr;
|
2013-12-04 10:24:26 +00:00
|
|
|
}
|
2016-08-03 18:27:40 +02:00
|
|
|
RTC_DCHECK_EQ(sequence_number,
|
|
|
|
|
stored_packets_[index].packet->SequenceNumber());
|
2012-01-16 11:06:31 +00:00
|
|
|
|
2015-10-21 13:46:33 -07:00
|
|
|
// Verify elapsed time since last retrieve, but only for retransmissions and
|
|
|
|
|
// always send packet upon first retransmission request.
|
2013-01-21 07:42:11 +00:00
|
|
|
int64_t now = clock_->TimeInMilliseconds();
|
2015-10-21 13:46:33 -07:00
|
|
|
if (min_elapsed_time_ms > 0 && retransmit &&
|
|
|
|
|
stored_packets_[index].has_been_retransmitted &&
|
2015-09-11 08:33:35 -07:00
|
|
|
((now - stored_packets_[index].send_time) < min_elapsed_time_ms)) {
|
2016-08-03 18:27:40 +02:00
|
|
|
return nullptr;
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-21 13:46:33 -07:00
|
|
|
if (retransmit) {
|
|
|
|
|
if (stored_packets_[index].storage_type == kDontRetransmit) {
|
2016-08-03 18:27:40 +02:00
|
|
|
// No bytes copied since this packet shouldn't be retransmitted.
|
|
|
|
|
return nullptr;
|
2015-10-21 13:46:33 -07:00
|
|
|
}
|
|
|
|
|
stored_packets_[index].has_been_retransmitted = true;
|
2013-12-04 10:24:26 +00:00
|
|
|
}
|
2015-09-11 08:33:35 -07:00
|
|
|
stored_packets_[index].send_time = clock_->TimeInMilliseconds();
|
2016-08-03 18:27:40 +02:00
|
|
|
return GetPacket(index);
|
2013-12-04 10:24:26 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetPacket(int index) const {
|
|
|
|
|
const RtpPacketToSend& stored = *stored_packets_[index].packet;
|
|
|
|
|
return std::unique_ptr<RtpPacketToSend>(new RtpPacketToSend(stored));
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetBestFittingPacket(
|
|
|
|
|
size_t packet_length) const {
|
2016-04-14 03:05:31 -07:00
|
|
|
rtc::CritScope cs(&critsect_);
|
2013-12-04 10:24:26 +00:00
|
|
|
if (!store_)
|
2016-08-03 18:27:40 +02:00
|
|
|
return nullptr;
|
|
|
|
|
int index = FindBestFittingPacket(packet_length);
|
2013-12-04 10:24:26 +00:00
|
|
|
if (index < 0)
|
2016-08-03 18:27:40 +02:00
|
|
|
return nullptr;
|
|
|
|
|
return GetPacket(index);
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
bool RtpPacketHistory::FindSeqNum(uint16_t sequence_number, int* index) const {
|
2012-01-16 11:06:31 +00:00
|
|
|
if (prev_index_ > 0) {
|
|
|
|
|
*index = prev_index_ - 1;
|
|
|
|
|
} else {
|
2016-08-03 18:27:40 +02:00
|
|
|
*index = stored_packets_.size() - 1; // Wrap.
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
2016-08-03 18:27:40 +02:00
|
|
|
uint16_t temp_sequence_number = stored_packets_[*index].sequence_number;
|
2012-01-16 11:06:31 +00:00
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
int idx = *index - (temp_sequence_number - sequence_number);
|
2015-09-11 08:33:35 -07:00
|
|
|
if (idx >= 0 && idx < static_cast<int>(stored_packets_.size())) {
|
2012-01-16 11:06:31 +00:00
|
|
|
*index = idx;
|
2015-09-11 08:33:35 -07:00
|
|
|
temp_sequence_number = stored_packets_[*index].sequence_number;
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (temp_sequence_number != sequence_number) {
|
|
|
|
|
// We did not found a match, search all.
|
2015-09-11 08:33:35 -07:00
|
|
|
for (uint16_t m = 0; m < stored_packets_.size(); m++) {
|
|
|
|
|
if (stored_packets_[m].sequence_number == sequence_number) {
|
2012-01-16 11:06:31 +00:00
|
|
|
*index = m;
|
2015-09-11 08:33:35 -07:00
|
|
|
temp_sequence_number = stored_packets_[*index].sequence_number;
|
2012-01-16 11:06:31 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-08-03 18:27:40 +02:00
|
|
|
return temp_sequence_number == sequence_number &&
|
|
|
|
|
stored_packets_[*index].packet;
|
2012-01-16 11:06:31 +00:00
|
|
|
}
|
2013-12-04 10:24:26 +00:00
|
|
|
|
2016-08-03 18:27:40 +02:00
|
|
|
int RtpPacketHistory::FindBestFittingPacket(size_t size) const {
|
2015-09-11 08:33:35 -07:00
|
|
|
if (size < kMinPacketRequestBytes || stored_packets_.empty())
|
2013-12-04 10:24:26 +00:00
|
|
|
return -1;
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
size_t min_diff = std::numeric_limits<size_t>::max();
|
|
|
|
|
int best_index = -1; // Returned unchanged if we don't find anything.
|
2015-09-11 08:33:35 -07:00
|
|
|
for (size_t i = 0; i < stored_packets_.size(); ++i) {
|
2016-08-03 18:27:40 +02:00
|
|
|
if (!stored_packets_[i].packet)
|
2013-12-04 10:24:26 +00:00
|
|
|
continue;
|
2016-08-03 18:27:40 +02:00
|
|
|
size_t stored_size = stored_packets_[i].packet->size();
|
|
|
|
|
size_t diff =
|
|
|
|
|
(stored_size > size) ? (stored_size - size) : (size - stored_size);
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
if (diff < min_diff) {
|
2013-12-04 10:24:26 +00:00
|
|
|
min_diff = diff;
|
Use size_t more consistently for packet/payload lengths.
See design doc at https://docs.google.com/a/chromium.org/document/d/1I6nmE9D_BmCY-IoV6MDPY2V6WYpEI-dg2apWXTfZyUI/edit?usp=sharing for more information.
This CL was reviewed and approved in pieces in the following CLs:
https://webrtc-codereview.appspot.com/24209004/
https://webrtc-codereview.appspot.com/24229004/
https://webrtc-codereview.appspot.com/24259004/
https://webrtc-codereview.appspot.com/25109004/
https://webrtc-codereview.appspot.com/26099004/
https://webrtc-codereview.appspot.com/27069004/
https://webrtc-codereview.appspot.com/27969004/
https://webrtc-codereview.appspot.com/27989004/
https://webrtc-codereview.appspot.com/29009004/
https://webrtc-codereview.appspot.com/30929004/
https://webrtc-codereview.appspot.com/30939004/
https://webrtc-codereview.appspot.com/31999004/
Committing as TBR to the original reviewers.
BUG=chromium:81439
TEST=none
TBR=pthatcher,henrik.lundin,tina.legrand,stefan,tkchin,glaznev,kjellander,perkj,mflodman,henrika,asapersson,niklas.enbom
Review URL: https://webrtc-codereview.appspot.com/23129004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7726 4adac7df-926f-26a2-2b94-8c16560cd09d
2014-11-20 22:28:14 +00:00
|
|
|
best_index = static_cast<int>(i);
|
2013-12-04 10:24:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return best_index;
|
|
|
|
|
}
|
2015-09-11 08:33:35 -07:00
|
|
|
|
2012-01-16 11:06:31 +00:00
|
|
|
} // namespace webrtc
|