blob: 502ac826017de81e05ac8651c3204083f1ce11be [file] [log] [blame]
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_tools/frame_analyzer/video_quality_analysis.h"
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h>
14#include <stdio.h>
15#include <stdlib.h>
mandermo74568172017-01-17 03:24:57 -080016#include <algorithm>
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000017#include <string>
mandermo74568172017-01-17 03:24:57 -080018#include <map>
19#include <utility>
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000020
Edward Lemur2e5966b2018-01-30 15:33:02 +010021#include "test/testsupport/perf_test.h"
22
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000023#define STATS_LINE_LENGTH 32
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +000024#define Y4M_FILE_HEADER_MAX_SIZE 200
25#define Y4M_FRAME_DELIMITER "FRAME"
26#define Y4M_FRAME_HEADER_SIZE 6
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000027
28namespace webrtc {
29namespace test {
30
Henrik Kjellander67bcb602015-10-07 08:42:52 +020031ResultsContainer::ResultsContainer() {}
32ResultsContainer::~ResultsContainer() {}
33
vspasova@webrtc.orgac410e22012-08-27 14:57:19 +000034int GetI420FrameSize(int width, int height) {
35 int half_width = (width + 1) >> 1;
36 int half_height = (height + 1) >> 1;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000037
vspasova@webrtc.orgac410e22012-08-27 14:57:19 +000038 int y_plane = width * height; // I420 Y plane.
39 int u_plane = half_width * half_height; // I420 U plane.
40 int v_plane = half_width * half_height; // I420 V plane.
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000041
42 return y_plane + u_plane + v_plane;
43}
44
45int ExtractFrameSequenceNumber(std::string line) {
kjellander@webrtc.orgb2d74972013-01-26 16:36:40 +000046 size_t space_position = line.find(' ');
ehmaldonado1dffc622017-02-02 08:10:00 -080047 if (space_position == std::string::npos) {
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000048 return -1;
49 }
50 std::string frame = line.substr(0, space_position);
51
kjellander@webrtc.orgb2d74972013-01-26 16:36:40 +000052 size_t underscore_position = frame.find('_');
ehmaldonado1dffc622017-02-02 08:10:00 -080053 if (underscore_position == std::string::npos) {
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000054 return -1;
55 }
56 std::string frame_number = frame.substr(underscore_position + 1);
57
58 return strtol(frame_number.c_str(), NULL, 10);
59}
60
61int ExtractDecodedFrameNumber(std::string line) {
kjellander@webrtc.orgb2d74972013-01-26 16:36:40 +000062 size_t space_position = line.find(' ');
ehmaldonado1dffc622017-02-02 08:10:00 -080063 if (space_position == std::string::npos) {
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000064 return -1;
65 }
66 std::string decoded_number = line.substr(space_position + 1);
67
68 return strtol(decoded_number.c_str(), NULL, 10);
69}
70
71bool IsThereBarcodeError(std::string line) {
kjellander@webrtc.orgb2d74972013-01-26 16:36:40 +000072 size_t barcode_error_position = line.find("Barcode error");
ehmaldonado1dffc622017-02-02 08:10:00 -080073 if (barcode_error_position != std::string::npos) {
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000074 return true;
75 }
76 return false;
77}
78
79bool GetNextStatsLine(FILE* stats_file, char* line) {
80 int chars = 0;
81 char buf = 0;
82
83 while (buf != '\n') {
84 size_t chars_read = fread(&buf, 1, 1, stats_file);
85 if (chars_read != 1 || feof(stats_file)) {
86 return false;
87 }
88 line[chars] = buf;
89 ++chars;
90 }
91 line[chars-1] = '\0'; // Strip the trailing \n and put end of string.
92 return true;
93}
94
Peter Boström0c4e06b2015-10-07 12:23:21 +020095bool ExtractFrameFromYuvFile(const char* i420_file_name,
96 int width,
97 int height,
98 int frame_number,
99 uint8_t* result_frame) {
vspasova@webrtc.orgac410e22012-08-27 14:57:19 +0000100 int frame_size = GetI420FrameSize(width, height);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000101 int offset = frame_number * frame_size; // Calculate offset for the frame.
102 bool errors = false;
103
104 FILE* input_file = fopen(i420_file_name, "rb");
105 if (input_file == NULL) {
106 fprintf(stderr, "Couldn't open input file for reading: %s\n",
107 i420_file_name);
108 return false;
109 }
110
111 // Change stream pointer to new offset.
112 fseek(input_file, offset, SEEK_SET);
113
114 size_t bytes_read = fread(result_frame, 1, frame_size, input_file);
vspasova@webrtc.orgac410e22012-08-27 14:57:19 +0000115 if (bytes_read != static_cast<size_t>(frame_size) &&
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000116 ferror(input_file)) {
117 fprintf(stdout, "Error while reading frame no %d from file %s\n",
118 frame_number, i420_file_name);
119 errors = true;
120 }
121 fclose(input_file);
122 return !errors;
123}
124
Peter Boström0c4e06b2015-10-07 12:23:21 +0200125bool ExtractFrameFromY4mFile(const char* y4m_file_name,
126 int width,
127 int height,
128 int frame_number,
129 uint8_t* result_frame) {
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000130 int frame_size = GetI420FrameSize(width, height);
charujain1b5b22d2016-11-29 02:00:52 -0800131 int inital_offset = frame_number * (frame_size + Y4M_FRAME_HEADER_SIZE);
132 int frame_offset = 0;
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000133
134 FILE* input_file = fopen(y4m_file_name, "rb");
135 if (input_file == NULL) {
136 fprintf(stderr, "Couldn't open input file for reading: %s\n",
137 y4m_file_name);
138 return false;
139 }
140
141 // YUV4MPEG2, a.k.a. Y4M File format has a file header and a frame header. The
142 // file header has the aspect: "YUV4MPEG2 C420 W640 H360 Ip F30:1 A1:1".
charujain1b5b22d2016-11-29 02:00:52 -0800143 char frame_header[Y4M_FILE_HEADER_MAX_SIZE];
144 size_t bytes_read =
145 fread(frame_header, 1, Y4M_FILE_HEADER_MAX_SIZE - 1, input_file);
146 if (bytes_read != static_cast<size_t>(frame_size) && ferror(input_file)) {
147 fprintf(stdout, "Error while reading frame from file %s\n",
148 y4m_file_name);
149 fclose(input_file);
150 return false;
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000151 }
charujain1b5b22d2016-11-29 02:00:52 -0800152 frame_header[bytes_read] = '\0';
153 std::string header_contents(frame_header);
154 std::size_t found = header_contents.find(Y4M_FRAME_DELIMITER);
155 if (found == std::string::npos) {
156 fprintf(stdout, "Corrupted Y4M header, could not find \"FRAME\" in %s\n",
157 header_contents.c_str());
158 fclose(input_file);
159 return false;
160 }
161 frame_offset = static_cast<int>(found);
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000162
163 // Change stream pointer to new offset, skipping the frame header as well.
charujain1b5b22d2016-11-29 02:00:52 -0800164 fseek(input_file, inital_offset + frame_offset + Y4M_FRAME_HEADER_SIZE,
165 SEEK_SET);
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000166
charujain1b5b22d2016-11-29 02:00:52 -0800167 bytes_read = fread(result_frame, 1, frame_size, input_file);
168 if (feof(input_file)) {
169 fclose(input_file);
170 return false;
171 }
172 if (bytes_read != static_cast<size_t>(frame_size) && ferror(input_file)) {
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000173 fprintf(stdout, "Error while reading frame no %d from file %s\n",
174 frame_number, y4m_file_name);
charujain1b5b22d2016-11-29 02:00:52 -0800175 fclose(input_file);
176 return false;
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000177 }
178
179 fclose(input_file);
charujain1b5b22d2016-11-29 02:00:52 -0800180 return true;
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000181}
182
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000183double CalculateMetrics(VideoAnalysisMetricsType video_metrics_type,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200184 const uint8_t* ref_frame,
185 const uint8_t* test_frame,
186 int width,
187 int height) {
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000188 if (!ref_frame || !test_frame)
189 return -1;
190 else if (height < 0 || width < 0)
191 return -1;
192 int half_width = (width + 1) >> 1;
193 int half_height = (height + 1) >> 1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200194 const uint8_t* src_y_a = ref_frame;
195 const uint8_t* src_u_a = src_y_a + width * height;
196 const uint8_t* src_v_a = src_u_a + half_width * half_height;
197 const uint8_t* src_y_b = test_frame;
198 const uint8_t* src_u_b = src_y_b + width * height;
199 const uint8_t* src_v_b = src_u_b + half_width * half_height;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000200
201 int stride_y = width;
202 int stride_uv = half_width;
203
204 double result = 0.0;
205
206 switch (video_metrics_type) {
207 case kPSNR:
208 // In the following: stride is determined by width.
209 result = libyuv::I420Psnr(src_y_a, width, src_u_a, half_width,
210 src_v_a, half_width, src_y_b, width,
211 src_u_b, half_width, src_v_b, half_width,
212 width, height);
213 // LibYuv sets the max psnr value to 128, we restrict it to 48.
214 // In case of 0 mse in one frame, 128 can skew the results significantly.
215 result = (result > 48.0) ? 48.0 : result;
216 break;
217 case kSSIM:
218 result = libyuv::I420Ssim(src_y_a, stride_y, src_u_a, stride_uv,
219 src_v_a, stride_uv, src_y_b, stride_y,
220 src_u_b, stride_uv, src_v_b, stride_uv,
221 width, height);
222 break;
223 default:
224 assert(false);
225 }
226
227 return result;
228}
229
mandermo74568172017-01-17 03:24:57 -0800230void RunAnalysis(const char* reference_file_name,
231 const char* test_file_name,
232 const char* stats_file_reference_name,
233 const char* stats_file_test_name,
234 int width,
235 int height,
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000236 ResultsContainer* results) {
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000237 // Check if the reference_file_name ends with "y4m".
238 bool y4m_mode = false;
jbauch0f2e9392015-12-10 03:11:42 -0800239 if (std::string(reference_file_name).find("y4m") != std::string::npos) {
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000240 y4m_mode = true;
241 }
242
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000243 int size = GetI420FrameSize(width, height);
mandermo74568172017-01-17 03:24:57 -0800244 FILE* stats_file_ref = fopen(stats_file_reference_name, "r");
245 FILE* stats_file_test = fopen(stats_file_test_name, "r");
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000246
247 // String buffer for the lines in the stats file.
248 char line[STATS_LINE_LENGTH];
249
250 // Allocate buffers for test and reference frames.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200251 uint8_t* test_frame = new uint8_t[size];
252 uint8_t* reference_frame = new uint8_t[size];
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000253 int previous_frame_number = -1;
254
mandermo74568172017-01-17 03:24:57 -0800255 // Maps barcode id to the frame id for the reference video.
256 // In case two frames have same id, then we only save the first one.
257 std::map<int, int> ref_barcode_to_frame;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000258 // While there are entries in the stats file.
mandermo74568172017-01-17 03:24:57 -0800259 while (GetNextStatsLine(stats_file_ref, line)) {
260 int extracted_ref_frame = ExtractFrameSequenceNumber(line);
261 int decoded_frame_number = ExtractDecodedFrameNumber(line);
262
263 // Insert will only add if it is not in map already.
264 ref_barcode_to_frame.insert(
265 std::make_pair(decoded_frame_number, extracted_ref_frame));
266 }
267
268 while (GetNextStatsLine(stats_file_test, line)) {
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000269 int extracted_test_frame = ExtractFrameSequenceNumber(line);
270 int decoded_frame_number = ExtractDecodedFrameNumber(line);
mandermo74568172017-01-17 03:24:57 -0800271 auto it = ref_barcode_to_frame.find(decoded_frame_number);
272 if (it == ref_barcode_to_frame.end()) {
273 // Not found in the reference video.
274 // TODO(mandermo) print
275 continue;
276 }
277 int extracted_ref_frame = it->second;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000278
279 // If there was problem decoding the barcode in this frame or the frame has
280 // been duplicated, continue.
281 if (IsThereBarcodeError(line) ||
282 decoded_frame_number == previous_frame_number) {
283 continue;
284 }
285
286 assert(extracted_test_frame != -1);
287 assert(decoded_frame_number != -1);
288
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000289 ExtractFrameFromYuvFile(test_file_name, width, height, extracted_test_frame,
290 test_frame);
291 if (y4m_mode) {
292 ExtractFrameFromY4mFile(reference_file_name, width, height,
mandermo74568172017-01-17 03:24:57 -0800293 extracted_ref_frame, reference_frame);
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000294 } else {
295 ExtractFrameFromYuvFile(reference_file_name, width, height,
mandermo74568172017-01-17 03:24:57 -0800296 extracted_ref_frame, reference_frame);
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000297 }
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000298
299 // Calculate the PSNR and SSIM.
mandermo74568172017-01-17 03:24:57 -0800300 double result_psnr =
301 CalculateMetrics(kPSNR, reference_frame, test_frame, width, height);
302 double result_ssim =
303 CalculateMetrics(kSSIM, reference_frame, test_frame, width, height);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000304
305 previous_frame_number = decoded_frame_number;
306
307 // Fill in the result struct.
308 AnalysisResult result;
309 result.frame_number = decoded_frame_number;
310 result.psnr_value = result_psnr;
311 result.ssim_value = result_ssim;
312
313 results->frames.push_back(result);
314 }
315
316 // Cleanup.
mandermo74568172017-01-17 03:24:57 -0800317 fclose(stats_file_ref);
318 fclose(stats_file_test);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000319 delete[] test_frame;
320 delete[] reference_frame;
321}
322
mandermo7cebe782017-02-16 01:36:43 -0800323std::vector<std::pair<int, int> > CalculateFrameClusters(
324 FILE* file,
325 int* num_decode_errors) {
326 if (num_decode_errors) {
327 *num_decode_errors = 0;
328 }
mandermo74568172017-01-17 03:24:57 -0800329 std::vector<std::pair<int, int> > frame_cnt;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000330 char line[STATS_LINE_LENGTH];
mandermo74568172017-01-17 03:24:57 -0800331 while (GetNextStatsLine(file, line)) {
mandermo7cebe782017-02-16 01:36:43 -0800332 int decoded_frame_number;
333 if (IsThereBarcodeError(line)) {
334 decoded_frame_number = DECODE_ERROR;
335 if (num_decode_errors) {
336 ++*num_decode_errors;
337 }
338 } else {
339 decoded_frame_number = ExtractDecodedFrameNumber(line);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000340 }
mandermo7cebe782017-02-16 01:36:43 -0800341 if (frame_cnt.size() >= 2 && decoded_frame_number != DECODE_ERROR &&
342 frame_cnt.back().first == DECODE_ERROR &&
343 frame_cnt[frame_cnt.size() - 2].first == decoded_frame_number) {
344 // Handle when there is a decoding error inside a cluster of frames.
345 frame_cnt[frame_cnt.size() - 2].second += frame_cnt.back().second + 1;
346 frame_cnt.pop_back();
347 } else if (frame_cnt.empty() ||
348 frame_cnt.back().first != decoded_frame_number) {
mandermo74568172017-01-17 03:24:57 -0800349 frame_cnt.push_back(std::make_pair(decoded_frame_number, 1));
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000350 } else {
mandermo74568172017-01-17 03:24:57 -0800351 ++frame_cnt.back().second;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000352 }
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000353 }
mandermo74568172017-01-17 03:24:57 -0800354 return frame_cnt;
355}
mandermo74568172017-01-17 03:24:57 -0800356
Edward Lemur2e5966b2018-01-30 15:33:02 +0100357void GetMaxRepeatedAndSkippedFrames(const std::string& stats_file_ref_name,
358 const std::string& stats_file_test_name,
359 ResultsContainer* results) {
mandermo74568172017-01-17 03:24:57 -0800360 FILE* stats_file_ref = fopen(stats_file_ref_name.c_str(), "r");
361 FILE* stats_file_test = fopen(stats_file_test_name.c_str(), "r");
362 if (stats_file_ref == NULL) {
363 fprintf(stderr, "Couldn't open reference stats file for reading: %s\n",
364 stats_file_ref_name.c_str());
365 return;
366 }
367 if (stats_file_test == NULL) {
368 fprintf(stderr, "Couldn't open test stats file for reading: %s\n",
369 stats_file_test_name.c_str());
370 fclose(stats_file_ref);
371 return;
372 }
373
374 int max_repeated_frames = 1;
mandermo7cebe782017-02-16 01:36:43 -0800375 int max_skipped_frames = 0;
376
377 int decode_errors_ref = 0;
378 int decode_errors_test = 0;
mandermo74568172017-01-17 03:24:57 -0800379
380 std::vector<std::pair<int, int> > frame_cnt_ref =
mandermo7cebe782017-02-16 01:36:43 -0800381 CalculateFrameClusters(stats_file_ref, &decode_errors_ref);
mandermo74568172017-01-17 03:24:57 -0800382
383 std::vector<std::pair<int, int> > frame_cnt_test =
mandermo7cebe782017-02-16 01:36:43 -0800384 CalculateFrameClusters(stats_file_test, &decode_errors_test);
mandermo74568172017-01-17 03:24:57 -0800385
386 fclose(stats_file_ref);
387 fclose(stats_file_test);
388
389 auto it_ref = frame_cnt_ref.begin();
390 auto it_test = frame_cnt_test.begin();
391 auto end_ref = frame_cnt_ref.end();
392 auto end_test = frame_cnt_test.end();
393
394 if (it_test == end_test || it_ref == end_ref) {
395 fprintf(stderr, "Either test or ref file is empty, nothing to print\n");
396 return;
397 }
398
mandermo7cebe782017-02-16 01:36:43 -0800399 while (it_test != end_test && it_test->first == DECODE_ERROR) {
400 ++it_test;
401 }
402
403 if (it_test == end_test) {
404 fprintf(stderr, "Test video only has barcode decode errors\n");
405 return;
406 }
407
mandermo74568172017-01-17 03:24:57 -0800408 // Find the first frame in the reference video that match the first frame in
409 // the test video.
mandermo7cebe782017-02-16 01:36:43 -0800410 while (it_ref != end_ref &&
411 (it_ref->first == DECODE_ERROR || it_ref->first != it_test->first)) {
mandermo74568172017-01-17 03:24:57 -0800412 ++it_ref;
413 }
414 if (it_ref == end_ref) {
415 fprintf(stderr,
416 "The barcode in the test video's first frame is not in the "
417 "reference video.\n");
418 return;
419 }
420
mandermo7cebe782017-02-16 01:36:43 -0800421 int total_skipped_frames = 0;
mandermo74568172017-01-17 03:24:57 -0800422 for (;;) {
423 max_repeated_frames =
424 std::max(max_repeated_frames, it_test->second - it_ref->second + 1);
mandermo7cebe782017-02-16 01:36:43 -0800425
426 bool passed_error = false;
427
mandermo74568172017-01-17 03:24:57 -0800428 ++it_test;
mandermo7cebe782017-02-16 01:36:43 -0800429 while (it_test != end_test && it_test->first == DECODE_ERROR) {
430 ++it_test;
431 passed_error = true;
432 }
mandermo74568172017-01-17 03:24:57 -0800433 if (it_test == end_test) {
434 break;
435 }
mandermo7cebe782017-02-16 01:36:43 -0800436
mandermo74568172017-01-17 03:24:57 -0800437 int skipped_frames = 0;
438 ++it_ref;
mandermo7cebe782017-02-16 01:36:43 -0800439 for (; it_ref != end_ref; ++it_ref) {
440 if (it_ref->first != DECODE_ERROR && it_ref->first >= it_test->first) {
441 break;
442 }
443 ++skipped_frames;
mandermo74568172017-01-17 03:24:57 -0800444 }
mandermo7cebe782017-02-16 01:36:43 -0800445 if (passed_error) {
446 // If we pass an error in the test video, then we are conservative
447 // and will not calculate skipped frames for that part.
448 skipped_frames = 0;
mandermo74568172017-01-17 03:24:57 -0800449 }
mandermo7cebe782017-02-16 01:36:43 -0800450 if (it_ref != end_ref && it_ref->first == it_test->first) {
451 total_skipped_frames += skipped_frames;
452 if (skipped_frames > max_skipped_frames) {
453 max_skipped_frames = skipped_frames;
454 }
455 continue;
mandermo74568172017-01-17 03:24:57 -0800456 }
Edward Lemur2e5966b2018-01-30 15:33:02 +0100457 fprintf(stdout,
janssond4d2ece2017-05-30 07:48:06 -0700458 "Found barcode %d in test video, which is not in reference video\n",
janssoncc8b14b2017-05-23 08:31:11 -0700459 it_test->first);
janssond4d2ece2017-05-30 07:48:06 -0700460 break;
mandermo74568172017-01-17 03:24:57 -0800461 }
462
Edward Lemur2e5966b2018-01-30 15:33:02 +0100463 results->max_repeated_frames = max_repeated_frames;
464 results->max_skipped_frames = max_skipped_frames;
465 results->total_skipped_frames = total_skipped_frames;
466 results->decode_errors_ref = decode_errors_ref;
467 results->decode_errors_test = decode_errors_test;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000468}
469
kjellander@webrtc.orgf880f862013-09-10 12:10:01 +0000470void PrintAnalysisResults(const std::string& label, ResultsContainer* results) {
kjellander@webrtc.orge2df8b72013-11-03 18:34:51 +0000471 PrintAnalysisResults(stdout, label, results);
472}
473
474void PrintAnalysisResults(FILE* output, const std::string& label,
475 ResultsContainer* results) {
Edward Lemur2e5966b2018-01-30 15:33:02 +0100476 SetPerfResultsOutput(output);
kjellander@webrtc.orgf880f862013-09-10 12:10:01 +0000477
478 if (results->frames.size() > 0u) {
Edward Lemur2e5966b2018-01-30 15:33:02 +0100479 PrintResult("Unique_frames_count", "", label, results->frames.size(),
480 "score", false);
kjellander@webrtc.orgf880f862013-09-10 12:10:01 +0000481
Edward Lemur2e5966b2018-01-30 15:33:02 +0100482 std::vector<double> psnr_values;
483 std::vector<double> ssim_values;
484 for (const auto& frame : results->frames) {
485 psnr_values.push_back(frame.psnr_value);
486 ssim_values.push_back(frame.ssim_value);
kjellander@webrtc.orgf880f862013-09-10 12:10:01 +0000487 }
Edward Lemur2e5966b2018-01-30 15:33:02 +0100488
489 PrintResultList("PSNR", "", label, psnr_values, "dB", false);
490 PrintResultList("SSIM", "", label, ssim_values, "score", false);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000491 }
Edward Lemur2e5966b2018-01-30 15:33:02 +0100492
493 PrintResult("Max_repeated", "", label, results->max_repeated_frames, "",
494 false);
495 PrintResult("Max_skipped", "", label, results->max_skipped_frames, "", false);
496 PrintResult("Total_skipped", "", label, results->total_skipped_frames, "",
497 false);
498 PrintResult("Decode_errors_reference", "", label, results->decode_errors_ref,
499 "", false);
500 PrintResult("Decode_errors_test", "", label, results->decode_errors_test, "",
501 false);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000502}
503
504} // namespace test
505} // namespace webrtc