1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef C2_E2E_TEST_COMMON_H_
6 #define C2_E2E_TEST_COMMON_H_
7 
8 #include <fstream>
9 #include <ios>
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 namespace android {
15 
16 // The enumeration of video codec profile. This would be better to align with
17 // VideoCodecProfile enum in Chromium so we could use the identical test stream
18 // data arguments for both ARC end-to-end and Chromium tests.
19 enum VideoCodecProfile {
20     VIDEO_CODEC_PROFILE_UNKNOWN = -1,
21     VIDEO_CODEC_PROFILE_MIN = VIDEO_CODEC_PROFILE_UNKNOWN,
22     H264PROFILE_MIN = 0,
23     H264PROFILE_BASELINE = H264PROFILE_MIN,
24     H264PROFILE_MAIN = 1,
25     H264PROFILE_EXTENDED = 2,
26     H264PROFILE_HIGH = 3,
27     H264PROFILE_HIGH10PROFILE = 4,
28     H264PROFILE_HIGH422PROFILE = 5,
29     H264PROFILE_HIGH444PREDICTIVEPROFILE = 6,
30     H264PROFILE_SCALABLEBASELINE = 7,
31     H264PROFILE_SCALABLEHIGH = 8,
32     H264PROFILE_STEREOHIGH = 9,
33     H264PROFILE_MULTIVIEWHIGH = 10,
34     H264PROFILE_MAX = H264PROFILE_MULTIVIEWHIGH,
35     VP8PROFILE_MIN = 11,
36     VP8PROFILE_ANY = VP8PROFILE_MIN,
37     VP8PROFILE_MAX = VP8PROFILE_ANY,
38     VP9PROFILE_MIN = 12,
39     VP9PROFILE_PROFILE0 = VP9PROFILE_MIN,
40     VP9PROFILE_PROFILE1 = 13,
41     VP9PROFILE_PROFILE2 = 14,
42     VP9PROFILE_PROFILE3 = 15,
43     VP9PROFILE_MAX = VP9PROFILE_PROFILE3,
44 };
45 
46 // The enum class of video codec type.
47 enum class VideoCodecType {
48     UNKNOWN,
49     H264,
50     VP8,
51     VP9,
52 };
53 
54 // Structure to store resolution.
55 struct Size {
SizeSize56     Size() : width(0), height(0) {}
SizeSize57     Size(int w, int h) : width(w), height(h) {}
IsEmptySize58     bool IsEmpty() const { return width <= 0 || height <= 0; }
59 
60     int width;
61     int height;
62 };
63 
64 class InputFile {
65 public:
66     explicit InputFile(std::string file_path);
67     InputFile(std::string file_path, std::ios_base::openmode openmode);
68 
69     // Check if the file is valid.
70     bool IsValid() const;
71     // Get the size of the file.
72     size_t GetLength();
73     // Set position to the beginning of the file.
74     virtual void Rewind();
75 
76 protected:
77     std::ifstream file_;
78 };
79 
80 // Wrapper of std::ifstream for reading binary file.
81 class CachedInputFileStream : public InputFile {
82 public:
83     explicit CachedInputFileStream(std::string file_path);
84 
85     // Read the given number of bytes to the buffer. Return the number of bytes
86     // read or -1 on error.
87     size_t Read(char* buffer, size_t size);
88 
89     void Rewind() override;
90 
91 private:
92     std::vector<char> data_;
93     size_t position_ = 0;
94 };
95 
96 // Wrapper of std::ifstream for reading ASCII file.
97 class InputFileASCII : public InputFile {
98 public:
99     explicit InputFileASCII(std::string file_path);
100 
101     // Read one line from the file. Return false if EOF.
102     bool ReadLine(std::string* line);
103 };
104 
105 // IVF file writer, can be used to write an encoded VP8/9 video to disk.
106 class IVFWriter {
107 public:
108     IVFWriter(std::ofstream* output_file, VideoCodecType codec);
109 
110     // Write the IVF file header.
111     bool WriteHeader(const Size& resolution, uint32_t frame_rate, uint32_t num_frames);
112     // Append the specified frame data to the IVF file.
113     bool WriteFrame(const uint8_t* data, uint32_t data_size, uint64_t timestamp);
114     // Set the number of video frames in the IVF file header.
115     bool SetNumFrames(uint32_t num_frames);
116 
117 private:
118     std::ofstream* output_file_;
119     VideoCodecType codec_ = VideoCodecType::UNKNOWN;
120 };
121 
122 class OutputFile {
123 public:
124     bool Open(const std::string& file_path, VideoCodecType codec);
125     void Close();
126     bool IsOpen();
127 
128     // Write the video file header.
129     bool WriteHeader(const Size& resolution, uint32_t frame_rate, uint32_t num_frames);
130     // Append the specified frame data to the video file.
131     bool WriteFrame(uint32_t data_size, const uint8_t* data);
132 
133 private:
134     std::ofstream output_file_;
135     std::unique_ptr<IVFWriter> ivf_writer_;
136     uint64_t frame_index_ = 0;
137 };
138 
139 // The helper class to calculate FPS.
140 class FPSCalculator {
141 public:
142     // Record the time interval of output buffers. Return false if is invalid.
143     // This should be called per output buffer ready callback.
144     bool RecordFrameTimeDiff();
145 
146     // Calucalate FPS value.
147     double CalculateFPS() const;
148 
149 private:
150     static constexpr double kMovingAvgWindowUs = 1000000;
151     static constexpr double kRegardedPercentile = 95;
152 
153     // Return the statistics for the moving average over a window over the
154     // cumulative sum. Basically, moves a window from: [0, window] to
155     // [sum - window, sum] over the cumulative sum, over ((sum - window)/average)
156     // steps, and returns the average value over each window.
157     // This method is used to average time-diff data over a window of a constant
158     // time.
159     std::vector<double> MovingAvgOverSum() const;
160 
161     std::vector<double> frame_time_diffs_us_;
162     int64_t last_frame_time_us_ = 0;
163 };
164 
165 // Helper function to get VideoCodecType from |profile|.
166 VideoCodecType VideoCodecProfileToType(VideoCodecProfile profile);
167 
168 // Split the string |src| by the delimiter |delim|.
169 std::vector<std::string> SplitString(const std::string& src, char delim);
170 
171 // Get monotonic timestamp for now in microseconds.
172 int64_t GetNowUs();
173 
174 // Get Mime type name from video codec type.
175 const char* GetMimeType(VideoCodecType type);
176 
177 }  // namespace android
178 #endif  // C2_E2E_TEST_COMMON_H_
179