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

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: Added newline in debug prints for PrintMaxRepeatedAndSkippedFrames Created 3 years, 11 months 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 // Clusters the frames in the file. First in the pair is the frame number and
302 FILE* stats_file = fopen(stats_file_name.c_str(), "r"); 332 // second is the number
303 if (stats_file == NULL) { 333 // of frames in that cluster. So if first frame in video has number 100 and it
304 fprintf(stderr, "Couldn't open stats file for reading: %s\n", 334 // is repeated 3 after
305 stats_file_name.c_str()); 335 // each other, then the first entry in the returned vector has first set to 100
306 return; 336 // and second set
307 } 337 // to 3.
338 std::vector<std::pair<int, int> > CalculateFrameClusters(FILE* file) {
339 std::vector<std::pair<int, int> > frame_cnt;
308 char line[STATS_LINE_LENGTH]; 340 char line[STATS_LINE_LENGTH];
309 341 while (GetNextStatsLine(file, line)) {
310 int repeated_frames = 1;
311 int max_repeated_frames = 1;
312 int max_skipped_frames = 1;
313 int previous_frame_number = -1;
314
315 while (GetNextStatsLine(stats_file, line)) {
316 int decoded_frame_number = ExtractDecodedFrameNumber(line); 342 int decoded_frame_number = ExtractDecodedFrameNumber(line);
317
318 if (decoded_frame_number == -1) { 343 if (decoded_frame_number == -1) {
319 continue; 344 continue;
320 } 345 }
346 if (frame_cnt.empty() || frame_cnt.back().first != decoded_frame_number) {
347 frame_cnt.push_back(std::make_pair(decoded_frame_number, 1));
348 } else {
349 ++frame_cnt.back().second;
350 }
351 }
352 return frame_cnt;
353 }
354 } // namespace
321 355
322 // Calculate how many frames a cluster of repeated frames contains. 356 void PrintMaxRepeatedAndSkippedFrames(FILE* output,
323 if (decoded_frame_number == previous_frame_number) { 357 const std::string& label,
324 ++repeated_frames; 358 const std::string& stats_file_ref_name,
325 if (repeated_frames > max_repeated_frames) { 359 const std::string& stats_file_test_name) {
326 max_repeated_frames = repeated_frames; 360 FILE* stats_file_ref = fopen(stats_file_ref_name.c_str(), "r");
327 } 361 FILE* stats_file_test = fopen(stats_file_test_name.c_str(), "r");
328 } else { 362 if (stats_file_ref == NULL) {
329 repeated_frames = 1; 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;
375 int max_skipped_frames = 1;
376
377 std::vector<std::pair<int, int> > frame_cnt_ref =
378 CalculateFrameClusters(stats_file_ref);
379
380 std::vector<std::pair<int, int> > frame_cnt_test =
381 CalculateFrameClusters(stats_file_test);
382
383 fclose(stats_file_ref);
384 fclose(stats_file_test);
385
386 auto it_ref = frame_cnt_ref.begin();
387 auto it_test = frame_cnt_test.begin();
388 auto end_ref = frame_cnt_ref.end();
389 auto end_test = frame_cnt_test.end();
390
391 if (it_test == end_test || it_ref == end_ref) {
392 fprintf(stderr, "Either test or ref file is empty, nothing to print\n");
393 return;
394 }
395
396 // Find the first frame in the reference video that match the first frame in
397 // the test video.
398 while (it_ref != end_ref && it_ref->first != it_test->first) {
399 ++it_ref;
400 }
401 if (it_ref == end_ref) {
402 fprintf(stderr,
403 "The barcode in the test video's first frame is not in the "
404 "reference video.\n");
405 return;
406 }
407
408 for (;;) {
409 max_repeated_frames =
410 std::max(max_repeated_frames, it_test->second - it_ref->second + 1);
411 ++it_test;
412 if (it_test == end_test) {
413 break;
330 } 414 }
415 int skipped_frames = 0;
416 ++it_ref;
417 while (it_ref != end_ref && it_ref->first != it_test->first) {
418 skipped_frames += it_ref->second;
419 ++it_ref;
420 }
421 if (it_ref == end_ref) {
422 fprintf(stderr,
423 "The barcode in the test video is not in the reference video.\n");
424 return;
425 }
426 if (skipped_frames > max_skipped_frames) {
427 max_skipped_frames = skipped_frames;
428 }
429 }
331 430
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(), 431 fprintf(output, "RESULT Max_repeated: %s= %d\n", label.c_str(),
342 max_repeated_frames); 432 max_repeated_frames);
343 fprintf(output, "RESULT Max_skipped: %s= %d\n", label.c_str(), 433 fprintf(output, "RESULT Max_skipped: %s= %d\n", label.c_str(),
344 max_skipped_frames); 434 max_skipped_frames);
345 fclose(stats_file);
346 } 435 }
347 436
348 void PrintAnalysisResults(const std::string& label, ResultsContainer* results) { 437 void PrintAnalysisResults(const std::string& label, ResultsContainer* results) {
349 PrintAnalysisResults(stdout, label, results); 438 PrintAnalysisResults(stdout, label, results);
350 } 439 }
351 440
352 void PrintAnalysisResults(FILE* output, const std::string& label, 441 void PrintAnalysisResults(FILE* output, const std::string& label,
353 ResultsContainer* results) { 442 ResultsContainer* results) {
354 std::vector<AnalysisResult>::iterator iter; 443 std::vector<AnalysisResult>::iterator iter;
355 444
(...skipping 12 matching lines...) Expand all
368 for (iter = results->frames.begin(); iter != results->frames.end() - 1; 457 for (iter = results->frames.begin(); iter != results->frames.end() - 1;
369 ++iter) { 458 ++iter) {
370 fprintf(output, "%f,", iter->ssim_value); 459 fprintf(output, "%f,", iter->ssim_value);
371 } 460 }
372 fprintf(output, "%f] score\n", iter->ssim_value); 461 fprintf(output, "%f] score\n", iter->ssim_value);
373 } 462 }
374 } 463 }
375 464
376 } // namespace test 465 } // namespace test
377 } // namespace webrtc 466 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/tools/frame_analyzer/video_quality_analysis.h ('k') | webrtc/tools/frame_analyzer/video_quality_analysis_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698