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