| /* | |
| * Copyright 2025 The WebRTC 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 "video/corruption_detection/evaluation/utils.h" | |
| #include <cstdint> | |
| #include <memory> | |
| #include <string> | |
| #include <vector> | |
| #include "api/scoped_refptr.h" | |
| #include "api/video/i420_buffer.h" | |
| #include "test/gmock.h" | |
| #include "test/gtest.h" | |
| #include "test/testsupport/file_utils.h" | |
| #include "test/testsupport/frame_reader.h" | |
| namespace webrtc { | |
| namespace { | |
| using ::testing::HasSubstr; | |
| using ::testing::Not; | |
| // Dimension for the test frames. | |
| constexpr int kWidth = 4; | |
| constexpr int kHeight = 4; | |
| constexpr int kChromaWidth = 2; | |
| constexpr int kChromaHeight = 2; | |
| constexpr int kFrameRate = 30; | |
| // An arbitrary 4x4 raw YUV420 frame. | |
| constexpr uint8_t kFrameYContent[kWidth * kHeight] = { | |
| 12, 5, 7, 11, // | |
| 159, 15, 11, 0, // | |
| 4, 240, 131, 59, // | |
| 61, 87, 11, 0 // | |
| }; | |
| constexpr uint8_t kFrameUContent[kChromaWidth * kChromaHeight] = { | |
| 248, 184, // | |
| 139, 229 // | |
| }; | |
| constexpr uint8_t kFrameVContent[kChromaWidth * kChromaHeight] = { | |
| 32, 69, // | |
| 7, 193 // | |
| }; | |
| // Concatenates and returns Y, U and V content into a single vector. | |
| std::vector<uint8_t> ConcatenateVideoChannels() { | |
| std::vector<uint8_t> file_content_flattened; | |
| file_content_flattened.insert(file_content_flattened.end(), kFrameYContent, | |
| kFrameYContent + kWidth * kHeight); | |
| file_content_flattened.insert(file_content_flattened.end(), kFrameUContent, | |
| kFrameUContent + kChromaWidth * kChromaHeight); | |
| file_content_flattened.insert(file_content_flattened.end(), kFrameVContent, | |
| kFrameVContent + kChromaWidth * kChromaHeight); | |
| return file_content_flattened; | |
| } | |
| TEST(TempY4mFileCreatorTest, CheckIfY4mFileIsCreated) { | |
| std::vector<uint8_t> file_content_flattened = ConcatenateVideoChannels(); | |
| TempY4mFileCreator temp_y4m_file_creator(kWidth, kHeight, kFrameRate); | |
| temp_y4m_file_creator.CreateTempY4mFile(file_content_flattened); | |
| EXPECT_TRUE(test::FileExists(temp_y4m_file_creator.y4m_filepath())); | |
| } | |
| TEST(TempY4mFileCreatorTest, CanCreateMultipleFiles) { | |
| std::vector<uint8_t> file_content_flattened = ConcatenateVideoChannels(); | |
| TempY4mFileCreator temp_y4m_file_creator_1(kWidth, kHeight, kFrameRate); | |
| TempY4mFileCreator temp_y4m_file_creator_2(kWidth, kHeight, kFrameRate); | |
| temp_y4m_file_creator_1.CreateTempY4mFile(file_content_flattened); | |
| temp_y4m_file_creator_2.CreateTempY4mFile(file_content_flattened); | |
| // Check that the files are created. | |
| ASSERT_TRUE(test::FileExists(temp_y4m_file_creator_1.y4m_filepath())); | |
| ASSERT_TRUE(test::FileExists(temp_y4m_file_creator_2.y4m_filepath())); | |
| // Check that the created files have different paths. | |
| EXPECT_THAT(temp_y4m_file_creator_1.y4m_filepath(), | |
| Not(temp_y4m_file_creator_2.y4m_filepath())); | |
| } | |
| TEST(TempY4mFileCreatorTest, CheckIfY4mFileHasCorrectContent) { | |
| std::vector<uint8_t> file_content_flattened = ConcatenateVideoChannels(); | |
| TempY4mFileCreator temp_y4m_file_creator(kWidth, kHeight, kFrameRate); | |
| temp_y4m_file_creator.CreateTempY4mFile(file_content_flattened); | |
| std::unique_ptr<test::FrameReader> frame_generator = | |
| CreateY4mFrameReader(std::string(temp_y4m_file_creator.y4m_filepath()), | |
| test::YuvFrameReaderImpl::RepeatMode::kSingle); | |
| scoped_refptr<I420Buffer> i420_buffer = frame_generator->PullFrame(); | |
| ASSERT_EQ(i420_buffer->width(), kWidth); | |
| ASSERT_EQ(i420_buffer->height(), kHeight); | |
| for (int i = 0; i < kWidth * kHeight; ++i) { | |
| EXPECT_EQ(i420_buffer->DataY()[i], kFrameYContent[i]); | |
| } | |
| for (int i = 0; i < kChromaWidth * kChromaHeight; ++i) { | |
| EXPECT_EQ(i420_buffer->DataU()[i], kFrameUContent[i]); | |
| EXPECT_EQ(i420_buffer->DataV()[i], kFrameVContent[i]); | |
| } | |
| // No more frames. | |
| EXPECT_THAT(frame_generator->PullFrame(), nullptr); | |
| } | |
| #if GTEST_HAS_DEATH_TEST | |
| TEST(TempY4mFileCreatorTest, ContentEndInMiddleError) { | |
| std::vector<uint8_t> file_content_flattened = ConcatenateVideoChannels(); | |
| std::vector<uint8_t> only_luma_content( | |
| file_content_flattened.begin(), | |
| file_content_flattened.begin() + kWidth * kHeight); | |
| TempY4mFileCreator temp_y4m_file_creator(kWidth, kHeight, kFrameRate); | |
| EXPECT_DEATH(temp_y4m_file_creator.CreateTempY4mFile(only_luma_content), | |
| HasSubstr("Content size is not a multiple of frame size.")); | |
| } | |
| #endif // GTEST_HAS_DEATH_TEST | |
| TEST(ReadMetadataFromY4mHeaderTest, ReadMetadataFromY4mHeader) { | |
| std::vector<uint8_t> file_content_flattened = ConcatenateVideoChannels(); | |
| TempY4mFileCreator temp_y4m_file_creator(kWidth, kHeight, kFrameRate); | |
| temp_y4m_file_creator.CreateTempY4mFile(file_content_flattened); | |
| Y4mMetadata y4m_metadata = | |
| ReadMetadataFromY4mHeader(temp_y4m_file_creator.y4m_filepath()); | |
| EXPECT_EQ(y4m_metadata.width, kWidth); | |
| EXPECT_EQ(y4m_metadata.height, kHeight); | |
| EXPECT_EQ(y4m_metadata.framerate, kFrameRate); | |
| } | |
| } // namespace | |
| } // namespace webrtc |