blob: 60a4a016ccab82e3f8c3dae5d2c12406ac215fe5 [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>
mandermo74568172017-01-17 03:24:57 -080017#include <map>
Yves Gerey665174f2018-06-19 15:03:05 +020018#include <string>
mandermo74568172017-01-17 03:24:57 -080019#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
Yves Gerey665174f2018-06-19 15:03:05 +020038 int y_plane = width * height; // I420 Y plane.
vspasova@webrtc.orgac410e22012-08-27 14:57:19 +000039 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 }
Yves Gerey665174f2018-06-19 15:03:05 +020091 line[chars - 1] = '\0'; // Strip the trailing \n and put end of string.
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +000092 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);
Yves Gerey665174f2018-06-19 15:03:05 +0200115 if (bytes_read != static_cast<size_t>(frame_size) && ferror(input_file)) {
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000116 fprintf(stdout, "Error while reading frame no %d from file %s\n",
117 frame_number, i420_file_name);
118 errors = true;
119 }
120 fclose(input_file);
121 return !errors;
122}
123
Peter Boström0c4e06b2015-10-07 12:23:21 +0200124bool ExtractFrameFromY4mFile(const char* y4m_file_name,
125 int width,
126 int height,
127 int frame_number,
128 uint8_t* result_frame) {
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000129 int frame_size = GetI420FrameSize(width, height);
charujain1b5b22d2016-11-29 02:00:52 -0800130 int inital_offset = frame_number * (frame_size + Y4M_FRAME_HEADER_SIZE);
131 int frame_offset = 0;
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000132
133 FILE* input_file = fopen(y4m_file_name, "rb");
134 if (input_file == NULL) {
135 fprintf(stderr, "Couldn't open input file for reading: %s\n",
136 y4m_file_name);
137 return false;
138 }
139
140 // YUV4MPEG2, a.k.a. Y4M File format has a file header and a frame header. The
141 // file header has the aspect: "YUV4MPEG2 C420 W640 H360 Ip F30:1 A1:1".
charujain1b5b22d2016-11-29 02:00:52 -0800142 char frame_header[Y4M_FILE_HEADER_MAX_SIZE];
143 size_t bytes_read =
144 fread(frame_header, 1, Y4M_FILE_HEADER_MAX_SIZE - 1, input_file);
145 if (bytes_read != static_cast<size_t>(frame_size) && ferror(input_file)) {
Yves Gerey665174f2018-06-19 15:03:05 +0200146 fprintf(stdout, "Error while reading frame from file %s\n", y4m_file_name);
charujain1b5b22d2016-11-29 02:00:52 -0800147 fclose(input_file);
148 return false;
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000149 }
charujain1b5b22d2016-11-29 02:00:52 -0800150 frame_header[bytes_read] = '\0';
151 std::string header_contents(frame_header);
152 std::size_t found = header_contents.find(Y4M_FRAME_DELIMITER);
153 if (found == std::string::npos) {
154 fprintf(stdout, "Corrupted Y4M header, could not find \"FRAME\" in %s\n",
Yves Gerey665174f2018-06-19 15:03:05 +0200155 header_contents.c_str());
charujain1b5b22d2016-11-29 02:00:52 -0800156 fclose(input_file);
157 return false;
158 }
159 frame_offset = static_cast<int>(found);
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000160
161 // Change stream pointer to new offset, skipping the frame header as well.
charujain1b5b22d2016-11-29 02:00:52 -0800162 fseek(input_file, inital_offset + frame_offset + Y4M_FRAME_HEADER_SIZE,
163 SEEK_SET);
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000164
charujain1b5b22d2016-11-29 02:00:52 -0800165 bytes_read = fread(result_frame, 1, frame_size, input_file);
166 if (feof(input_file)) {
167 fclose(input_file);
168 return false;
169 }
170 if (bytes_read != static_cast<size_t>(frame_size) && ferror(input_file)) {
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000171 fprintf(stdout, "Error while reading frame no %d from file %s\n",
172 frame_number, y4m_file_name);
charujain1b5b22d2016-11-29 02:00:52 -0800173 fclose(input_file);
174 return false;
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000175 }
176
177 fclose(input_file);
charujain1b5b22d2016-11-29 02:00:52 -0800178 return true;
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000179}
180
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000181double CalculateMetrics(VideoAnalysisMetricsType video_metrics_type,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200182 const uint8_t* ref_frame,
183 const uint8_t* test_frame,
184 int width,
185 int height) {
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000186 if (!ref_frame || !test_frame)
187 return -1;
188 else if (height < 0 || width < 0)
189 return -1;
190 int half_width = (width + 1) >> 1;
191 int half_height = (height + 1) >> 1;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200192 const uint8_t* src_y_a = ref_frame;
193 const uint8_t* src_u_a = src_y_a + width * height;
194 const uint8_t* src_v_a = src_u_a + half_width * half_height;
195 const uint8_t* src_y_b = test_frame;
196 const uint8_t* src_u_b = src_y_b + width * height;
197 const uint8_t* src_v_b = src_u_b + half_width * half_height;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000198
199 int stride_y = width;
200 int stride_uv = half_width;
201
202 double result = 0.0;
203
204 switch (video_metrics_type) {
205 case kPSNR:
206 // In the following: stride is determined by width.
Yves Gerey665174f2018-06-19 15:03:05 +0200207 result = libyuv::I420Psnr(src_y_a, width, src_u_a, half_width, src_v_a,
208 half_width, src_y_b, width, src_u_b, half_width,
209 src_v_b, half_width, width, height);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000210 // LibYuv sets the max psnr value to 128, we restrict it to 48.
211 // In case of 0 mse in one frame, 128 can skew the results significantly.
212 result = (result > 48.0) ? 48.0 : result;
213 break;
214 case kSSIM:
Yves Gerey665174f2018-06-19 15:03:05 +0200215 result = libyuv::I420Ssim(src_y_a, stride_y, src_u_a, stride_uv, src_v_a,
216 stride_uv, src_y_b, stride_y, src_u_b,
217 stride_uv, src_v_b, stride_uv, width, height);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000218 break;
219 default:
220 assert(false);
221 }
222
223 return result;
224}
225
mandermo74568172017-01-17 03:24:57 -0800226void RunAnalysis(const char* reference_file_name,
227 const char* test_file_name,
228 const char* stats_file_reference_name,
229 const char* stats_file_test_name,
230 int width,
231 int height,
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000232 ResultsContainer* results) {
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000233 // Check if the reference_file_name ends with "y4m".
234 bool y4m_mode = false;
jbauch0f2e9392015-12-10 03:11:42 -0800235 if (std::string(reference_file_name).find("y4m") != std::string::npos) {
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000236 y4m_mode = true;
237 }
238
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000239 int size = GetI420FrameSize(width, height);
mandermo74568172017-01-17 03:24:57 -0800240 FILE* stats_file_ref = fopen(stats_file_reference_name, "r");
241 FILE* stats_file_test = fopen(stats_file_test_name, "r");
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000242
243 // String buffer for the lines in the stats file.
244 char line[STATS_LINE_LENGTH];
245
246 // Allocate buffers for test and reference frames.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200247 uint8_t* test_frame = new uint8_t[size];
248 uint8_t* reference_frame = new uint8_t[size];
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000249 int previous_frame_number = -1;
250
mandermo74568172017-01-17 03:24:57 -0800251 // Maps barcode id to the frame id for the reference video.
252 // In case two frames have same id, then we only save the first one.
253 std::map<int, int> ref_barcode_to_frame;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000254 // While there are entries in the stats file.
mandermo74568172017-01-17 03:24:57 -0800255 while (GetNextStatsLine(stats_file_ref, line)) {
256 int extracted_ref_frame = ExtractFrameSequenceNumber(line);
257 int decoded_frame_number = ExtractDecodedFrameNumber(line);
258
259 // Insert will only add if it is not in map already.
260 ref_barcode_to_frame.insert(
261 std::make_pair(decoded_frame_number, extracted_ref_frame));
262 }
263
264 while (GetNextStatsLine(stats_file_test, line)) {
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000265 int extracted_test_frame = ExtractFrameSequenceNumber(line);
266 int decoded_frame_number = ExtractDecodedFrameNumber(line);
mandermo74568172017-01-17 03:24:57 -0800267 auto it = ref_barcode_to_frame.find(decoded_frame_number);
268 if (it == ref_barcode_to_frame.end()) {
269 // Not found in the reference video.
270 // TODO(mandermo) print
271 continue;
272 }
273 int extracted_ref_frame = it->second;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000274
275 // If there was problem decoding the barcode in this frame or the frame has
276 // been duplicated, continue.
277 if (IsThereBarcodeError(line) ||
278 decoded_frame_number == previous_frame_number) {
279 continue;
280 }
281
282 assert(extracted_test_frame != -1);
283 assert(decoded_frame_number != -1);
284
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000285 ExtractFrameFromYuvFile(test_file_name, width, height, extracted_test_frame,
286 test_frame);
287 if (y4m_mode) {
288 ExtractFrameFromY4mFile(reference_file_name, width, height,
mandermo74568172017-01-17 03:24:57 -0800289 extracted_ref_frame, reference_frame);
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000290 } else {
291 ExtractFrameFromYuvFile(reference_file_name, width, height,
mandermo74568172017-01-17 03:24:57 -0800292 extracted_ref_frame, reference_frame);
mcasas@webrtc.org6e2d0122014-03-14 12:45:45 +0000293 }
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000294
295 // Calculate the PSNR and SSIM.
mandermo74568172017-01-17 03:24:57 -0800296 double result_psnr =
297 CalculateMetrics(kPSNR, reference_frame, test_frame, width, height);
298 double result_ssim =
299 CalculateMetrics(kSSIM, reference_frame, test_frame, width, height);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000300
301 previous_frame_number = decoded_frame_number;
302
303 // Fill in the result struct.
304 AnalysisResult result;
305 result.frame_number = decoded_frame_number;
306 result.psnr_value = result_psnr;
307 result.ssim_value = result_ssim;
308
309 results->frames.push_back(result);
310 }
311
312 // Cleanup.
mandermo74568172017-01-17 03:24:57 -0800313 fclose(stats_file_ref);
314 fclose(stats_file_test);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000315 delete[] test_frame;
316 delete[] reference_frame;
317}
318
mandermo7cebe782017-02-16 01:36:43 -0800319std::vector<std::pair<int, int> > CalculateFrameClusters(
320 FILE* file,
321 int* num_decode_errors) {
322 if (num_decode_errors) {
323 *num_decode_errors = 0;
324 }
mandermo74568172017-01-17 03:24:57 -0800325 std::vector<std::pair<int, int> > frame_cnt;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000326 char line[STATS_LINE_LENGTH];
mandermo74568172017-01-17 03:24:57 -0800327 while (GetNextStatsLine(file, line)) {
mandermo7cebe782017-02-16 01:36:43 -0800328 int decoded_frame_number;
329 if (IsThereBarcodeError(line)) {
330 decoded_frame_number = DECODE_ERROR;
331 if (num_decode_errors) {
332 ++*num_decode_errors;
333 }
334 } else {
335 decoded_frame_number = ExtractDecodedFrameNumber(line);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000336 }
mandermo7cebe782017-02-16 01:36:43 -0800337 if (frame_cnt.size() >= 2 && decoded_frame_number != DECODE_ERROR &&
338 frame_cnt.back().first == DECODE_ERROR &&
339 frame_cnt[frame_cnt.size() - 2].first == decoded_frame_number) {
340 // Handle when there is a decoding error inside a cluster of frames.
341 frame_cnt[frame_cnt.size() - 2].second += frame_cnt.back().second + 1;
342 frame_cnt.pop_back();
343 } else if (frame_cnt.empty() ||
344 frame_cnt.back().first != decoded_frame_number) {
mandermo74568172017-01-17 03:24:57 -0800345 frame_cnt.push_back(std::make_pair(decoded_frame_number, 1));
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000346 } else {
mandermo74568172017-01-17 03:24:57 -0800347 ++frame_cnt.back().second;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000348 }
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000349 }
mandermo74568172017-01-17 03:24:57 -0800350 return frame_cnt;
351}
mandermo74568172017-01-17 03:24:57 -0800352
Edward Lemur2e5966b2018-01-30 15:33:02 +0100353void GetMaxRepeatedAndSkippedFrames(const std::string& stats_file_ref_name,
354 const std::string& stats_file_test_name,
355 ResultsContainer* results) {
mandermo74568172017-01-17 03:24:57 -0800356 FILE* stats_file_ref = fopen(stats_file_ref_name.c_str(), "r");
357 FILE* stats_file_test = fopen(stats_file_test_name.c_str(), "r");
358 if (stats_file_ref == NULL) {
359 fprintf(stderr, "Couldn't open reference stats file for reading: %s\n",
360 stats_file_ref_name.c_str());
361 return;
362 }
363 if (stats_file_test == NULL) {
364 fprintf(stderr, "Couldn't open test stats file for reading: %s\n",
365 stats_file_test_name.c_str());
366 fclose(stats_file_ref);
367 return;
368 }
369
370 int max_repeated_frames = 1;
mandermo7cebe782017-02-16 01:36:43 -0800371 int max_skipped_frames = 0;
372
373 int decode_errors_ref = 0;
374 int decode_errors_test = 0;
mandermo74568172017-01-17 03:24:57 -0800375
376 std::vector<std::pair<int, int> > frame_cnt_ref =
mandermo7cebe782017-02-16 01:36:43 -0800377 CalculateFrameClusters(stats_file_ref, &decode_errors_ref);
mandermo74568172017-01-17 03:24:57 -0800378
379 std::vector<std::pair<int, int> > frame_cnt_test =
mandermo7cebe782017-02-16 01:36:43 -0800380 CalculateFrameClusters(stats_file_test, &decode_errors_test);
mandermo74568172017-01-17 03:24:57 -0800381
382 fclose(stats_file_ref);
383 fclose(stats_file_test);
384
385 auto it_ref = frame_cnt_ref.begin();
386 auto it_test = frame_cnt_test.begin();
387 auto end_ref = frame_cnt_ref.end();
388 auto end_test = frame_cnt_test.end();
389
390 if (it_test == end_test || it_ref == end_ref) {
391 fprintf(stderr, "Either test or ref file is empty, nothing to print\n");
392 return;
393 }
394
mandermo7cebe782017-02-16 01:36:43 -0800395 while (it_test != end_test && it_test->first == DECODE_ERROR) {
396 ++it_test;
397 }
398
399 if (it_test == end_test) {
400 fprintf(stderr, "Test video only has barcode decode errors\n");
401 return;
402 }
403
mandermo74568172017-01-17 03:24:57 -0800404 // Find the first frame in the reference video that match the first frame in
405 // the test video.
mandermo7cebe782017-02-16 01:36:43 -0800406 while (it_ref != end_ref &&
407 (it_ref->first == DECODE_ERROR || it_ref->first != it_test->first)) {
mandermo74568172017-01-17 03:24:57 -0800408 ++it_ref;
409 }
410 if (it_ref == end_ref) {
411 fprintf(stderr,
412 "The barcode in the test video's first frame is not in the "
413 "reference video.\n");
414 return;
415 }
416
mandermo7cebe782017-02-16 01:36:43 -0800417 int total_skipped_frames = 0;
mandermo74568172017-01-17 03:24:57 -0800418 for (;;) {
419 max_repeated_frames =
420 std::max(max_repeated_frames, it_test->second - it_ref->second + 1);
mandermo7cebe782017-02-16 01:36:43 -0800421
422 bool passed_error = false;
423
mandermo74568172017-01-17 03:24:57 -0800424 ++it_test;
mandermo7cebe782017-02-16 01:36:43 -0800425 while (it_test != end_test && it_test->first == DECODE_ERROR) {
426 ++it_test;
427 passed_error = true;
428 }
mandermo74568172017-01-17 03:24:57 -0800429 if (it_test == end_test) {
430 break;
431 }
mandermo7cebe782017-02-16 01:36:43 -0800432
mandermo74568172017-01-17 03:24:57 -0800433 int skipped_frames = 0;
434 ++it_ref;
mandermo7cebe782017-02-16 01:36:43 -0800435 for (; it_ref != end_ref; ++it_ref) {
436 if (it_ref->first != DECODE_ERROR && it_ref->first >= it_test->first) {
437 break;
438 }
439 ++skipped_frames;
mandermo74568172017-01-17 03:24:57 -0800440 }
mandermo7cebe782017-02-16 01:36:43 -0800441 if (passed_error) {
442 // If we pass an error in the test video, then we are conservative
443 // and will not calculate skipped frames for that part.
444 skipped_frames = 0;
mandermo74568172017-01-17 03:24:57 -0800445 }
mandermo7cebe782017-02-16 01:36:43 -0800446 if (it_ref != end_ref && it_ref->first == it_test->first) {
447 total_skipped_frames += skipped_frames;
448 if (skipped_frames > max_skipped_frames) {
449 max_skipped_frames = skipped_frames;
450 }
451 continue;
mandermo74568172017-01-17 03:24:57 -0800452 }
Edward Lemur2e5966b2018-01-30 15:33:02 +0100453 fprintf(stdout,
janssond4d2ece2017-05-30 07:48:06 -0700454 "Found barcode %d in test video, which is not in reference video\n",
janssoncc8b14b2017-05-23 08:31:11 -0700455 it_test->first);
janssond4d2ece2017-05-30 07:48:06 -0700456 break;
mandermo74568172017-01-17 03:24:57 -0800457 }
458
Edward Lemur2e5966b2018-01-30 15:33:02 +0100459 results->max_repeated_frames = max_repeated_frames;
460 results->max_skipped_frames = max_skipped_frames;
461 results->total_skipped_frames = total_skipped_frames;
462 results->decode_errors_ref = decode_errors_ref;
463 results->decode_errors_test = decode_errors_test;
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000464}
465
kjellander@webrtc.orgf880f862013-09-10 12:10:01 +0000466void PrintAnalysisResults(const std::string& label, ResultsContainer* results) {
kjellander@webrtc.orge2df8b72013-11-03 18:34:51 +0000467 PrintAnalysisResults(stdout, label, results);
468}
469
Yves Gerey665174f2018-06-19 15:03:05 +0200470void PrintAnalysisResults(FILE* output,
471 const std::string& label,
kjellander@webrtc.orge2df8b72013-11-03 18:34:51 +0000472 ResultsContainer* results) {
Edward Lemur2e5966b2018-01-30 15:33:02 +0100473 SetPerfResultsOutput(output);
kjellander@webrtc.orgf880f862013-09-10 12:10:01 +0000474
475 if (results->frames.size() > 0u) {
Edward Lemur2e5966b2018-01-30 15:33:02 +0100476 PrintResult("Unique_frames_count", "", label, results->frames.size(),
477 "score", false);
kjellander@webrtc.orgf880f862013-09-10 12:10:01 +0000478
Edward Lemur2e5966b2018-01-30 15:33:02 +0100479 std::vector<double> psnr_values;
480 std::vector<double> ssim_values;
481 for (const auto& frame : results->frames) {
482 psnr_values.push_back(frame.psnr_value);
483 ssim_values.push_back(frame.ssim_value);
kjellander@webrtc.orgf880f862013-09-10 12:10:01 +0000484 }
Edward Lemur2e5966b2018-01-30 15:33:02 +0100485
486 PrintResultList("PSNR", "", label, psnr_values, "dB", false);
487 PrintResultList("SSIM", "", label, ssim_values, "score", false);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000488 }
Edward Lemur2e5966b2018-01-30 15:33:02 +0100489
490 PrintResult("Max_repeated", "", label, results->max_repeated_frames, "",
491 false);
492 PrintResult("Max_skipped", "", label, results->max_skipped_frames, "", false);
493 PrintResult("Total_skipped", "", label, results->total_skipped_frames, "",
494 false);
495 PrintResult("Decode_errors_reference", "", label, results->decode_errors_ref,
496 "", false);
497 PrintResult("Decode_errors_test", "", label, results->decode_errors_test, "",
498 false);
vspasova@webrtc.orgfd800702012-08-16 14:07:02 +0000499}
500
501} // namespace test
502} // namespace webrtc