Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(718)

Side by Side Diff: webrtc/tools/frame_analyzer/video_quality_analysis.cc

Issue 2553693002: Comparison of videos with reference frame not starting from zero (Closed)
Patch Set: Updated based on review comments Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/tools/frame_analyzer/video_quality_analysis.h" 11 #include "webrtc/tools/frame_analyzer/video_quality_analysis.h"
12 12
13 #include <assert.h> 13 #include <assert.h>
14 #include <stdio.h> 14 #include <stdio.h>
15 #include <stdlib.h> 15 #include <stdlib.h>
16 #include <algorithm>
16 #include <string> 17 #include <string>
18 #include <map>
19 #include <utility>
17 20
18 #define STATS_LINE_LENGTH 32 21 #define STATS_LINE_LENGTH 32
19 #define Y4M_FILE_HEADER_MAX_SIZE 200 22 #define Y4M_FILE_HEADER_MAX_SIZE 200
20 #define Y4M_FRAME_DELIMITER "FRAME" 23 #define Y4M_FRAME_DELIMITER "FRAME"
21 #define Y4M_FRAME_HEADER_SIZE 6 24 #define Y4M_FRAME_HEADER_SIZE 6
22 25
23 namespace webrtc { 26 namespace webrtc {
24 namespace test { 27 namespace test {
25 28
26 using std::string; 29 using std::string;
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 src_u_b, stride_uv, src_v_b, stride_uv, 220 src_u_b, stride_uv, src_v_b, stride_uv,
218 width, height); 221 width, height);
219 break; 222 break;
220 default: 223 default:
221 assert(false); 224 assert(false);
222 } 225 }
223 226
224 return result; 227 return result;
225 } 228 }
226 229
227 void RunAnalysis(const char* reference_file_name, const char* test_file_name, 230 void RunAnalysis(const char* reference_file_name,
228 const char* stats_file_name, int width, int height, 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,
229 ResultsContainer* results) { 236 ResultsContainer* results) {
230 // Check if the reference_file_name ends with "y4m". 237 // Check if the reference_file_name ends with "y4m".
231 bool y4m_mode = false; 238 bool y4m_mode = false;
232 if (std::string(reference_file_name).find("y4m") != std::string::npos) { 239 if (std::string(reference_file_name).find("y4m") != std::string::npos) {
233 y4m_mode = true; 240 y4m_mode = true;
234 } 241 }
235 242
236 int size = GetI420FrameSize(width, height); 243 int size = GetI420FrameSize(width, height);
237 FILE* stats_file = fopen(stats_file_name, "r"); 244 FILE* stats_file_ref = fopen(stats_file_reference_name, "r");
245 FILE* stats_file_test = fopen(stats_file_test_name, "r");
238 246
239 // String buffer for the lines in the stats file. 247 // String buffer for the lines in the stats file.
240 char line[STATS_LINE_LENGTH]; 248 char line[STATS_LINE_LENGTH];
241 249
242 // Allocate buffers for test and reference frames. 250 // Allocate buffers for test and reference frames.
243 uint8_t* test_frame = new uint8_t[size]; 251 uint8_t* test_frame = new uint8_t[size];
244 uint8_t* reference_frame = new uint8_t[size]; 252 uint8_t* reference_frame = new uint8_t[size];
245 int previous_frame_number = -1; 253 int previous_frame_number = -1;
246 254
255 // 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;
247 // While there are entries in the stats file. 258 // While there are entries in the stats file.
248 while (GetNextStatsLine(stats_file, line)) { 259 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)) {
249 int extracted_test_frame = ExtractFrameSequenceNumber(line); 269 int extracted_test_frame = ExtractFrameSequenceNumber(line);
250 int decoded_frame_number = ExtractDecodedFrameNumber(line); 270 int decoded_frame_number = ExtractDecodedFrameNumber(line);
271 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;
251 278
252 // If there was problem decoding the barcode in this frame or the frame has 279 // If there was problem decoding the barcode in this frame or the frame has
253 // been duplicated, continue. 280 // been duplicated, continue.
254 if (IsThereBarcodeError(line) || 281 if (IsThereBarcodeError(line) ||
255 decoded_frame_number == previous_frame_number) { 282 decoded_frame_number == previous_frame_number) {
256 continue; 283 continue;
257 } 284 }
258 285
259 assert(extracted_test_frame != -1); 286 assert(extracted_test_frame != -1);
260 assert(decoded_frame_number != -1); 287 assert(decoded_frame_number != -1);
261 288
262 ExtractFrameFromYuvFile(test_file_name, width, height, extracted_test_frame, 289 ExtractFrameFromYuvFile(test_file_name, width, height, extracted_test_frame,
263 test_frame); 290 test_frame);
264 if (y4m_mode) { 291 if (y4m_mode) {
265 ExtractFrameFromY4mFile(reference_file_name, width, height, 292 ExtractFrameFromY4mFile(reference_file_name, width, height,
266 decoded_frame_number, reference_frame); 293 extracted_ref_frame, reference_frame);
267 } else { 294 } else {
268 ExtractFrameFromYuvFile(reference_file_name, width, height, 295 ExtractFrameFromYuvFile(reference_file_name, width, height,
269 decoded_frame_number, reference_frame); 296 extracted_ref_frame, reference_frame);
270 } 297 }
271 298
272 // Calculate the PSNR and SSIM. 299 // Calculate the PSNR and SSIM.
273 double result_psnr = CalculateMetrics(kPSNR, reference_frame, test_frame, 300 double result_psnr =
274 width, height); 301 CalculateMetrics(kPSNR, reference_frame, test_frame, width, height);
275 double result_ssim = CalculateMetrics(kSSIM, reference_frame, test_frame, 302 double result_ssim =
276 width, height); 303 CalculateMetrics(kSSIM, reference_frame, test_frame, width, height);
277 304
278 previous_frame_number = decoded_frame_number; 305 previous_frame_number = decoded_frame_number;
279 306
280 // Fill in the result struct. 307 // Fill in the result struct.
281 AnalysisResult result; 308 AnalysisResult result;
282 result.frame_number = decoded_frame_number; 309 result.frame_number = decoded_frame_number;
283 result.psnr_value = result_psnr; 310 result.psnr_value = result_psnr;
284 result.ssim_value = result_ssim; 311 result.ssim_value = result_ssim;
285 312
286 results->frames.push_back(result); 313 results->frames.push_back(result);
287 } 314 }
288 315
289 // Cleanup. 316 // Cleanup.
290 fclose(stats_file); 317 fclose(stats_file_ref);
318 fclose(stats_file_test);
291 delete[] test_frame; 319 delete[] test_frame;
292 delete[] reference_frame; 320 delete[] reference_frame;
293 } 321 }
294 322
295 void PrintMaxRepeatedAndSkippedFrames(const std::string& label, 323 void PrintMaxRepeatedAndSkippedFrames(const std::string& label,
296 const std::string& stats_file_name) { 324 const std::string& stats_file_ref_name,
297 PrintMaxRepeatedAndSkippedFrames(stdout, label, stats_file_name); 325 const std::string& stats_file_test_name) {
326 PrintMaxRepeatedAndSkippedFrames(stdout, label, stats_file_ref_name,
327 stats_file_test_name);
298 } 328 }
299 329
300 void PrintMaxRepeatedAndSkippedFrames(FILE* output, const std::string& label, 330 namespace {
301 const std::string& stats_file_name) { 331 std::vector<std::pair<int, int> > GetBarcodeNrToFrequency(FILE* file) {
302 FILE* stats_file = fopen(stats_file_name.c_str(), "r"); 332 std::vector<std::pair<int, int> > frame_cnt;
303 if (stats_file == NULL) { 333 char line[STATS_LINE_LENGTH];
304 fprintf(stderr, "Couldn't open stats file for reading: %s\n", 334 while (GetNextStatsLine(file, line)) {
305 stats_file_name.c_str()); 335 int decoded_frame_number = ExtractDecodedFrameNumber(line);
336 if (frame_cnt.empty() || frame_cnt.back().first != decoded_frame_number) {
337 frame_cnt.push_back(std::make_pair(decoded_frame_number, 1));
338 } else {
339 ++frame_cnt.back().second;
340 }
341 }
342 return frame_cnt;
343 }
344 } // namespace
345
346 void PrintMaxRepeatedAndSkippedFrames(FILE* output,
347 const std::string& label,
348 const std::string& stats_file_ref_name,
349 const std::string& stats_file_test_name) {
350 FILE* stats_file_ref = fopen(stats_file_ref_name.c_str(), "r");
351 FILE* stats_file_test = fopen(stats_file_test_name.c_str(), "r");
352 if (stats_file_ref == NULL) {
353 fprintf(stderr, "Couldn't open reference stats file for reading: %s\n",
354 stats_file_ref_name.c_str());
306 return; 355 return;
307 } 356 }
308 char line[STATS_LINE_LENGTH]; 357 if (stats_file_test == NULL) {
358 fprintf(stderr, "Couldn't open test stats file for reading: %s\n",
359 stats_file_test_name.c_str());
360 fclose(stats_file_ref);
361 return;
362 }
309 363
310 int repeated_frames = 1;
311 int max_repeated_frames = 1; 364 int max_repeated_frames = 1;
312 int max_skipped_frames = 1; 365 int max_skipped_frames = 1;
313 int previous_frame_number = -1;
314 366
315 while (GetNextStatsLine(stats_file, line)) { 367 std::vector<std::pair<int, int> > frame_cnt_ref =
316 int decoded_frame_number = ExtractDecodedFrameNumber(line); 368 GetBarcodeNrToFrequency(stats_file_ref);
317 369
318 if (decoded_frame_number == -1) { 370 std::vector<std::pair<int, int> > frame_cnt_test =
319 continue; 371 GetBarcodeNrToFrequency(stats_file_test);
372
373 fclose(stats_file_ref);
374 fclose(stats_file_test);
375
376 auto it_ref = frame_cnt_ref.begin();
377 auto it_test = frame_cnt_test.begin();
378 auto end_ref = frame_cnt_ref.end();
379 auto end_test = frame_cnt_test.end();
380
381 if (it_test == end_test || it_ref == end_ref) {
382 fprintf(stderr, "Either test or ref file is empty, nothing to print");
383 return;
384 }
385
386 // Find the first frame in the reference video that match the first frame in
387 // the test video.
388 while (it_ref != end_ref && it_ref->first != it_test->first) {
389 ++it_ref;
390 }
391 if (it_ref == end_ref) {
392 fprintf(stderr,
393 "The barcode in the test videos first frame is not in the "
394 "reference video.");
395 return;
396 }
397
398 for (;;) {
399 max_repeated_frames =
400 std::max(max_repeated_frames, it_test->second - it_ref->second + 1);
401 ++it_test;
402 if (it_test == end_test) {
403 break;
320 } 404 }
405 int skipped_frames = 0;
406 ++it_ref;
407 while (it_ref != end_ref && it_ref->first != it_test->first) {
408 skipped_frames += it_ref->second;
409 ++it_ref;
410 }
411 if (it_ref == end_ref) {
412 fprintf(stderr,
413 "The barcode in the test video is not in the reference video.");
414 return;
415 }
416 if (skipped_frames > max_skipped_frames) {
417 max_skipped_frames = skipped_frames;
418 }
419 }
321 420
322 // Calculate how many frames a cluster of repeated frames contains.
323 if (decoded_frame_number == previous_frame_number) {
324 ++repeated_frames;
325 if (repeated_frames > max_repeated_frames) {
326 max_repeated_frames = repeated_frames;
327 }
328 } else {
329 repeated_frames = 1;
330 }
331
332 // Calculate how much frames have been skipped.
333 if (decoded_frame_number != 0 && previous_frame_number != -1) {
334 int skipped_frames = decoded_frame_number - previous_frame_number - 1;
335 if (skipped_frames > max_skipped_frames) {
336 max_skipped_frames = skipped_frames;
337 }
338 }
339 previous_frame_number = decoded_frame_number;
340 }
341 fprintf(output, "RESULT Max_repeated: %s= %d\n", label.c_str(), 421 fprintf(output, "RESULT Max_repeated: %s= %d\n", label.c_str(),
342 max_repeated_frames); 422 max_repeated_frames);
343 fprintf(output, "RESULT Max_skipped: %s= %d\n", label.c_str(), 423 fprintf(output, "RESULT Max_skipped: %s= %d\n", label.c_str(),
344 max_skipped_frames); 424 max_skipped_frames);
345 fclose(stats_file);
346 } 425 }
347 426
348 void PrintAnalysisResults(const std::string& label, ResultsContainer* results) { 427 void PrintAnalysisResults(const std::string& label, ResultsContainer* results) {
349 PrintAnalysisResults(stdout, label, results); 428 PrintAnalysisResults(stdout, label, results);
350 } 429 }
351 430
352 void PrintAnalysisResults(FILE* output, const std::string& label, 431 void PrintAnalysisResults(FILE* output, const std::string& label,
353 ResultsContainer* results) { 432 ResultsContainer* results) {
354 std::vector<AnalysisResult>::iterator iter; 433 std::vector<AnalysisResult>::iterator iter;
355 434
(...skipping 12 matching lines...) Expand all
368 for (iter = results->frames.begin(); iter != results->frames.end() - 1; 447 for (iter = results->frames.begin(); iter != results->frames.end() - 1;
369 ++iter) { 448 ++iter) {
370 fprintf(output, "%f,", iter->ssim_value); 449 fprintf(output, "%f,", iter->ssim_value);
371 } 450 }
372 fprintf(output, "%f] score\n", iter->ssim_value); 451 fprintf(output, "%f] score\n", iter->ssim_value);
373 } 452 }
374 } 453 }
375 454
376 } // namespace test 455 } // namespace test
377 } // namespace webrtc 456 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698