<commit_before>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/cast/rtcp/rtcp_sender.h"

#include <algorithm>
#include <vector>

#include "base/big_endian.h"
#include "base/logging.h"
#include "media/cast/cast_environment.h"
#include "media/cast/rtcp/rtcp_defines.h"
#include "media/cast/rtcp/rtcp_utility.h"
#include "media/cast/transport/cast_transport_defines.h"
#include "media/cast/transport/pacing/paced_sender.h"

namespace media {
namespace cast {
namespace {

// Max delta is 4095 milliseconds because we need to be able to encode it in
// 12 bits.
const int64 kMaxWireFormatTimeDeltaMs = GG_INT64_C(0xfff);

// We limit the size of receiver logs to avoid queuing up packets. We also
// do not need the amount of redundancy that results from filling up every
// RTCP packet with log messages. This number should give a redundancy of
// about 2-3 per log message.
const size_t kMaxReceiverLogBytes = 200;

// Converts a log event type to an integer value.
// NOTE: We have only allocated 4 bits to represent the type of event over the
// wire. Therefore, this function can only return values from 0 to 15.
int ConvertEventTypeToWireFormat(const CastLoggingEvent& event) {
  switch (event) {
    case kAudioAckSent:
      return 1;
    case kAudioPlayoutDelay:
      return 2;
    case kAudioFrameDecoded:
      return 3;
    case kAudioPacketReceived:
      return 4;
    case kVideoAckSent:
      return 5;
    case kVideoFrameDecoded:
      return 6;
    case kVideoRenderDelay:
      return 7;
    case kVideoPacketReceived:
      return 8;
    case kDuplicateAudioPacketReceived:
      return 9;
    case kDuplicateVideoPacketReceived:
      return 10;
    default:
      return 0;  // Not an interesting event.
  }
}

uint16 MergeEventTypeAndTimestampForWireFormat(
    const CastLoggingEvent& event,
    const base::TimeDelta& time_delta) {
  int64 time_delta_ms = time_delta.InMilliseconds();

  DCHECK_GE(time_delta_ms, 0);
  DCHECK_LE(time_delta_ms, kMaxWireFormatTimeDeltaMs);

  uint16 time_delta_12_bits =
      static_cast<uint16>(time_delta_ms & kMaxWireFormatTimeDeltaMs);

  uint16 event_type_4_bits = ConvertEventTypeToWireFormat(event);
  DCHECK(event_type_4_bits);
  DCHECK(~(event_type_4_bits & 0xfff0));
  return (event_type_4_bits << 12) | time_delta_12_bits;
}

bool EventTimestampLessThan(const RtcpReceiverEventLogMessage& lhs,
                            const RtcpReceiverEventLogMessage& rhs) {
  return lhs.event_timestamp < rhs.event_timestamp;
}

bool BuildRtcpReceiverLogMessage(
    const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events,
    size_t start_size,
    RtcpReceiverLogMessage* receiver_log_message,
    size_t* number_of_frames,
    size_t* total_number_of_messages_to_send,
    size_t* rtcp_log_size) {
  size_t remaining_space =
      std::min(kMaxReceiverLogBytes, kMaxIpPacketSize - start_size);
  if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize +
                            kRtcpReceiverEventLogSize) {
    return false;
  }

  // We use this to do event timestamp sorting and truncating for events of
  // a single frame.
  std::vector<RtcpReceiverEventLogMessage> sorted_log_messages;

  // Account for the RTCP header for an application-defined packet.
  remaining_space -= kRtcpCastLogHeaderSize;

  ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit =
      rtcp_events.rbegin();

