Upstream version 7.36.149.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 typedef PacketMap::iterator PacketMapIterator;
16
17 PacketStorage::PacketStorage(int stored_frames)
18     : stored_frames_(stored_frames) {
19 }
20
21 PacketStorage::~PacketStorage() {
22 }
23
24 bool PacketStorage::IsValid() const {
25   return stored_frames_ > 0 && stored_frames_ <= kMaxStoredFrames;
26 }
27
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,
32                        frame_to_remove)) {
33       stored_packets_.erase(stored_packets_.begin());
34     } else {
35       break;
36     }
37   }
38 }
39
40 void PacketStorage::StorePacket(uint32 frame_id,
41                                 uint16 packet_id,
42                                 const PacketKey& key,
43                                 PacketRef packet) {
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";
50     return;
51   }
52   stored_packets_[index] = std::make_pair(key, packet);
53 }
54
55 void PacketStorage::GetPackets(
56     const MissingFramesAndPacketsMap& missing_frames_and_packets,
57     SendPacketVector* packets_to_resend) {
58
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();
63        ++it) {
64     uint8 frame_id = it->first;
65     const PacketIdSet& packets_set = it->second;
66     bool success = false;
67
68     if (packets_set.empty()) {
69       VLOG(1) << "Missing all packets in frame " << static_cast<int>(frame_id);
70       uint16 packet_id = 0;
71       do {
72         // Get packet from storage.
73         success = GetPacket(frame_id, packet_id, packets_to_resend);
74         ++packet_id;
75       } while (success);
76     } else {
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();
80            ++set_it) {
81         GetPacket(frame_id, *set_it, packets_to_resend);
82       }
83     }
84   }
85 }
86
87 bool PacketStorage::GetPacket32(uint32 frame_id,
88                                 uint16 packet_id,
89                                 SendPacketVector* packets) {
90   StorageIndex index(frame_id, packet_id);
91   PacketMapIterator it = stored_packets_.find(index);
92   if (it == stored_packets_.end()) {
93     return false;
94   }
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
101   // queue to sent.
102   if (it->second.second->HasOneRef()) {
103     packets->push_back(it->second);
104   } else {
105     packets->push_back(
106         std::make_pair(it->second.first,
107                        make_scoped_refptr(
108                            new base::RefCountedData<Packet>(
109                                it->second.second->data))));
110   }
111   return true;
112 }
113
114 bool PacketStorage::GetPacket(uint8 frame_id_8bit,
115                               uint16 packet_id,
116                               SendPacketVector* packets) {
117   if (stored_packets_.empty()) {
118     return false;
119   }
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;
124   }
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);
132 }
133
134 }  // namespace transport
135 }  // namespace cast
136 }  // namespace media