cast_message_builder.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/cast_message_builder.h" 6 7#include "media/cast/cast_defines.h" 8 9namespace media { 10namespace cast { 11 12CastMessageBuilder::CastMessageBuilder( 13 base::TickClock* clock, 14 RtpPayloadFeedback* incoming_payload_feedback, 15 FrameIdMap* frame_id_map, 16 uint32 media_ssrc, 17 bool decoder_faster_than_max_frame_rate, 18 int max_unacked_frames) 19 : clock_(clock), 20 cast_feedback_(incoming_payload_feedback), 21 frame_id_map_(frame_id_map), 22 media_ssrc_(media_ssrc), 23 decoder_faster_than_max_frame_rate_(decoder_faster_than_max_frame_rate), 24 max_unacked_frames_(max_unacked_frames), 25 cast_msg_(media_ssrc), 26 waiting_for_key_frame_(true), 27 slowing_down_ack_(false), 28 acked_last_frame_(true), 29 last_acked_frame_id_(kStartFrameId) { 30 cast_msg_.ack_frame_id_ = kStartFrameId; 31} 32 33CastMessageBuilder::~CastMessageBuilder() {} 34 35void CastMessageBuilder::CompleteFrameReceived(uint32 frame_id, 36 bool is_key_frame) { 37 if (last_update_time_.is_null()) { 38 // Our first update. 39 last_update_time_ = clock_->NowTicks(); 40 } 41 if (waiting_for_key_frame_) { 42 if (!is_key_frame) { 43 // Ignore that we have received this complete frame since we are 44 // waiting on a key frame. 45 return; 46 } 47 waiting_for_key_frame_ = false; 48 cast_msg_.missing_frames_and_packets_.clear(); 49 cast_msg_.ack_frame_id_ = frame_id; 50 last_update_time_ = clock_->NowTicks(); 51 // We might have other complete frames waiting after we receive the last 52 // packet in the key-frame. 53 UpdateAckMessage(); 54 } else { 55 if (!UpdateAckMessage()) 56 return; 57 58 BuildPacketList(); 59 } 60 // Send cast message. 61 VLOG(2) << "Send cast message Ack:" << static_cast<int>(frame_id); 62 cast_feedback_->CastFeedback(cast_msg_); 63} 64 65bool CastMessageBuilder::UpdateAckMessage() { 66 if (!decoder_faster_than_max_frame_rate_) { 67 int complete_frame_count = frame_id_map_->NumberOfCompleteFrames(); 68 if (complete_frame_count > max_unacked_frames_) { 69 // We have too many frames pending in our framer; slow down ACK. 70 slowing_down_ack_ = true; 71 } else if (complete_frame_count <= 1) { 72 // We are down to one or less frames in our framer; ACK normally. 73 slowing_down_ack_ = false; 74 } 75 } 76 if (slowing_down_ack_) { 77 // We are slowing down acknowledgment by acknowledging every other frame. 78 if (acked_last_frame_) { 79 acked_last_frame_ = false; 80 } else { 81 acked_last_frame_ = true; 82 last_acked_frame_id_++; 83 // Note: frame skipping and slowdown ACK is not supported at the same 84 // time; and it's not needed since we can skip frames to catch up. 85 } 86 } else { 87 uint32 frame_id = frame_id_map_->LastContinuousFrame(); 88 89 // Is it a new frame? 90 if (last_acked_frame_id_ == frame_id) 91 return false; 92 93 last_acked_frame_id_ = frame_id; 94 acked_last_frame_ = true; 95 } 96 cast_msg_.ack_frame_id_ = last_acked_frame_id_; 97 cast_msg_.missing_frames_and_packets_.clear(); 98 last_update_time_ = clock_->NowTicks(); 99 return true; 100} 101 102bool CastMessageBuilder::TimeToSendNextCastMessage( 103 base::TimeTicks* time_to_send) { 104 // We haven't received any packets. 105 if (last_update_time_.is_null() && frame_id_map_->Empty()) 106 return false; 107 108 *time_to_send = last_update_time_ + base::TimeDelta::FromMilliseconds( 109 kCastMessageUpdateIntervalMs); 110 return true; 111} 112 113void CastMessageBuilder::UpdateCastMessage() { 114 RtcpCastMessage message(media_ssrc_); 115 if (!UpdateCastMessageInternal(&message)) 116 return; 117 118 // Send cast message. 119 cast_feedback_->CastFeedback(message); 120} 121 122void CastMessageBuilder::Reset() { 123 waiting_for_key_frame_ = true; 124 cast_msg_.ack_frame_id_ = kStartFrameId; 125 cast_msg_.missing_frames_and_packets_.clear(); 126 time_last_nacked_map_.clear(); 127} 128 129bool CastMessageBuilder::UpdateCastMessageInternal(RtcpCastMessage* message) { 130 if (last_update_time_.is_null()) { 131 if (!frame_id_map_->Empty()) { 132 // We have received packets. 133 last_update_time_ = clock_->NowTicks(); 134 } 135 return false; 136 } 137 // Is it time to update the cast message? 138 base::TimeTicks now = clock_->NowTicks(); 139 if (now - last_update_time_ < 140 base::TimeDelta::FromMilliseconds(kCastMessageUpdateIntervalMs)) { 141 return false; 142 } 143 last_update_time_ = now; 144 145 UpdateAckMessage(); // Needed to cover when a frame is skipped. 146 BuildPacketList(); 147 message->Copy(cast_msg_); 148 return true; 149} 150 151void CastMessageBuilder::BuildPacketList() { 152 base::TimeTicks now = clock_->NowTicks(); 153 154 // Clear message NACK list. 155 cast_msg_.missing_frames_and_packets_.clear(); 156 157 // Are we missing packets? 158 if (frame_id_map_->Empty()) 159 return; 160 161 uint32 newest_frame_id = frame_id_map_->NewestFrameId(); 162 uint32 next_expected_frame_id = cast_msg_.ack_frame_id_ + 1; 163 164 // Iterate over all frames. 165 for (; !IsNewerFrameId(next_expected_frame_id, newest_frame_id); 166 ++next_expected_frame_id) { 167 TimeLastNackMap::iterator it = 168 time_last_nacked_map_.find(next_expected_frame_id); 169 if (it != time_last_nacked_map_.end()) { 170 // We have sent a NACK in this frame before, make sure enough time have 171 // passed. 172 if (now - it->second < 173 base::TimeDelta::FromMilliseconds(kNackRepeatIntervalMs)) { 174 continue; 175 } 176 } 177 178 PacketIdSet missing; 179 if (frame_id_map_->FrameExists(next_expected_frame_id)) { 180 bool last_frame = (newest_frame_id == next_expected_frame_id); 181 frame_id_map_->GetMissingPackets( 182 next_expected_frame_id, last_frame, &missing); 183 if (!missing.empty()) { 184 time_last_nacked_map_[next_expected_frame_id] = now; 185 cast_msg_.missing_frames_and_packets_.insert( 186 std::make_pair(next_expected_frame_id, missing)); 187 } 188 } else { 189 time_last_nacked_map_[next_expected_frame_id] = now; 190 missing.insert(kRtcpCastAllPacketsLost); 191 cast_msg_.missing_frames_and_packets_[next_expected_frame_id] = missing; 192 } 193 } 194} 195 196} // namespace cast 197} // namespace media 198