Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / media / cast / transport / rtp_sender / packet_storage / packet_storage.cc
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/transport/rtp_sender/packet_storage/packet_storage.h"
6
7 #include <string>
8
9 #include "base/logging.h"
10
11 namespace media {
12 namespace cast {
13 namespace transport {
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() { packet_.reserve(kMaxIpPacketSize); }
24
25   void Save(const Packet* packet) {
26     DCHECK_LT(packet->size(), kMaxIpPacketSize) << "Invalid argument";
27     packet_.clear();
28     packet_.insert(packet_.begin(), packet->begin(), packet->end());
29   }
30
31   void GetCopy(PacketList* packets) {
32     packets->push_back(Packet(packet_.begin(), packet_.end()));
33   }
34
35  private:
36   Packet packet_;
37
38   DISALLOW_COPY_AND_ASSIGN(StoredPacket);
39 };
40
41 PacketStorage::PacketStorage(base::TickClock* clock, int max_time_stored_ms)
42     : clock_(clock) {
43   max_time_stored_ = base::TimeDelta::FromMilliseconds(max_time_stored_ms);
44   DCHECK_LE(max_time_stored_ms, kMaxAllowedTimeStoredMs) << "Invalid argument";
45 }
46
47 PacketStorage::~PacketStorage() {
48   time_to_packet_map_.clear();
49
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);
54   }
55   while (!free_packets_.empty()) {
56     free_packets_.pop_front();
57   }
58 }
59
60 void PacketStorage::CleanupOldPackets(base::TimeTicks now) {
61   TimeToPacketIterator time_it = time_to_packet_map_.begin();
62
63   // Check max size.
64   while (time_to_packet_map_.size() >= kMaxStoredPackets) {
65     PacketMapIterator store_it = stored_packets_.find(time_it->second);
66
67     // We should always find the packet.
68     DCHECK(store_it != stored_packets_.end()) << "Invalid state";
69     time_to_packet_map_.erase(time_it);
70     // Save the pointer.
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();
76   }
77
78   // Time out old packets.
79   while (time_it != time_to_packet_map_.end()) {
80     if (now < time_it->first + max_time_stored_) {
81       break;
82     }
83     // Packet too old.
84     PacketMapIterator store_it = stored_packets_.find(time_it->second);
85
86     // We should always find the packet.
87     DCHECK(store_it != stored_packets_.end()) << "Invalid state";
88     time_to_packet_map_.erase(time_it);
89     // Save the pointer.
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();
95   }
96 }
97
98 void PacketStorage::StorePacket(uint32 frame_id,
99                                 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();
134        ++it) {
135     uint8 frame_id = it->first;
136     const PacketIdSet& packets_set = it->second;
137     bool success = false;
138
139     if (packets_set.empty()) {
140       VLOG(1) << "Missing all packets in frame " << static_cast<int>(frame_id);
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();
151            ++set_it) {
152         GetPacket(frame_id, *set_it, &packets_to_resend);
153       }
154     }
155   }
156   return packets_to_resend;
157 }
158
159 bool PacketStorage::GetPacket(uint8 frame_id,
160                               uint16 packet_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()) {
166     return false;
167   }
168   it->second->GetCopy(packets);
169   VLOG(1) << "Resend " << static_cast<int>(frame_id) << ":" << packet_id;
170   return true;
171 }
172
173 }  // namespace transport
174 }  // namespace cast
175 }  // namespace media