OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2016 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 "webrtc/modules/video_coding/utility/ivf_file_writer.h" |
| 12 |
| 13 #include <memory> |
| 14 |
| 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "webrtc/base/logging.h" |
| 17 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
| 18 #include "webrtc/system_wrappers/include/tick_util.h" |
| 19 #include "webrtc/test/testsupport/fileutils.h" |
| 20 |
| 21 namespace webrtc { |
| 22 |
| 23 namespace { |
| 24 static const int kHeaderSize = 32; |
| 25 static const int kFrameHeaderSize = 12; |
| 26 static uint8_t dummy_payload[4] = {0, 1, 2, 3}; |
| 27 } // namespace |
| 28 |
| 29 class IvfFileWriterTest : public ::testing::Test { |
| 30 protected: |
| 31 void SetUp() override { |
| 32 const int64_t start_id = |
| 33 reinterpret_cast<int64_t>(this) ^ TickTime::MicrosecondTimestamp(); |
| 34 int64_t id = start_id; |
| 35 do { |
| 36 std::ostringstream oss; |
| 37 oss << test::OutputPath() << "ivf_test_file_" << id++ << ".ivf"; |
| 38 file_name_ = oss.str(); |
| 39 } while (id < start_id + 100 && FileExists()); |
| 40 ASSERT_LT(id, start_id + 100); |
| 41 } |
| 42 |
| 43 bool WriteDummyTestFrames(int width, |
| 44 int height, |
| 45 int num_frames, |
| 46 bool use_capture_tims_ms) { |
| 47 EncodedImage frame; |
| 48 frame._buffer = dummy_payload; |
| 49 frame._encodedWidth = width; |
| 50 frame._encodedHeight = height; |
| 51 for (int i = 1; i <= num_frames; ++i) { |
| 52 frame._length = i % sizeof(dummy_payload); |
| 53 if (use_capture_tims_ms) { |
| 54 frame.capture_time_ms_ = i; |
| 55 } else { |
| 56 frame._timeStamp = i; |
| 57 } |
| 58 if (!file_writer_->WriteFrame(frame)) |
| 59 return false; |
| 60 } |
| 61 return true; |
| 62 } |
| 63 |
| 64 void VerifyIvfHeader(FileWrapper* file, |
| 65 const uint8_t fourcc[4], |
| 66 int width, |
| 67 int height, |
| 68 uint32_t num_frames, |
| 69 bool use_capture_tims_ms) { |
| 70 uint8_t data[kHeaderSize]; |
| 71 ASSERT_EQ(kHeaderSize, file->Read(data, kHeaderSize)); |
| 72 |
| 73 uint8_t dkif[4] = {'D', 'K', 'I', 'F'}; |
| 74 EXPECT_EQ(0, memcmp(dkif, data, 4)); |
| 75 EXPECT_EQ(0u, ByteReader<uint16_t>::ReadLittleEndian(&data[4])); |
| 76 EXPECT_EQ(32u, ByteReader<uint16_t>::ReadLittleEndian(&data[6])); |
| 77 EXPECT_EQ(0, memcmp(fourcc, &data[8], 4)); |
| 78 EXPECT_EQ(width, ByteReader<uint16_t>::ReadLittleEndian(&data[12])); |
| 79 EXPECT_EQ(height, ByteReader<uint16_t>::ReadLittleEndian(&data[14])); |
| 80 EXPECT_EQ(use_capture_tims_ms ? 1000u : 90000u, |
| 81 ByteReader<uint32_t>::ReadLittleEndian(&data[16])); |
| 82 EXPECT_EQ(1u, ByteReader<uint32_t>::ReadLittleEndian(&data[20])); |
| 83 EXPECT_EQ(num_frames, ByteReader<uint32_t>::ReadLittleEndian(&data[24])); |
| 84 EXPECT_EQ(0u, ByteReader<uint32_t>::ReadLittleEndian(&data[28])); |
| 85 } |
| 86 |
| 87 void VerifyDummyTestFrames(FileWrapper* file, uint32_t num_frames) { |
| 88 const int kMaxFrameSize = 4; |
| 89 for (uint32_t i = 1; i <= num_frames; ++i) { |
| 90 uint8_t frame_header[kFrameHeaderSize]; |
| 91 ASSERT_EQ(kFrameHeaderSize, file->Read(frame_header, kFrameHeaderSize)); |
| 92 uint32_t frame_length = |
| 93 ByteReader<uint32_t>::ReadLittleEndian(&frame_header[0]); |
| 94 EXPECT_EQ(i % 4, frame_length); |
| 95 uint64_t timestamp = |
| 96 ByteReader<uint64_t>::ReadLittleEndian(&frame_header[4]); |
| 97 EXPECT_EQ(i, timestamp); |
| 98 |
| 99 uint8_t data[kMaxFrameSize] = {}; |
| 100 ASSERT_EQ(frame_length, |
| 101 static_cast<uint32_t>(file->Read(data, frame_length))); |
| 102 EXPECT_EQ(0, memcmp(data, dummy_payload, frame_length)); |
| 103 } |
| 104 } |
| 105 |
| 106 void RunBasicFileStructureTest(RtpVideoCodecTypes codec_type, |
| 107 const uint8_t fourcc[4], |
| 108 bool use_capture_tims_ms) { |
| 109 file_writer_ = IvfFileWriter::Open(file_name_, codec_type); |
| 110 ASSERT_TRUE(file_writer_.get()); |
| 111 const int kWidth = 320; |
| 112 const int kHeight = 240; |
| 113 const int kNumFrames = 257; |
| 114 EXPECT_TRUE( |
| 115 WriteDummyTestFrames(kWidth, kHeight, kNumFrames, use_capture_tims_ms)); |
| 116 EXPECT_TRUE(file_writer_->Close()); |
| 117 |
| 118 std::unique_ptr<FileWrapper> out_file(FileWrapper::Create()); |
| 119 ASSERT_EQ(0, out_file->OpenFile(file_name_.c_str(), true)); |
| 120 VerifyIvfHeader(out_file.get(), fourcc, kWidth, kHeight, kNumFrames, |
| 121 use_capture_tims_ms); |
| 122 VerifyDummyTestFrames(out_file.get(), kNumFrames); |
| 123 |
| 124 EXPECT_EQ(0, out_file->CloseFile()); |
| 125 EXPECT_EQ(0, remove(file_name_.c_str())); |
| 126 } |
| 127 |
| 128 bool FileExists() { |
| 129 std::unique_ptr<FileWrapper> file_wrapper(FileWrapper::Create()); |
| 130 return file_wrapper->OpenFile(file_name_.c_str(), true) == 0; |
| 131 } |
| 132 |
| 133 std::string file_name_; |
| 134 std::unique_ptr<IvfFileWriter> file_writer_; |
| 135 }; |
| 136 |
| 137 TEST_F(IvfFileWriterTest, RemovesUnusedFile) { |
| 138 file_writer_ = IvfFileWriter::Open(file_name_, kRtpVideoVp8); |
| 139 ASSERT_TRUE(file_writer_.get() != nullptr); |
| 140 EXPECT_TRUE(FileExists()); |
| 141 EXPECT_TRUE(file_writer_->Close()); |
| 142 EXPECT_FALSE(FileExists()); |
| 143 EXPECT_FALSE(file_writer_->Close()); // Can't close twice. |
| 144 } |
| 145 |
| 146 TEST_F(IvfFileWriterTest, WritesBasicVP8FileNtpTimestamp) { |
| 147 const uint8_t fourcc[4] = {'V', 'P', '8', '0'}; |
| 148 RunBasicFileStructureTest(kRtpVideoVp8, fourcc, false); |
| 149 } |
| 150 |
| 151 TEST_F(IvfFileWriterTest, WritesBasicVP8FileMsTimestamp) { |
| 152 const uint8_t fourcc[4] = {'V', 'P', '8', '0'}; |
| 153 RunBasicFileStructureTest(kRtpVideoVp8, fourcc, true); |
| 154 } |
| 155 |
| 156 TEST_F(IvfFileWriterTest, WritesBasicVP9FileNtpTimestamp) { |
| 157 const uint8_t fourcc[4] = {'V', 'P', '9', '0'}; |
| 158 RunBasicFileStructureTest(kRtpVideoVp9, fourcc, false); |
| 159 } |
| 160 |
| 161 TEST_F(IvfFileWriterTest, WritesBasicVP9FileMsTimestamp) { |
| 162 const uint8_t fourcc[4] = {'V', 'P', '9', '0'}; |
| 163 RunBasicFileStructureTest(kRtpVideoVp9, fourcc, true); |
| 164 } |
| 165 |
| 166 TEST_F(IvfFileWriterTest, WritesBasicH264FileNtpTimestamp) { |
| 167 const uint8_t fourcc[4] = {'H', '2', '6', '4'}; |
| 168 RunBasicFileStructureTest(kRtpVideoH264, fourcc, false); |
| 169 } |
| 170 |
| 171 TEST_F(IvfFileWriterTest, WritesBasicH264FileMsTimestamp) { |
| 172 const uint8_t fourcc[4] = {'H', '2', '6', '4'}; |
| 173 RunBasicFileStructureTest(kRtpVideoH264, fourcc, true); |
| 174 } |
| 175 |
| 176 } // namespace webrtc |
OLD | NEW |