• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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