/*
 *  Copyright (c) 2012 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 "webrtc/modules/video_coding/codecs/test/stats.h"

#include <assert.h>
#include <stdio.h>

#include <algorithm>  // min_element, max_element

namespace webrtc {
namespace test {

FrameStatistic::FrameStatistic()
    : encoding_successful(false),
      decoding_successful(false),
      encode_return_code(0),
      decode_return_code(0),
      encode_time_in_us(0),
      decode_time_in_us(0),
      frame_number(0),
      packets_dropped(0),
      total_packets(0),
      bit_rate_in_kbps(0),
      encoded_frame_length_in_bytes(0),
      frame_type(kDeltaFrame) {}

Stats::Stats() {}

Stats::~Stats() {}

bool LessForEncodeTime(const FrameStatistic& s1, const FrameStatistic& s2) {
    return s1.encode_time_in_us < s2.encode_time_in_us;
}

bool LessForDecodeTime(const FrameStatistic& s1, const FrameStatistic& s2) {
    return s1.decode_time_in_us < s2.decode_time_in_us;
}

bool LessForEncodedSize(const FrameStatistic& s1, const FrameStatistic& s2) {
    return s1.encoded_frame_length_in_bytes < s2.encoded_frame_length_in_bytes;
}

bool LessForBitRate(const FrameStatistic& s1, const FrameStatistic& s2) {
    return s1.bit_rate_in_kbps < s2.bit_rate_in_kbps;
}

FrameStatistic& Stats::NewFrame(int frame_number) {
  assert(frame_number >= 0);
  FrameStatistic stat;
  stat.frame_number = frame_number;
  stats_.push_back(stat);
  return stats_[frame_number];
}

void Stats::PrintSummary() {
  printf("Processing summary:\n");
  if (stats_.size() == 0) {
    printf("No frame statistics have been logged yet.\n");
    return;
  }

  // Calculate min, max, average and total encoding time
  int total_encoding_time_in_us = 0;
  int total_decoding_time_in_us = 0;
  int total_encoded_frames_lengths = 0;
  int total_encoded_key_frames_lengths = 0;
  int total_encoded_nonkey_frames_lengths = 0;
  int nbr_keyframes = 0;
  int nbr_nonkeyframes = 0;

  for (FrameStatisticsIterator it = stats_.begin();
      it != stats_.end(); ++it) {
    total_encoding_time_in_us += it->encode_time_in_us;
    total_decoding_time_in_us += it->decode_time_in_us;
    total_encoded_frames_lengths += it->encoded_frame_length_in_bytes;
    if (it->frame_type == webrtc::kKeyFrame) {
      total_encoded_key_frames_lengths += it->encoded_frame_length_in_bytes;
      nbr_keyframes++;
    } else {
      total_encoded_nonkey_frames_lengths += it->encoded_frame_length_in_bytes;
      nbr_nonkeyframes++;
    }
  }

  FrameStatisticsIterator frame;

  // ENCODING
  printf("Encoding time:\n");
  frame = std::min_element(stats_.begin(),
                      stats_.end(), LessForEncodeTime);
  printf("  Min     : %7d us (frame %d)\n",
         frame->encode_time_in_us, frame->frame_number);

  frame = std::max_element(stats_.begin(),
                      stats_.end(), LessForEncodeTime);
  printf("  Max     : %7d us (frame %d)\n",
         frame->encode_time_in_us, frame->frame_number);

  printf("  Average : %7d us\n",
         static_cast<int>(total_encoding_time_in_us / stats_.size()));

  // DECODING
  printf("Decoding time:\n");
  // only consider frames that were successfully decoded (packet loss may cause
  // failures)
  std::vector<FrameStatistic> decoded_frames;
  for (std::vector<FrameStatistic>::iterator it = stats_.begin();
      it != stats_.end(); ++it) {
    if (it->decoding_successful) {
      decoded_frames.push_back(*it);
    }
  }
  if (decoded_frames.size() == 0) {
    printf("No successfully decoded frames exist in this statistics.\n");
  } else {
    frame = std::min_element(decoded_frames.begin(),
                        decoded_frames.end(), LessForDecodeTime);
    printf("  Min     : %7d us (frame %d)\n",
           frame->decode_time_in_us, frame->frame_number);

    frame = std::max_element(decoded_frames.begin(),
                        decoded_frames.end(), LessForDecodeTime);
    printf("  Max     : %7d us (frame %d)\n",
           frame->decode_time_in_us, frame->frame_number);

    printf("  Average : %7d us\n",
           static_cast<int>(total_decoding_time_in_us / decoded_frames.size()));
    printf("  Failures: %d frames failed to decode.\n",
           static_cast<int>(stats_.size() - decoded_frames.size()));
  }

  // SIZE
  printf("Frame sizes:\n");
  frame = std::min_element(stats_.begin(),
                      stats_.end(), LessForEncodedSize);
  printf("  Min     : %7d bytes (frame %d)\n",
         frame->encoded_frame_length_in_bytes, frame->frame_number);

  frame = std::max_element(stats_.begin(),
                      stats_.end(), LessForEncodedSize);
  printf("  Max     : %7d bytes (frame %d)\n",
         frame->encoded_frame_length_in_bytes, frame->frame_number);

  printf("  Average : %7d bytes\n",
         static_cast<int>(total_encoded_frames_lengths / stats_.size()));
  if (nbr_keyframes > 0) {
    printf("  Average key frame size    : %7d bytes (%d keyframes)\n",
           total_encoded_key_frames_lengths / nbr_keyframes,
           nbr_keyframes);
  }
  if (nbr_nonkeyframes > 0) {
    printf("  Average non-key frame size: %7d bytes (%d frames)\n",
           total_encoded_nonkey_frames_lengths / nbr_nonkeyframes,
           nbr_nonkeyframes);
  }

  // BIT RATE
  printf("Bit rates:\n");
  frame = std::min_element(stats_.begin(),
                      stats_.end(), LessForBitRate);
  printf("  Min bit rate: %7d kbps (frame %d)\n",
         frame->bit_rate_in_kbps, frame->frame_number);

  frame = std::max_element(stats_.begin(),
                      stats_.end(), LessForBitRate);
  printf("  Max bit rate: %7d kbps (frame %d)\n",
         frame->bit_rate_in_kbps, frame->frame_number);

  printf("\n");
  printf("Total encoding time  : %7d ms.\n",
         total_encoding_time_in_us / 1000);
  printf("Total decoding time  : %7d ms.\n",
         total_decoding_time_in_us / 1000);
  printf("Total processing time: %7d ms.\n",
         (total_encoding_time_in_us + total_decoding_time_in_us) / 1000);
}

}  // namespace test
}  // namespace webrtc
