1*103e46e4SHarish Mahendrakar // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2*103e46e4SHarish Mahendrakar //
3*103e46e4SHarish Mahendrakar // Use of this source code is governed by a BSD-style license
4*103e46e4SHarish Mahendrakar // that can be found in the LICENSE file in the root of the source
5*103e46e4SHarish Mahendrakar // tree. An additional intellectual property rights grant can be found
6*103e46e4SHarish Mahendrakar // in the file PATENTS. All contributing project authors may
7*103e46e4SHarish Mahendrakar // be found in the AUTHORS file in the root of the source tree.
8*103e46e4SHarish Mahendrakar #include "common/vp9_level_stats.h"
9*103e46e4SHarish Mahendrakar
10*103e46e4SHarish Mahendrakar #include <memory>
11*103e46e4SHarish Mahendrakar #include <string>
12*103e46e4SHarish Mahendrakar #include <vector>
13*103e46e4SHarish Mahendrakar
14*103e46e4SHarish Mahendrakar #include "gtest/gtest.h"
15*103e46e4SHarish Mahendrakar
16*103e46e4SHarish Mahendrakar #include "common/hdr_util.h"
17*103e46e4SHarish Mahendrakar #include "common/vp9_header_parser.h"
18*103e46e4SHarish Mahendrakar #include "mkvparser/mkvparser.h"
19*103e46e4SHarish Mahendrakar #include "mkvparser/mkvreader.h"
20*103e46e4SHarish Mahendrakar #include "testing/test_util.h"
21*103e46e4SHarish Mahendrakar
22*103e46e4SHarish Mahendrakar namespace {
23*103e46e4SHarish Mahendrakar
24*103e46e4SHarish Mahendrakar // TODO(fgalligan): Refactor this test with other test files in this directory.
25*103e46e4SHarish Mahendrakar class Vp9LevelStatsTests : public ::testing::Test {
26*103e46e4SHarish Mahendrakar public:
Vp9LevelStatsTests()27*103e46e4SHarish Mahendrakar Vp9LevelStatsTests() : is_reader_open_(false) {}
28*103e46e4SHarish Mahendrakar
~Vp9LevelStatsTests()29*103e46e4SHarish Mahendrakar ~Vp9LevelStatsTests() override { CloseReader(); }
30*103e46e4SHarish Mahendrakar
CloseReader()31*103e46e4SHarish Mahendrakar void CloseReader() {
32*103e46e4SHarish Mahendrakar if (is_reader_open_) {
33*103e46e4SHarish Mahendrakar reader_.Close();
34*103e46e4SHarish Mahendrakar }
35*103e46e4SHarish Mahendrakar is_reader_open_ = false;
36*103e46e4SHarish Mahendrakar }
37*103e46e4SHarish Mahendrakar
CreateAndLoadSegment(const std::string & filename,int expected_doc_type_ver)38*103e46e4SHarish Mahendrakar void CreateAndLoadSegment(const std::string& filename,
39*103e46e4SHarish Mahendrakar int expected_doc_type_ver) {
40*103e46e4SHarish Mahendrakar ASSERT_NE(0u, filename.length());
41*103e46e4SHarish Mahendrakar filename_ = test::GetTestFilePath(filename);
42*103e46e4SHarish Mahendrakar ASSERT_EQ(0, reader_.Open(filename_.c_str()));
43*103e46e4SHarish Mahendrakar is_reader_open_ = true;
44*103e46e4SHarish Mahendrakar pos_ = 0;
45*103e46e4SHarish Mahendrakar mkvparser::EBMLHeader ebml_header;
46*103e46e4SHarish Mahendrakar ebml_header.Parse(&reader_, pos_);
47*103e46e4SHarish Mahendrakar ASSERT_EQ(1, ebml_header.m_version);
48*103e46e4SHarish Mahendrakar ASSERT_EQ(1, ebml_header.m_readVersion);
49*103e46e4SHarish Mahendrakar ASSERT_STREQ("webm", ebml_header.m_docType);
50*103e46e4SHarish Mahendrakar ASSERT_EQ(expected_doc_type_ver, ebml_header.m_docTypeVersion);
51*103e46e4SHarish Mahendrakar ASSERT_EQ(2, ebml_header.m_docTypeReadVersion);
52*103e46e4SHarish Mahendrakar mkvparser::Segment* temp;
53*103e46e4SHarish Mahendrakar ASSERT_EQ(0, mkvparser::Segment::CreateInstance(&reader_, pos_, temp));
54*103e46e4SHarish Mahendrakar segment_.reset(temp);
55*103e46e4SHarish Mahendrakar ASSERT_FALSE(HasFailure());
56*103e46e4SHarish Mahendrakar ASSERT_GE(0, segment_->Load());
57*103e46e4SHarish Mahendrakar }
58*103e46e4SHarish Mahendrakar
CreateAndLoadSegment(const std::string & filename)59*103e46e4SHarish Mahendrakar void CreateAndLoadSegment(const std::string& filename) {
60*103e46e4SHarish Mahendrakar CreateAndLoadSegment(filename, 4);
61*103e46e4SHarish Mahendrakar }
62*103e46e4SHarish Mahendrakar
ProcessTheFrames()63*103e46e4SHarish Mahendrakar void ProcessTheFrames() {
64*103e46e4SHarish Mahendrakar std::vector<uint8_t> data;
65*103e46e4SHarish Mahendrakar size_t data_len = 0;
66*103e46e4SHarish Mahendrakar const mkvparser::Tracks* const parser_tracks = segment_->GetTracks();
67*103e46e4SHarish Mahendrakar ASSERT_TRUE(parser_tracks != NULL);
68*103e46e4SHarish Mahendrakar const mkvparser::Cluster* cluster = segment_->GetFirst();
69*103e46e4SHarish Mahendrakar ASSERT_TRUE(cluster);
70*103e46e4SHarish Mahendrakar
71*103e46e4SHarish Mahendrakar while ((cluster != NULL) && !cluster->EOS()) {
72*103e46e4SHarish Mahendrakar const mkvparser::BlockEntry* block_entry;
73*103e46e4SHarish Mahendrakar long status = cluster->GetFirst(block_entry); // NOLINT
74*103e46e4SHarish Mahendrakar ASSERT_EQ(0, status);
75*103e46e4SHarish Mahendrakar
76*103e46e4SHarish Mahendrakar while ((block_entry != NULL) && !block_entry->EOS()) {
77*103e46e4SHarish Mahendrakar const mkvparser::Block* const block = block_entry->GetBlock();
78*103e46e4SHarish Mahendrakar ASSERT_TRUE(block != NULL);
79*103e46e4SHarish Mahendrakar const long long trackNum = block->GetTrackNumber(); // NOLINT
80*103e46e4SHarish Mahendrakar const mkvparser::Track* const parser_track =
81*103e46e4SHarish Mahendrakar parser_tracks->GetTrackByNumber(
82*103e46e4SHarish Mahendrakar static_cast<unsigned long>(trackNum)); // NOLINT
83*103e46e4SHarish Mahendrakar ASSERT_TRUE(parser_track != NULL);
84*103e46e4SHarish Mahendrakar const long long track_type = parser_track->GetType(); // NOLINT
85*103e46e4SHarish Mahendrakar
86*103e46e4SHarish Mahendrakar if (track_type == mkvparser::Track::kVideo) {
87*103e46e4SHarish Mahendrakar const int frame_count = block->GetFrameCount();
88*103e46e4SHarish Mahendrakar const long long time_ns = block->GetTime(cluster); // NOLINT
89*103e46e4SHarish Mahendrakar
90*103e46e4SHarish Mahendrakar for (int i = 0; i < frame_count; ++i) {
91*103e46e4SHarish Mahendrakar const mkvparser::Block::Frame& frame = block->GetFrame(i);
92*103e46e4SHarish Mahendrakar if (static_cast<size_t>(frame.len) > data.size()) {
93*103e46e4SHarish Mahendrakar data.resize(frame.len);
94*103e46e4SHarish Mahendrakar data_len = static_cast<size_t>(frame.len);
95*103e46e4SHarish Mahendrakar }
96*103e46e4SHarish Mahendrakar ASSERT_FALSE(frame.Read(&reader_, &data[0]));
97*103e46e4SHarish Mahendrakar parser_.ParseUncompressedHeader(&data[0], data_len);
98*103e46e4SHarish Mahendrakar stats_.AddFrame(parser_, time_ns);
99*103e46e4SHarish Mahendrakar }
100*103e46e4SHarish Mahendrakar }
101*103e46e4SHarish Mahendrakar
102*103e46e4SHarish Mahendrakar status = cluster->GetNext(block_entry, block_entry);
103*103e46e4SHarish Mahendrakar ASSERT_EQ(0, status);
104*103e46e4SHarish Mahendrakar }
105*103e46e4SHarish Mahendrakar
106*103e46e4SHarish Mahendrakar cluster = segment_->GetNext(cluster);
107*103e46e4SHarish Mahendrakar }
108*103e46e4SHarish Mahendrakar }
109*103e46e4SHarish Mahendrakar
110*103e46e4SHarish Mahendrakar protected:
111*103e46e4SHarish Mahendrakar mkvparser::MkvReader reader_;
112*103e46e4SHarish Mahendrakar bool is_reader_open_;
113*103e46e4SHarish Mahendrakar std::unique_ptr<mkvparser::Segment> segment_;
114*103e46e4SHarish Mahendrakar std::string filename_;
115*103e46e4SHarish Mahendrakar long long pos_; // NOLINT
116*103e46e4SHarish Mahendrakar vp9_parser::Vp9HeaderParser parser_;
117*103e46e4SHarish Mahendrakar vp9_parser::Vp9LevelStats stats_;
118*103e46e4SHarish Mahendrakar };
119*103e46e4SHarish Mahendrakar
TEST_F(Vp9LevelStatsTests,VideoOnlyFile)120*103e46e4SHarish Mahendrakar TEST_F(Vp9LevelStatsTests, VideoOnlyFile) {
121*103e46e4SHarish Mahendrakar ASSERT_NO_FATAL_FAILURE(CreateAndLoadSegment("test_stereo_left_right.webm"));
122*103e46e4SHarish Mahendrakar ProcessTheFrames();
123*103e46e4SHarish Mahendrakar EXPECT_EQ(256, parser_.width());
124*103e46e4SHarish Mahendrakar EXPECT_EQ(144, parser_.height());
125*103e46e4SHarish Mahendrakar EXPECT_EQ(1, parser_.column_tiles());
126*103e46e4SHarish Mahendrakar EXPECT_EQ(0, parser_.frame_parallel_mode());
127*103e46e4SHarish Mahendrakar
128*103e46e4SHarish Mahendrakar EXPECT_EQ(11, stats_.GetLevel());
129*103e46e4SHarish Mahendrakar EXPECT_EQ(479232, stats_.GetMaxLumaSampleRate());
130*103e46e4SHarish Mahendrakar EXPECT_EQ(36864, stats_.GetMaxLumaPictureSize());
131*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(264.03233333333333, stats_.GetAverageBitRate());
132*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(147.136, stats_.GetMaxCpbSize());
133*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(19.267458404715583, stats_.GetCompressionRatio());
134*103e46e4SHarish Mahendrakar EXPECT_EQ(1, stats_.GetMaxColumnTiles());
135*103e46e4SHarish Mahendrakar EXPECT_EQ(11, stats_.GetMinimumAltrefDistance());
136*103e46e4SHarish Mahendrakar EXPECT_EQ(3, stats_.GetMaxReferenceFrames());
137*103e46e4SHarish Mahendrakar
138*103e46e4SHarish Mahendrakar EXPECT_TRUE(stats_.estimate_last_frame_duration());
139*103e46e4SHarish Mahendrakar stats_.set_estimate_last_frame_duration(false);
140*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(275.512, stats_.GetAverageBitRate());
141*103e46e4SHarish Mahendrakar }
142*103e46e4SHarish Mahendrakar
TEST_F(Vp9LevelStatsTests,Muxed)143*103e46e4SHarish Mahendrakar TEST_F(Vp9LevelStatsTests, Muxed) {
144*103e46e4SHarish Mahendrakar ASSERT_NO_FATAL_FAILURE(
145*103e46e4SHarish Mahendrakar CreateAndLoadSegment("bbb_480p_vp9_opus_1second.webm", 4));
146*103e46e4SHarish Mahendrakar ProcessTheFrames();
147*103e46e4SHarish Mahendrakar EXPECT_EQ(854, parser_.width());
148*103e46e4SHarish Mahendrakar EXPECT_EQ(480, parser_.height());
149*103e46e4SHarish Mahendrakar EXPECT_EQ(2, parser_.column_tiles());
150*103e46e4SHarish Mahendrakar EXPECT_EQ(1, parser_.frame_parallel_mode());
151*103e46e4SHarish Mahendrakar
152*103e46e4SHarish Mahendrakar EXPECT_EQ(30, stats_.GetLevel());
153*103e46e4SHarish Mahendrakar EXPECT_EQ(9838080, stats_.GetMaxLumaSampleRate());
154*103e46e4SHarish Mahendrakar EXPECT_EQ(409920, stats_.GetMaxLumaPictureSize());
155*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(447.09394572025053, stats_.GetAverageBitRate());
156*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(118.464, stats_.GetMaxCpbSize());
157*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(241.17670131398313, stats_.GetCompressionRatio());
158*103e46e4SHarish Mahendrakar EXPECT_EQ(2, stats_.GetMaxColumnTiles());
159*103e46e4SHarish Mahendrakar EXPECT_EQ(9, stats_.GetMinimumAltrefDistance());
160*103e46e4SHarish Mahendrakar EXPECT_EQ(3, stats_.GetMaxReferenceFrames());
161*103e46e4SHarish Mahendrakar
162*103e46e4SHarish Mahendrakar stats_.set_estimate_last_frame_duration(false);
163*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(468.38413361169108, stats_.GetAverageBitRate());
164*103e46e4SHarish Mahendrakar }
165*103e46e4SHarish Mahendrakar
TEST_F(Vp9LevelStatsTests,SetDuration)166*103e46e4SHarish Mahendrakar TEST_F(Vp9LevelStatsTests, SetDuration) {
167*103e46e4SHarish Mahendrakar ASSERT_NO_FATAL_FAILURE(CreateAndLoadSegment("test_stereo_left_right.webm"));
168*103e46e4SHarish Mahendrakar ProcessTheFrames();
169*103e46e4SHarish Mahendrakar const int64_t kDurationNano = 2080000000; // 2.08 seconds
170*103e46e4SHarish Mahendrakar stats_.set_duration(kDurationNano);
171*103e46e4SHarish Mahendrakar EXPECT_EQ(256, parser_.width());
172*103e46e4SHarish Mahendrakar EXPECT_EQ(144, parser_.height());
173*103e46e4SHarish Mahendrakar EXPECT_EQ(1, parser_.column_tiles());
174*103e46e4SHarish Mahendrakar EXPECT_EQ(0, parser_.frame_parallel_mode());
175*103e46e4SHarish Mahendrakar
176*103e46e4SHarish Mahendrakar EXPECT_EQ(11, stats_.GetLevel());
177*103e46e4SHarish Mahendrakar EXPECT_EQ(479232, stats_.GetMaxLumaSampleRate());
178*103e46e4SHarish Mahendrakar EXPECT_EQ(36864, stats_.GetMaxLumaPictureSize());
179*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(264.9153846153846, stats_.GetAverageBitRate());
180*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(147.136, stats_.GetMaxCpbSize());
181*103e46e4SHarish Mahendrakar EXPECT_DOUBLE_EQ(19.267458404715583, stats_.GetCompressionRatio());
182*103e46e4SHarish Mahendrakar EXPECT_EQ(1, stats_.GetMaxColumnTiles());
183*103e46e4SHarish Mahendrakar EXPECT_EQ(11, stats_.GetMinimumAltrefDistance());
184*103e46e4SHarish Mahendrakar EXPECT_EQ(3, stats_.GetMaxReferenceFrames());
185*103e46e4SHarish Mahendrakar }
186*103e46e4SHarish Mahendrakar
187*103e46e4SHarish Mahendrakar } // namespace
188*103e46e4SHarish Mahendrakar
main(int argc,char * argv[])189*103e46e4SHarish Mahendrakar int main(int argc, char* argv[]) {
190*103e46e4SHarish Mahendrakar ::testing::InitGoogleTest(&argc, argv);
191*103e46e4SHarish Mahendrakar return RUN_ALL_TESTS();
192*103e46e4SHarish Mahendrakar }
193