Home | History | Annotate | Download | only in packet_storage
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/cast/net/rtp_sender/packet_storage/packet_storage.h"
      6 
      7 #include <string>
      8 
      9 #include "base/logging.h"
     10 #include "media/cast/cast_defines.h"
     11 
     12 namespace media {
     13 namespace cast {
     14 
     15 // Limit the max time delay to avoid frame id wrap around; 256 / 60 fps.
     16 const int kMaxAllowedTimeStoredMs = 4000;
     17 
     18 typedef PacketMap::iterator PacketMapIterator;
     19 typedef TimeToPacketMap::iterator TimeToPacketIterator;
     20 
     21 class StoredPacket {
     22  public:
     23   StoredPacket() {
     24     packet_.reserve(kIpPacketSize);
     25   }
     26 
     27   void Save(const Packet* packet) {
     28     DCHECK_LT(packet->size(), kIpPacketSize) << "Invalid argument";
     29     packet_.clear();
     30     packet_.insert(packet_.begin(), packet->begin(), packet->end());
     31   }
     32 
     33   void GetCopy(PacketList* packets) {
     34     packets->push_back(Packet(packet_.begin(), packet_.end()));
     35   }
     36 
     37  private:
     38   Packet packet_;
     39 };
     40 
     41 PacketStorage::PacketStorage(base::TickClock* clock,
     42                              int max_time_stored_ms)
     43     : clock_(clock) {
     44   max_time_stored_ = base::TimeDelta::FromMilliseconds(max_time_stored_ms);
     45   DCHECK_LE(max_time_stored_ms, kMaxAllowedTimeStoredMs) << "Invalid argument";
     46 }
     47 
     48 PacketStorage::~PacketStorage() {
     49   time_to_packet_map_.clear();
     50 
     51   PacketMapIterator store_it = stored_packets_.begin();
     52   for (; store_it != stored_packets_.end();
     53       store_it = stored_packets_.begin()) {
     54     stored_packets_.erase(store_it);
     55   }
     56   while (!free_packets_.empty()) {
     57     free_packets_.pop_front();
     58   }
     59 }
     60 
     61 void PacketStorage::CleanupOldPackets(base::TimeTicks now) {
     62   TimeToPacketIterator time_it = time_to_packet_map_.begin();
     63 
     64   // Check max size.
     65   while (time_to_packet_map_.size() >= kMaxStoredPackets) {
     66     PacketMapIterator store_it = stored_packets_.find(time_it->second);
     67 
     68     // We should always find the packet.
     69     DCHECK(store_it != stored_packets_.end()) << "Invalid state";
     70     time_to_packet_map_.erase(time_it);
     71     // Save the pointer.
     72     linked_ptr<StoredPacket> storted_packet = store_it->second;
     73     stored_packets_.erase(store_it);
     74     // Add this packet to the free list for later re-use.
     75     free_packets_.push_back(storted_packet);
     76     time_it = time_to_packet_map_.begin();
     77   }
     78 
     79   // Time out old packets.
     80   while (time_it != time_to_packet_map_.end()) {
     81     if (now < time_it->first + max_time_stored_) {
     82       break;
     83     }
     84     // Packet too old.
     85     PacketMapIterator store_it = stored_packets_.find(time_it->second);
     86 
     87     // We should always find the packet.
     88     DCHECK(store_it != stored_packets_.end()) << "Invalid state";
     89     time_to_packet_map_.erase(time_it);
     90     // Save the pointer.
     91     linked_ptr<StoredPacket> storted_packet = store_it->second;
     92     stored_packets_.erase(store_it);
     93     // Add this packet to the free list for later re-use.
     94     free_packets_.push_back(storted_packet);
     95     time_it = time_to_packet_map_.begin();
     96   }
     97 }
     98 
     99 void PacketStorage::StorePacket(uint32 frame_id, uint16 packet_id,
    100                                 const Packet* packet) {
    101   base::TimeTicks now = clock_->NowTicks();
    102   CleanupOldPackets(now);
    103 
    104   // Internally we only use the 8 LSB of the frame id.
    105   uint32 index = ((0xff & frame_id) << 16) + packet_id;
    106   PacketMapIterator it = stored_packets_.find(index);
    107   if (it != stored_packets_.end()) {
    108     // We have already saved this.
    109     DCHECK(false) << "Invalid state";
    110     return;
    111   }
    112   linked_ptr<StoredPacket> stored_packet;
    113   if (free_packets_.empty()) {
    114     // No previous allocated packets allocate one.
    115     stored_packet.reset(new StoredPacket());
    116   } else {
    117     // Re-use previous allocated packet.
    118     stored_packet = free_packets_.front();
    119     free_packets_.pop_front();
    120   }
    121   stored_packet->Save(packet);
    122   stored_packets_[index] = stored_packet;
    123   time_to_packet_map_.insert(std::make_pair(now, index));
    124 }
    125 
    126 PacketList PacketStorage::GetPackets(
    127     const MissingFramesAndPacketsMap& missing_frames_and_packets) {
    128   PacketList packets_to_resend;
    129 
    130   // Iterate over all frames in the list.
    131   for (MissingFramesAndPacketsMap::const_iterator it =
    132        missing_frames_and_packets.begin();
    133        it != missing_frames_and_packets.end(); ++it) {
    134     uint8 frame_id = it->first;
    135     const PacketIdSet& packets_set = it->second;
    136     bool success = false;
    137 
    138     if (packets_set.empty()) {
    139       VLOG(1) << "Missing all packets in frame " << static_cast<int>(frame_id);
    140 
    141       uint16 packet_id = 0;
    142       do {
    143         // Get packet from storage.
    144         success = GetPacket(frame_id, packet_id, &packets_to_resend);
    145         ++packet_id;
    146       } while (success);
    147     } else {
    148       // Iterate over all of the packets in the frame.
    149       for (PacketIdSet::const_iterator set_it = packets_set.begin();
    150           set_it != packets_set.end(); ++set_it) {
    151         GetPacket(frame_id, *set_it, &packets_to_resend);
    152       }
    153     }
    154   }
    155   return packets_to_resend;
    156 }
    157 
    158 bool PacketStorage::GetPacket(uint8 frame_id,
    159                               uint16 packet_id,
    160                               PacketList* packets) {
    161   // Internally we only use the 8 LSB of the frame id.
    162   uint32 index = (static_cast<uint32>(frame_id) << 16) + packet_id;
    163   PacketMapIterator it = stored_packets_.find(index);
    164   if (it == stored_packets_.end()) {
    165     return false;
    166   }
    167   it->second->GetCopy(packets);
    168   VLOG(1) << "Resend " << static_cast<int>(frame_id)
    169           << ":" << packet_id;
    170   return true;
    171 }
    172 
    173 }  // namespace cast
    174 }  // namespace media
    175