| /* |
| * 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 <stdio.h> |
| |
| #include <algorithm> |
| |
| #include "webrtc/rtc_base/checks.h" |
| #include "webrtc/rtc_base/format_macros.h" |
| |
| namespace webrtc { |
| namespace test { |
| |
| namespace { |
| |
| bool LessForEncodeTime(const FrameStatistic& s1, const FrameStatistic& s2) { |
| RTC_DCHECK_NE(s1.frame_number, s2.frame_number); |
| return s1.encode_time_us < s2.encode_time_us; |
| } |
| |
| bool LessForDecodeTime(const FrameStatistic& s1, const FrameStatistic& s2) { |
| RTC_DCHECK_NE(s1.frame_number, s2.frame_number); |
| return s1.decode_time_us < s2.decode_time_us; |
| } |
| |
| bool LessForEncodedSize(const FrameStatistic& s1, const FrameStatistic& s2) { |
| RTC_DCHECK_NE(s1.frame_number, s2.frame_number); |
| return s1.encoded_frame_size_bytes < s2.encoded_frame_size_bytes; |
| } |
| |
| bool LessForBitRate(const FrameStatistic& s1, const FrameStatistic& s2) { |
| RTC_DCHECK_NE(s1.frame_number, s2.frame_number); |
| return s1.bitrate_kbps < s2.bitrate_kbps; |
| } |
| |
| } // namespace |
| |
| FrameStatistic* Stats::AddFrame() { |
| // We don't expect more frames than what can be stored in an int. |
| stats_.emplace_back(static_cast<int>(stats_.size())); |
| return &stats_.back(); |
| } |
| |
| FrameStatistic* Stats::GetFrame(int frame_number) { |
| RTC_CHECK_GE(frame_number, 0); |
| RTC_CHECK_LT(frame_number, stats_.size()); |
| return &stats_[frame_number]; |
| } |
| |
| size_t Stats::size() const { |
| return stats_.size(); |
| } |
| |
| void Stats::PrintSummary() const { |
| if (stats_.empty()) { |
| printf("No frame statistics have been logged yet.\n"); |
| return; |
| } |
| |
| // Calculate min, max, average and total encoding time. |
| int total_encoding_time_us = 0; |
| int total_decoding_time_us = 0; |
| size_t total_encoded_frame_size_bytes = 0; |
| size_t total_encoded_key_frame_size_bytes = 0; |
| size_t total_encoded_delta_frame_size_bytes = 0; |
| size_t num_key_frames = 0; |
| size_t num_delta_frames = 0; |
| |
| for (const FrameStatistic& stat : stats_) { |
| total_encoding_time_us += stat.encode_time_us; |
| total_decoding_time_us += stat.decode_time_us; |
| total_encoded_frame_size_bytes += stat.encoded_frame_size_bytes; |
| if (stat.frame_type == webrtc::kVideoFrameKey) { |
| total_encoded_key_frame_size_bytes += stat.encoded_frame_size_bytes; |
| ++num_key_frames; |
| } else { |
| total_encoded_delta_frame_size_bytes += stat.encoded_frame_size_bytes; |
| ++num_delta_frames; |
| } |
| } |
| |
| // Encoding stats. |
| printf("Encoding time:\n"); |
| auto frame_it = |
| std::min_element(stats_.begin(), stats_.end(), LessForEncodeTime); |
| printf(" Min : %7d us (frame %d)\n", frame_it->encode_time_us, |
| frame_it->frame_number); |
| frame_it = std::max_element(stats_.begin(), stats_.end(), LessForEncodeTime); |
| printf(" Max : %7d us (frame %d)\n", frame_it->encode_time_us, |
| frame_it->frame_number); |
| printf(" Average : %7d us\n", |
| static_cast<int>(total_encoding_time_us / stats_.size())); |
| |
| // Decoding stats. |
| printf("Decoding time:\n"); |
| // Only consider successfully decoded frames (packet loss may cause failures). |
| std::vector<FrameStatistic> decoded_frames; |
| for (const FrameStatistic& stat : stats_) { |
| if (stat.decoding_successful) { |
| decoded_frames.push_back(stat); |
| } |
| } |
| if (decoded_frames.empty()) { |
| printf("No successfully decoded frames exist in this statistics.\n"); |
| } else { |
| frame_it = std::min_element(decoded_frames.begin(), decoded_frames.end(), |
| LessForDecodeTime); |
| printf(" Min : %7d us (frame %d)\n", frame_it->decode_time_us, |
| frame_it->frame_number); |
| frame_it = std::max_element(decoded_frames.begin(), decoded_frames.end(), |
| LessForDecodeTime); |
| printf(" Max : %7d us (frame %d)\n", frame_it->decode_time_us, |
| frame_it->frame_number); |
| printf(" Average : %7d us\n", |
| static_cast<int>(total_decoding_time_us / decoded_frames.size())); |
| printf(" Failures: %d frames failed to decode.\n", |
| static_cast<int>(stats_.size() - decoded_frames.size())); |
| } |
| |
| // Frame size stats. |
| printf("Frame sizes:\n"); |
| frame_it = std::min_element(stats_.begin(), stats_.end(), LessForEncodedSize); |
| printf(" Min : %7" PRIuS " bytes (frame %d)\n", |
| frame_it->encoded_frame_size_bytes, frame_it->frame_number); |
| frame_it = std::max_element(stats_.begin(), stats_.end(), LessForEncodedSize); |
| printf(" Max : %7" PRIuS " bytes (frame %d)\n", |
| frame_it->encoded_frame_size_bytes, frame_it->frame_number); |
| printf(" Average : %7" PRIuS " bytes\n", |
| total_encoded_frame_size_bytes / stats_.size()); |
| if (num_key_frames > 0) { |
| printf(" Average key frame size : %7" PRIuS " bytes (%" PRIuS |
| " keyframes)\n", |
| total_encoded_key_frame_size_bytes / num_key_frames, num_key_frames); |
| } |
| if (num_delta_frames > 0) { |
| printf(" Average non-key frame size: %7" PRIuS " bytes (%" PRIuS |
| " frames)\n", |
| total_encoded_delta_frame_size_bytes / num_delta_frames, |
| num_delta_frames); |
| } |
| |
| // Bitrate stats. |
| printf("Bitrates:\n"); |
| frame_it = std::min_element(stats_.begin(), stats_.end(), LessForBitRate); |
| printf(" Min bitrate: %7d kbps (frame %d)\n", frame_it->bitrate_kbps, |
| frame_it->frame_number); |
| frame_it = std::max_element(stats_.begin(), stats_.end(), LessForBitRate); |
| printf(" Max bitrate: %7d kbps (frame %d)\n", frame_it->bitrate_kbps, |
| frame_it->frame_number); |
| |
| printf("\n"); |
| printf("Total encoding time : %7d ms.\n", total_encoding_time_us / 1000); |
| printf("Total decoding time : %7d ms.\n", total_decoding_time_us / 1000); |
| printf("Total processing time: %7d ms.\n", |
| (total_encoding_time_us + total_decoding_time_us) / 1000); |
| |
| // QP stats. |
| int total_qp = 0; |
| int total_qp_count = 0; |
| for (const FrameStatistic& stat : stats_) { |
| if (stat.qp >= 0) { |
| total_qp += stat.qp; |
| ++total_qp_count; |
| } |
| } |
| int avg_qp = (total_qp_count > 0) ? (total_qp / total_qp_count) : -1; |
| printf("Average QP: %d\n", avg_qp); |
| } |
| |
| } // namespace test |
| } // namespace webrtc |