  while (rit != rtcp_events.rend() &&
         remaining_space >=
             kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
    const RtpTimestamp rtp_timestamp = rit->first;
    RtcpReceiverFrameLogMessage frame_log(rtp_timestamp);
    remaining_space -= kRtcpReceiverFrameLogSize;
    ++*number_of_frames;

    // Get all events of a single frame.
    sorted_log_messages.clear();
    do {
      RtcpReceiverEventLogMessage event_log_message;
      event_log_message.type = rit->second.type;
      event_log_message.event_timestamp = rit->second.timestamp;
      event_log_message.delay_delta = rit->second.delay_delta;<commit_msg>Revert 255602 "Cast: Cap max receiver log size per rtcp packet t..." Broke  RtcpReceiverReportWithOversizedFrameLog and RtcpReceiverReportWithTooManyLogFrames tests > Cast: Cap max receiver log size per rtcp packet to 200 bytes. >  > This is a short term fix to hopefully reduce the effects of packets > queueing up on the receiver side. Previously we try fill up the RTCP > packet with as many receiver log as possible so we can have redundancy. > The redundancy that has been observed was more than 30 per message, and > we don't need this much redundancy. 200 is a good number where each > log message will be sent with redundancy of around 2-3, without losing > too many (< 1%) messages, assuming default rtcp interval settings. > That's fine because we don't need the logs to be completely reliable. >  >  > BUG=349265 >  > Review URL: https://codereview.chromium.org/189423002<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/cast/rtcp/rtcp_sender.h"

#include <algorithm>
#include <vector>

#include "base/big_endian.h"
#include "base/logging.h"
#include "media/cast/cast_environment.h"
#include "media/cast/rtcp/rtcp_defines.h"
#include "media/cast/rtcp/rtcp_utility.h"
#include "media/cast/transport/cast_transport_defines.h"
#include "media/cast/transport/pacing/paced_sender.h"

namespace media {
namespace cast {
namespace {

// Max delta is 4095 milliseconds because we need to be able to encode it in
// 12 bits.
const int64 kMaxWireFormatTimeDeltaMs = GG_INT64_C(0xfff);

// Converts a log event type to an integer value.
// NOTE: We have only allocated 4 bits to represent the type of event over the
// wire. Therefore, this function can only return values from 0 to 15.
int ConvertEventTypeToWireFormat(const CastLoggingEvent& event) {
  switch (event) {
    case kAudioAckSent:
      return 1;
    case kAudioPlayoutDelay:
      return 2;
    case kAudioFrameDecoded:
      return 3;
    case kAudioPacketReceived:
      return 4;
    case kVideoAckSent:
      return 5;
    case kVideoFrameDecoded:
      return 6;
    case kVideoRenderDelay:
      return 7;
    case kVideoPacketReceived:
      return 8;
    case kDuplicateAudioPacketReceived:
      return 9;
    case kDuplicateVideoPacketReceived:
      return 10;
    default:
      return 0;  // Not an interesting event.
  }
}

uint16 MergeEventTypeAndTimestampForWireFormat(
    const CastLoggingEvent& event,
    const base::TimeDelta& time_delta) {
  int64 time_delta_ms = time_delta.InMilliseconds();

  DCHECK_GE(time_delta_ms, 0);
  DCHECK_LE(time_delta_ms, kMaxWireFormatTimeDeltaMs);

  uint16 time_delta_12_bits =
      static_cast<uint16>(time_delta_ms & kMaxWireFormatTimeDeltaMs);

  uint16 event_type_4_bits = ConvertEventTypeToWireFormat(event);
  DCHECK(event_type_4_bits);
  DCHECK(~(event_type_4_bits & 0xfff0));
  return (event_type_4_bits << 12) | time_delta_12_bits;
}

bool EventTimestampLessThan(const RtcpReceiverEventLogMessage& lhs,
                            const RtcpReceiverEventLogMessage& rhs) {
  return lhs.event_timestamp < rhs.event_timestamp;
}

bool BuildRtcpReceiverLogMessage(
    const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events,
    size_t start_size,
    RtcpReceiverLogMessage* receiver_log_message,
    size_t* number_of_frames,
    size_t* total_number_of_messages_to_send,
    size_t* rtcp_log_size) {
  size_t remaining_space = kMaxIpPacketSize - start_size;
  if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize +
                            kRtcpReceiverEventLogSize) {
    return false;
  }

  // We use this to do event timestamp sorting and truncating for events of
  // a single frame.
  std::vector<RtcpReceiverEventLogMessage> sorted_log_messages;

  // Account for the RTCP header for an application-defined packet.
  remaining_space -= kRtcpCastLogHeaderSize;

  ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit =
      rtcp_events.rbegin();

  while (rit != rtcp_events.rend() &&
         remaining_space >=
             kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
    const RtpTimestamp rtp_timestamp = rit->first;
    RtcpReceiverFrameLogMessage frame_log(rtp_timestamp);
    remaining_space -= kRtcpReceiverFrameLogSize;
    ++*number_of_frames;

    // Get all events of a single frame.
    sorted_log_messages.clear();
    do {
      RtcpReceiverEventLogMessage event_log_message;
      event_log_message.type = rit->second.type;
      event_log_message.event_timestamp = rit->second.timestamp;
      event_log_message.delay_delta = rit->second.delay_delta;
{'fraction_non_alphanumeric': 0.07344188658057271, 'fraction_numerical': 0.016282987085906794, 'mean_word_length': 3.958797327394209, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 36, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3372557', 'n_tokens_mistral': 2850, 'n_tokens_neox': 2698, 'n_words': 762}