| 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
|
|
|