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:
StoredPacket()23 StoredPacket() {
24 packet_.reserve(kIpPacketSize);
25 }
26
Save(const Packet * packet)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
GetCopy(PacketList * packets)33 void GetCopy(PacketList* packets) {
34 packets->push_back(Packet(packet_.begin(), packet_.end()));
35 }
36
37 private:
38 Packet packet_;
39 };
40
PacketStorage(base::TickClock * clock,int max_time_stored_ms)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
~PacketStorage()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
CleanupOldPackets(base::TimeTicks now)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
StorePacket(uint32 frame_id,uint16 packet_id,const Packet * packet)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
GetPackets(const MissingFramesAndPacketsMap & missing_frames_and_packets)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
GetPacket(uint8 frame_id,uint16 packet_id,PacketList * packets)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