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