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..ded7627fd9a98f674b465d34ec1f058edaf5e2eb |
--- /dev/null |
+++ b/webrtc/modules/video_coding/utility/ivf_file_writer_unittest.cc |
@@ -0,0 +1,140 @@ |
+/* |
+ * 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/fileutils.h" |
+#include "webrtc/base/logging.h" |
+#include "webrtc/base/pathutils.h" |
+#include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
+ |
+namespace webrtc { |
+ |
+namespace { |
+static const size_t kHeaderSize = 32; |
+const size_t kFrameHeaderSize = 12; |
+uint8_t dummy_payload[4] = {0, 1, 2, 3}; |
+} // namespace |
+ |
+class IvfFileWriterTest : public ::testing::Test { |
+ protected: |
+ void SetUp() override { |
+ ASSERT_TRUE(rtc::CreateUniqueFile(file_name_, false)); |
+ } |
+ |
+ bool WriteDummyTestFrames(int width, int height, int num_frames) { |
+ EncodedImage frame; |
+ frame._buffer = dummy_payload; |
+ frame._encodedWidth = width; |
+ frame._encodedHeight = height; |
+ for (int i = 0; i < num_frames; ++i) { |
+ frame._length = i % sizeof(dummy_payload); |
+ frame.ntp_time_ms_ = i; |
+ if (!file_writer_->WriteFrame(frame)) |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ void VerifyIvfHeader(const uint8_t* data, |
+ const uint8_t fourcc[4], |
+ int width, |
+ int height, |
+ uint32_t num_frames) { |
+ uint8_t dkif[4] = {'D', 'K', 'I', 'F'}; |
+ EXPECT_EQ(0, memcmp(dkif, data, 4)); |
+ EXPECT_EQ(0, ByteReader<uint16_t>::ReadLittleEndian(&data[4])); |
+ EXPECT_EQ(32, 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(1000u, 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(const uint8_t* data, |
+ size_t size, |
+ uint32_t num_frames) { |
+ size_t bytes_read = 0; |
+ for (uint32_t i = 0; i < num_frames; ++i) { |
+ ASSERT_LE(bytes_read + kFrameHeaderSize, size); |
+ uint32_t frame_length = |
+ ByteReader<uint32_t>::ReadLittleEndian(&data[bytes_read]); |
+ EXPECT_EQ(i % 4, frame_length); |
+ uint64_t timestamp = |
+ ByteReader<uint64_t>::ReadLittleEndian(&data[bytes_read + 4]); |
+ EXPECT_EQ(i, timestamp); |
+ bytes_read += kFrameHeaderSize; |
+ |
+ ASSERT_LE(bytes_read + frame_length, size); |
+ EXPECT_EQ(0, memcmp(&data[bytes_read], dummy_payload, frame_length)); |
+ bytes_read += frame_length; |
+ } |
+ } |
+ |
+ void RunBasicFileStructureTest(RtpVideoCodecTypes codec_type, |
+ const uint8_t fourcc[4]) { |
+ rtc::MemoryStream* out_stream = new rtc::MemoryStream(); |
+ file_writer_ = IvfFileWriter::Open(out_stream, 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)); |
+ |
+ size_t size = 0; |
+ ASSERT_TRUE(out_stream->GetSize(&size)); |
+ ASSERT_GE(size, kHeaderSize); |
+ EXPECT_TRUE(file_writer_->Close()); |
+ |
+ const uint8_t* out_buffer = |
+ reinterpret_cast<const uint8_t*>(out_stream->GetBuffer()); |
+ VerifyIvfHeader(out_buffer, fourcc, kWidth, kHeight, kNumFrames); |
+ VerifyDummyTestFrames(&out_buffer[kHeaderSize], size - kHeaderSize, |
+ kNumFrames); |
+ |
+ EXPECT_TRUE(file_writer_->Close()); |
+ } |
+ |
+ rtc::Pathname file_name_; |
+ std::unique_ptr<IvfFileWriter> file_writer_; |
+}; |
+ |
+TEST_F(IvfFileWriterTest, RemovesUnusedFile) { |
+ file_writer_ = IvfFileWriter::Open(file_name_, kRtpVideoVp8); |
+ ASSERT_TRUE(file_writer_.get()); |
+ rtc::FilesystemInterface* file_system = rtc::Filesystem::default_filesystem(); |
+ EXPECT_FALSE(file_system->IsAbsent(file_name_)); |
+ EXPECT_TRUE(file_writer_->Close()); |
+ EXPECT_TRUE(file_system->IsAbsent(file_name_)); |
+ EXPECT_FALSE(file_writer_->Close()); // Can't close twice. |
+} |
+ |
+TEST_F(IvfFileWriterTest, WritesBasicVP8File) { |
+ const uint8_t fourcc[4] = {'V', 'P', '8', '0'}; |
+ RunBasicFileStructureTest(kRtpVideoVp8, fourcc); |
+} |
+ |
+TEST_F(IvfFileWriterTest, WritesBasicVP9File) { |
+ const uint8_t fourcc[4] = {'V', 'P', '9', '0'}; |
+ RunBasicFileStructureTest(kRtpVideoVp9, fourcc); |
+} |
+ |
+TEST_F(IvfFileWriterTest, WritesBasicH264File) { |
+ const uint8_t fourcc[4] = {'H', '2', '6', '4'}; |
+ RunBasicFileStructureTest(kRtpVideoH264, fourcc); |
+} |
+ |
+} // namespace webrtc |