1 /*
2 * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/video_coding/utility/ivf_file_reader.h"
12 #include "modules/video_coding/utility/ivf_file_writer.h"
13
14 #include <memory>
15 #include <string>
16
17 #include "test/gtest.h"
18 #include "test/testsupport/file_utils.h"
19
20 namespace webrtc {
21 namespace {
22
23 constexpr int kWidth = 320;
24 constexpr int kHeight = 240;
25 constexpr int kNumFrames = 3;
26 constexpr uint8_t kDummyPayload[4] = {'0', '1', '2', '3'};
27
28 } // namespace
29
30 class IvfFileReaderTest : public ::testing::Test {
31 protected:
SetUp()32 void SetUp() override {
33 file_name_ =
34 webrtc::test::TempFilename(webrtc::test::OutputPath(), "test_file.ivf");
35 }
TearDown()36 void TearDown() override { webrtc::test::RemoveFile(file_name_); }
37
WriteDummyTestFrames(IvfFileWriter * file_writer,VideoCodecType codec_type,int width,int height,int num_frames,bool use_capture_tims_ms,int spatial_layers_count)38 bool WriteDummyTestFrames(IvfFileWriter* file_writer,
39 VideoCodecType codec_type,
40 int width,
41 int height,
42 int num_frames,
43 bool use_capture_tims_ms,
44 int spatial_layers_count) {
45 EncodedImage frame;
46 frame.SetSpatialIndex(spatial_layers_count);
47 rtc::scoped_refptr<EncodedImageBuffer> payload = EncodedImageBuffer::Create(
48 sizeof(kDummyPayload) * spatial_layers_count);
49 for (int i = 0; i < spatial_layers_count; ++i) {
50 memcpy(&payload->data()[i * sizeof(kDummyPayload)], kDummyPayload,
51 sizeof(kDummyPayload));
52 frame.SetSpatialLayerFrameSize(i, sizeof(kDummyPayload));
53 }
54 frame.SetEncodedData(payload);
55 frame._encodedWidth = width;
56 frame._encodedHeight = height;
57 for (int i = 1; i <= num_frames; ++i) {
58 if (use_capture_tims_ms) {
59 frame.capture_time_ms_ = i;
60 } else {
61 frame.SetTimestamp(i);
62 }
63 if (!file_writer->WriteFrame(frame, codec_type))
64 return false;
65 }
66 return true;
67 }
68
CreateTestFile(VideoCodecType codec_type,bool use_capture_tims_ms,int spatial_layers_count)69 void CreateTestFile(VideoCodecType codec_type,
70 bool use_capture_tims_ms,
71 int spatial_layers_count) {
72 std::unique_ptr<IvfFileWriter> file_writer =
73 IvfFileWriter::Wrap(FileWrapper::OpenWriteOnly(file_name_), 0);
74 ASSERT_TRUE(file_writer.get());
75 ASSERT_TRUE(WriteDummyTestFrames(file_writer.get(), codec_type, kWidth,
76 kHeight, kNumFrames, use_capture_tims_ms,
77 spatial_layers_count));
78 ASSERT_TRUE(file_writer->Close());
79 }
80
ValidateFrame(absl::optional<EncodedImage> frame,int frame_index,bool use_capture_tims_ms,int spatial_layers_count)81 void ValidateFrame(absl::optional<EncodedImage> frame,
82 int frame_index,
83 bool use_capture_tims_ms,
84 int spatial_layers_count) {
85 ASSERT_TRUE(frame);
86 EXPECT_EQ(frame->SpatialIndex(), spatial_layers_count - 1);
87 if (use_capture_tims_ms) {
88 EXPECT_EQ(frame->capture_time_ms_, static_cast<int64_t>(frame_index));
89 EXPECT_EQ(frame->Timestamp(), static_cast<int64_t>(90 * frame_index));
90 } else {
91 EXPECT_EQ(frame->Timestamp(), static_cast<int64_t>(frame_index));
92 }
93 ASSERT_EQ(frame->size(), sizeof(kDummyPayload) * spatial_layers_count);
94 for (int i = 0; i < spatial_layers_count; ++i) {
95 EXPECT_EQ(memcmp(&frame->data()[i * sizeof(kDummyPayload)], kDummyPayload,
96 sizeof(kDummyPayload)),
97 0)
98 << std::string(reinterpret_cast<char const*>(
99 &frame->data()[i * sizeof(kDummyPayload)]),
100 sizeof(kDummyPayload));
101 }
102 }
103
ValidateContent(VideoCodecType codec_type,bool use_capture_tims_ms,int spatial_layers_count)104 void ValidateContent(VideoCodecType codec_type,
105 bool use_capture_tims_ms,
106 int spatial_layers_count) {
107 std::unique_ptr<IvfFileReader> reader =
108 IvfFileReader::Create(FileWrapper::OpenReadOnly(file_name_));
109 ASSERT_TRUE(reader.get());
110 EXPECT_EQ(reader->GetVideoCodecType(), codec_type);
111 EXPECT_EQ(reader->GetFramesCount(),
112 spatial_layers_count * static_cast<size_t>(kNumFrames));
113 for (int i = 1; i <= kNumFrames; ++i) {
114 ASSERT_TRUE(reader->HasMoreFrames());
115 ValidateFrame(reader->NextFrame(), i, use_capture_tims_ms,
116 spatial_layers_count);
117 EXPECT_FALSE(reader->HasError());
118 }
119 EXPECT_FALSE(reader->HasMoreFrames());
120 EXPECT_FALSE(reader->NextFrame());
121 EXPECT_FALSE(reader->HasError());
122 ASSERT_TRUE(reader->Close());
123 }
124
125 std::string file_name_;
126 };
127
TEST_F(IvfFileReaderTest,BasicVp8FileNtpTimestamp)128 TEST_F(IvfFileReaderTest, BasicVp8FileNtpTimestamp) {
129 CreateTestFile(kVideoCodecVP8, false, 1);
130 ValidateContent(kVideoCodecVP8, false, 1);
131 }
132
TEST_F(IvfFileReaderTest,BasicVP8FileMsTimestamp)133 TEST_F(IvfFileReaderTest, BasicVP8FileMsTimestamp) {
134 CreateTestFile(kVideoCodecVP8, true, 1);
135 ValidateContent(kVideoCodecVP8, true, 1);
136 }
137
TEST_F(IvfFileReaderTest,BasicVP9FileNtpTimestamp)138 TEST_F(IvfFileReaderTest, BasicVP9FileNtpTimestamp) {
139 CreateTestFile(kVideoCodecVP9, false, 1);
140 ValidateContent(kVideoCodecVP9, false, 1);
141 }
142
TEST_F(IvfFileReaderTest,BasicVP9FileMsTimestamp)143 TEST_F(IvfFileReaderTest, BasicVP9FileMsTimestamp) {
144 CreateTestFile(kVideoCodecVP9, true, 1);
145 ValidateContent(kVideoCodecVP9, true, 1);
146 }
147
TEST_F(IvfFileReaderTest,BasicAv1FileNtpTimestamp)148 TEST_F(IvfFileReaderTest, BasicAv1FileNtpTimestamp) {
149 CreateTestFile(kVideoCodecAV1, false, 1);
150 ValidateContent(kVideoCodecAV1, false, 1);
151 }
152
TEST_F(IvfFileReaderTest,BasicAv1FileMsTimestamp)153 TEST_F(IvfFileReaderTest, BasicAv1FileMsTimestamp) {
154 CreateTestFile(kVideoCodecAV1, true, 1);
155 ValidateContent(kVideoCodecAV1, true, 1);
156 }
157
TEST_F(IvfFileReaderTest,BasicH264FileNtpTimestamp)158 TEST_F(IvfFileReaderTest, BasicH264FileNtpTimestamp) {
159 CreateTestFile(kVideoCodecH264, false, 1);
160 ValidateContent(kVideoCodecH264, false, 1);
161 }
162
TEST_F(IvfFileReaderTest,BasicH264FileMsTimestamp)163 TEST_F(IvfFileReaderTest, BasicH264FileMsTimestamp) {
164 CreateTestFile(kVideoCodecH264, true, 1);
165 ValidateContent(kVideoCodecH264, true, 1);
166 }
167
TEST_F(IvfFileReaderTest,MultilayerVp8FileNtpTimestamp)168 TEST_F(IvfFileReaderTest, MultilayerVp8FileNtpTimestamp) {
169 CreateTestFile(kVideoCodecVP8, false, 3);
170 ValidateContent(kVideoCodecVP8, false, 3);
171 }
172
TEST_F(IvfFileReaderTest,MultilayerVP9FileNtpTimestamp)173 TEST_F(IvfFileReaderTest, MultilayerVP9FileNtpTimestamp) {
174 CreateTestFile(kVideoCodecVP9, false, 3);
175 ValidateContent(kVideoCodecVP9, false, 3);
176 }
177
TEST_F(IvfFileReaderTest,MultilayerAv1FileNtpTimestamp)178 TEST_F(IvfFileReaderTest, MultilayerAv1FileNtpTimestamp) {
179 CreateTestFile(kVideoCodecAV1, false, 3);
180 ValidateContent(kVideoCodecAV1, false, 3);
181 }
182
TEST_F(IvfFileReaderTest,MultilayerH264FileNtpTimestamp)183 TEST_F(IvfFileReaderTest, MultilayerH264FileNtpTimestamp) {
184 CreateTestFile(kVideoCodecH264, false, 3);
185 ValidateContent(kVideoCodecH264, false, 3);
186 }
187
188 } // namespace webrtc
189