Home | History | Annotate | Download | only in test
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/video_coding/codecs/test/stats.h"
     12 
     13 #include <assert.h>
     14 #include <stdio.h>
     15 
     16 #include <algorithm>  // min_element, max_element
     17 
     18 #include "webrtc/base/format_macros.h"
     19 
     20 namespace webrtc {
     21 namespace test {
     22 
     23 FrameStatistic::FrameStatistic()
     24     : encoding_successful(false),
     25       decoding_successful(false),
     26       encode_return_code(0),
     27       decode_return_code(0),
     28       encode_time_in_us(0),
     29       decode_time_in_us(0),
     30       frame_number(0),
     31       packets_dropped(0),
     32       total_packets(0),
     33       bit_rate_in_kbps(0),
     34       encoded_frame_length_in_bytes(0),
     35       frame_type(kVideoFrameDelta) {}
     36 
     37 Stats::Stats() {}
     38 
     39 Stats::~Stats() {}
     40 
     41 bool LessForEncodeTime(const FrameStatistic& s1, const FrameStatistic& s2) {
     42   return s1.encode_time_in_us < s2.encode_time_in_us;
     43 }
     44 
     45 bool LessForDecodeTime(const FrameStatistic& s1, const FrameStatistic& s2) {
     46   return s1.decode_time_in_us < s2.decode_time_in_us;
     47 }
     48 
     49 bool LessForEncodedSize(const FrameStatistic& s1, const FrameStatistic& s2) {
     50   return s1.encoded_frame_length_in_bytes < s2.encoded_frame_length_in_bytes;
     51 }
     52 
     53 bool LessForBitRate(const FrameStatistic& s1, const FrameStatistic& s2) {
     54   return s1.bit_rate_in_kbps < s2.bit_rate_in_kbps;
     55 }
     56 
     57 FrameStatistic& Stats::NewFrame(int frame_number) {
     58   assert(frame_number >= 0);
     59   FrameStatistic stat;
     60   stat.frame_number = frame_number;
     61   stats_.push_back(stat);
     62   return stats_[frame_number];
     63 }
     64 
     65 void Stats::PrintSummary() {
     66   printf("Processing summary:\n");
     67   if (stats_.size() == 0) {
     68     printf("No frame statistics have been logged yet.\n");
     69     return;
     70   }
     71 
     72   // Calculate min, max, average and total encoding time
     73   int total_encoding_time_in_us = 0;
     74   int total_decoding_time_in_us = 0;
     75   size_t total_encoded_frames_lengths = 0;
     76   size_t total_encoded_key_frames_lengths = 0;
     77   size_t total_encoded_nonkey_frames_lengths = 0;
     78   size_t nbr_keyframes = 0;
     79   size_t nbr_nonkeyframes = 0;
     80 
     81   for (FrameStatisticsIterator it = stats_.begin(); it != stats_.end(); ++it) {
     82     total_encoding_time_in_us += it->encode_time_in_us;
     83     total_decoding_time_in_us += it->decode_time_in_us;
     84     total_encoded_frames_lengths += it->encoded_frame_length_in_bytes;
     85     if (it->frame_type == webrtc::kVideoFrameKey) {
     86       total_encoded_key_frames_lengths += it->encoded_frame_length_in_bytes;
     87       nbr_keyframes++;
     88     } else {
     89       total_encoded_nonkey_frames_lengths += it->encoded_frame_length_in_bytes;
     90       nbr_nonkeyframes++;
     91     }
     92   }
     93 
     94   FrameStatisticsIterator frame;
     95 
     96   // ENCODING
     97   printf("Encoding time:\n");
     98   frame = std::min_element(stats_.begin(), stats_.end(), LessForEncodeTime);
     99   printf("  Min     : %7d us (frame %d)\n", frame->encode_time_in_us,
    100          frame->frame_number);
    101 
    102   frame = std::max_element(stats_.begin(), stats_.end(), LessForEncodeTime);
    103   printf("  Max     : %7d us (frame %d)\n", frame->encode_time_in_us,
    104          frame->frame_number);
    105 
    106   printf("  Average : %7d us\n",
    107          static_cast<int>(total_encoding_time_in_us / stats_.size()));
    108 
    109   // DECODING
    110   printf("Decoding time:\n");
    111   // only consider frames that were successfully decoded (packet loss may cause
    112   // failures)
    113   std::vector<FrameStatistic> decoded_frames;
    114   for (std::vector<FrameStatistic>::iterator it = stats_.begin();
    115        it != stats_.end(); ++it) {
    116     if (it->decoding_successful) {
    117       decoded_frames.push_back(*it);
    118     }
    119   }
    120   if (decoded_frames.size() == 0) {
    121     printf("No successfully decoded frames exist in this statistics.\n");
    122   } else {
    123     frame = std::min_element(decoded_frames.begin(), decoded_frames.end(),
    124                              LessForDecodeTime);
    125     printf("  Min     : %7d us (frame %d)\n", frame->decode_time_in_us,
    126            frame->frame_number);
    127 
    128     frame = std::max_element(decoded_frames.begin(), decoded_frames.end(),
    129                              LessForDecodeTime);
    130     printf("  Max     : %7d us (frame %d)\n", frame->decode_time_in_us,
    131            frame->frame_number);
    132 
    133     printf("  Average : %7d us\n",
    134            static_cast<int>(total_decoding_time_in_us / decoded_frames.size()));
    135     printf("  Failures: %d frames failed to decode.\n",
    136            static_cast<int>(stats_.size() - decoded_frames.size()));
    137   }
    138 
    139   // SIZE
    140   printf("Frame sizes:\n");
    141   frame = std::min_element(stats_.begin(), stats_.end(), LessForEncodedSize);
    142   printf("  Min     : %7" PRIuS " bytes (frame %d)\n",
    143          frame->encoded_frame_length_in_bytes, frame->frame_number);
    144 
    145   frame = std::max_element(stats_.begin(), stats_.end(), LessForEncodedSize);
    146   printf("  Max     : %7" PRIuS " bytes (frame %d)\n",
    147          frame->encoded_frame_length_in_bytes, frame->frame_number);
    148 
    149   printf("  Average : %7" PRIuS " bytes\n",
    150          total_encoded_frames_lengths / stats_.size());
    151   if (nbr_keyframes > 0) {
    152     printf("  Average key frame size    : %7" PRIuS " bytes (%" PRIuS
    153            " keyframes)\n",
    154            total_encoded_key_frames_lengths / nbr_keyframes, nbr_keyframes);
    155   }
    156   if (nbr_nonkeyframes > 0) {
    157     printf("  Average non-key frame size: %7" PRIuS " bytes (%" PRIuS
    158            " frames)\n",
    159            total_encoded_nonkey_frames_lengths / nbr_nonkeyframes,
    160            nbr_nonkeyframes);
    161   }
    162 
    163   // BIT RATE
    164   printf("Bit rates:\n");
    165   frame = std::min_element(stats_.begin(), stats_.end(), LessForBitRate);
    166   printf("  Min bit rate: %7d kbps (frame %d)\n", frame->bit_rate_in_kbps,
    167          frame->frame_number);
    168 
    169   frame = std::max_element(stats_.begin(), stats_.end(), LessForBitRate);
    170   printf("  Max bit rate: %7d kbps (frame %d)\n", frame->bit_rate_in_kbps,
    171          frame->frame_number);
    172 
    173   printf("\n");
    174   printf("Total encoding time  : %7d ms.\n", total_encoding_time_in_us / 1000);
    175   printf("Total decoding time  : %7d ms.\n", total_decoding_time_in_us / 1000);
    176   printf("Total processing time: %7d ms.\n",
    177          (total_encoding_time_in_us + total_decoding_time_in_us) / 1000);
    178 }
    179 
    180 }  // namespace test
    181 }  // namespace webrtc
    182