• 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 <stdio.h>
12 #include <stdlib.h>
13 
14 #include <algorithm>
15 #include <string>
16 
17 #include "absl/flags/flag.h"
18 #include "absl/flags/parse.h"
19 #include "absl/flags/usage.h"
20 #include "api/scoped_refptr.h"
21 #include "api/video/video_frame_buffer.h"
22 #include "rtc_tools/frame_analyzer/video_quality_analysis.h"
23 #include "rtc_tools/video_file_reader.h"
24 
25 ABSL_FLAG(std::string,
26           results_file,
27           "results.txt",
28           "The full name of the file where the results will be written");
29 ABSL_FLAG(std::string,
30           reference_file,
31           "ref.yuv",
32           "The reference YUV file to compare against");
33 ABSL_FLAG(std::string,
34           test_file,
35           "test.yuv",
36           "The test YUV file to run the analysis for");
37 
CompareFiles(const rtc::scoped_refptr<webrtc::test::Video> & reference_video,const rtc::scoped_refptr<webrtc::test::Video> & test_video,const char * results_file_name)38 void CompareFiles(
39     const rtc::scoped_refptr<webrtc::test::Video>& reference_video,
40     const rtc::scoped_refptr<webrtc::test::Video>& test_video,
41     const char* results_file_name) {
42   FILE* results_file = fopen(results_file_name, "w");
43 
44   const size_t num_frames = std::min(reference_video->number_of_frames(),
45                                      test_video->number_of_frames());
46   for (size_t i = 0; i < num_frames; ++i) {
47     const rtc::scoped_refptr<webrtc::I420BufferInterface> ref_buffer =
48         reference_video->GetFrame(i);
49     const rtc::scoped_refptr<webrtc::I420BufferInterface> test_buffer =
50         test_video->GetFrame(i);
51 
52     // Calculate the PSNR and SSIM.
53     double result_psnr = webrtc::test::Psnr(ref_buffer, test_buffer);
54     double result_ssim = webrtc::test::Ssim(ref_buffer, test_buffer);
55     fprintf(results_file, "Frame: %zu, PSNR: %f, SSIM: %f\n", i, result_psnr,
56             result_ssim);
57   }
58 
59   fclose(results_file);
60 }
61 
62 /*
63  * A tool running PSNR and SSIM analysis on two videos - a reference video and a
64  * test video. The two videos should be I420 Y4M videos.
65  * The tool just runs PSNR and SSIM on the corresponding frames in the test and
66  * the reference videos until either the first or the second video runs out of
67  * frames. The result is written in a results text file in the format:
68  * Frame: <frame_number>, PSNR: <psnr_value>, SSIM: <ssim_value>
69  * Frame: <frame_number>, ........
70  *
71  * The max value for PSNR is 48.0 (between equal frames), as for SSIM it is 1.0.
72  *
73  * Usage:
74  * psnr_ssim_analyzer --reference_file=<name_of_file> --test_file=<name_of_file>
75  * --results_file=<name_of_file>
76  */
main(int argc,char * argv[])77 int main(int argc, char* argv[]) {
78   absl::SetProgramUsageMessage(
79       "Runs PSNR and SSIM on two I420 videos and write the"
80       "results in a file.\n"
81       "Example usage:\n"
82       "./psnr_ssim_analyzer --reference_file=ref.yuv "
83       "--test_file=test.yuv --results_file=results.txt\n");
84   absl::ParseCommandLine(argc, argv);
85 
86   rtc::scoped_refptr<webrtc::test::Video> reference_video =
87       webrtc::test::OpenY4mFile(absl::GetFlag(FLAGS_reference_file));
88   rtc::scoped_refptr<webrtc::test::Video> test_video =
89       webrtc::test::OpenY4mFile(absl::GetFlag(FLAGS_test_file));
90 
91   if (!reference_video || !test_video) {
92     fprintf(stderr, "Error opening video files\n");
93     return 0;
94   }
95   if (reference_video->width() != test_video->width() ||
96       reference_video->height() != test_video->height()) {
97     fprintf(stderr,
98             "Reference and test video files do not have same size: %dx%d "
99             "versus %dx%d\n",
100             reference_video->width(), reference_video->height(),
101             test_video->width(), test_video->height());
102     return 0;
103   }
104 
105   CompareFiles(reference_video, test_video,
106                absl::GetFlag(FLAGS_results_file).c_str());
107   return 0;
108 }
109