| 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..e7e4242fb26a687faa1dfc285b0ef1ef5ba8d33a
 | 
| --- /dev/null
 | 
| +++ b/webrtc/modules/video_coding/utility/ivf_file_writer_unittest.cc
 | 
| @@ -0,0 +1,174 @@
 | 
| +/*
 | 
| + *  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"
 | 
| +
 | 
| +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 << "ivf_test_file_" << id++ << ".ivf";
 | 
| +      file_name_ = oss.str();
 | 
| +    } while (id < start_id + 100 && FileExists());
 | 
| +  }
 | 
| +
 | 
| +  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
 | 
| 
 |