Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: webrtc/modules/video_coding/utility/ivf_file_writer_unittest.cc

Issue 2303273002: Expose Ivf logging through the native API (Closed)
Patch Set: Don't make a change in base here, make a separate CL Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h" 11 #include "webrtc/modules/video_coding/utility/ivf_file_writer.h"
12 12
13 #include <memory> 13 #include <memory>
14 14
15 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "webrtc/base/helpers.h" 16 #include "webrtc/base/helpers.h"
17 #include "webrtc/base/logging.h" 17 #include "webrtc/base/logging.h"
18 #include "webrtc/base/thread.h" 18 #include "webrtc/base/thread.h"
19 #include "webrtc/base/timeutils.h" 19 #include "webrtc/base/timeutils.h"
20 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 20 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
21 #include "webrtc/test/testsupport/fileutils.h" 21 #include "webrtc/test/testsupport/fileutils.h"
22 22
23 #if defined(WEBRTC_WIN)
24 #include "webrtc/base/win32.h"
25 #else
26 #include <unistd.h>
27 #endif
28
23 namespace webrtc { 29 namespace webrtc {
24 30
25 namespace { 31 namespace {
26 static const int kHeaderSize = 32; 32 static const int kHeaderSize = 32;
27 static const int kFrameHeaderSize = 12; 33 static const int kFrameHeaderSize = 12;
28 static uint8_t dummy_payload[4] = {0, 1, 2, 3}; 34 static uint8_t dummy_payload[4] = {0, 1, 2, 3};
29 static const int kMaxFileRetries = 5;
30 } // namespace 35 } // namespace
31 36
37 void RemoveFile(const std::string& path) {
38 #if defined(WEBRTC_WIN)
39 ::DeleteFile(rtc::ToUtf16(path).c_str());
40 #else
41 ::unlink(path.c_str());
42 #endif
43 }
44
32 class IvfFileWriterTest : public ::testing::Test { 45 class IvfFileWriterTest : public ::testing::Test {
33 protected: 46 protected:
34 void SetUp() override { 47 void SetUp() override {
35 const uint64_t start_id = rtc::CreateRandomId64(); 48 file_name_ =
36 uint64_t id = start_id; 49 webrtc::test::TempFilename(webrtc::test::OutputPath(), "test_file");
37 do {
38 std::ostringstream oss;
39 oss << test::OutputPath() << "ivf_test_file_" << id++ << ".ivf";
40 file_name_ = oss.str();
41 } while ((id - start_id) < 100u && FileExists(false));
42 ASSERT_LT(id - start_id, 100u);
43 } 50 }
51 void TearDown() override { RemoveFile(file_name_); }
44 52
45 bool WriteDummyTestFrames(int width, 53 bool WriteDummyTestFrames(VideoCodecType codec_type,
54 int width,
46 int height, 55 int height,
47 int num_frames, 56 int num_frames,
48 bool use_capture_tims_ms) { 57 bool use_capture_tims_ms) {
49 EncodedImage frame; 58 EncodedImage frame;
50 frame._buffer = dummy_payload; 59 frame._buffer = dummy_payload;
51 frame._encodedWidth = width; 60 frame._encodedWidth = width;
52 frame._encodedHeight = height; 61 frame._encodedHeight = height;
53 for (int i = 1; i <= num_frames; ++i) { 62 for (int i = 1; i <= num_frames; ++i) {
54 frame._length = i % sizeof(dummy_payload); 63 frame._length = i % sizeof(dummy_payload);
55 if (use_capture_tims_ms) { 64 if (use_capture_tims_ms) {
56 frame.capture_time_ms_ = i; 65 frame.capture_time_ms_ = i;
57 } else { 66 } else {
58 frame._timeStamp = i; 67 frame._timeStamp = i;
59 } 68 }
60 if (!file_writer_->WriteFrame(frame)) 69 if (!file_writer_->WriteFrame(frame, codec_type))
61 return false; 70 return false;
62 } 71 }
63 return true; 72 return true;
64 } 73 }
65 74
66 void VerifyIvfHeader(FileWrapper* file, 75 void VerifyIvfHeader(rtc::File* file,
67 const uint8_t fourcc[4], 76 const uint8_t fourcc[4],
68 int width, 77 int width,
69 int height, 78 int height,
70 uint32_t num_frames, 79 uint32_t num_frames,
71 bool use_capture_tims_ms) { 80 bool use_capture_tims_ms) {
72 ASSERT_TRUE(file->is_open()); 81 ASSERT_TRUE(file->IsOpen());
73 uint8_t data[kHeaderSize]; 82 uint8_t data[kHeaderSize];
74 ASSERT_EQ(kHeaderSize, file->Read(data, kHeaderSize)); 83 ASSERT_EQ(static_cast<size_t>(kHeaderSize), file->Read(data, kHeaderSize));
75 84
76 uint8_t dkif[4] = {'D', 'K', 'I', 'F'}; 85 uint8_t dkif[4] = {'D', 'K', 'I', 'F'};
77 EXPECT_EQ(0, memcmp(dkif, data, 4)); 86 EXPECT_EQ(0, memcmp(dkif, data, 4));
78 EXPECT_EQ(0u, ByteReader<uint16_t>::ReadLittleEndian(&data[4])); 87 EXPECT_EQ(0u, ByteReader<uint16_t>::ReadLittleEndian(&data[4]));
79 EXPECT_EQ(32u, ByteReader<uint16_t>::ReadLittleEndian(&data[6])); 88 EXPECT_EQ(32u, ByteReader<uint16_t>::ReadLittleEndian(&data[6]));
80 EXPECT_EQ(0, memcmp(fourcc, &data[8], 4)); 89 EXPECT_EQ(0, memcmp(fourcc, &data[8], 4));
81 EXPECT_EQ(width, ByteReader<uint16_t>::ReadLittleEndian(&data[12])); 90 EXPECT_EQ(width, ByteReader<uint16_t>::ReadLittleEndian(&data[12]));
82 EXPECT_EQ(height, ByteReader<uint16_t>::ReadLittleEndian(&data[14])); 91 EXPECT_EQ(height, ByteReader<uint16_t>::ReadLittleEndian(&data[14]));
83 EXPECT_EQ(use_capture_tims_ms ? 1000u : 90000u, 92 EXPECT_EQ(use_capture_tims_ms ? 1000u : 90000u,
84 ByteReader<uint32_t>::ReadLittleEndian(&data[16])); 93 ByteReader<uint32_t>::ReadLittleEndian(&data[16]));
85 EXPECT_EQ(1u, ByteReader<uint32_t>::ReadLittleEndian(&data[20])); 94 EXPECT_EQ(1u, ByteReader<uint32_t>::ReadLittleEndian(&data[20]));
86 EXPECT_EQ(num_frames, ByteReader<uint32_t>::ReadLittleEndian(&data[24])); 95 EXPECT_EQ(num_frames, ByteReader<uint32_t>::ReadLittleEndian(&data[24]));
87 EXPECT_EQ(0u, ByteReader<uint32_t>::ReadLittleEndian(&data[28])); 96 EXPECT_EQ(0u, ByteReader<uint32_t>::ReadLittleEndian(&data[28]));
88 } 97 }
89 98
90 void VerifyDummyTestFrames(FileWrapper* file, uint32_t num_frames) { 99 void VerifyDummyTestFrames(rtc::File* file, uint32_t num_frames) {
91 const int kMaxFrameSize = 4; 100 const int kMaxFrameSize = 4;
92 for (uint32_t i = 1; i <= num_frames; ++i) { 101 for (uint32_t i = 1; i <= num_frames; ++i) {
93 uint8_t frame_header[kFrameHeaderSize]; 102 uint8_t frame_header[kFrameHeaderSize];
94 ASSERT_EQ(kFrameHeaderSize, file->Read(frame_header, kFrameHeaderSize)); 103 ASSERT_EQ(static_cast<unsigned int>(kFrameHeaderSize),
104 file->Read(frame_header, kFrameHeaderSize));
95 uint32_t frame_length = 105 uint32_t frame_length =
96 ByteReader<uint32_t>::ReadLittleEndian(&frame_header[0]); 106 ByteReader<uint32_t>::ReadLittleEndian(&frame_header[0]);
97 EXPECT_EQ(i % 4, frame_length); 107 EXPECT_EQ(i % 4, frame_length);
98 uint64_t timestamp = 108 uint64_t timestamp =
99 ByteReader<uint64_t>::ReadLittleEndian(&frame_header[4]); 109 ByteReader<uint64_t>::ReadLittleEndian(&frame_header[4]);
100 EXPECT_EQ(i, timestamp); 110 EXPECT_EQ(i, timestamp);
101 111
102 uint8_t data[kMaxFrameSize] = {}; 112 uint8_t data[kMaxFrameSize] = {};
103 ASSERT_EQ(frame_length, 113 ASSERT_EQ(frame_length,
104 static_cast<uint32_t>(file->Read(data, frame_length))); 114 static_cast<uint32_t>(file->Read(data, frame_length)));
105 EXPECT_EQ(0, memcmp(data, dummy_payload, frame_length)); 115 EXPECT_EQ(0, memcmp(data, dummy_payload, frame_length));
106 } 116 }
107 } 117 }
108 118
109 void RunBasicFileStructureTest(VideoCodecType codec_type, 119 void RunBasicFileStructureTest(VideoCodecType codec_type,
110 const uint8_t fourcc[4], 120 const uint8_t fourcc[4],
111 bool use_capture_tims_ms) { 121 bool use_capture_tims_ms) {
112 file_writer_ = IvfFileWriter::Open(file_name_, codec_type); 122 file_writer_ = IvfFileWriter::Wrap(rtc::File::Open(file_name_), 0);
113 ASSERT_TRUE(file_writer_.get()); 123 ASSERT_TRUE(file_writer_.get());
114 const int kWidth = 320; 124 const int kWidth = 320;
115 const int kHeight = 240; 125 const int kHeight = 240;
116 const int kNumFrames = 257; 126 const int kNumFrames = 257;
117 EXPECT_TRUE( 127 ASSERT_TRUE(WriteDummyTestFrames(codec_type, kWidth, kHeight, kNumFrames,
118 WriteDummyTestFrames(kWidth, kHeight, kNumFrames, use_capture_tims_ms)); 128 use_capture_tims_ms));
119 EXPECT_TRUE(file_writer_->Close()); 129 EXPECT_TRUE(file_writer_->Close());
120 130
121 std::unique_ptr<FileWrapper> out_file(FileWrapper::Create()); 131 rtc::File out_file = rtc::File::Open(file_name_);
122 ASSERT_TRUE(out_file->OpenFile(file_name_.c_str(), true)); 132 VerifyIvfHeader(&out_file, fourcc, kWidth, kHeight, kNumFrames,
123 VerifyIvfHeader(out_file.get(), fourcc, kWidth, kHeight, kNumFrames,
124 use_capture_tims_ms); 133 use_capture_tims_ms);
125 VerifyDummyTestFrames(out_file.get(), kNumFrames); 134 VerifyDummyTestFrames(&out_file, kNumFrames);
126 135
127 out_file->CloseFile(); 136 out_file.Close();
128
129 bool file_removed = false;
130 for (int i = 0; i < kMaxFileRetries; ++i) {
131 file_removed = remove(file_name_.c_str()) == 0;
132 if (file_removed)
133 break;
134
135 // Couldn't remove file for some reason, wait a sec and try again.
136 rtc::Thread::SleepMs(1000);
137 }
138 EXPECT_TRUE(file_removed);
139 }
140
141 // Check whether file exists or not, and if it does not meet expectation,
142 // wait a bit and check again, up to kMaxFileRetries times. This is an ugly
143 // hack to avoid flakiness on certain operating systems where antivirus
144 // software may unexpectedly lock files and keep them from disappearing or
145 // being reused.
146 bool FileExists(bool expected) {
147 bool file_exists = expected;
148 std::unique_ptr<FileWrapper> file_wrapper;
149 int iterations = 0;
150 do {
151 if (file_wrapper.get() != nullptr)
152 rtc::Thread::SleepMs(1000);
153 file_wrapper.reset(FileWrapper::Create());
154 file_exists = file_wrapper->OpenFile(file_name_.c_str(), true);
155 file_wrapper->CloseFile();
156 } while (file_exists != expected && ++iterations < kMaxFileRetries);
157 return file_exists;
158 } 137 }
159 138
160 std::string file_name_; 139 std::string file_name_;
161 std::unique_ptr<IvfFileWriter> file_writer_; 140 std::unique_ptr<IvfFileWriter> file_writer_;
162 }; 141 };
163 142
164 TEST_F(IvfFileWriterTest, RemovesUnusedFile) {
165 file_writer_ = IvfFileWriter::Open(file_name_, kVideoCodecVP8);
166 ASSERT_TRUE(file_writer_.get() != nullptr);
167 EXPECT_TRUE(FileExists(true));
168 EXPECT_TRUE(file_writer_->Close());
169 EXPECT_FALSE(FileExists(false));
170 EXPECT_FALSE(file_writer_->Close()); // Can't close twice.
171 }
172
173 TEST_F(IvfFileWriterTest, WritesBasicVP8FileNtpTimestamp) { 143 TEST_F(IvfFileWriterTest, WritesBasicVP8FileNtpTimestamp) {
174 const uint8_t fourcc[4] = {'V', 'P', '8', '0'}; 144 const uint8_t fourcc[4] = {'V', 'P', '8', '0'};
175 RunBasicFileStructureTest(kVideoCodecVP8, fourcc, false); 145 RunBasicFileStructureTest(kVideoCodecVP8, fourcc, false);
176 } 146 }
177 147
178 TEST_F(IvfFileWriterTest, WritesBasicVP8FileMsTimestamp) { 148 TEST_F(IvfFileWriterTest, WritesBasicVP8FileMsTimestamp) {
179 const uint8_t fourcc[4] = {'V', 'P', '8', '0'}; 149 const uint8_t fourcc[4] = {'V', 'P', '8', '0'};
180 RunBasicFileStructureTest(kVideoCodecVP8, fourcc, true); 150 RunBasicFileStructureTest(kVideoCodecVP8, fourcc, true);
181 } 151 }
182 152
(...skipping 10 matching lines...) Expand all
193 TEST_F(IvfFileWriterTest, WritesBasicH264FileNtpTimestamp) { 163 TEST_F(IvfFileWriterTest, WritesBasicH264FileNtpTimestamp) {
194 const uint8_t fourcc[4] = {'H', '2', '6', '4'}; 164 const uint8_t fourcc[4] = {'H', '2', '6', '4'};
195 RunBasicFileStructureTest(kVideoCodecH264, fourcc, false); 165 RunBasicFileStructureTest(kVideoCodecH264, fourcc, false);
196 } 166 }
197 167
198 TEST_F(IvfFileWriterTest, WritesBasicH264FileMsTimestamp) { 168 TEST_F(IvfFileWriterTest, WritesBasicH264FileMsTimestamp) {
199 const uint8_t fourcc[4] = {'H', '2', '6', '4'}; 169 const uint8_t fourcc[4] = {'H', '2', '6', '4'};
200 RunBasicFileStructureTest(kVideoCodecH264, fourcc, true); 170 RunBasicFileStructureTest(kVideoCodecH264, fourcc, true);
201 } 171 }
202 172
173 TEST_F(IvfFileWriterTest, ClosesWhenReachesLimit) {
174 const uint8_t fourcc[4] = {'V', 'P', '8', '0'};
175 const int kWidth = 320;
176 const int kHeight = 240;
177 const int kNumFramesToWrite = 2;
178 const int kNumFramesToFit = 1;
179
180 file_writer_ = IvfFileWriter::Wrap(
181 rtc::File::Open(file_name_),
182 kHeaderSize +
183 kNumFramesToFit * (kFrameHeaderSize + sizeof(dummy_payload)));
184 ASSERT_TRUE(file_writer_.get());
185
186 ASSERT_FALSE(WriteDummyTestFrames(kVideoCodecVP8, kWidth, kHeight,
187 kNumFramesToWrite, true));
188 ASSERT_FALSE(file_writer_->Close());
189
190 rtc::File out_file = rtc::File::Open(file_name_);
191 VerifyIvfHeader(&out_file, fourcc, kWidth, kHeight, kNumFramesToFit, true);
192 VerifyDummyTestFrames(&out_file, kNumFramesToFit);
193
194 out_file.Close();
195 }
196
203 } // namespace webrtc 197 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698