LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/rtp_rtcp/source - rtp_packet_history.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 121 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h"
      12             : 
      13             : #include <algorithm>
      14             : #include <limits>
      15             : 
      16             : #include "webrtc/base/checks.h"
      17             : #include "webrtc/base/logging.h"
      18             : #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
      19             : #include "webrtc/system_wrappers/include/clock.h"
      20             : 
      21             : namespace webrtc {
      22             : namespace {
      23             : constexpr size_t kMinPacketRequestBytes = 50;
      24             : }  // namespace
      25             : constexpr size_t RtpPacketHistory::kMaxCapacity;
      26             : 
      27           0 : RtpPacketHistory::RtpPacketHistory(Clock* clock)
      28           0 :     : clock_(clock), store_(false), prev_index_(0) {}
      29             : 
      30           0 : RtpPacketHistory::~RtpPacketHistory() {}
      31             : 
      32           0 : void RtpPacketHistory::SetStorePacketsStatus(bool enable,
      33             :                                              uint16_t number_to_store) {
      34           0 :   rtc::CritScope cs(&critsect_);
      35           0 :   if (enable) {
      36           0 :     if (store_) {
      37           0 :       LOG(LS_WARNING) << "Purging packet history in order to re-set status.";
      38           0 :       Free();
      39             :     }
      40           0 :     RTC_DCHECK(!store_);
      41           0 :     Allocate(number_to_store);
      42             :   } else {
      43           0 :     Free();
      44             :   }
      45           0 : }
      46             : 
      47           0 : void RtpPacketHistory::Allocate(size_t number_to_store) {
      48           0 :   RTC_DCHECK_GT(number_to_store, 0);
      49           0 :   RTC_DCHECK_LE(number_to_store, kMaxCapacity);
      50           0 :   store_ = true;
      51           0 :   stored_packets_.resize(number_to_store);
      52           0 : }
      53             : 
      54           0 : void RtpPacketHistory::Free() {
      55           0 :   if (!store_) {
      56           0 :     return;
      57             :   }
      58             : 
      59           0 :   stored_packets_.clear();
      60             : 
      61           0 :   store_ = false;
      62           0 :   prev_index_ = 0;
      63             : }
      64             : 
      65           0 : bool RtpPacketHistory::StorePackets() const {
      66           0 :   rtc::CritScope cs(&critsect_);
      67           0 :   return store_;
      68             : }
      69             : 
      70           0 : void RtpPacketHistory::PutRtpPacket(std::unique_ptr<RtpPacketToSend> packet,
      71             :                                     StorageType type,
      72             :                                     bool sent) {
      73           0 :   RTC_DCHECK(packet);
      74           0 :   rtc::CritScope cs(&critsect_);
      75           0 :   if (!store_) {
      76           0 :     return;
      77             :   }
      78             : 
      79             :   // If index we're about to overwrite contains a packet that has not
      80             :   // yet been sent (probably pending in paced sender), we need to expand
      81             :   // the buffer.
      82           0 :   if (stored_packets_[prev_index_].packet &&
      83           0 :       stored_packets_[prev_index_].send_time == 0) {
      84           0 :     size_t current_size = static_cast<uint16_t>(stored_packets_.size());
      85           0 :     if (current_size < kMaxCapacity) {
      86           0 :       size_t expanded_size = std::max(current_size * 3 / 2, current_size + 1);
      87           0 :       expanded_size = std::min(expanded_size, kMaxCapacity);
      88           0 :       Allocate(expanded_size);
      89             :       // Causes discontinuity, but that's OK-ish. FindSeqNum() will still work,
      90             :       // but may be slower - at least until buffer has wrapped around once.
      91           0 :       prev_index_ = current_size;
      92             :     }
      93             :   }
      94             : 
      95             :   // Store packet.
      96           0 :   if (packet->capture_time_ms() <= 0)
      97           0 :     packet->set_capture_time_ms(clock_->TimeInMilliseconds());
      98           0 :   stored_packets_[prev_index_].sequence_number = packet->SequenceNumber();
      99           0 :   stored_packets_[prev_index_].send_time =
     100           0 :       (sent ? clock_->TimeInMilliseconds() : 0);
     101           0 :   stored_packets_[prev_index_].storage_type = type;
     102           0 :   stored_packets_[prev_index_].has_been_retransmitted = false;
     103           0 :   stored_packets_[prev_index_].packet = std::move(packet);
     104             : 
     105           0 :   ++prev_index_;
     106           0 :   if (prev_index_ >= stored_packets_.size()) {
     107           0 :     prev_index_ = 0;
     108             :   }
     109             : }
     110             : 
     111           0 : bool RtpPacketHistory::HasRtpPacket(uint16_t sequence_number) const {
     112           0 :   rtc::CritScope cs(&critsect_);
     113           0 :   if (!store_) {
     114           0 :     return false;
     115             :   }
     116             : 
     117           0 :   int unused_index = 0;
     118           0 :   return FindSeqNum(sequence_number, &unused_index);
     119             : }
     120             : 
     121           0 : std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetPacketAndSetSendTime(
     122             :     uint16_t sequence_number,
     123             :     int64_t min_elapsed_time_ms,
     124             :     bool retransmit) {
     125           0 :   rtc::CritScope cs(&critsect_);
     126           0 :   if (!store_) {
     127           0 :     return nullptr;
     128             :   }
     129             : 
     130           0 :   int index = 0;
     131           0 :   if (!FindSeqNum(sequence_number, &index)) {
     132           0 :     LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number;
     133           0 :     return nullptr;
     134             :   }
     135           0 :   RTC_DCHECK_EQ(sequence_number,
     136           0 :                 stored_packets_[index].packet->SequenceNumber());
     137             : 
     138             :   // Verify elapsed time since last retrieve, but only for retransmissions and
     139             :   // always send packet upon first retransmission request.
     140           0 :   int64_t now = clock_->TimeInMilliseconds();
     141           0 :   if (min_elapsed_time_ms > 0 && retransmit &&
     142           0 :       stored_packets_[index].has_been_retransmitted &&
     143           0 :       ((now - stored_packets_[index].send_time) < min_elapsed_time_ms)) {
     144           0 :     return nullptr;
     145             :   }
     146             : 
     147           0 :   if (retransmit) {
     148           0 :     if (stored_packets_[index].storage_type == kDontRetransmit) {
     149             :       // No bytes copied since this packet shouldn't be retransmitted.
     150           0 :       return nullptr;
     151             :     }
     152           0 :     stored_packets_[index].has_been_retransmitted = true;
     153             :   }
     154           0 :   stored_packets_[index].send_time = clock_->TimeInMilliseconds();
     155           0 :   return GetPacket(index);
     156             : }
     157             : 
     158           0 : std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetPacket(int index) const {
     159           0 :   const RtpPacketToSend& stored = *stored_packets_[index].packet;
     160           0 :   return std::unique_ptr<RtpPacketToSend>(new RtpPacketToSend(stored));
     161             : }
     162             : 
     163           0 : std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetBestFittingPacket(
     164             :     size_t packet_length) const {
     165           0 :   rtc::CritScope cs(&critsect_);
     166           0 :   if (!store_)
     167           0 :     return nullptr;
     168           0 :   int index = FindBestFittingPacket(packet_length);
     169           0 :   if (index < 0)
     170           0 :     return nullptr;
     171           0 :   return GetPacket(index);
     172             : }
     173             : 
     174           0 : bool RtpPacketHistory::FindSeqNum(uint16_t sequence_number, int* index) const {
     175           0 :   if (prev_index_ > 0) {
     176           0 :     *index = prev_index_ - 1;
     177             :   } else {
     178           0 :     *index = stored_packets_.size() - 1;  // Wrap.
     179             :   }
     180           0 :   uint16_t temp_sequence_number = stored_packets_[*index].sequence_number;
     181             : 
     182           0 :   int idx = *index - (temp_sequence_number - sequence_number);
     183           0 :   if (idx >= 0 && idx < static_cast<int>(stored_packets_.size())) {
     184           0 :     *index = idx;
     185           0 :     temp_sequence_number = stored_packets_[*index].sequence_number;
     186             :   }
     187             : 
     188           0 :   if (temp_sequence_number != sequence_number) {
     189             :     // We did not found a match, search all.
     190           0 :     for (uint16_t m = 0; m < stored_packets_.size(); m++) {
     191           0 :       if (stored_packets_[m].sequence_number == sequence_number) {
     192           0 :         *index = m;
     193           0 :         temp_sequence_number = stored_packets_[*index].sequence_number;
     194           0 :         break;
     195             :       }
     196             :     }
     197             :   }
     198           0 :   return temp_sequence_number == sequence_number &&
     199           0 :          stored_packets_[*index].packet;
     200             : }
     201             : 
     202           0 : int RtpPacketHistory::FindBestFittingPacket(size_t size) const {
     203           0 :   if (size < kMinPacketRequestBytes || stored_packets_.empty())
     204           0 :     return -1;
     205           0 :   size_t min_diff = std::numeric_limits<size_t>::max();
     206           0 :   int best_index = -1;  // Returned unchanged if we don't find anything.
     207           0 :   for (size_t i = 0; i < stored_packets_.size(); ++i) {
     208           0 :     if (!stored_packets_[i].packet)
     209           0 :       continue;
     210           0 :     size_t stored_size = stored_packets_[i].packet->size();
     211             :     size_t diff =
     212           0 :         (stored_size > size) ? (stored_size - size) : (size - stored_size);
     213           0 :     if (diff < min_diff) {
     214           0 :       min_diff = diff;
     215           0 :       best_index = static_cast<int>(i);
     216             :     }
     217             :   }
     218           0 :   return best_index;
     219             : }
     220             : 
     221             : }  // namespace webrtc

Generated by: LCOV version 1.13