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

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2016 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/video_coding/packet_buffer.h"
      12             : 
      13             : #include <algorithm>
      14             : #include <limits>
      15             : #include <utility>
      16             : 
      17             : #include "webrtc/base/atomicops.h"
      18             : #include "webrtc/base/checks.h"
      19             : #include "webrtc/base/logging.h"
      20             : #include "webrtc/modules/video_coding/frame_object.h"
      21             : #include "webrtc/system_wrappers/include/clock.h"
      22             : 
      23             : namespace webrtc {
      24             : namespace video_coding {
      25             : 
      26           0 : rtc::scoped_refptr<PacketBuffer> PacketBuffer::Create(
      27             :     Clock* clock,
      28             :     size_t start_buffer_size,
      29             :     size_t max_buffer_size,
      30             :     OnReceivedFrameCallback* received_frame_callback) {
      31             :   return rtc::scoped_refptr<PacketBuffer>(new PacketBuffer(
      32           0 :       clock, start_buffer_size, max_buffer_size, received_frame_callback));
      33             : }
      34             : 
      35           0 : PacketBuffer::PacketBuffer(Clock* clock,
      36             :                            size_t start_buffer_size,
      37             :                            size_t max_buffer_size,
      38           0 :                            OnReceivedFrameCallback* received_frame_callback)
      39             :     : clock_(clock),
      40             :       size_(start_buffer_size),
      41             :       max_size_(max_buffer_size),
      42             :       first_seq_num_(0),
      43             :       first_packet_received_(false),
      44             :       is_cleared_to_first_seq_num_(false),
      45             :       data_buffer_(start_buffer_size),
      46             :       sequence_buffer_(start_buffer_size),
      47           0 :       received_frame_callback_(received_frame_callback) {
      48           0 :   RTC_DCHECK_LE(start_buffer_size, max_buffer_size);
      49             :   // Buffer size must always be a power of 2.
      50           0 :   RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0);
      51           0 :   RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0);
      52           0 : }
      53             : 
      54           0 : PacketBuffer::~PacketBuffer() {
      55           0 :   Clear();
      56           0 : }
      57             : 
      58           0 : bool PacketBuffer::InsertPacket(VCMPacket* packet) {
      59           0 :   std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
      60             :   {
      61           0 :     rtc::CritScope lock(&crit_);
      62           0 :     uint16_t seq_num = packet->seqNum;
      63           0 :     size_t index = seq_num % size_;
      64             : 
      65           0 :     if (!first_packet_received_) {
      66           0 :       first_seq_num_ = seq_num;
      67           0 :       first_packet_received_ = true;
      68           0 :     } else if (AheadOf(first_seq_num_, seq_num)) {
      69             :       // If we have explicitly cleared past this packet then it's old,
      70             :       // don't insert it.
      71           0 :       if (is_cleared_to_first_seq_num_) {
      72           0 :         delete[] packet->dataPtr;
      73           0 :         packet->dataPtr = nullptr;
      74           0 :         return false;
      75             :       }
      76             : 
      77           0 :       first_seq_num_ = seq_num;
      78             :     }
      79             : 
      80           0 :     if (sequence_buffer_[index].used) {
      81             :       // Duplicate packet, just delete the payload.
      82           0 :       if (data_buffer_[index].seqNum == packet->seqNum) {
      83           0 :         delete[] packet->dataPtr;
      84           0 :         packet->dataPtr = nullptr;
      85           0 :         return true;
      86             :       }
      87             : 
      88             :       // The packet buffer is full, try to expand the buffer.
      89           0 :       while (ExpandBufferSize() && sequence_buffer_[seq_num % size_].used) {
      90             :       }
      91           0 :       index = seq_num % size_;
      92             : 
      93             :       // Packet buffer is still full.
      94           0 :       if (sequence_buffer_[index].used) {
      95           0 :         delete[] packet->dataPtr;
      96           0 :         packet->dataPtr = nullptr;
      97           0 :         return false;
      98             :       }
      99             :     }
     100             : 
     101           0 :     sequence_buffer_[index].frame_begin = packet->is_first_packet_in_frame;
     102           0 :     sequence_buffer_[index].frame_end = packet->markerBit;
     103           0 :     sequence_buffer_[index].seq_num = packet->seqNum;
     104           0 :     sequence_buffer_[index].continuous = false;
     105           0 :     sequence_buffer_[index].frame_created = false;
     106           0 :     sequence_buffer_[index].used = true;
     107           0 :     data_buffer_[index] = *packet;
     108           0 :     packet->dataPtr = nullptr;
     109             : 
     110           0 :     found_frames = FindFrames(seq_num);
     111             :   }
     112             : 
     113           0 :   for (std::unique_ptr<RtpFrameObject>& frame : found_frames)
     114           0 :     received_frame_callback_->OnReceivedFrame(std::move(frame));
     115             : 
     116           0 :   return true;
     117             : }
     118             : 
     119           0 : void PacketBuffer::ClearTo(uint16_t seq_num) {
     120           0 :   rtc::CritScope lock(&crit_);
     121             : 
     122             :   // If the packet buffer was cleared between a frame was created and returned.
     123           0 :   if (!first_packet_received_)
     124           0 :     return;
     125             : 
     126           0 :   is_cleared_to_first_seq_num_ = true;
     127           0 :   while (AheadOrAt<uint16_t>(seq_num, first_seq_num_)) {
     128           0 :     size_t index = first_seq_num_ % size_;
     129           0 :     delete[] data_buffer_[index].dataPtr;
     130           0 :     data_buffer_[index].dataPtr = nullptr;
     131           0 :     sequence_buffer_[index].used = false;
     132           0 :     ++first_seq_num_;
     133             :   }
     134             : }
     135             : 
     136           0 : void PacketBuffer::Clear() {
     137           0 :   rtc::CritScope lock(&crit_);
     138           0 :   for (size_t i = 0; i < size_; ++i) {
     139           0 :     delete[] data_buffer_[i].dataPtr;
     140           0 :     data_buffer_[i].dataPtr = nullptr;
     141           0 :     sequence_buffer_[i].used = false;
     142             :   }
     143             : 
     144           0 :   first_packet_received_ = false;
     145           0 :   is_cleared_to_first_seq_num_ = false;
     146           0 : }
     147             : 
     148           0 : bool PacketBuffer::ExpandBufferSize() {
     149           0 :   if (size_ == max_size_) {
     150           0 :     LOG(LS_WARNING) << "PacketBuffer is already at max size (" << max_size_
     151           0 :                     << "), failed to increase size.";
     152           0 :     return false;
     153             :   }
     154             : 
     155           0 :   size_t new_size = std::min(max_size_, 2 * size_);
     156           0 :   std::vector<VCMPacket> new_data_buffer(new_size);
     157           0 :   std::vector<ContinuityInfo> new_sequence_buffer(new_size);
     158           0 :   for (size_t i = 0; i < size_; ++i) {
     159           0 :     if (sequence_buffer_[i].used) {
     160           0 :       size_t index = sequence_buffer_[i].seq_num % new_size;
     161           0 :       new_sequence_buffer[index] = sequence_buffer_[i];
     162           0 :       new_data_buffer[index] = data_buffer_[i];
     163             :     }
     164             :   }
     165           0 :   size_ = new_size;
     166           0 :   sequence_buffer_ = std::move(new_sequence_buffer);
     167           0 :   data_buffer_ = std::move(new_data_buffer);
     168           0 :   LOG(LS_INFO) << "PacketBuffer size expanded to " << new_size;
     169           0 :   return true;
     170             : }
     171             : 
     172           0 : bool PacketBuffer::PotentialNewFrame(uint16_t seq_num) const {
     173           0 :   size_t index = seq_num % size_;
     174           0 :   int prev_index = index > 0 ? index - 1 : size_ - 1;
     175             : 
     176           0 :   if (!sequence_buffer_[index].used)
     177           0 :     return false;
     178           0 :   if (sequence_buffer_[index].frame_created)
     179           0 :     return false;
     180           0 :   if (sequence_buffer_[index].frame_begin)
     181           0 :     return true;
     182           0 :   if (!sequence_buffer_[prev_index].used)
     183           0 :     return false;
     184           0 :   if (sequence_buffer_[prev_index].frame_created)
     185           0 :     return false;
     186           0 :   if (sequence_buffer_[prev_index].seq_num !=
     187           0 :       static_cast<uint16_t>(sequence_buffer_[index].seq_num - 1)) {
     188           0 :     return false;
     189             :   }
     190           0 :   if (sequence_buffer_[prev_index].continuous)
     191           0 :     return true;
     192             : 
     193           0 :   return false;
     194             : }
     195             : 
     196           0 : std::vector<std::unique_ptr<RtpFrameObject>> PacketBuffer::FindFrames(
     197             :     uint16_t seq_num) {
     198           0 :   std::vector<std::unique_ptr<RtpFrameObject>> found_frames;
     199           0 :   size_t packets_tested = 0;
     200           0 :   while (packets_tested < size_ && PotentialNewFrame(seq_num)) {
     201           0 :     size_t index = seq_num % size_;
     202           0 :     sequence_buffer_[index].continuous = true;
     203             : 
     204             :     // If all packets of the frame is continuous, find the first packet of the
     205             :     // frame and create an RtpFrameObject.
     206           0 :     if (sequence_buffer_[index].frame_end) {
     207           0 :       size_t frame_size = 0;
     208           0 :       int max_nack_count = -1;
     209           0 :       uint16_t start_seq_num = seq_num;
     210             : 
     211             :       // Find the start index by searching backward until the packet with
     212             :       // the |frame_begin| flag is set.
     213           0 :       int start_index = index;
     214             :       while (true) {
     215           0 :         frame_size += data_buffer_[start_index].sizeBytes;
     216           0 :         max_nack_count =
     217           0 :             std::max(max_nack_count, data_buffer_[start_index].timesNacked);
     218           0 :         sequence_buffer_[start_index].frame_created = true;
     219             : 
     220           0 :         if (sequence_buffer_[start_index].frame_begin)
     221           0 :           break;
     222             : 
     223           0 :         start_index = start_index > 0 ? start_index - 1 : size_ - 1;
     224           0 :         start_seq_num--;
     225             :       }
     226             : 
     227             :       found_frames.emplace_back(
     228           0 :           new RtpFrameObject(this, start_seq_num, seq_num, frame_size,
     229           0 :                              max_nack_count, clock_->TimeInMilliseconds()));
     230             :     }
     231           0 :     ++seq_num;
     232           0 :     ++packets_tested;
     233             :   }
     234           0 :   return found_frames;
     235             : }
     236             : 
     237           0 : void PacketBuffer::ReturnFrame(RtpFrameObject* frame) {
     238           0 :   rtc::CritScope lock(&crit_);
     239           0 :   size_t index = frame->first_seq_num() % size_;
     240           0 :   size_t end = (frame->last_seq_num() + 1) % size_;
     241           0 :   uint16_t seq_num = frame->first_seq_num();
     242           0 :   while (index != end) {
     243           0 :     if (sequence_buffer_[index].seq_num == seq_num) {
     244           0 :       delete[] data_buffer_[index].dataPtr;
     245           0 :       data_buffer_[index].dataPtr = nullptr;
     246           0 :       sequence_buffer_[index].used = false;
     247             :     }
     248             : 
     249           0 :     index = (index + 1) % size_;
     250           0 :     ++seq_num;
     251             :   }
     252           0 : }
     253             : 
     254           0 : bool PacketBuffer::GetBitstream(const RtpFrameObject& frame,
     255             :                                 uint8_t* destination) {
     256           0 :   rtc::CritScope lock(&crit_);
     257             : 
     258           0 :   size_t index = frame.first_seq_num() % size_;
     259           0 :   size_t end = (frame.last_seq_num() + 1) % size_;
     260           0 :   uint16_t seq_num = frame.first_seq_num();
     261           0 :   while (index != end) {
     262           0 :     if (!sequence_buffer_[index].used ||
     263           0 :         sequence_buffer_[index].seq_num != seq_num) {
     264           0 :       return false;
     265             :     }
     266             : 
     267           0 :     const uint8_t* source = data_buffer_[index].dataPtr;
     268           0 :     size_t length = data_buffer_[index].sizeBytes;
     269           0 :     memcpy(destination, source, length);
     270           0 :     destination += length;
     271           0 :     index = (index + 1) % size_;
     272           0 :     ++seq_num;
     273             :   }
     274           0 :   return true;
     275             : }
     276             : 
     277           0 : VCMPacket* PacketBuffer::GetPacket(uint16_t seq_num) {
     278           0 :   size_t index = seq_num % size_;
     279           0 :   if (!sequence_buffer_[index].used ||
     280           0 :       seq_num != sequence_buffer_[index].seq_num) {
     281           0 :     return nullptr;
     282             :   }
     283           0 :   return &data_buffer_[index];
     284             : }
     285             : 
     286           0 : int PacketBuffer::AddRef() const {
     287           0 :   return rtc::AtomicOps::Increment(&ref_count_);
     288             : }
     289             : 
     290           0 : int PacketBuffer::Release() const {
     291           0 :   int count = rtc::AtomicOps::Decrement(&ref_count_);
     292           0 :   if (!count) {
     293           0 :     delete this;
     294             :   }
     295           0 :   return count;
     296             : }
     297             : 
     298             : }  // namespace video_coding
     299             : }  // namespace webrtc

Generated by: LCOV version 1.13