| // Copyright (c) 2016 The WebM project authors. All Rights Reserved. |
| // |
| // Use of this source code is governed by a BSD-style license |
| // that can be found in the LICENSE file in the root of the source |
| // tree. An additional intellectual property rights grant can be found |
| // in the file PATENTS. All contributing project authors may |
| // be found in the AUTHORS file in the root of the source tree. |
| #include "common/vp9_level_stats.h" |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "gtest/gtest.h" |
| |
| #include "common/hdr_util.h" |
| #include "common/vp9_header_parser.h" |
| #include "mkvparser/mkvparser.h" |
| #include "mkvparser/mkvreader.h" |
| #include "testing/test_util.h" |
| |
| namespace { |
| |
| // TODO(fgalligan): Refactor this test with other test files in this directory. |
| class Vp9LevelStatsTests : public ::testing::Test { |
| public: |
| Vp9LevelStatsTests() : is_reader_open_(false) {} |
| |
| ~Vp9LevelStatsTests() override { CloseReader(); } |
| |
| void CloseReader() { |
| if (is_reader_open_) { |
| reader_.Close(); |
| } |
| is_reader_open_ = false; |
| } |
| |
| void CreateAndLoadSegment(const std::string& filename, |
| int expected_doc_type_ver) { |
| ASSERT_NE(0u, filename.length()); |
| filename_ = test::GetTestFilePath(filename); |
| ASSERT_EQ(0, reader_.Open(filename_.c_str())); |
| is_reader_open_ = true; |
| pos_ = 0; |
| mkvparser::EBMLHeader ebml_header; |
| ebml_header.Parse(&reader_, pos_); |
| ASSERT_EQ(1, ebml_header.m_version); |
| ASSERT_EQ(1, ebml_header.m_readVersion); |
| ASSERT_STREQ("webm", ebml_header.m_docType); |
| ASSERT_EQ(expected_doc_type_ver, ebml_header.m_docTypeVersion); |
| ASSERT_EQ(2, ebml_header.m_docTypeReadVersion); |
| mkvparser::Segment* temp; |
| ASSERT_EQ(0, mkvparser::Segment::CreateInstance(&reader_, pos_, temp)); |
| segment_.reset(temp); |
| ASSERT_FALSE(HasFailure()); |
| ASSERT_GE(0, segment_->Load()); |
| } |
| |
| void CreateAndLoadSegment(const std::string& filename) { |
| CreateAndLoadSegment(filename, 4); |
| } |
| |
| void ProcessTheFrames() { |
| std::vector<uint8_t> data; |
| size_t data_len = 0; |
| const mkvparser::Tracks* const parser_tracks = segment_->GetTracks(); |
| ASSERT_TRUE(parser_tracks != NULL); |
| const mkvparser::Cluster* cluster = segment_->GetFirst(); |
| ASSERT_TRUE(cluster); |
| |
| while ((cluster != NULL) && !cluster->EOS()) { |
| const mkvparser::BlockEntry* block_entry; |
| long status = cluster->GetFirst(block_entry); // NOLINT |
| ASSERT_EQ(0, status); |
| |
| while ((block_entry != NULL) && !block_entry->EOS()) { |
| const mkvparser::Block* const block = block_entry->GetBlock(); |
| ASSERT_TRUE(block != NULL); |
| const long long trackNum = block->GetTrackNumber(); // NOLINT |
| const mkvparser::Track* const parser_track = |
| parser_tracks->GetTrackByNumber( |
| static_cast<unsigned long>(trackNum)); // NOLINT |
| ASSERT_TRUE(parser_track != NULL); |
| const long long track_type = parser_track->GetType(); // NOLINT |
| |
| if (track_type == mkvparser::Track::kVideo) { |
| const int frame_count = block->GetFrameCount(); |
| const long long time_ns = block->GetTime(cluster); // NOLINT |
| |
| for (int i = 0; i < frame_count; ++i) { |
| const mkvparser::Block::Frame& frame = block->GetFrame(i); |
| if (static_cast<size_t>(frame.len) > data.size()) { |
| data.resize(frame.len); |
| data_len = static_cast<size_t>(frame.len); |
| } |
| ASSERT_FALSE(frame.Read(&reader_, &data[0])); |
| parser_.ParseUncompressedHeader(&data[0], data_len); |
| stats_.AddFrame(parser_, time_ns); |
| } |
| } |
| |
| status = cluster->GetNext(block_entry, block_entry); |
| ASSERT_EQ(0, status); |
| } |
| |
| cluster = segment_->GetNext(cluster); |
| } |
| } |
| |
| protected: |
| mkvparser::MkvReader reader_; |
| bool is_reader_open_; |
| std::unique_ptr<mkvparser::Segment> segment_; |
| std::string filename_; |
| long long pos_; // NOLINT |
| vp9_parser::Vp9HeaderParser parser_; |
| vp9_parser::Vp9LevelStats stats_; |
| }; |
| |
| TEST_F(Vp9LevelStatsTests, VideoOnlyFile) { |
| CreateAndLoadSegment("test_stereo_left_right.webm"); |
| ProcessTheFrames(); |
| EXPECT_EQ(256, parser_.width()); |
| EXPECT_EQ(144, parser_.height()); |
| EXPECT_EQ(1, parser_.column_tiles()); |
| EXPECT_EQ(0, parser_.frame_parallel_mode()); |
| |
| EXPECT_EQ(11, stats_.GetLevel()); |
| EXPECT_EQ(479232, stats_.GetMaxLumaSampleRate()); |
| EXPECT_EQ(36864, stats_.GetMaxLumaPictureSize()); |
| EXPECT_DOUBLE_EQ(264.03233333333333, stats_.GetAverageBitRate()); |
| EXPECT_DOUBLE_EQ(147.136, stats_.GetMaxCpbSize()); |
| EXPECT_DOUBLE_EQ(19.267458404715583, stats_.GetCompressionRatio()); |
| EXPECT_EQ(1, stats_.GetMaxColumnTiles()); |
| EXPECT_EQ(11, stats_.GetMinimumAltrefDistance()); |
| EXPECT_EQ(3, stats_.GetMaxReferenceFrames()); |
| |
| EXPECT_TRUE(stats_.estimate_last_frame_duration()); |
| stats_.set_estimate_last_frame_duration(false); |
| EXPECT_DOUBLE_EQ(275.512, stats_.GetAverageBitRate()); |
| } |
| |
| TEST_F(Vp9LevelStatsTests, Muxed) { |
| CreateAndLoadSegment("bbb_480p_vp9_opus_1second.webm", 4); |
| ProcessTheFrames(); |
| EXPECT_EQ(854, parser_.width()); |
| EXPECT_EQ(480, parser_.height()); |
| EXPECT_EQ(2, parser_.column_tiles()); |
| EXPECT_EQ(1, parser_.frame_parallel_mode()); |
| |
| EXPECT_EQ(30, stats_.GetLevel()); |
| EXPECT_EQ(9838080, stats_.GetMaxLumaSampleRate()); |
| EXPECT_EQ(409920, stats_.GetMaxLumaPictureSize()); |
| EXPECT_DOUBLE_EQ(447.09394572025053, stats_.GetAverageBitRate()); |
| EXPECT_DOUBLE_EQ(118.464, stats_.GetMaxCpbSize()); |
| EXPECT_DOUBLE_EQ(241.17670131398313, stats_.GetCompressionRatio()); |
| EXPECT_EQ(2, stats_.GetMaxColumnTiles()); |
| EXPECT_EQ(9, stats_.GetMinimumAltrefDistance()); |
| EXPECT_EQ(3, stats_.GetMaxReferenceFrames()); |
| |
| stats_.set_estimate_last_frame_duration(false); |
| EXPECT_DOUBLE_EQ(468.38413361169108, stats_.GetAverageBitRate()); |
| } |
| |
| TEST_F(Vp9LevelStatsTests, SetDuration) { |
| CreateAndLoadSegment("test_stereo_left_right.webm"); |
| ProcessTheFrames(); |
| const int64_t kDurationNano = 2080000000; // 2.08 seconds |
| stats_.set_duration(kDurationNano); |
| EXPECT_EQ(256, parser_.width()); |
| EXPECT_EQ(144, parser_.height()); |
| EXPECT_EQ(1, parser_.column_tiles()); |
| EXPECT_EQ(0, parser_.frame_parallel_mode()); |
| |
| EXPECT_EQ(11, stats_.GetLevel()); |
| EXPECT_EQ(479232, stats_.GetMaxLumaSampleRate()); |
| EXPECT_EQ(36864, stats_.GetMaxLumaPictureSize()); |
| EXPECT_DOUBLE_EQ(264.9153846153846, stats_.GetAverageBitRate()); |
| EXPECT_DOUBLE_EQ(147.136, stats_.GetMaxCpbSize()); |
| EXPECT_DOUBLE_EQ(19.267458404715583, stats_.GetCompressionRatio()); |
| EXPECT_EQ(1, stats_.GetMaxColumnTiles()); |
| EXPECT_EQ(11, stats_.GetMinimumAltrefDistance()); |
| EXPECT_EQ(3, stats_.GetMaxReferenceFrames()); |
| } |
| |
| } // namespace |
| |
| int main(int argc, char* argv[]) { |
| ::testing::InitGoogleTest(&argc, argv); |
| return RUN_ALL_TESTS(); |
| } |