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
FrameStatistic()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
Stats()37 Stats::Stats() {}
38
~Stats()39 Stats::~Stats() {}
40
LessForEncodeTime(const FrameStatistic & s1,const FrameStatistic & s2)41 bool LessForEncodeTime(const FrameStatistic& s1, const FrameStatistic& s2) {
42 return s1.encode_time_in_us < s2.encode_time_in_us;
43 }
44
LessForDecodeTime(const FrameStatistic & s1,const FrameStatistic & s2)45 bool LessForDecodeTime(const FrameStatistic& s1, const FrameStatistic& s2) {
46 return s1.decode_time_in_us < s2.decode_time_in_us;
47 }
48
LessForEncodedSize(const FrameStatistic & s1,const FrameStatistic & s2)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
LessForBitRate(const FrameStatistic & s1,const FrameStatistic & s2)53 bool LessForBitRate(const FrameStatistic& s1, const FrameStatistic& s2) {
54 return s1.bit_rate_in_kbps < s2.bit_rate_in_kbps;
55 }
56
NewFrame(int frame_number)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
PrintSummary()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