| /* | |
| * Copyright (c) 2019 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 "modules/video_coding/utility/ivf_file_reader.h" | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <cstring> | |
| #include <memory> | |
| #include <optional> | |
| #include <string> | |
| #include "api/scoped_refptr.h" | |
| #include "api/video/encoded_image.h" | |
| #include "api/video/video_codec_type.h" | |
| #include "modules/video_coding/utility/ivf_file_writer.h" | |
| #include "rtc_base/system/file_wrapper.h" | |
| #include "test/gtest.h" | |
| #include "test/testsupport/file_utils.h" | |
| namespace webrtc { | |
| namespace { | |
| constexpr int kWidth = 320; | |
| constexpr int kHeight = 240; | |
| constexpr int kNumFrames = 3; | |
| constexpr uint8_t kDummyPayload[4] = {'0', '1', '2', '3'}; | |
| } // namespace | |
| class IvfFileReaderTest : public ::testing::Test { | |
| protected: | |
| void SetUp() override { | |
| file_name_ = test::TempFilename(test::OutputPath(), "test_file.ivf"); | |
| } | |
| void TearDown() override { test::RemoveFile(file_name_); } | |
| bool WriteDummyTestFrames(IvfFileWriter* file_writer, | |
| VideoCodecType codec_type, | |
| int width, | |
| int height, | |
| int num_frames, | |
| bool use_capture_tims_ms, | |
| int spatial_layers_count) { | |
| EncodedImage frame; | |
| frame.SetSpatialIndex(spatial_layers_count); | |
| scoped_refptr<EncodedImageBuffer> payload = EncodedImageBuffer::Create( | |
| sizeof(kDummyPayload) * spatial_layers_count); | |
| for (int i = 0; i < spatial_layers_count; ++i) { | |
| memcpy(&payload->data()[i * sizeof(kDummyPayload)], kDummyPayload, | |
| sizeof(kDummyPayload)); | |
| frame.SetSpatialLayerFrameSize(i, sizeof(kDummyPayload)); | |
| } | |
| frame.SetEncodedData(payload); | |
| frame._encodedWidth = width; | |
| frame._encodedHeight = height; | |
| for (int i = 1; i <= num_frames; ++i) { | |
| if (use_capture_tims_ms) { | |
| frame.capture_time_ms_ = i; | |
| } else { | |
| frame.SetRtpTimestamp(i); | |
| } | |
| if (!file_writer->WriteFrame(frame, codec_type)) | |
| return false; | |
| } | |
| return true; | |
| } | |
| void CreateTestFile(VideoCodecType codec_type, | |
| bool use_capture_tims_ms, | |
| int spatial_layers_count) { | |
| std::unique_ptr<IvfFileWriter> file_writer = | |
| IvfFileWriter::Wrap(FileWrapper::OpenWriteOnly(file_name_), 0); | |
| ASSERT_TRUE(file_writer.get()); | |
| ASSERT_TRUE(WriteDummyTestFrames(file_writer.get(), codec_type, kWidth, | |
| kHeight, kNumFrames, use_capture_tims_ms, | |
| spatial_layers_count)); | |
| ASSERT_TRUE(file_writer->Close()); | |
| } | |
| void ValidateFrame(std::optional<EncodedImage> frame, | |
| int frame_index, | |
| bool use_capture_tims_ms, | |
| int spatial_layers_count) { | |
| ASSERT_TRUE(frame); | |
| EXPECT_EQ(frame->SpatialIndex(), spatial_layers_count - 1); | |
| if (use_capture_tims_ms) { | |
| EXPECT_EQ(frame->capture_time_ms_, static_cast<int64_t>(frame_index)); | |
| EXPECT_EQ(frame->RtpTimestamp(), static_cast<int64_t>(90 * frame_index)); | |
| } else { | |
| EXPECT_EQ(frame->RtpTimestamp(), static_cast<int64_t>(frame_index)); | |
| } | |
| ASSERT_EQ(frame->size(), sizeof(kDummyPayload) * spatial_layers_count); | |
| for (int i = 0; i < spatial_layers_count; ++i) { | |
| EXPECT_EQ(memcmp(&frame->data()[i * sizeof(kDummyPayload)], kDummyPayload, | |
| sizeof(kDummyPayload)), | |
| 0) | |
| << std::string(reinterpret_cast<char const*>( | |
| &frame->data()[i * sizeof(kDummyPayload)]), | |
| sizeof(kDummyPayload)); | |
| } | |
| } | |
| void ValidateContent(VideoCodecType codec_type, | |
| bool use_capture_tims_ms, | |
| int spatial_layers_count) { | |
| std::unique_ptr<IvfFileReader> reader = | |
| IvfFileReader::Create(FileWrapper::OpenReadOnly(file_name_)); | |
| ASSERT_TRUE(reader.get()); | |
| EXPECT_EQ(reader->GetVideoCodecType(), codec_type); | |
| EXPECT_EQ(reader->GetFramesCount(), | |
| spatial_layers_count * static_cast<size_t>(kNumFrames)); | |
| for (int i = 1; i <= kNumFrames; ++i) { | |
| ASSERT_TRUE(reader->HasMoreFrames()); | |
| ValidateFrame(reader->NextFrame(), i, use_capture_tims_ms, | |
| spatial_layers_count); | |
| EXPECT_FALSE(reader->HasError()); | |
| } | |
| EXPECT_FALSE(reader->HasMoreFrames()); | |
| EXPECT_FALSE(reader->NextFrame()); | |
| EXPECT_FALSE(reader->HasError()); | |
| ASSERT_TRUE(reader->Close()); | |
| } | |
| std::string file_name_; | |
| }; | |
| TEST_F(IvfFileReaderTest, BasicVp8FileNtpTimestamp) { | |
| CreateTestFile(kVideoCodecVP8, false, 1); | |
| ValidateContent(kVideoCodecVP8, false, 1); | |
| } | |
| TEST_F(IvfFileReaderTest, BasicVP8FileMsTimestamp) { | |
| CreateTestFile(kVideoCodecVP8, true, 1); | |
| ValidateContent(kVideoCodecVP8, true, 1); | |
| } | |
| TEST_F(IvfFileReaderTest, BasicVP9FileNtpTimestamp) { | |
| CreateTestFile(kVideoCodecVP9, false, 1); | |
| ValidateContent(kVideoCodecVP9, false, 1); | |
| } | |
| TEST_F(IvfFileReaderTest, BasicVP9FileMsTimestamp) { | |
| CreateTestFile(kVideoCodecVP9, true, 1); | |
| ValidateContent(kVideoCodecVP9, true, 1); | |
| } | |
| TEST_F(IvfFileReaderTest, BasicAv1FileNtpTimestamp) { | |
| CreateTestFile(kVideoCodecAV1, false, 1); | |
| ValidateContent(kVideoCodecAV1, false, 1); | |
| } | |
| TEST_F(IvfFileReaderTest, BasicAv1FileMsTimestamp) { | |
| CreateTestFile(kVideoCodecAV1, true, 1); | |
| ValidateContent(kVideoCodecAV1, true, 1); | |
| } | |
| TEST_F(IvfFileReaderTest, BasicH264FileNtpTimestamp) { | |
| CreateTestFile(kVideoCodecH264, false, 1); | |
| ValidateContent(kVideoCodecH264, false, 1); | |
| } | |
| TEST_F(IvfFileReaderTest, BasicH264FileMsTimestamp) { | |
| CreateTestFile(kVideoCodecH264, true, 1); | |
| ValidateContent(kVideoCodecH264, true, 1); | |
| } | |
| TEST_F(IvfFileReaderTest, MultilayerVp8FileNtpTimestamp) { | |
| CreateTestFile(kVideoCodecVP8, false, 3); | |
| ValidateContent(kVideoCodecVP8, false, 3); | |
| } | |
| TEST_F(IvfFileReaderTest, MultilayerVP9FileNtpTimestamp) { | |
| CreateTestFile(kVideoCodecVP9, false, 3); | |
| ValidateContent(kVideoCodecVP9, false, 3); | |
| } | |
| TEST_F(IvfFileReaderTest, MultilayerAv1FileNtpTimestamp) { | |
| CreateTestFile(kVideoCodecAV1, false, 3); | |
| ValidateContent(kVideoCodecAV1, false, 3); | |
| } | |
| TEST_F(IvfFileReaderTest, MultilayerH264FileNtpTimestamp) { | |
| CreateTestFile(kVideoCodecH264, false, 3); | |
| ValidateContent(kVideoCodecH264, false, 3); | |
| } | |
| } // namespace webrtc |