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_receiver/rtp_receiver_defines.h"
9
10namespace media {
11namespace cast {
12
13FrameInfo::FrameInfo(uint32 frame_id,
14                     uint32 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
29FrameInfo::~FrameInfo() {}
30
31bool 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
40bool FrameInfo::Complete() const {
41  return missing_packets_.empty();
42}
43
44void 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
57FrameIdMap::FrameIdMap()
58    : waiting_for_key_(true),
59      last_released_frame_(kStartFrameId),
60      newest_frame_id_(kStartFrameId) {
61}
62
63FrameIdMap::~FrameIdMap() {}
64
65bool FrameIdMap::InsertPacket(const RtpCastHeader& rtp_header, bool* complete) {
66  uint32 frame_id = rtp_header.frame_id;
67  uint32 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<uint32>(frame_id - 1);
72  }
73
74  if (rtp_header.is_key_frame && waiting_for_key_) {
75    last_released_frame_ = static_cast<uint32>(frame_id - 1);
76    waiting_for_key_ = false;
77  }
78
79  VLOG(1) << "InsertPacket frame:" << frame_id
80          << " packet:" << static_cast<int>(rtp_header.packet_id)
81          << " max packet:" << static_cast<int>(rtp_header.max_packet_id);
82
83  if (IsOlderFrameId(frame_id, last_released_frame_) && !waiting_for_key_) {
84    return false;
85  }
86
87  // Update the last received frame id.
88  if (IsNewerFrameId(frame_id, newest_frame_id_)) {
89    newest_frame_id_ = frame_id;
90  }
91
92  // Does this packet belong to a new frame?
93  FrameMap::iterator it = frame_map_.find(frame_id);
94  if (it == frame_map_.end()) {
95    // New frame.
96    linked_ptr<FrameInfo> frame_info(new FrameInfo(frame_id,
97                                                   reference_frame_id,
98                                                   rtp_header.max_packet_id,
99                                                   rtp_header.is_key_frame));
100    std::pair<FrameMap::iterator, bool> retval =
101        frame_map_.insert(std::make_pair(frame_id, frame_info));
102
103    *complete = retval.first->second->InsertPacket(rtp_header.packet_id);
104  } else {
105    // Insert packet to existing frame.
106    *complete = it->second->InsertPacket(rtp_header.packet_id);
107  }
108  return true;
109}
110
111void FrameIdMap::RemoveOldFrames(uint32 frame_id) {
112  FrameMap::iterator it = frame_map_.begin();
113
114  while (it != frame_map_.end()) {
115    if (IsNewerFrameId(it->first, frame_id)) {
116      ++it;
117    } else {
118      // Older or equal; erase.
119      frame_map_.erase(it++);
120    }
121  }
122  last_released_frame_ = frame_id;
123}
124
125void FrameIdMap::Clear() {
126  frame_map_.clear();
127  waiting_for_key_ = true;
128  last_released_frame_ = kStartFrameId;
129  newest_frame_id_ = kStartFrameId;
130}
131
132uint32 FrameIdMap::NewestFrameId() const {
133  return newest_frame_id_;
134}
135
136bool FrameIdMap::NextContinuousFrame(uint32* frame_id) const {
137  FrameMap::const_iterator it;
138
139  for (it = frame_map_.begin(); it != frame_map_.end(); ++it) {
140    if (it->second->Complete() && ContinuousFrame(it->second.get())) {
141      *frame_id = it->first;
142      return true;
143    }
144  }
145  return false;
146}
147
148uint32 FrameIdMap::LastContinuousFrame() const {
149  uint32 last_continuous_frame_id = last_released_frame_;
150  uint32 next_expected_frame = last_released_frame_;
151
152  FrameMap::const_iterator it;
153
154  do {
155    next_expected_frame++;
156    it = frame_map_.find(next_expected_frame);
157    if (it == frame_map_.end()) break;
158    if (!it->second->Complete()) break;
159
160    // We found the next continuous frame.
161    last_continuous_frame_id = it->first;
162  } while (next_expected_frame != newest_frame_id_);
163  return last_continuous_frame_id;
164}
165
166bool FrameIdMap::NextAudioFrameAllowingMissingFrames(uint32* frame_id) const {
167  // First check if we have continuous frames.
168  if (NextContinuousFrame(frame_id)) return true;
169
170  // Find the oldest frame.
171  FrameMap::const_iterator it_best_match = frame_map_.end();
172  FrameMap::const_iterator it;
173
174  // Find first complete frame.
175  for (it = frame_map_.begin(); it != frame_map_.end(); ++it) {
176    if (it->second->Complete()) {
177      it_best_match = it;
178      break;
179    }
180  }
181  if (it_best_match == frame_map_.end()) return false;  // No complete frame.
182
183  ++it;
184  for (; it != frame_map_.end(); ++it) {
185    if (it->second->Complete() &&
186        IsOlderFrameId(it->first, it_best_match->first)) {
187      it_best_match = it;
188    }
189  }
190  *frame_id = it_best_match->first;
191  return true;
192}
193
194bool FrameIdMap::NextVideoFrameAllowingSkippingFrames(uint32* frame_id) const {
195  // Find the oldest decodable frame.
196  FrameMap::const_iterator it_best_match = frame_map_.end();
197  FrameMap::const_iterator it;
198  for (it = frame_map_.begin(); it != frame_map_.end(); ++it) {
199    if (it->second->Complete() && DecodableVideoFrame(it->second.get())) {
200      it_best_match = it;
201    }
202  }
203  if (it_best_match == frame_map_.end()) return false;
204
205  *frame_id = it_best_match->first;
206  return true;
207}
208
209bool FrameIdMap::Empty() const {
210  return frame_map_.empty();
211}
212
213int FrameIdMap::NumberOfCompleteFrames() const {
214  int count = 0;
215  FrameMap::const_iterator it;
216  for (it = frame_map_.begin(); it != frame_map_.end(); ++it) {
217    if (it->second->Complete()) {
218      ++count;
219    }
220  }
221  return count;
222}
223
224bool FrameIdMap::FrameExists(uint32 frame_id) const {
225  return frame_map_.end() != frame_map_.find(frame_id);
226}
227
228void FrameIdMap::GetMissingPackets(uint32 frame_id,
229                                   bool last_frame,
230                                   PacketIdSet* missing_packets) const {
231  FrameMap::const_iterator it = frame_map_.find(frame_id);
232  if (it == frame_map_.end()) return;
233
234  it->second->GetMissingPackets(last_frame, missing_packets);
235}
236
237bool FrameIdMap::ContinuousFrame(FrameInfo* frame) const {
238  DCHECK(frame);
239  if (waiting_for_key_ && !frame->is_key_frame()) return false;
240  return static_cast<uint32>(last_released_frame_ + 1) == frame->frame_id();
241}
242
243bool FrameIdMap::DecodableVideoFrame(FrameInfo* frame) const {
244  if (frame->is_key_frame()) return true;
245  if (waiting_for_key_ && !frame->is_key_frame()) return false;
246
247  // Current frame is not necessarily referencing the last frame.
248  // Do we have the reference frame?
249  if (IsOlderFrameId(frame->referenced_frame_id(), last_released_frame_)) {
250    return true;
251  }
252  return frame->referenced_frame_id() == last_released_frame_;
253}
254
255}  //  namespace cast
256}  //  namespace media
257