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#ifndef WEBRTC_TOOLS_FRAME_ANALYZER_VIDEO_QUALITY_ANALYSIS_H_
12#define WEBRTC_TOOLS_FRAME_ANALYZER_VIDEO_QUALITY_ANALYSIS_H_
13
14#include <string>
15#include <vector>
16
17#include "libyuv/compare.h"  // NOLINT
18#include "libyuv/convert.h"  // NOLINT
19
20namespace webrtc {
21namespace test {
22
23struct AnalysisResult {
24  AnalysisResult() {}
25  AnalysisResult(int frame_number, double psnr_value, double ssim_value)
26      : frame_number(frame_number),
27        psnr_value(psnr_value),
28        ssim_value(ssim_value) {}
29  int frame_number;
30  double psnr_value;
31  double ssim_value;
32};
33
34struct ResultsContainer {
35  ResultsContainer();
36  ~ResultsContainer();
37
38  std::vector<AnalysisResult> frames;
39};
40
41enum VideoAnalysisMetricsType {kPSNR, kSSIM};
42
43// A function to run the PSNR and SSIM analysis on the test file. The test file
44// comprises the frames that were captured during the quality measurement test.
45// There may be missing or duplicate frames. Also the frames start at a random
46// position in the original video. We should provide a statistics file along
47// with the test video. The stats file contains the connection between the
48// actual frames in the test file and their position in the reference video, so
49// that the analysis could run with the right frames from both videos. The stats
50// file should be in the form 'frame_xxxx yyyy', where xxxx is the consecutive
51// number of the frame in the test video, and yyyy is the equivalent frame in
52// the reference video. The stats file could be produced by
53// tools/barcode_tools/barcode_decoder.py. This script decodes the barcodes
54// integrated in every video and generates the stats file. If three was some
55// problem with the decoding there would be 'Barcode error' instead of yyyy.
56void RunAnalysis(const char* reference_file_name, const char* test_file_name,
57                 const char* stats_file_name, int width, int height,
58                 ResultsContainer* results);
59
60// Compute PSNR or SSIM for an I420 frame (all planes). When we are calculating
61// PSNR values, the max return value (in the case where the test and reference
62// frames are exactly the same) will be 48. In the case of SSIM the max return
63// value will be 1.
64double CalculateMetrics(VideoAnalysisMetricsType video_metrics_type,
65                        const uint8_t* ref_frame,
66                        const uint8_t* test_frame,
67                        int width,
68                        int height);
69
70// Prints the result from the analysis in Chromium performance
71// numbers compatible format to stdout. If the results object contains no frames
72// no output will be written.
73void PrintAnalysisResults(const std::string& label, ResultsContainer* results);
74
75// Similar to the above, but will print to the specified file handle.
76void PrintAnalysisResults(FILE* output, const std::string& label,
77                          ResultsContainer* results);
78
79// Calculates max repeated and skipped frames and prints them to stdout in a
80// format that is compatible with Chromium performance numbers.
81void PrintMaxRepeatedAndSkippedFrames(const std::string& label,
82                                      const std::string& stats_file_name);
83
84// Similar to the above, but will print to the specified file handle.
85void PrintMaxRepeatedAndSkippedFrames(FILE* output, const std::string& label,
86                                      const std::string& stats_file_name);
87
88// Gets the next line from an open stats file.
89bool GetNextStatsLine(FILE* stats_file, char* line);
90
91// Calculates the size of a I420 frame if given the width and height.
92int GetI420FrameSize(int width, int height);
93
94// Extract the sequence of the frame in the video. I.e. if line is
95// frame_0023 0284, we will get 23.
96int ExtractFrameSequenceNumber(std::string line);
97
98// Checks if there is 'Barcode error' for the given line.
99bool IsThereBarcodeError(std::string line);
100
101// Extract the frame number in the reference video. I.e. if line is
102// frame_0023 0284, we will get 284.
103int ExtractDecodedFrameNumber(std::string line);
104
105// Extracts an I420 frame at position frame_number from the raw YUV file.
106bool ExtractFrameFromYuvFile(const char* i420_file_name,
107                             int width,
108                             int height,
109                             int frame_number,
110                             uint8_t* result_frame);
111
112// Extracts an I420 frame at position frame_number from the Y4M file. The first
113// frame has corresponded |frame_number| 0.
114bool ExtractFrameFromY4mFile(const char* i420_file_name,
115                             int width,
116                             int height,
117                             int frame_number,
118                             uint8_t* result_frame);
119
120}  // namespace test
121}  // namespace webrtc
122
123#endif  // WEBRTC_TOOLS_FRAME_ANALYZER_VIDEO_QUALITY_ANALYSIS_H_
124