/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "reference_picture_selection.h"

#include "typedefs.h"
#include "vpx/vpx_encoder.h"
#include "vpx/vp8cx.h"

namespace webrtc {

ReferencePictureSelection::ReferencePictureSelection()
    : kRttConfidence(1.33),
      update_golden_next_(true),
      established_golden_(false),
      received_ack_(false),
      last_sent_ref_picture_id_(0),
      last_sent_ref_update_time_(0),
      established_ref_picture_id_(0),
      last_refresh_time_(0),
      rtt_(0) {
}

void ReferencePictureSelection::Init() {
  update_golden_next_ = true;
  established_golden_ = false;
  received_ack_ = false;
  last_sent_ref_picture_id_ = 0;
  last_sent_ref_update_time_ = 0;
  established_ref_picture_id_ = 0;
  last_refresh_time_ = 0;
  rtt_ = 0;
}

void ReferencePictureSelection::ReceivedRPSI(int rpsi_picture_id) {
  // Assume RPSI is signaled with 14 bits.
  if ((rpsi_picture_id & 0x3fff) == (last_sent_ref_picture_id_ & 0x3fff)) {
    // Remote peer has received our last reference frame, switch frame type.
    received_ack_ = true;
    established_golden_ = update_golden_next_;
    update_golden_next_ = !update_golden_next_;
    established_ref_picture_id_ = last_sent_ref_picture_id_;
  }
}

bool ReferencePictureSelection::ReceivedSLI(uint32_t now_ts) {
  bool send_refresh = false;
  // Don't send a refresh more than once per round-trip time.
  // This is to avoid too frequent refreshes, since the receiver
  // will signal an SLI for every corrupt frame.
  if (TimestampDiff(now_ts, last_refresh_time_) > rtt_) {
    send_refresh = true;
    last_refresh_time_ = now_ts;
  }
  return send_refresh;
}

int ReferencePictureSelection::EncodeFlags(int picture_id, bool send_refresh,
                                           uint32_t now_ts) {
  int flags = 0;
  // We can't refresh the decoder until we have established the key frame.
  if (send_refresh && received_ack_) {
    flags |= VP8_EFLAG_NO_REF_LAST;  // Don't reference the last frame
    if (established_golden_)
      flags |= VP8_EFLAG_NO_REF_ARF;  // Don't reference the alt-ref frame.
    else
      flags |= VP8_EFLAG_NO_REF_GF;  // Don't reference the golden frame
  }

  // Make sure we don't update the reference frames too often. We must wait long
  // enough for an RPSI to arrive after the decoder decoded the reference frame.
  // Ideally that should happen after one round-trip time.
  // Add a margin defined by |kRttConfidence|.
  uint32_t update_interval = kRttConfidence * rtt_;
  if (update_interval < kMinUpdateInterval)
    update_interval = kMinUpdateInterval;
  // Don't send reference frame updates until we have an established reference.
  if (TimestampDiff(now_ts, last_sent_ref_update_time_) > update_interval &&
      received_ack_) {
    flags |= VP8_EFLAG_NO_REF_LAST;  // Don't reference the last frame.
    if (update_golden_next_) {
      flags |= VP8_EFLAG_FORCE_GF;  // Update the golden reference.
      flags |= VP8_EFLAG_NO_UPD_ARF;  // Don't update alt-ref.
      flags |= VP8_EFLAG_NO_REF_GF;  // Don't reference the golden frame.
    } else {
      flags |= VP8_EFLAG_FORCE_ARF;  // Update the alt-ref reference.
      flags |= VP8_EFLAG_NO_UPD_GF;  // Don't update the golden frame.
      flags |= VP8_EFLAG_NO_REF_ARF;  // Don't reference the alt-ref frame.
    }
    last_sent_ref_picture_id_ = picture_id;
    last_sent_ref_update_time_ = now_ts;
  } else {
    // No update of golden or alt-ref. We can therefore freely reference the
    // established reference frame and the last frame.
    if (established_golden_)
      flags |= VP8_EFLAG_NO_REF_ARF;  // Don't reference the alt-ref frame.
    else
      flags |= VP8_EFLAG_NO_REF_GF;   // Don't reference the golden frame.
    flags |= VP8_EFLAG_NO_UPD_GF;  // Don't update the golden frame.
    flags |= VP8_EFLAG_NO_UPD_ARF;  // Don't update the alt-ref frame.
  }
  return flags;
}

void ReferencePictureSelection::EncodedKeyFrame(int picture_id) {
  last_sent_ref_picture_id_ = picture_id;
  received_ack_ = false;
}

void ReferencePictureSelection::SetRtt(int rtt) {
  // Convert from milliseconds to timestamp frequency.
  rtt_ = 90 * rtt;
}

uint32_t ReferencePictureSelection::TimestampDiff(uint32_t new_ts,
                                                  uint32_t old_ts) {
  if (old_ts > new_ts) {
    // Assuming this is a wrap, doing a compensated subtraction.
    return (new_ts + (static_cast<int64_t>(1) << 32)) - old_ts;
  }
  return new_ts - old_ts;
}

}  // namespace webrtc
