Index: webrtc/modules/video_coding/utility/ivf_file_writer_unittest.cc |
diff --git a/webrtc/modules/video_coding/utility/ivf_file_writer_unittest.cc b/webrtc/modules/video_coding/utility/ivf_file_writer_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bdd74a491b0a8b3d8430bc029b206d500114feff |
--- /dev/null |
+++ b/webrtc/modules/video_coding/utility/ivf_file_writer_unittest.cc |
@@ -0,0 +1,176 @@ |
+/* |
+ * Copyright (c) 2016 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 "webrtc/modules/video_coding/utility/ivf_file_writer.h" |
+ |
+#include <memory> |
+ |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "webrtc/base/logging.h" |
+#include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
+#include "webrtc/system_wrappers/include/tick_util.h" |
+#include "webrtc/test/testsupport/fileutils.h" |
+ |
+namespace webrtc { |
+ |
+namespace { |
+static const int kHeaderSize = 32; |
+static const int kFrameHeaderSize = 12; |
+static uint8_t dummy_payload[4] = {0, 1, 2, 3}; |
+} // namespace |
+ |
+class IvfFileWriterTest : public ::testing::Test { |
+ protected: |
+ void SetUp() override { |
+ const int64_t start_id = |
+ reinterpret_cast<int64_t>(this) ^ TickTime::MicrosecondTimestamp(); |
+ int64_t id = start_id; |
+ do { |
+ std::ostringstream oss; |
+ oss << test::OutputPath() << "ivf_test_file_" << id++ << ".ivf"; |
+ file_name_ = oss.str(); |
+ } while (id < start_id + 100 && FileExists()); |
+ ASSERT_LT(id, start_id + 100); |
+ } |
+ |
+ bool WriteDummyTestFrames(int width, |
+ int height, |
+ int num_frames, |
+ bool use_capture_tims_ms) { |
+ EncodedImage frame; |
+ frame._buffer = dummy_payload; |
+ frame._encodedWidth = width; |
+ frame._encodedHeight = height; |
+ for (int i = 1; i <= num_frames; ++i) { |
+ frame._length = i % sizeof(dummy_payload); |
+ if (use_capture_tims_ms) { |
+ frame.capture_time_ms_ = i; |
+ } else { |
+ frame._timeStamp = i; |
+ } |
+ if (!file_writer_->WriteFrame(frame)) |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ void VerifyIvfHeader(FileWrapper* file, |
+ const uint8_t fourcc[4], |
+ int width, |
+ int height, |
+ uint32_t num_frames, |
+ bool use_capture_tims_ms) { |
+ uint8_t data[kHeaderSize]; |
+ ASSERT_EQ(kHeaderSize, file->Read(data, kHeaderSize)); |
+ |
+ uint8_t dkif[4] = {'D', 'K', 'I', 'F'}; |
+ EXPECT_EQ(0, memcmp(dkif, data, 4)); |
+ EXPECT_EQ(0u, ByteReader<uint16_t>::ReadLittleEndian(&data[4])); |
+ EXPECT_EQ(32u, ByteReader<uint16_t>::ReadLittleEndian(&data[6])); |
+ EXPECT_EQ(0, memcmp(fourcc, &data[8], 4)); |
+ EXPECT_EQ(width, ByteReader<uint16_t>::ReadLittleEndian(&data[12])); |
+ EXPECT_EQ(height, ByteReader<uint16_t>::ReadLittleEndian(&data[14])); |
+ EXPECT_EQ(use_capture_tims_ms ? 1000u : 90000u, |
+ ByteReader<uint32_t>::ReadLittleEndian(&data[16])); |
+ EXPECT_EQ(1u, ByteReader<uint32_t>::ReadLittleEndian(&data[20])); |
+ EXPECT_EQ(num_frames, ByteReader<uint32_t>::ReadLittleEndian(&data[24])); |
+ EXPECT_EQ(0u, ByteReader<uint32_t>::ReadLittleEndian(&data[28])); |
+ } |
+ |
+ void VerifyDummyTestFrames(FileWrapper* file, uint32_t num_frames) { |
+ const int kMaxFrameSize = 4; |
+ for (uint32_t i = 1; i <= num_frames; ++i) { |
+ uint8_t frame_header[kFrameHeaderSize]; |
+ ASSERT_EQ(kFrameHeaderSize, file->Read(frame_header, kFrameHeaderSize)); |
+ uint32_t frame_length = |
+ ByteReader<uint32_t>::ReadLittleEndian(&frame_header[0]); |
+ EXPECT_EQ(i % 4, frame_length); |
+ uint64_t timestamp = |
+ ByteReader<uint64_t>::ReadLittleEndian(&frame_header[4]); |
+ EXPECT_EQ(i, timestamp); |
+ |
+ uint8_t data[kMaxFrameSize] = {}; |
+ ASSERT_EQ(frame_length, |
+ static_cast<uint32_t>(file->Read(data, frame_length))); |
+ EXPECT_EQ(0, memcmp(data, dummy_payload, frame_length)); |
+ } |
+ } |
+ |
+ void RunBasicFileStructureTest(RtpVideoCodecTypes codec_type, |
+ const uint8_t fourcc[4], |
+ bool use_capture_tims_ms) { |
+ file_writer_ = IvfFileWriter::Open(file_name_, codec_type); |
+ ASSERT_TRUE(file_writer_.get()); |
+ const int kWidth = 320; |
+ const int kHeight = 240; |
+ const int kNumFrames = 257; |
+ EXPECT_TRUE( |
+ WriteDummyTestFrames(kWidth, kHeight, kNumFrames, use_capture_tims_ms)); |
+ EXPECT_TRUE(file_writer_->Close()); |
+ |
+ std::unique_ptr<FileWrapper> out_file(FileWrapper::Create()); |
+ ASSERT_EQ(0, out_file->OpenFile(file_name_.c_str(), true)); |
+ VerifyIvfHeader(out_file.get(), fourcc, kWidth, kHeight, kNumFrames, |
+ use_capture_tims_ms); |
+ VerifyDummyTestFrames(out_file.get(), kNumFrames); |
+ |
+ EXPECT_EQ(0, out_file->CloseFile()); |
+ EXPECT_EQ(0, remove(file_name_.c_str())); |
+ } |
+ |
+ bool FileExists() { |
+ std::unique_ptr<FileWrapper> file_wrapper(FileWrapper::Create()); |
+ return file_wrapper->OpenFile(file_name_.c_str(), true) == 0; |
+ } |
+ |
+ std::string file_name_; |
+ std::unique_ptr<IvfFileWriter> file_writer_; |
+}; |
+ |
+TEST_F(IvfFileWriterTest, RemovesUnusedFile) { |
+ file_writer_ = IvfFileWriter::Open(file_name_, kRtpVideoVp8); |
+ ASSERT_TRUE(file_writer_.get() != nullptr); |
+ EXPECT_TRUE(FileExists()); |
+ EXPECT_TRUE(file_writer_->Close()); |
+ EXPECT_FALSE(FileExists()); |
+ EXPECT_FALSE(file_writer_->Close()); // Can't close twice. |
+} |
+ |
+TEST_F(IvfFileWriterTest, WritesBasicVP8FileNtpTimestamp) { |
+ const uint8_t fourcc[4] = {'V', 'P', '8', '0'}; |
+ RunBasicFileStructureTest(kRtpVideoVp8, fourcc, false); |
+} |
+ |
+TEST_F(IvfFileWriterTest, WritesBasicVP8FileMsTimestamp) { |
+ const uint8_t fourcc[4] = {'V', 'P', '8', '0'}; |
+ RunBasicFileStructureTest(kRtpVideoVp8, fourcc, true); |
+} |
+ |
+TEST_F(IvfFileWriterTest, WritesBasicVP9FileNtpTimestamp) { |
+ const uint8_t fourcc[4] = {'V', 'P', '9', '0'}; |
+ RunBasicFileStructureTest(kRtpVideoVp9, fourcc, false); |
+} |
+ |
+TEST_F(IvfFileWriterTest, WritesBasicVP9FileMsTimestamp) { |
+ const uint8_t fourcc[4] = {'V', 'P', '9', '0'}; |
+ RunBasicFileStructureTest(kRtpVideoVp9, fourcc, true); |
+} |
+ |
+TEST_F(IvfFileWriterTest, WritesBasicH264FileNtpTimestamp) { |
+ const uint8_t fourcc[4] = {'H', '2', '6', '4'}; |
+ RunBasicFileStructureTest(kRtpVideoH264, fourcc, false); |
+} |
+ |
+TEST_F(IvfFileWriterTest, WritesBasicH264FileMsTimestamp) { |
+ const uint8_t fourcc[4] = {'H', '2', '6', '4'}; |
+ RunBasicFileStructureTest(kRtpVideoH264, fourcc, true); |
+} |
+ |
+} // namespace webrtc |