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.
5 #include "media/cast/transport/rtp_sender/packet_storage/packet_storage.h"
9 #include "base/logging.h"
15 // Limit the max time delay to avoid frame id wrap around; 256 / 60 fps.
16 const int kMaxAllowedTimeStoredMs = 4000;
18 typedef PacketMap::iterator PacketMapIterator;
19 typedef TimeToPacketMap::iterator TimeToPacketIterator;
23 StoredPacket() { packet_.reserve(kMaxIpPacketSize); }
25 void Save(const Packet* packet) {
26 DCHECK_LT(packet->size(), kMaxIpPacketSize) << "Invalid argument";
28 packet_.insert(packet_.begin(), packet->begin(), packet->end());
31 void GetCopy(PacketList* packets) {
32 packets->push_back(Packet(packet_.begin(), packet_.end()));
38 DISALLOW_COPY_AND_ASSIGN(StoredPacket);
41 PacketStorage::PacketStorage(base::TickClock* clock, int max_time_stored_ms)
43 max_time_stored_ = base::TimeDelta::FromMilliseconds(max_time_stored_ms);
44 DCHECK_LE(max_time_stored_ms, kMaxAllowedTimeStoredMs) << "Invalid argument";
47 PacketStorage::~PacketStorage() {
48 time_to_packet_map_.clear();
50 PacketMapIterator store_it = stored_packets_.begin();
51 for (; store_it != stored_packets_.end();
52 store_it = stored_packets_.begin()) {
53 stored_packets_.erase(store_it);
55 while (!free_packets_.empty()) {
56 free_packets_.pop_front();
60 void PacketStorage::CleanupOldPackets(base::TimeTicks now) {
61 TimeToPacketIterator time_it = time_to_packet_map_.begin();
64 while (time_to_packet_map_.size() >= kMaxStoredPackets) {
65 PacketMapIterator store_it = stored_packets_.find(time_it->second);
67 // We should always find the packet.
68 DCHECK(store_it != stored_packets_.end()) << "Invalid state";
69 time_to_packet_map_.erase(time_it);
71 linked_ptr<StoredPacket> storted_packet = store_it->second;
72 stored_packets_.erase(store_it);
73 // Add this packet to the free list for later re-use.
74 free_packets_.push_back(storted_packet);
75 time_it = time_to_packet_map_.begin();
78 // Time out old packets.
79 while (time_it != time_to_packet_map_.end()) {
80 if (now < time_it->first + max_time_stored_) {
84 PacketMapIterator store_it = stored_packets_.find(time_it->second);
86 // We should always find the packet.
87 DCHECK(store_it != stored_packets_.end()) << "Invalid state";
88 time_to_packet_map_.erase(time_it);
90 linked_ptr<StoredPacket> storted_packet = store_it->second;
91 stored_packets_.erase(store_it);
92 // Add this packet to the free list for later re-use.
93 free_packets_.push_back(storted_packet);
94 time_it = time_to_packet_map_.begin();
98 void PacketStorage::StorePacket(uint32 frame_id,
100 const Packet* packet) {
101 base::TimeTicks now = clock_->NowTicks();
102 CleanupOldPackets(now);
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";
112 linked_ptr<StoredPacket> stored_packet;
113 if (free_packets_.empty()) {
114 // No previous allocated packets allocate one.
115 stored_packet.reset(new StoredPacket());
117 // Re-use previous allocated packet.
118 stored_packet = free_packets_.front();
119 free_packets_.pop_front();
121 stored_packet->Save(packet);
122 stored_packets_[index] = stored_packet;
123 time_to_packet_map_.insert(std::make_pair(now, index));
126 PacketList PacketStorage::GetPackets(
127 const MissingFramesAndPacketsMap& missing_frames_and_packets) {
128 PacketList packets_to_resend;
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();
135 uint8 frame_id = it->first;
136 const PacketIdSet& packets_set = it->second;
137 bool success = false;
139 if (packets_set.empty()) {
140 VLOG(1) << "Missing all packets in frame " << static_cast<int>(frame_id);
141 uint16 packet_id = 0;
143 // Get packet from storage.
144 success = GetPacket(frame_id, packet_id, &packets_to_resend);
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();
152 GetPacket(frame_id, *set_it, &packets_to_resend);
156 return packets_to_resend;
159 bool PacketStorage::GetPacket(uint8 frame_id,
161 PacketList* packets) {
162 // Internally we only use the 8 LSB of the frame id.
163 uint32 index = (static_cast<uint32>(frame_id) << 16) + packet_id;
164 PacketMapIterator it = stored_packets_.find(index);
165 if (it == stored_packets_.end()) {
168 it->second->GetCopy(packets);
169 VLOG(1) << "Resend " << static_cast<int>(frame_id) << ":" << packet_id;
173 } // namespace transport