Reland of Add optional visualization file writers to VideoProcessor tests. (patchset #1 id:1 of https://codereview.webrtc.org/2708103002/ )
Reason for revert:
Necessary calls were "protected" by RTC_DCHECKs, that were optimized away in some release builds.
Replacing the RTC_DCHECKs with EXPECTs.
Original issue's description:
> Revert of Add optional visualization file writers to VideoProcessor tests. (patchset #4 id:220001 of https://codereview.webrtc.org/2700493006/ )
>
> Reason for revert:
> Breaks downstream project.
>
> Original issue's description:
> > Add optional visualization file writers to VideoProcessor tests.
> >
> > The purpose of this visualization CL is to add the ability to record
> > video at the source, after encode, and after decode, in the VideoProcessor
> > tests. These output files can then be replayed and used as a subjective
> > complement to the objective metric plots given by the existing Python
> > plotting script.
> >
> > BUG=webrtc:6634
> >
> > Review-Url: https://codereview.webrtc.org/2700493006
> > Cr-Commit-Position: refs/heads/master@{#16738}
> > Committed: https://chromium.googlesource.com/external/webrtc/+/872104ac41d7764f8676c9ea55555210bea4605c
>
> TBR=asapersson@webrtc.org,sprang@webrtc.org,kjellander@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=webrtc:6634
>
> Review-Url: https://codereview.webrtc.org/2708103002
> Cr-Commit-Position: refs/heads/master@{#16745}
> Committed: https://chromium.googlesource.com/external/webrtc/+/2a8135a1741761bd6de52163c0dc35f6eff7c8eb
TBR=asapersson@webrtc.org,sprang@webrtc.org,kjellander@webrtc.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
BUG=webrtc:6634
Review-Url: https://codereview.webrtc.org/2706123003
Cr-Commit-Position: refs/heads/master@{#16769}
diff --git a/webrtc/test/BUILD.gn b/webrtc/test/BUILD.gn
index a4c0185..07ffbee 100644
--- a/webrtc/test/BUILD.gn
+++ b/webrtc/test/BUILD.gn
@@ -129,14 +129,15 @@
testonly = true
sources = [
- "testsupport/frame_reader.cc",
"testsupport/frame_reader.h",
- "testsupport/frame_writer.cc",
"testsupport/frame_writer.h",
"testsupport/metrics/video_metrics.cc",
"testsupport/metrics/video_metrics.h",
"testsupport/mock/mock_frame_reader.h",
"testsupport/mock/mock_frame_writer.h",
+ "testsupport/y4m_frame_writer.cc",
+ "testsupport/yuv_frame_reader.cc",
+ "testsupport/yuv_frame_writer.cc",
]
deps = [
@@ -259,12 +260,13 @@
"rtp_file_reader_unittest.cc",
"rtp_file_writer_unittest.cc",
"testsupport/always_passing_unittest.cc",
- "testsupport/frame_reader_unittest.cc",
- "testsupport/frame_writer_unittest.cc",
"testsupport/isolated_output_unittest.cc",
"testsupport/metrics/video_metrics_unittest.cc",
"testsupport/packet_reader_unittest.cc",
"testsupport/perf_test_unittest.cc",
+ "testsupport/y4m_frame_writer_unittest.cc",
+ "testsupport/yuv_frame_reader_unittest.cc",
+ "testsupport/yuv_frame_writer_unittest.cc",
]
# TODO(jschuh): Bug 1348: fix this warning.
diff --git a/webrtc/test/testsupport/frame_reader.h b/webrtc/test/testsupport/frame_reader.h
index 13800cd..94dd78b 100644
--- a/webrtc/test/testsupport/frame_reader.h
+++ b/webrtc/test/testsupport/frame_reader.h
@@ -46,14 +46,14 @@
virtual int NumberOfFrames() = 0;
};
-class FrameReaderImpl : public FrameReader {
+class YuvFrameReaderImpl : public FrameReader {
public:
// Creates a file handler. The input file is assumed to exist and be readable.
// Parameters:
// input_filename The file to read from.
// width, height Size of each frame to read.
- FrameReaderImpl(std::string input_filename, int width, int height);
- ~FrameReaderImpl() override;
+ YuvFrameReaderImpl(std::string input_filename, int width, int height);
+ ~YuvFrameReaderImpl() override;
bool Init() override;
rtc::scoped_refptr<I420Buffer> ReadFrame() override;
void Close() override;
@@ -61,10 +61,10 @@
int NumberOfFrames() override;
private:
- std::string input_filename_;
+ const std::string input_filename_;
size_t frame_length_in_bytes_;
- int width_;
- int height_;
+ const int width_;
+ const int height_;
int number_of_frames_;
FILE* input_file_;
};
diff --git a/webrtc/test/testsupport/frame_reader_unittest.cc b/webrtc/test/testsupport/frame_reader_unittest.cc
deleted file mode 100644
index 58a3245..0000000
--- a/webrtc/test/testsupport/frame_reader_unittest.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2011 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/test/testsupport/frame_reader.h"
-
-#include "webrtc/api/video/i420_buffer.h"
-#include "webrtc/test/gtest.h"
-#include "webrtc/test/testsupport/fileutils.h"
-
-namespace webrtc {
-namespace test {
-
-const std::string kInputFileContents = "baz";
-const size_t kFrameLength = 3;
-
-class FrameReaderTest: public testing::Test {
- protected:
- FrameReaderTest() {}
- virtual ~FrameReaderTest() {}
- void SetUp() {
- // Create a dummy input file.
- temp_filename_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
- "frame_reader_unittest");
- FILE* dummy = fopen(temp_filename_.c_str(), "wb");
- fprintf(dummy, "%s", kInputFileContents.c_str());
- fclose(dummy);
-
- frame_reader_ = new FrameReaderImpl(temp_filename_, 1, 1);
- ASSERT_TRUE(frame_reader_->Init());
- }
- void TearDown() {
- delete frame_reader_;
- // Cleanup the dummy input file.
- remove(temp_filename_.c_str());
- }
- FrameReader* frame_reader_;
- std::string temp_filename_;
-};
-
-TEST_F(FrameReaderTest, InitSuccess) {
- FrameReaderImpl frame_reader(temp_filename_, 1, 1);
- ASSERT_TRUE(frame_reader.Init());
- ASSERT_EQ(kFrameLength, frame_reader.FrameLength());
- ASSERT_EQ(1, frame_reader.NumberOfFrames());
-}
-
-TEST_F(FrameReaderTest, ReadFrame) {
- rtc::scoped_refptr<VideoFrameBuffer> buffer;
- buffer = frame_reader_->ReadFrame();
- ASSERT_TRUE(buffer);
- ASSERT_EQ(kInputFileContents[0], buffer->DataY()[0]);
- ASSERT_EQ(kInputFileContents[1], buffer->DataU()[0]);
- ASSERT_EQ(kInputFileContents[2], buffer->DataV()[0]);
- ASSERT_FALSE(frame_reader_->ReadFrame()); // End of file
-}
-
-TEST_F(FrameReaderTest, ReadFrameUninitialized) {
- FrameReaderImpl file_reader(temp_filename_, 1, 1);
- ASSERT_FALSE(file_reader.ReadFrame());
-}
-
-} // namespace test
-} // namespace webrtc
diff --git a/webrtc/test/testsupport/frame_writer.cc b/webrtc/test/testsupport/frame_writer.cc
deleted file mode 100644
index 1b9e8a8..0000000
--- a/webrtc/test/testsupport/frame_writer.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2011 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/test/testsupport/frame_writer.h"
-
-#include <assert.h>
-
-namespace webrtc {
-namespace test {
-
-FrameWriterImpl::FrameWriterImpl(std::string output_filename,
- size_t frame_length_in_bytes)
- : output_filename_(output_filename),
- frame_length_in_bytes_(frame_length_in_bytes),
- output_file_(NULL) {
-}
-
-FrameWriterImpl::~FrameWriterImpl() {
- Close();
-}
-
-bool FrameWriterImpl::Init() {
- if (frame_length_in_bytes_ <= 0) {
- fprintf(stderr, "Frame length must be >0, was %zu\n",
- frame_length_in_bytes_);
- return false;
- }
- output_file_ = fopen(output_filename_.c_str(), "wb");
- if (output_file_ == NULL) {
- fprintf(stderr, "Couldn't open output file for writing: %s\n",
- output_filename_.c_str());
- return false;
- }
- return true;
-}
-
-void FrameWriterImpl::Close() {
- if (output_file_ != NULL) {
- fclose(output_file_);
- output_file_ = NULL;
- }
-}
-
-size_t FrameWriterImpl::FrameLength() { return frame_length_in_bytes_; }
-
-bool FrameWriterImpl::WriteFrame(uint8_t* frame_buffer) {
- assert(frame_buffer);
- if (output_file_ == NULL) {
- fprintf(stderr, "FrameWriter is not initialized (output file is NULL)\n");
- return false;
- }
- size_t bytes_written = fwrite(frame_buffer, 1, frame_length_in_bytes_,
- output_file_);
- if (bytes_written != frame_length_in_bytes_) {
- fprintf(stderr, "Failed to write %zu bytes to file %s\n",
- frame_length_in_bytes_, output_filename_.c_str());
- return false;
- }
- return true;
-}
-
-} // namespace test
-} // namespace webrtc
diff --git a/webrtc/test/testsupport/frame_writer.h b/webrtc/test/testsupport/frame_writer.h
index 8a6b1c2..7629849 100644
--- a/webrtc/test/testsupport/frame_writer.h
+++ b/webrtc/test/testsupport/frame_writer.h
@@ -42,28 +42,46 @@
virtual size_t FrameLength() = 0;
};
-class FrameWriterImpl : public FrameWriter {
+// Writes raw I420 frames in sequence.
+class YuvFrameWriterImpl : public FrameWriter {
public:
// Creates a file handler. The input file is assumed to exist and be readable
// and the output file must be writable.
// Parameters:
// output_filename The file to write. Will be overwritten if already
// existing.
- // frame_length_in_bytes The size of each frame.
- // For YUV: 3*width*height/2
- FrameWriterImpl(std::string output_filename, size_t frame_length_in_bytes);
- ~FrameWriterImpl() override;
+ // width, height Size of each frame to read.
+ YuvFrameWriterImpl(std::string output_filename, int width, int height);
+ ~YuvFrameWriterImpl() override;
bool Init() override;
bool WriteFrame(uint8_t* frame_buffer) override;
void Close() override;
size_t FrameLength() override;
- private:
- std::string output_filename_;
+ protected:
+ const std::string output_filename_;
size_t frame_length_in_bytes_;
+ const int width_;
+ const int height_;
FILE* output_file_;
};
+// Writes raw I420 frames in sequence, but with Y4M file and frame headers for
+// more convenient playback in external media players.
+class Y4mFrameWriterImpl : public YuvFrameWriterImpl {
+ public:
+ Y4mFrameWriterImpl(std::string output_filename,
+ int width,
+ int height,
+ int frame_rate);
+ ~Y4mFrameWriterImpl() override;
+ bool Init() override;
+ bool WriteFrame(uint8_t* frame_buffer) override;
+
+ private:
+ const int frame_rate_;
+};
+
} // namespace test
} // namespace webrtc
diff --git a/webrtc/test/testsupport/frame_writer_unittest.cc b/webrtc/test/testsupport/frame_writer_unittest.cc
deleted file mode 100644
index 59173bd..0000000
--- a/webrtc/test/testsupport/frame_writer_unittest.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2011 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/test/testsupport/frame_writer.h"
-
-#include "webrtc/test/gtest.h"
-#include "webrtc/test/testsupport/fileutils.h"
-
-namespace webrtc {
-namespace test {
-
-const size_t kFrameLength = 1000;
-
-class FrameWriterTest: public testing::Test {
- protected:
- FrameWriterTest() {}
- virtual ~FrameWriterTest() {}
- void SetUp() {
- temp_filename_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
- "frame_writer_unittest");
- frame_writer_ = new FrameWriterImpl(temp_filename_, kFrameLength);
- ASSERT_TRUE(frame_writer_->Init());
- }
- void TearDown() {
- delete frame_writer_;
- // Cleanup the temporary file.
- remove(temp_filename_.c_str());
- }
- FrameWriter* frame_writer_;
- std::string temp_filename_;
-};
-
-TEST_F(FrameWriterTest, InitSuccess) {
- FrameWriterImpl frame_writer(temp_filename_, kFrameLength);
- ASSERT_TRUE(frame_writer.Init());
- ASSERT_EQ(kFrameLength, frame_writer.FrameLength());
-}
-
-TEST_F(FrameWriterTest, WriteFrame) {
- uint8_t buffer[kFrameLength];
- memset(buffer, 9, kFrameLength); // Write lots of 9s to the buffer
- bool result = frame_writer_->WriteFrame(buffer);
- ASSERT_TRUE(result); // success
- // Close the file and verify the size.
- frame_writer_->Close();
- ASSERT_EQ(kFrameLength, GetFileSize(temp_filename_));
-}
-
-TEST_F(FrameWriterTest, WriteFrameUninitialized) {
- uint8_t buffer[3];
- FrameWriterImpl frame_writer(temp_filename_, kFrameLength);
- ASSERT_FALSE(frame_writer.WriteFrame(buffer));
-}
-
-} // namespace test
-} // namespace webrtc
diff --git a/webrtc/test/testsupport/y4m_frame_writer.cc b/webrtc/test/testsupport/y4m_frame_writer.cc
new file mode 100644
index 0000000..28fb4b0
--- /dev/null
+++ b/webrtc/test/testsupport/y4m_frame_writer.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017 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/base/checks.h"
+#include "webrtc/test/testsupport/frame_writer.h"
+
+namespace webrtc {
+namespace test {
+
+Y4mFrameWriterImpl::Y4mFrameWriterImpl(std::string output_filename,
+ int width,
+ int height,
+ int frame_rate)
+ : YuvFrameWriterImpl(output_filename, width, height),
+ frame_rate_(frame_rate) {}
+
+Y4mFrameWriterImpl::~Y4mFrameWriterImpl() = default;
+
+bool Y4mFrameWriterImpl::Init() {
+ if (!YuvFrameWriterImpl::Init()) {
+ return false;
+ }
+ int bytes_written = fprintf(output_file_, "YUV4MPEG2 W%d H%d F%d:1 C420\n",
+ width_, height_, frame_rate_);
+ if (bytes_written < 0) {
+ fprintf(stderr, "Failed to write Y4M file header to file %s\n",
+ output_filename_.c_str());
+ return false;
+ }
+ return true;
+}
+
+bool Y4mFrameWriterImpl::WriteFrame(uint8_t* frame_buffer) {
+ if (output_file_ == nullptr) {
+ fprintf(stderr,
+ "Y4mFrameWriterImpl is not initialized (output file is NULL)\n");
+ return false;
+ }
+ int bytes_written = fprintf(output_file_, "FRAME\n");
+ if (bytes_written < 0) {
+ fprintf(stderr, "Failed to write Y4M frame header to file %s\n",
+ output_filename_.c_str());
+ return false;
+ }
+ return YuvFrameWriterImpl::WriteFrame(frame_buffer);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/webrtc/test/testsupport/y4m_frame_writer_unittest.cc b/webrtc/test/testsupport/y4m_frame_writer_unittest.cc
new file mode 100644
index 0000000..a4e4172
--- /dev/null
+++ b/webrtc/test/testsupport/y4m_frame_writer_unittest.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017 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 <memory>
+#include <string>
+
+#include "webrtc/test/gtest.h"
+#include "webrtc/test/testsupport/fileutils.h"
+#include "webrtc/test/testsupport/frame_writer.h"
+
+namespace webrtc {
+namespace test {
+
+namespace {
+const size_t kFrameWidth = 50;
+const size_t kFrameHeight = 20;
+const size_t kFrameLength = 3 * kFrameWidth * kFrameHeight / 2; // I420.
+const size_t kFrameRate = 30;
+
+const std::string kFileHeader = "YUV4MPEG2 W50 H20 F30:1 C420\n";
+const std::string kFrameHeader = "FRAME\n";
+} // namespace
+
+class Y4mFrameWriterTest : public testing::Test {
+ protected:
+ Y4mFrameWriterTest() = default;
+ ~Y4mFrameWriterTest() override = default;
+
+ void SetUp() override {
+ temp_filename_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
+ "y4m_frame_writer_unittest");
+ frame_writer_.reset(new Y4mFrameWriterImpl(temp_filename_, kFrameWidth,
+ kFrameHeight, kFrameRate));
+ ASSERT_TRUE(frame_writer_->Init());
+ }
+
+ void TearDown() override { remove(temp_filename_.c_str()); }
+
+ std::unique_ptr<FrameWriter> frame_writer_;
+ std::string temp_filename_;
+};
+
+TEST_F(Y4mFrameWriterTest, InitSuccess) {}
+
+TEST_F(Y4mFrameWriterTest, FrameLength) {
+ EXPECT_EQ(kFrameLength, frame_writer_->FrameLength());
+}
+
+TEST_F(Y4mFrameWriterTest, WriteFrame) {
+ uint8_t buffer[kFrameLength];
+ memset(buffer, 9, kFrameLength); // Write lots of 9s to the buffer.
+ bool result = frame_writer_->WriteFrame(buffer);
+ ASSERT_TRUE(result);
+ result = frame_writer_->WriteFrame(buffer);
+ ASSERT_TRUE(result);
+
+ frame_writer_->Close();
+ EXPECT_EQ(kFileHeader.size() + 2 * kFrameHeader.size() + 2 * kFrameLength,
+ GetFileSize(temp_filename_));
+}
+
+TEST_F(Y4mFrameWriterTest, WriteFrameUninitialized) {
+ uint8_t buffer[kFrameLength];
+ Y4mFrameWriterImpl frame_writer(temp_filename_, kFrameWidth, kFrameHeight,
+ kFrameRate);
+ EXPECT_FALSE(frame_writer.WriteFrame(buffer));
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/webrtc/test/testsupport/frame_reader.cc b/webrtc/test/testsupport/yuv_frame_reader.cc
similarity index 61%
rename from webrtc/test/testsupport/frame_reader.cc
rename to webrtc/test/testsupport/yuv_frame_reader.cc
index 2593afd..3fe481e 100644
--- a/webrtc/test/testsupport/frame_reader.cc
+++ b/webrtc/test/testsupport/yuv_frame_reader.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * Copyright (c) 2017 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
@@ -10,8 +10,6 @@
#include "webrtc/test/testsupport/frame_reader.h"
-#include <assert.h>
-
#include "webrtc/api/video/i420_buffer.h"
#include "webrtc/test/frame_utils.h"
#include "webrtc/test/testsupport/fileutils.h"
@@ -19,28 +17,31 @@
namespace webrtc {
namespace test {
-FrameReaderImpl::FrameReaderImpl(std::string input_filename,
- int width, int height)
+YuvFrameReaderImpl::YuvFrameReaderImpl(std::string input_filename,
+ int width,
+ int height)
: input_filename_(input_filename),
- width_(width), height_(height),
- input_file_(NULL) {
-}
+ frame_length_in_bytes_(0),
+ width_(width),
+ height_(height),
+ number_of_frames_(-1),
+ input_file_(nullptr) {}
-FrameReaderImpl::~FrameReaderImpl() {
+YuvFrameReaderImpl::~YuvFrameReaderImpl() {
Close();
}
-bool FrameReaderImpl::Init() {
+bool YuvFrameReaderImpl::Init() {
if (width_ <= 0 || height_ <= 0) {
- fprintf(stderr, "Frame width and height must be >0, was %d x %d\n",
- width_, height_);
+ fprintf(stderr, "Frame width and height must be >0, was %d x %d\n", width_,
+ height_);
return false;
}
frame_length_in_bytes_ =
width_ * height_ + 2 * ((width_ + 1) / 2) * ((height_ + 1) / 2);
input_file_ = fopen(input_filename_.c_str(), "rb");
- if (input_file_ == NULL) {
+ if (input_file_ == nullptr) {
fprintf(stderr, "Couldn't open input file for reading: %s\n",
input_filename_.c_str());
return false;
@@ -51,21 +52,15 @@
fprintf(stderr, "Found empty file: %s\n", input_filename_.c_str());
return false;
}
- number_of_frames_ = static_cast<int>(source_file_size /
- frame_length_in_bytes_);
+ number_of_frames_ =
+ static_cast<int>(source_file_size / frame_length_in_bytes_);
return true;
}
-void FrameReaderImpl::Close() {
- if (input_file_ != NULL) {
- fclose(input_file_);
- input_file_ = NULL;
- }
-}
-
-rtc::scoped_refptr<I420Buffer> FrameReaderImpl::ReadFrame() {
- if (input_file_ == NULL) {
- fprintf(stderr, "FrameReader is not initialized (input file is NULL)\n");
+rtc::scoped_refptr<I420Buffer> YuvFrameReaderImpl::ReadFrame() {
+ if (input_file_ == nullptr) {
+ fprintf(stderr,
+ "YuvFrameReaderImpl is not initialized (input file is NULL)\n");
return nullptr;
}
rtc::scoped_refptr<I420Buffer> buffer(
@@ -77,8 +72,20 @@
return buffer;
}
-size_t FrameReaderImpl::FrameLength() { return frame_length_in_bytes_; }
-int FrameReaderImpl::NumberOfFrames() { return number_of_frames_; }
+void YuvFrameReaderImpl::Close() {
+ if (input_file_ != nullptr) {
+ fclose(input_file_);
+ input_file_ = nullptr;
+ }
+}
+
+size_t YuvFrameReaderImpl::FrameLength() {
+ return frame_length_in_bytes_;
+}
+
+int YuvFrameReaderImpl::NumberOfFrames() {
+ return number_of_frames_;
+}
} // namespace test
} // namespace webrtc
diff --git a/webrtc/test/testsupport/yuv_frame_reader_unittest.cc b/webrtc/test/testsupport/yuv_frame_reader_unittest.cc
new file mode 100644
index 0000000..9590814
--- /dev/null
+++ b/webrtc/test/testsupport/yuv_frame_reader_unittest.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017 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 <memory>
+#include <string>
+
+#include "webrtc/api/video/i420_buffer.h"
+#include "webrtc/test/gtest.h"
+#include "webrtc/test/testsupport/fileutils.h"
+#include "webrtc/test/testsupport/frame_reader.h"
+
+namespace webrtc {
+namespace test {
+
+namespace {
+const std::string kInputFileContents = "bazouk";
+
+const size_t kFrameWidth = 2;
+const size_t kFrameHeight = 2;
+const size_t kFrameLength = 3 * kFrameWidth * kFrameHeight / 2; // I420.
+} // namespace
+
+class YuvFrameReaderTest : public testing::Test {
+ protected:
+ YuvFrameReaderTest() = default;
+ ~YuvFrameReaderTest() override = default;
+
+ void SetUp() override {
+ temp_filename_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
+ "yuv_frame_reader_unittest");
+ FILE* dummy = fopen(temp_filename_.c_str(), "wb");
+ fprintf(dummy, "%s", kInputFileContents.c_str());
+ fclose(dummy);
+
+ frame_reader_.reset(
+ new YuvFrameReaderImpl(temp_filename_, kFrameWidth, kFrameHeight));
+ ASSERT_TRUE(frame_reader_->Init());
+ }
+
+ void TearDown() override { remove(temp_filename_.c_str()); }
+
+ std::unique_ptr<FrameReader> frame_reader_;
+ std::string temp_filename_;
+};
+
+TEST_F(YuvFrameReaderTest, InitSuccess) {}
+
+TEST_F(YuvFrameReaderTest, FrameLength) {
+ EXPECT_EQ(kFrameLength, frame_reader_->FrameLength());
+}
+
+TEST_F(YuvFrameReaderTest, NumberOfFrames) {
+ EXPECT_EQ(1, frame_reader_->NumberOfFrames());
+}
+
+TEST_F(YuvFrameReaderTest, ReadFrame) {
+ rtc::scoped_refptr<VideoFrameBuffer> buffer;
+ buffer = frame_reader_->ReadFrame();
+ ASSERT_TRUE(buffer);
+ // Expect I420 packed as YUV.
+ EXPECT_EQ(kInputFileContents[0], buffer->DataY()[0]);
+ EXPECT_EQ(kInputFileContents[1], buffer->DataY()[1]);
+ EXPECT_EQ(kInputFileContents[2], buffer->DataY()[2]);
+ EXPECT_EQ(kInputFileContents[3], buffer->DataY()[3]);
+ EXPECT_EQ(kInputFileContents[4], buffer->DataU()[0]);
+ EXPECT_EQ(kInputFileContents[5], buffer->DataV()[0]);
+ EXPECT_FALSE(frame_reader_->ReadFrame()); // End of file.
+}
+
+TEST_F(YuvFrameReaderTest, ReadFrameUninitialized) {
+ YuvFrameReaderImpl file_reader(temp_filename_, kFrameWidth, kFrameHeight);
+ EXPECT_FALSE(file_reader.ReadFrame());
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/webrtc/test/testsupport/yuv_frame_writer.cc b/webrtc/test/testsupport/yuv_frame_writer.cc
new file mode 100644
index 0000000..3c00761
--- /dev/null
+++ b/webrtc/test/testsupport/yuv_frame_writer.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017 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/base/checks.h"
+#include "webrtc/test/testsupport/frame_writer.h"
+
+namespace webrtc {
+namespace test {
+
+YuvFrameWriterImpl::YuvFrameWriterImpl(std::string output_filename,
+ int width,
+ int height)
+ : output_filename_(output_filename),
+ frame_length_in_bytes_(0),
+ width_(width),
+ height_(height),
+ output_file_(nullptr) {}
+
+YuvFrameWriterImpl::~YuvFrameWriterImpl() {
+ Close();
+}
+
+bool YuvFrameWriterImpl::Init() {
+ if (width_ <= 0 || height_ <= 0) {
+ fprintf(stderr, "Frame width and height must be >0, was %d x %d\n", width_,
+ height_);
+ return false;
+ }
+ frame_length_in_bytes_ =
+ width_ * height_ + 2 * ((width_ + 1) / 2) * ((height_ + 1) / 2);
+
+ output_file_ = fopen(output_filename_.c_str(), "wb");
+ if (output_file_ == nullptr) {
+ fprintf(stderr, "Couldn't open output file for writing: %s\n",
+ output_filename_.c_str());
+ return false;
+ }
+ return true;
+}
+
+bool YuvFrameWriterImpl::WriteFrame(uint8_t* frame_buffer) {
+ RTC_DCHECK(frame_buffer);
+ if (output_file_ == nullptr) {
+ fprintf(stderr,
+ "YuvFrameWriterImpl is not initialized (output file is NULL)\n");
+ return false;
+ }
+ size_t bytes_written =
+ fwrite(frame_buffer, 1, frame_length_in_bytes_, output_file_);
+ if (bytes_written != frame_length_in_bytes_) {
+ fprintf(stderr, "Failed to write %zu bytes to file %s\n",
+ frame_length_in_bytes_, output_filename_.c_str());
+ return false;
+ }
+ return true;
+}
+
+void YuvFrameWriterImpl::Close() {
+ if (output_file_ != nullptr) {
+ fclose(output_file_);
+ output_file_ = nullptr;
+ }
+}
+
+size_t YuvFrameWriterImpl::FrameLength() {
+ return frame_length_in_bytes_;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/webrtc/test/testsupport/yuv_frame_writer_unittest.cc b/webrtc/test/testsupport/yuv_frame_writer_unittest.cc
new file mode 100644
index 0000000..5e3cc5c
--- /dev/null
+++ b/webrtc/test/testsupport/yuv_frame_writer_unittest.cc
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 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 <memory>
+
+#include "webrtc/test/gtest.h"
+#include "webrtc/test/testsupport/fileutils.h"
+#include "webrtc/test/testsupport/frame_writer.h"
+
+namespace webrtc {
+namespace test {
+
+namespace {
+const size_t kFrameWidth = 50;
+const size_t kFrameHeight = 20;
+const size_t kFrameLength = 3 * kFrameWidth * kFrameHeight / 2; // I420.
+} // namespace
+
+class YuvFrameWriterTest : public testing::Test {
+ protected:
+ YuvFrameWriterTest() = default;
+ ~YuvFrameWriterTest() override = default;
+
+ void SetUp() override {
+ temp_filename_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
+ "yuv_frame_writer_unittest");
+ frame_writer_.reset(
+ new YuvFrameWriterImpl(temp_filename_, kFrameWidth, kFrameHeight));
+ ASSERT_TRUE(frame_writer_->Init());
+ }
+
+ void TearDown() override { remove(temp_filename_.c_str()); }
+
+ std::unique_ptr<FrameWriter> frame_writer_;
+ std::string temp_filename_;
+};
+
+TEST_F(YuvFrameWriterTest, InitSuccess) {}
+
+TEST_F(YuvFrameWriterTest, FrameLength) {
+ EXPECT_EQ(kFrameLength, frame_writer_->FrameLength());
+}
+
+TEST_F(YuvFrameWriterTest, WriteFrame) {
+ uint8_t buffer[kFrameLength];
+ memset(buffer, 9, kFrameLength); // Write lots of 9s to the buffer.
+ bool result = frame_writer_->WriteFrame(buffer);
+ ASSERT_TRUE(result);
+
+ frame_writer_->Close();
+ EXPECT_EQ(kFrameLength, GetFileSize(temp_filename_));
+}
+
+TEST_F(YuvFrameWriterTest, WriteFrameUninitialized) {
+ uint8_t buffer[kFrameLength];
+ YuvFrameWriterImpl frame_writer(temp_filename_, kFrameWidth, kFrameHeight);
+ EXPECT_FALSE(frame_writer.WriteFrame(buffer));
+}
+
+} // namespace test
+} // namespace webrtc