/* * 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 #include // min_element, max_element #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) { 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; } } // namespace Stats::Stats() {} Stats::~Stats() {} FrameStatistic& Stats::NewFrame(int frame_number) { RTC_DCHECK_GE(frame_number, 0); FrameStatistic stat; stat.frame_number = frame_number; stats_.push_back(stat); return stats_[frame_number]; } void Stats::PrintSummary() { 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_in_us = 0; int total_decoding_time_in_us = 0; int total_qp = 0; int total_qp_count = 0; size_t total_encoded_frames_lengths = 0; size_t total_encoded_key_frames_lengths = 0; size_t total_encoded_nonkey_frames_lengths = 0; size_t num_keyframes = 0; size_t num_nonkeyframes = 0; for (const FrameStatistic& stat : stats_) { total_encoding_time_in_us += stat.encode_time_in_us; total_decoding_time_in_us += stat.decode_time_in_us; total_encoded_frames_lengths += stat.encoded_frame_length_in_bytes; if (stat.frame_type == webrtc::kVideoFrameKey) { total_encoded_key_frames_lengths += stat.encoded_frame_length_in_bytes; ++num_keyframes; } else { total_encoded_nonkey_frames_lengths += stat.encoded_frame_length_in_bytes; ++num_nonkeyframes; } if (stat.qp >= 0) { total_qp += stat.qp; ++total_qp_count; } } // Encoding stats. printf("Encoding time:\n"); FrameStatisticsIterator frame; 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(total_encoding_time_in_us / stats_.size())); // Decoding stats. printf("Decoding time:\n"); // Only consider successfully decoded frames (packet loss may cause failures). std::vector 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 = 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(total_decoding_time_in_us / decoded_frames.size())); printf(" Failures: %d frames failed to decode.\n", static_cast(stats_.size() - decoded_frames.size())); } // Frame size stats. printf("Frame sizes:\n"); frame = std::min_element(stats_.begin(), stats_.end(), LessForEncodedSize); printf(" Min : %7" PRIuS " bytes (frame %d)\n", frame->encoded_frame_length_in_bytes, frame->frame_number); frame = std::max_element(stats_.begin(), stats_.end(), LessForEncodedSize); printf(" Max : %7" PRIuS " bytes (frame %d)\n", frame->encoded_frame_length_in_bytes, frame->frame_number); printf(" Average : %7" PRIuS " bytes\n", total_encoded_frames_lengths / stats_.size()); if (num_keyframes > 0) { printf(" Average key frame size : %7" PRIuS " bytes (%" PRIuS " keyframes)\n", total_encoded_key_frames_lengths / num_keyframes, num_keyframes); } if (num_nonkeyframes > 0) { printf(" Average non-key frame size: %7" PRIuS " bytes (%" PRIuS " frames)\n", total_encoded_nonkey_frames_lengths / num_nonkeyframes, num_nonkeyframes); } // Bitrate stats. printf("Bitrates:\n"); frame = std::min_element(stats_.begin(), stats_.end(), LessForBitRate); printf(" Min bitrate: %7d kbps (frame %d)\n", frame->bit_rate_in_kbps, frame->frame_number); frame = std::max_element(stats_.begin(), stats_.end(), LessForBitRate); printf(" Max bitrate: %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); int avg_qp = (total_qp_count > 0) ? (total_qp / total_qp_count) : -1; printf("Average QP: %d\n", avg_qp); } } // namespace test } // namespace webrtc