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 typedef PacketMap::iterator PacketMapIterator;
17 PacketStorage::PacketStorage(int stored_frames)
18 : stored_frames_(stored_frames) {
21 PacketStorage::~PacketStorage() {
24 bool PacketStorage::IsValid() const {
25 return stored_frames_ > 0 && stored_frames_ <= kMaxStoredFrames;
28 void PacketStorage::CleanupOldPackets(uint32 current_frame_id) {
29 uint32 frame_to_remove = current_frame_id - stored_frames_;
30 while (!stored_packets_.empty()) {
31 if (IsOlderFrameId(stored_packets_.begin()->first.first,
33 stored_packets_.erase(stored_packets_.begin());
40 void PacketStorage::StorePacket(uint32 frame_id,
44 CleanupOldPackets(frame_id);
45 StorageIndex index(frame_id, packet_id);
46 PacketMapIterator it = stored_packets_.find(index);
47 if (it != stored_packets_.end()) {
48 // We have already saved this.
49 DCHECK(false) << "Invalid state";
52 stored_packets_[index] = std::make_pair(key, packet);
55 void PacketStorage::GetPackets(
56 const MissingFramesAndPacketsMap& missing_frames_and_packets,
57 SendPacketVector* packets_to_resend) {
59 // Iterate over all frames in the list.
60 for (MissingFramesAndPacketsMap::const_iterator it =
61 missing_frames_and_packets.begin();
62 it != missing_frames_and_packets.end();
64 uint8 frame_id = it->first;
65 const PacketIdSet& packets_set = it->second;
68 if (packets_set.empty()) {
69 VLOG(1) << "Missing all packets in frame " << static_cast<int>(frame_id);
72 // Get packet from storage.
73 success = GetPacket(frame_id, packet_id, packets_to_resend);
77 // Iterate over all of the packets in the frame.
78 for (PacketIdSet::const_iterator set_it = packets_set.begin();
79 set_it != packets_set.end();
81 GetPacket(frame_id, *set_it, packets_to_resend);
87 bool PacketStorage::GetPacket32(uint32 frame_id,
89 SendPacketVector* packets) {
90 StorageIndex index(frame_id, packet_id);
91 PacketMapIterator it = stored_packets_.find(index);
92 if (it == stored_packets_.end()) {
95 // Minor trickery, the caller (rtp_sender.cc) really wants a copy of the
96 // packet so that it can update the sequence number before it sends it to
97 // the transport. If the packet only has one ref, we can safely let
98 // rtp_sender.cc have our packet and modify it. If it has more references
99 // then we must return a copy of it instead. This should really only happen
100 // when rtp_sender.cc is trying to re-send a packet that is already in the
102 if (it->second.second->HasOneRef()) {
103 packets->push_back(it->second);
106 std::make_pair(it->second.first,
108 new base::RefCountedData<Packet>(
109 it->second.second->data))));
114 bool PacketStorage::GetPacket(uint8 frame_id_8bit,
116 SendPacketVector* packets) {
117 if (stored_packets_.empty()) {
120 uint32 last_stored = stored_packets_.rbegin()->first.first;
121 uint32 frame_id_32bit = (last_stored & ~0xFF) | frame_id_8bit;
122 if (IsNewerFrameId(frame_id_32bit, last_stored)) {
123 frame_id_32bit -= 0x100;
125 DCHECK_EQ(frame_id_8bit, frame_id_32bit & 0xff);
126 DCHECK(IsOlderFrameId(frame_id_32bit, last_stored) &&
127 IsNewerFrameId(frame_id_32bit + stored_frames_ + 1, last_stored))
128 << " 32bit: " << frame_id_32bit
129 << " 8bit: " << static_cast<int>(frame_id_8bit)
130 << " last_stored: " << last_stored;
131 return GetPacket32(frame_id_32bit, packet_id, packets);
134 } // namespace transport