OLD | NEW |
---|---|
(Empty) | |
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/framer/frame_id_map.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "media/cast/rtp_common/rtp_defines.h" | |
9 | |
10 namespace media { | |
11 namespace cast { | |
12 | |
13 FrameInfo::FrameInfo(uint8 frame_id, | |
14 uint8 referenced_frame_id, | |
15 uint16 max_packet_id, | |
16 bool key_frame) | |
17 : is_key_frame_(key_frame), | |
18 frame_id_(frame_id), | |
19 referenced_frame_id_(referenced_frame_id), | |
20 max_received_packet_id_(0) { | |
21 if (max_packet_id > 0) { | |
22 // Create the set with all packets missing. | |
23 for (uint16 i = 0; i <= max_packet_id; i++) { | |
24 missing_packets_.insert(i); | |
25 } | |
26 } | |
27 } | |
28 | |
29 FrameInfo::~FrameInfo() {} | |
30 | |
31 bool FrameInfo::InsertPacket(uint16 packet_id) { | |
32 // Update the last received packet id. | |
33 if (IsNewerPacketId(packet_id, max_received_packet_id_)) { | |
34 max_received_packet_id_ = packet_id; | |
35 } | |
36 missing_packets_.erase(packet_id); | |
37 return missing_packets_.empty(); | |
38 } | |
39 | |
40 bool FrameInfo::Complete() const { | |
41 return missing_packets_.empty(); | |
42 } | |
43 | |
44 void FrameInfo::GetMissingPackets(bool newest_frame, | |
45 PacketIdSet* missing_packets) const { | |
46 if (newest_frame) { | |
47 // Missing packets capped by max_received_packet_id_. | |
48 PacketIdSet::const_iterator it_after_last_received = | |
49 missing_packets_.lower_bound(max_received_packet_id_); | |
50 missing_packets->insert(missing_packets_.begin(), it_after_last_received); | |
51 } else { | |
52 missing_packets->insert(missing_packets_.begin(), missing_packets_.end()); | |
53 } | |
54 } | |
55 | |
56 | |
57 FrameIdMap::FrameIdMap() | |
58 : waiting_for_key_(true), | |
59 last_released_frame_(kStartFrameId), | |
60 newest_frame_id_(kStartFrameId) { | |
61 } | |
62 | |
63 FrameIdMap::~FrameIdMap() {} | |
64 | |
65 bool FrameIdMap::InsertPacket(const RtpCastHeader& rtp_header, bool* complete) { | |
66 uint8 frame_id = rtp_header.frame_id; | |
67 uint8 reference_frame_id; | |
68 if (rtp_header.is_reference) { | |
69 reference_frame_id = rtp_header.reference_frame_id; | |
70 } else { | |
71 reference_frame_id = static_cast<uint8>(frame_id - 1); | |
72 } | |
73 | |
74 if (rtp_header.is_key_frame && waiting_for_key_) { | |
75 last_released_frame_ = static_cast<uint8>(frame_id - 1); | |
76 waiting_for_key_ = false; | |
77 } | |
78 | |
79 if (IsOlderFrameId(frame_id, last_released_frame_) && !waiting_for_key_) { | |
80 return false; | |
81 } | |
82 | |
83 // Update the last received frame id. | |
84 if (IsNewerFrameId(frame_id, newest_frame_id_)) { | |
85 newest_frame_id_ = frame_id; | |
86 } | |
87 | |
88 // Does this packet belong to a new frame? | |
89 FrameMap::iterator it = frame_map_.find(frame_id); | |
90 if (it == frame_map_.end()) { | |
91 // New frame. | |
92 FrameInfo* frame_info = new FrameInfo(frame_id, | |
Alpha Left Google
2013/08/28 19:13:48
Should be linked_ptr<FrameInfo> frame_info = ...
pwestin
2013/08/28 20:37:21
Done.
| |
93 reference_frame_id, | |
94 rtp_header.max_packet_id, | |
95 rtp_header.is_key_frame); | |
96 std::pair<FrameMap::iterator, bool> retval = | |
97 frame_map_.insert(std::make_pair(frame_id, frame_info)); | |
98 | |
99 *complete = retval.first->second->InsertPacket(rtp_header.packet_id); | |
100 } else { | |
101 // Insert packet to existing frame. | |
102 *complete = it->second->InsertPacket(rtp_header.packet_id); | |
103 } | |
104 return true; | |
105 } | |
106 | |
107 void FrameIdMap::RemoveOldFrames(uint8 frame_id) { | |
108 FrameMap::iterator it = frame_map_.begin(); | |
109 | |
110 while (it != frame_map_.end()) { | |
111 if (IsNewerFrameId(it->first, frame_id)) { | |
112 ++it; | |
113 } else { | |
114 // Older or equal; erase. | |
115 frame_map_.erase(it++); | |
116 } | |
117 } | |
118 last_released_frame_ = frame_id; | |
119 } | |
120 | |
121 void FrameIdMap::Clear() { | |
122 frame_map_.clear(); | |
123 waiting_for_key_ = true; | |
124 last_released_frame_ = kStartFrameId; | |
125 newest_frame_id_ = kStartFrameId; | |
126 } | |
127 | |
128 uint8 FrameIdMap::NewestFrameId() const { | |
129 return newest_frame_id_; | |
130 } | |
131 | |
132 bool FrameIdMap::NextContinuousFrame(uint8* frame_id) const { | |
133 FrameMap::const_iterator it; | |
134 | |
135 for (it = frame_map_.begin(); it != frame_map_.end(); ++it) { | |
136 if (it->second->Complete() && ContinuousFrame(it->second.get())) { | |
137 *frame_id = it->first; | |
138 return true; | |
139 } | |
140 } | |
141 return false; | |
142 } | |
143 | |
144 uint8 FrameIdMap::LastContinuousFrame() const { | |
145 uint8 last_continuous_frame_id = last_released_frame_; | |
146 uint8 next_expected_frame = last_released_frame_; | |
147 | |
148 FrameMap::const_iterator it; | |
149 | |
150 do { | |
151 next_expected_frame++; | |
152 it = frame_map_.find(next_expected_frame); | |
153 if (it == frame_map_.end()) break; | |
154 if (!it->second->Complete()) break; | |
155 | |
156 // We found the next continuous frame. | |
157 last_continuous_frame_id = it->first; | |
158 } while (next_expected_frame != newest_frame_id_); | |
159 return last_continuous_frame_id; | |
160 } | |
161 | |
162 bool FrameIdMap::NextAudioFrameAllowingMissingFrames(uint8* frame_id) const { | |
163 // First check if we have continuous frames. | |
164 if (NextContinuousFrame(frame_id)) return true; | |
165 | |
166 // Find the oldest frame. | |
167 FrameMap::const_iterator it_best_match = frame_map_.end(); | |
168 FrameMap::const_iterator it; | |
169 | |
170 // Find first complete frame. | |
171 for (it = frame_map_.begin(); it != frame_map_.end(); ++it) { | |
172 if (it->second->Complete()) { | |
173 it_best_match = it; | |
174 break; | |
175 } | |
176 } | |
177 if (it_best_match == frame_map_.end()) return false; // No complete frame. | |
178 | |
179 ++it; | |
180 for (; it != frame_map_.end(); ++it) { | |
181 if (it->second->Complete() && | |
182 IsOlderFrameId(it->first, it_best_match->first)) { | |
183 it_best_match = it; | |
184 } | |
185 } | |
186 *frame_id = it_best_match->first; | |
187 return true; | |
188 } | |
189 | |
190 bool FrameIdMap::NextVideoFrameAllowingSkippingFrames(uint8* frame_id) const { | |
191 // Find the oldest decodable frame. | |
192 FrameMap::const_iterator it_best_match = frame_map_.end(); | |
193 FrameMap::const_iterator it; | |
194 for (it = frame_map_.begin(); it != frame_map_.end(); ++it) { | |
195 if (it->second->Complete() && DecodableVideoFrame(it->second.get())) { | |
196 it_best_match = it; | |
197 } | |
198 } | |
199 if (it_best_match == frame_map_.end()) return false; | |
200 | |
201 *frame_id = it_best_match->first; | |
202 return true; | |
203 } | |
204 | |
205 bool FrameIdMap::Empty() const { | |
206 return frame_map_.empty(); | |
207 } | |
208 | |
209 int FrameIdMap::NumberOfCompleteFrames() const { | |
210 int count = 0; | |
211 FrameMap::const_iterator it; | |
212 for (it = frame_map_.begin(); it != frame_map_.end(); ++it) { | |
213 if (it->second->Complete()) { | |
214 ++count; | |
215 } | |
216 } | |
217 return count; | |
218 } | |
219 | |
220 bool FrameIdMap::FrameExists(uint8 frame_id) const { | |
221 return frame_map_.end() != frame_map_.find(frame_id); | |
222 } | |
223 | |
224 void FrameIdMap::GetMissingPackets(uint8 frame_id, | |
225 bool last_frame, | |
226 PacketIdSet* missing_packets) const { | |
227 FrameMap::const_iterator it = frame_map_.find(frame_id); | |
228 if (it == frame_map_.end()) return; | |
229 | |
230 it->second->GetMissingPackets(last_frame, missing_packets); | |
231 } | |
232 | |
233 bool FrameIdMap::ContinuousFrame(FrameInfo* frame) const { | |
234 DCHECK(frame); | |
235 if (waiting_for_key_ && !frame->is_key_frame()) return false; | |
236 return static_cast<uint8>(last_released_frame_ + 1) == frame->frame_id(); | |
237 } | |
238 | |
239 bool FrameIdMap::DecodableVideoFrame(FrameInfo* frame) const { | |
240 if (frame->is_key_frame()) return true; | |
241 if (waiting_for_key_ && !frame->is_key_frame()) return false; | |
242 | |
243 // Current frame is not necessarily referencing the last frame. | |
244 // Do we have the reference frame? | |
245 if (IsOlderFrameId(frame->referenced_frame_id(), last_released_frame_)) { | |
246 return true; | |
247 } | |
248 return frame->referenced_frame_id() == last_released_frame_; | |
249 } | |
250 | |
251 } // namespace cast | |
252 } // namespace media | |
OLD | NEW |