summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/webrtc/test/testsupport
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/libwebrtc/webrtc/test/testsupport
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/webrtc/test/testsupport')
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/always_passing_unittest.cc19
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/fileutils.cc363
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/fileutils.h110
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/fileutils_unittest.cc240
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/frame_reader.h75
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/frame_writer.h105
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/iosfileutils.mm63
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer.cc90
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer_ios.cc31
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.cc193
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.h121
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics_unittest.cc147
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/mock/mock_frame_reader.h33
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/packet_reader.cc49
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/packet_reader.h54
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/packet_reader_unittest.cc125
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/perf_test.cc92
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/perf_test.h71
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/perf_test_unittest.cc39
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.cc70
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.h39
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/test_artifacts_unittest.cc61
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/unittest_utils.h56
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer.cc56
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer_unittest.cc77
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader.cc91
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader_unittest.cc82
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer.cc77
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer_unittest.cc68
29 files changed, 2697 insertions, 0 deletions
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/always_passing_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/always_passing_unittest.cc
new file mode 100644
index 0000000000..e6318f7e0b
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/always_passing_unittest.cc
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2014 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 "test/gtest.h"
+
+namespace webrtc {
+
+// A test that always passes. Useful when all tests in a executable are
+// disabled, since a gtest returns exit code 1 if no tests have executed.
+TEST(AlwaysPassingTest, AlwaysPassingTest) {}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/fileutils.cc b/third_party/libwebrtc/webrtc/test/testsupport/fileutils.cc
new file mode 100644
index 0000000000..2aff75a4d9
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/fileutils.cc
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2012 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 "test/testsupport/fileutils.h"
+
+#include <assert.h>
+
+#ifdef WIN32
+#include <direct.h>
+#include <tchar.h>
+#include <windows.h>
+#include <algorithm>
+
+#include "Shlwapi.h"
+#include "WinDef.h"
+
+#include "rtc_base/win32.h"
+#define GET_CURRENT_DIR _getcwd
+#else
+#include <dirent.h>
+#include <unistd.h>
+
+#define GET_CURRENT_DIR getcwd
+#endif
+
+#include <sys/stat.h> // To check for directory existence.
+#ifndef S_ISDIR // Not defined in stat.h on Windows.
+#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <memory>
+#include <utility>
+
+#include "rtc_base/checks.h"
+#include "typedefs.h" // NOLINT(build/include) // For architecture defines
+
+namespace webrtc {
+namespace test {
+
+#if defined(WEBRTC_IOS)
+// Defined in iosfileutils.mm. No header file to discourage use elsewhere.
+std::string IOSOutputPath();
+std::string IOSRootPath();
+std::string IOSResourcePath(std::string name, std::string extension);
+#endif
+
+namespace {
+
+#ifdef WIN32
+const char* kPathDelimiter = "\\";
+#else
+const char* kPathDelimiter = "/";
+#endif
+
+#ifdef WEBRTC_ANDROID
+const char* kRootDirName = "/sdcard/chromium_tests_root/";
+#else
+#if !defined(WEBRTC_IOS)
+const char* kOutputDirName = "out";
+#endif
+const char* kFallbackPath = "./";
+#endif // !defined(WEBRTC_ANDROID)
+
+#if !defined(WEBRTC_IOS)
+const char* kResourcesDirName = "resources";
+#endif
+
+char relative_dir_path[FILENAME_MAX];
+bool relative_dir_path_set = false;
+
+} // namespace
+
+const char* kCannotFindProjectRootDir = "ERROR_CANNOT_FIND_PROJECT_ROOT_DIR";
+
+void SetExecutablePath(const std::string& path) {
+ std::string working_dir = WorkingDir();
+ std::string temp_path = path;
+
+ // Handle absolute paths; convert them to relative paths to the working dir.
+ if (path.find(working_dir) != std::string::npos) {
+ temp_path = path.substr(working_dir.length() + 1);
+ }
+ // On Windows, when tests are run under memory tools like DrMemory and TSan,
+ // slashes occur in the path as directory separators. Make sure we replace
+ // such cases with backslashes in order for the paths to be correct.
+#ifdef WIN32
+ std::replace(temp_path.begin(), temp_path.end(), '/', '\\');
+#endif
+
+ // Trim away the executable name; only store the relative dir path.
+ temp_path = temp_path.substr(0, temp_path.find_last_of(kPathDelimiter));
+ strncpy(relative_dir_path, temp_path.c_str(), FILENAME_MAX);
+ relative_dir_path_set = true;
+}
+
+bool FileExists(const std::string& file_name) {
+ struct stat file_info = {0};
+ return stat(file_name.c_str(), &file_info) == 0;
+}
+
+bool DirExists(const std::string& directory_name) {
+ struct stat directory_info = {0};
+ return stat(directory_name.c_str(), &directory_info) == 0 && S_ISDIR(
+ directory_info.st_mode);
+}
+
+#ifdef WEBRTC_ANDROID
+
+std::string ProjectRootPath() {
+ return kRootDirName;
+}
+
+std::string OutputPath() {
+ return kRootDirName;
+}
+
+std::string WorkingDir() {
+ return kRootDirName;
+}
+
+#else // WEBRTC_ANDROID
+
+std::string ProjectRootPath() {
+#if defined(WEBRTC_IOS)
+ return IOSRootPath();
+#else
+ std::string path = WorkingDir();
+ if (path == kFallbackPath) {
+ return kCannotFindProjectRootDir;
+ }
+ if (relative_dir_path_set) {
+ path = path + kPathDelimiter + relative_dir_path;
+ }
+ path = path + kPathDelimiter + ".." + kPathDelimiter + "..";
+ char canonical_path[FILENAME_MAX];
+#ifdef WIN32
+ BOOL succeeded = PathCanonicalizeA(canonical_path, path.c_str());
+#else
+ bool succeeded = realpath(path.c_str(), canonical_path) != NULL;
+#endif
+ if (succeeded) {
+ path = std::string(canonical_path) + kPathDelimiter;
+ return path;
+ } else {
+ fprintf(stderr, "Cannot find project root directory!\n");
+ return kCannotFindProjectRootDir;
+ }
+#endif
+}
+
+std::string OutputPath() {
+#if defined(WEBRTC_IOS)
+ return IOSOutputPath();
+#else
+ std::string path = ProjectRootPath();
+ if (path == kCannotFindProjectRootDir) {
+ return kFallbackPath;
+ }
+ path += kOutputDirName;
+ if (!CreateDir(path)) {
+ return kFallbackPath;
+ }
+ return path + kPathDelimiter;
+#endif
+}
+
+std::string WorkingDir() {
+ char path_buffer[FILENAME_MAX];
+ if (!GET_CURRENT_DIR(path_buffer, sizeof(path_buffer))) {
+ fprintf(stderr, "Cannot get current directory!\n");
+ return kFallbackPath;
+ } else {
+ return std::string(path_buffer);
+ }
+}
+
+#endif // !WEBRTC_ANDROID
+
+// Generate a temporary filename in a safe way.
+// Largely copied from talk/base/{unixfilesystem,win32filesystem}.cc.
+std::string TempFilename(const std::string &dir, const std::string &prefix) {
+#ifdef WIN32
+ wchar_t filename[MAX_PATH];
+ if (::GetTempFileName(rtc::ToUtf16(dir).c_str(),
+ rtc::ToUtf16(prefix).c_str(), 0, filename) != 0)
+ return rtc::ToUtf8(filename);
+ assert(false);
+ return "";
+#else
+ int len = dir.size() + prefix.size() + 2 + 6;
+ std::unique_ptr<char[]> tempname(new char[len]);
+
+ snprintf(tempname.get(), len, "%s/%sXXXXXX", dir.c_str(),
+ prefix.c_str());
+ int fd = ::mkstemp(tempname.get());
+ if (fd == -1) {
+ assert(false);
+ return "";
+ } else {
+ ::close(fd);
+ }
+ std::string ret(tempname.get());
+ return ret;
+#endif
+}
+
+rtc::Optional<std::vector<std::string>> ReadDirectory(std::string path) {
+ if (path.length() == 0)
+ return rtc::Optional<std::vector<std::string>>();
+
+#if defined(WEBRTC_WIN)
+ // Append separator character if needed.
+ if (path.back() != '\\')
+ path += '\\';
+
+ // Init.
+ WIN32_FIND_DATA data;
+ HANDLE handle = ::FindFirstFile(rtc::ToUtf16(path + '*').c_str(), &data);
+ if (handle == INVALID_HANDLE_VALUE)
+ return rtc::Optional<std::vector<std::string>>();
+
+ // Populate output.
+ std::vector<std::string> found_entries;
+ do {
+ const std::string name = rtc::ToUtf8(data.cFileName);
+ if (name != "." && name != "..")
+ found_entries.emplace_back(path + name);
+ } while (::FindNextFile(handle, &data) == TRUE);
+
+ // Release resources.
+ if (handle != INVALID_HANDLE_VALUE)
+ ::FindClose(handle);
+#else
+ // Append separator character if needed.
+ if (path.back() != '/')
+ path += '/';
+
+ // Init.
+ DIR* dir = ::opendir(path.c_str());
+ if (dir == nullptr)
+ return rtc::Optional<std::vector<std::string>>();
+
+ // Populate output.
+ std::vector<std::string> found_entries;
+ while (dirent* dirent = readdir(dir)) {
+ const std::string& name = dirent->d_name;
+ if (name != "." && name != "..")
+ found_entries.emplace_back(path + name);
+ }
+
+ // Release resources.
+ closedir(dir);
+#endif
+
+ return rtc::Optional<std::vector<std::string>>(std::move(found_entries));
+}
+
+bool CreateDir(const std::string& directory_name) {
+ struct stat path_info = {0};
+ // Check if the path exists already:
+ if (stat(directory_name.c_str(), &path_info) == 0) {
+ if (!S_ISDIR(path_info.st_mode)) {
+ fprintf(stderr, "Path %s exists but is not a directory! Remove this "
+ "file and re-run to create the directory.\n",
+ directory_name.c_str());
+ return false;
+ }
+ } else {
+#ifdef WIN32
+ return _mkdir(directory_name.c_str()) == 0;
+#else
+ return mkdir(directory_name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0;
+#endif
+ }
+ return true;
+}
+
+bool RemoveDir(const std::string& directory_name) {
+#ifdef WIN32
+ return RemoveDirectoryA(directory_name.c_str()) != FALSE;
+#else
+ return rmdir(directory_name.c_str()) == 0;
+#endif
+}
+
+bool RemoveFile(const std::string& file_name) {
+#ifdef WIN32
+ return DeleteFileA(file_name.c_str()) != FALSE;
+#else
+ return unlink(file_name.c_str()) == 0;
+#endif
+}
+
+std::string ResourcePath(const std::string& name,
+ const std::string& extension) {
+#if defined(WEBRTC_IOS)
+ return IOSResourcePath(name, extension);
+#else
+ std::string platform = "win";
+#ifdef WEBRTC_LINUX
+ platform = "linux";
+#endif // WEBRTC_LINUX
+#ifdef WEBRTC_MAC
+ platform = "mac";
+#endif // WEBRTC_MAC
+#ifdef WEBRTC_ANDROID
+ platform = "android";
+#endif // WEBRTC_ANDROID
+
+#ifdef WEBRTC_ARCH_64_BITS
+ std::string architecture = "64";
+#else
+ std::string architecture = "32";
+#endif // WEBRTC_ARCH_64_BITS
+
+ std::string resources_path = ProjectRootPath() + kResourcesDirName +
+ kPathDelimiter;
+ std::string resource_file = resources_path + name + "_" + platform + "_" +
+ architecture + "." + extension;
+ if (FileExists(resource_file)) {
+ return resource_file;
+ }
+ // Try without architecture.
+ resource_file = resources_path + name + "_" + platform + "." + extension;
+ if (FileExists(resource_file)) {
+ return resource_file;
+ }
+ // Try without platform.
+ resource_file = resources_path + name + "_" + architecture + "." + extension;
+ if (FileExists(resource_file)) {
+ return resource_file;
+ }
+
+ // Fall back on name without architecture or platform.
+ return resources_path + name + "." + extension;
+#endif // defined (WEBRTC_IOS)
+}
+
+size_t GetFileSize(const std::string& filename) {
+ FILE* f = fopen(filename.c_str(), "rb");
+ size_t size = 0;
+ if (f != NULL) {
+ if (fseek(f, 0, SEEK_END) == 0) {
+ size = ftell(f);
+ }
+ fclose(f);
+ }
+ return size;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/fileutils.h b/third_party/libwebrtc/webrtc/test/testsupport/fileutils.h
new file mode 100644
index 0000000000..f0560cf979
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/fileutils.h
@@ -0,0 +1,110 @@
+/*
+ * 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 <stdio.h>
+
+#ifndef TEST_TESTSUPPORT_FILEUTILS_H_
+#define TEST_TESTSUPPORT_FILEUTILS_H_
+
+#include <string>
+#include <vector>
+
+#include "api/optional.h"
+
+namespace webrtc {
+namespace test {
+
+// This is the "directory" returned if the ProjectPath() function fails
+// to find the project root.
+extern const char* kCannotFindProjectRootDir;
+
+// Creates and returns the absolute path to the output directory where log files
+// and other test artifacts should be put. The output directory is generally a
+// directory named "out" at the top-level of the project, i.e. a subfolder to
+// the path returned by ProjectRootPath(). The exception is Android where we use
+// /sdcard/ instead.
+//
+// If symbolic links occur in the path they will be resolved and the actual
+// directory will be returned.
+//
+// Returns the path WITH a trailing path delimiter. If the project root is not
+// found, the current working directory ("./") is returned as a fallback.
+std::string OutputPath();
+
+// Generates an empty file with a unique name in the specified directory and
+// returns the file name and path.
+std::string TempFilename(const std::string &dir, const std::string &prefix);
+
+// Returns a path to a resource file for the currently executing platform.
+// Adapts to what filenames are currently present in the
+// [project-root]/resources/ dir.
+// Returns an absolute path according to this priority list (the directory
+// part of the path is left out for readability):
+// 1. [name]_[platform]_[architecture].[extension]
+// 2. [name]_[platform].[extension]
+// 3. [name]_[architecture].[extension]
+// 4. [name].[extension]
+// Where
+// * platform is either of "win", "mac" or "linux".
+// * architecture is either of "32" or "64".
+//
+// Arguments:
+// name - Name of the resource file. If a plain filename (no directory path)
+// is supplied, the file is assumed to be located in resources/
+// If a directory path is prepended to the filename, a subdirectory
+// hierarchy reflecting that path is assumed to be present.
+// extension - File extension, without the dot, i.e. "bmp" or "yuv".
+std::string ResourcePath(const std::string& name,
+ const std::string& extension);
+
+// Gets the current working directory for the executing program.
+// Returns "./" if for some reason it is not possible to find the working
+// directory.
+std::string WorkingDir();
+
+// Reads the content of a directory and, in case of success, returns a vector
+// of strings with one element for each found file or directory. Each element is
+// a path created by prepending |dir| to the file/directory name. "." and ".."
+// are never added in the returned vector.
+rtc::Optional<std::vector<std::string>> ReadDirectory(std::string path);
+
+// Creates a directory if it not already exists.
+// Returns true if successful. Will print an error message to stderr and return
+// false if a file with the same name already exists.
+bool CreateDir(const std::string& directory_name);
+
+// Removes a directory, which must already be empty.
+bool RemoveDir(const std::string& directory_name);
+
+// Removes a file.
+bool RemoveFile(const std::string& file_name);
+
+// Checks if a file exists.
+bool FileExists(const std::string& file_name);
+
+// Checks if a directory exists.
+bool DirExists(const std::string& directory_name);
+
+// File size of the supplied file in bytes. Will return 0 if the file is
+// empty or if the file does not exist/is readable.
+size_t GetFileSize(const std::string& filename);
+
+// Sets the executable path, i.e. the path to the executable that is being used
+// when launching it. This is usually the path relative to the working directory
+// but can also be an absolute path. The intention with this function is to pass
+// the argv[0] being sent into the main function to make it possible for
+// fileutils.h to find the correct project paths even when the working directory
+// is outside the project tree (which happens in some cases).
+void SetExecutablePath(const std::string& path_to_executable);
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_FILEUTILS_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/fileutils_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/fileutils_unittest.cc
new file mode 100644
index 0000000000..79988c0dd3
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/fileutils_unittest.cc
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2012 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 "test/testsupport/fileutils.h"
+
+#include <stdio.h>
+
+#include <fstream>
+#include <iostream>
+#include <list>
+#include <string>
+
+#include "api/optional.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/pathutils.h"
+#include "test/gtest.h"
+
+#ifdef WIN32
+#define chdir _chdir
+static const char* kPathDelimiter = "\\";
+#else
+static const char* kPathDelimiter = "/";
+#endif
+
+static const char kTestName[] = "fileutils_unittest";
+static const char kExtension[] = "tmp";
+
+namespace webrtc {
+namespace test {
+
+namespace {
+
+// Remove files and directories in a directory non-recursively and writes the
+// number of deleted items in |num_deleted_entries|.
+void CleanDir(const std::string& dir, size_t* num_deleted_entries) {
+ RTC_DCHECK(num_deleted_entries);
+ *num_deleted_entries = 0;
+ rtc::Optional<std::vector<std::string>> dir_content = ReadDirectory(dir);
+ EXPECT_TRUE(dir_content);
+ for (const auto& entry : *dir_content) {
+ if (DirExists(entry)) {
+ EXPECT_TRUE(RemoveDir(entry));
+ (*num_deleted_entries)++;
+ } else if (FileExists(entry)) {
+ EXPECT_TRUE(RemoveFile(entry));
+ (*num_deleted_entries)++;
+ } else {
+ FAIL();
+ }
+ }
+}
+
+void WriteStringInFile(const std::string& what, const std::string& file_path) {
+ std::ofstream out(file_path);
+ out << what;
+ out.close();
+}
+
+} // namespace
+
+// Test fixture to restore the working directory between each test, since some
+// of them change it with chdir during execution (not restored by the
+// gtest framework).
+class FileUtilsTest : public testing::Test {
+ protected:
+ FileUtilsTest() {
+ }
+ ~FileUtilsTest() override {}
+ // Runs before the first test
+ static void SetUpTestCase() {
+ original_working_dir_ = webrtc::test::WorkingDir();
+ }
+ void SetUp() override {
+ ASSERT_EQ(chdir(original_working_dir_.c_str()), 0);
+ }
+ void TearDown() override {
+ ASSERT_EQ(chdir(original_working_dir_.c_str()), 0);
+ }
+ private:
+ static std::string original_working_dir_;
+};
+
+std::string FileUtilsTest::original_working_dir_ = "";
+
+// Tests that the project output dir path is returned for the default working
+// directory that is automatically set when the test executable is launched.
+// The test is not fully testing the implementation, since we cannot be sure
+// of where the executable was launched from.
+#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
+#define MAYBE_OutputPathFromUnchangedWorkingDir \
+ DISABLED_OutputPathFromUnchangedWorkingDir
+#else
+#define MAYBE_OutputPathFromUnchangedWorkingDir \
+ OutputPathFromUnchangedWorkingDir
+#endif
+TEST_F(FileUtilsTest, MAYBE_OutputPathFromUnchangedWorkingDir) {
+ std::string path = webrtc::test::OutputPath();
+ std::string expected_end = "out";
+ expected_end = kPathDelimiter + expected_end + kPathDelimiter;
+ ASSERT_EQ(path.length() - expected_end.length(), path.find(expected_end));
+}
+
+// Tests with current working directory set to a directory higher up in the
+// directory tree than the project root dir.
+#if defined(WEBRTC_ANDROID) || defined(WIN32) || defined(WEBRTC_IOS)
+#define MAYBE_OutputPathFromRootWorkingDir DISABLED_OutputPathFromRootWorkingDir
+#else
+#define MAYBE_OutputPathFromRootWorkingDir OutputPathFromRootWorkingDir
+#endif
+TEST_F(FileUtilsTest, MAYBE_OutputPathFromRootWorkingDir) {
+ ASSERT_EQ(0, chdir(kPathDelimiter));
+ ASSERT_EQ("./", webrtc::test::OutputPath());
+}
+
+TEST_F(FileUtilsTest, TempFilename) {
+ std::string temp_filename = webrtc::test::TempFilename(
+ webrtc::test::OutputPath(), "TempFilenameTest");
+ ASSERT_TRUE(webrtc::test::FileExists(temp_filename))
+ << "Couldn't find file: " << temp_filename;
+ remove(temp_filename.c_str());
+}
+
+// Only tests that the code executes
+#if defined(WEBRTC_IOS)
+#define MAYBE_CreateDir DISABLED_CreateDir
+#else
+#define MAYBE_CreateDir CreateDir
+#endif
+TEST_F(FileUtilsTest, MAYBE_CreateDir) {
+ std::string directory = "fileutils-unittest-empty-dir";
+ // Make sure it's removed if a previous test has failed:
+ remove(directory.c_str());
+ ASSERT_TRUE(webrtc::test::CreateDir(directory));
+ remove(directory.c_str());
+}
+
+TEST_F(FileUtilsTest, WorkingDirReturnsValue) {
+ // Hard to cover all platforms. Just test that it returns something without
+ // crashing:
+ std::string working_dir = webrtc::test::WorkingDir();
+ ASSERT_GT(working_dir.length(), 0u);
+}
+
+// Due to multiple platforms, it is hard to make a complete test for
+// ResourcePath. Manual testing has been performed by removing files and
+// verified the result confirms with the specified documentation for the
+// function.
+TEST_F(FileUtilsTest, ResourcePathReturnsValue) {
+ std::string resource = webrtc::test::ResourcePath(kTestName, kExtension);
+ ASSERT_GT(resource.find(kTestName), 0u);
+ ASSERT_GT(resource.find(kExtension), 0u);
+}
+
+TEST_F(FileUtilsTest, ResourcePathFromRootWorkingDir) {
+ ASSERT_EQ(0, chdir(kPathDelimiter));
+ std::string resource = webrtc::test::ResourcePath(kTestName, kExtension);
+#if !defined(WEBRTC_IOS)
+ ASSERT_NE(resource.find("resources"), std::string::npos);
+#endif
+ ASSERT_GT(resource.find(kTestName), 0u);
+ ASSERT_GT(resource.find(kExtension), 0u);
+}
+
+TEST_F(FileUtilsTest, GetFileSizeExistingFile) {
+ // Create a file with some dummy data in.
+ std::string temp_filename = webrtc::test::TempFilename(
+ webrtc::test::OutputPath(), "fileutils_unittest");
+ FILE* file = fopen(temp_filename.c_str(), "wb");
+ ASSERT_TRUE(file != NULL) << "Failed to open file: " << temp_filename;
+ ASSERT_GT(fprintf(file, "%s", "Dummy data"), 0) <<
+ "Failed to write to file: " << temp_filename;
+ fclose(file);
+ ASSERT_GT(webrtc::test::GetFileSize(std::string(temp_filename.c_str())), 0u);
+ remove(temp_filename.c_str());
+}
+
+TEST_F(FileUtilsTest, GetFileSizeNonExistingFile) {
+ ASSERT_EQ(0u, webrtc::test::GetFileSize("non-existing-file.tmp"));
+}
+
+TEST_F(FileUtilsTest, DirExists) {
+ // Check that an existing directory is recognized as such.
+ ASSERT_TRUE(webrtc::test::DirExists(webrtc::test::OutputPath()))
+ << "Existing directory not found";
+
+ // Check that a non-existing directory is recognized as such.
+ std::string directory = "direxists-unittest-non_existing-dir";
+ ASSERT_FALSE(webrtc::test::DirExists(directory))
+ << "Non-existing directory found";
+
+ // Check that an existing file is not recognized as an existing directory.
+ std::string temp_filename = webrtc::test::TempFilename(
+ webrtc::test::OutputPath(), "TempFilenameTest");
+ ASSERT_TRUE(webrtc::test::FileExists(temp_filename))
+ << "Couldn't find file: " << temp_filename;
+ ASSERT_FALSE(webrtc::test::DirExists(temp_filename))
+ << "Existing file recognized as existing directory";
+ remove(temp_filename.c_str());
+}
+
+TEST_F(FileUtilsTest, WriteReadDeleteFilesAndDirs) {
+ size_t num_deleted_entries;
+
+ // Create an empty temporary directory for this test.
+ const std::string temp_directory =
+ OutputPath() + "TempFileUtilsTestReadDirectory" + kPathDelimiter;
+ CreateDir(temp_directory);
+ EXPECT_NO_FATAL_FAILURE(CleanDir(temp_directory, &num_deleted_entries));
+ EXPECT_TRUE(DirExists(temp_directory));
+
+ // Add a file.
+ const std::string temp_filename = temp_directory + "TempFilenameTest";
+ WriteStringInFile("test\n", temp_filename);
+ EXPECT_TRUE(FileExists(temp_filename));
+
+ // Add an empty directory.
+ const std::string temp_subdir = temp_directory + "subdir" + kPathDelimiter;
+ EXPECT_TRUE(CreateDir(temp_subdir));
+ EXPECT_TRUE(DirExists(temp_subdir));
+
+ // Checks.
+ rtc::Optional<std::vector<std::string>> dir_content =
+ ReadDirectory(temp_directory);
+ EXPECT_TRUE(dir_content);
+ EXPECT_EQ(2u, dir_content->size());
+ EXPECT_NO_FATAL_FAILURE(CleanDir(temp_directory, &num_deleted_entries));
+ EXPECT_EQ(2u, num_deleted_entries);
+ EXPECT_TRUE(RemoveDir(temp_directory));
+ EXPECT_FALSE(DirExists(temp_directory));
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/frame_reader.h b/third_party/libwebrtc/webrtc/test/testsupport/frame_reader.h
new file mode 100644
index 0000000000..2e19af344e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/frame_reader.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_TESTSUPPORT_FRAME_READER_H_
+#define TEST_TESTSUPPORT_FRAME_READER_H_
+
+#include <stdio.h>
+
+#include <string>
+
+#include "rtc_base/scoped_ref_ptr.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+class I420Buffer;
+namespace test {
+
+// Handles reading of I420 frames from video files.
+class FrameReader {
+ public:
+ virtual ~FrameReader() {}
+
+ // Initializes the frame reader, i.e. opens the input file.
+ // This must be called before reading of frames has started.
+ // Returns false if an error has occurred, in addition to printing to stderr.
+ virtual bool Init() = 0;
+
+ // Reads a frame from the input file. On success, returns the frame.
+ // Returns nullptr if encountering end of file or a read error.
+ virtual rtc::scoped_refptr<I420Buffer> ReadFrame() = 0;
+
+ // Closes the input file if open. Essentially makes this class impossible
+ // to use anymore. Will also be invoked by the destructor.
+ virtual void Close() = 0;
+
+ // Frame length in bytes of a single frame image.
+ virtual size_t FrameLength() = 0;
+ // Total number of frames in the input video source.
+ virtual int NumberOfFrames() = 0;
+};
+
+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.
+ YuvFrameReaderImpl(std::string input_filename, int width, int height);
+ ~YuvFrameReaderImpl() override;
+ bool Init() override;
+ rtc::scoped_refptr<I420Buffer> ReadFrame() override;
+ void Close() override;
+ size_t FrameLength() override;
+ int NumberOfFrames() override;
+
+ private:
+ const std::string input_filename_;
+ size_t frame_length_in_bytes_;
+ const int width_;
+ const int height_;
+ int number_of_frames_;
+ FILE* input_file_;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_FRAME_READER_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/frame_writer.h b/third_party/libwebrtc/webrtc/test/testsupport/frame_writer.h
new file mode 100644
index 0000000000..7556050a21
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/frame_writer.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#ifndef TEST_TESTSUPPORT_FRAME_WRITER_H_
+#define TEST_TESTSUPPORT_FRAME_WRITER_H_
+
+#include <stdio.h>
+
+#include <string>
+
+#include "api/video/video_frame.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+// Handles writing of video files.
+class FrameWriter {
+ public:
+ virtual ~FrameWriter() {}
+
+ // Initializes the file handler, i.e. opens the input and output files etc.
+ // This must be called before reading or writing frames has started.
+ // Returns false if an error has occurred, in addition to printing to stderr.
+ virtual bool Init() = 0;
+
+ // Writes a frame of the configured frame length to the output file.
+ // Returns true if the write was successful, false otherwise.
+ virtual bool WriteFrame(uint8_t* frame_buffer) = 0;
+
+ // Closes the output file if open. Essentially makes this class impossible
+ // to use anymore. Will also be invoked by the destructor.
+ virtual void Close() = 0;
+
+ // Frame length in bytes of a single frame image.
+ virtual size_t FrameLength() = 0;
+};
+
+// 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.
+ // 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;
+
+ 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_;
+};
+
+// LibJpeg is not available on iOS. This class will do nothing on iOS.
+class JpegFrameWriter {
+ public:
+ JpegFrameWriter(const std::string &output_filename);
+ // Quality can be from 0 (worst) to 100 (best). Best quality is still lossy.
+ // WriteFrame can be called only once. Subsequent calls will fail.
+ bool WriteFrame(const VideoFrame& input_frame, int quality);
+
+#if !defined(WEBRTC_IOS)
+ private:
+ bool frame_written_;
+ const std::string output_filename_;
+ FILE* output_file_;
+#endif
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_FRAME_WRITER_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/iosfileutils.mm b/third_party/libwebrtc/webrtc/test/testsupport/iosfileutils.mm
new file mode 100644
index 0000000000..a9156db656
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/iosfileutils.mm
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2015 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.
+ */
+
+#if defined(WEBRTC_IOS)
+
+#import <Foundation/Foundation.h>
+#include <string.h>
+
+#include "rtc_base/checks.h"
+#include "sdk/objc/Framework/Classes/Common/helpers.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+using webrtc::ios::NSStringFromStdString;
+using webrtc::ios::StdStringFromNSString;
+
+// For iOS, resource files are added to the application bundle in the root
+// and not in separate folders as is the case for other platforms. This method
+// therefore removes any prepended folders and uses only the actual file name.
+std::string IOSResourcePath(std::string name, std::string extension) {
+ @autoreleasepool {
+ NSString* path = NSStringFromStdString(name);
+ NSString* fileName = path.lastPathComponent;
+ NSString* fileType = NSStringFromStdString(extension);
+ // Get full pathname for the resource identified by the name and extension.
+ NSString* pathString = [[NSBundle mainBundle] pathForResource:fileName
+ ofType:fileType];
+ return StdStringFromNSString(pathString);
+ }
+}
+
+std::string IOSRootPath() {
+ @autoreleasepool {
+ NSBundle* mainBundle = [NSBundle mainBundle];
+ return StdStringFromNSString(mainBundle.bundlePath) + "/";
+ }
+}
+
+// For iOS, we don't have access to the output directory. Return the path to the
+// temporary directory instead. This is mostly used by tests that need to write
+// output files to disk.
+std::string IOSOutputPath() {
+ @autoreleasepool {
+ NSString* tempDir = NSTemporaryDirectory();
+ if (tempDir == nil)
+ tempDir = @"/tmp";
+ return StdStringFromNSString(tempDir);
+ }
+}
+
+} // namespace test
+} // namespace webrtc
+
+#endif // defined(WEBRTC_IOS)
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer.cc b/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer.cc
new file mode 100644
index 0000000000..4888f65aeb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer.cc
@@ -0,0 +1,90 @@
+/*
+ * 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 <stdio.h>
+
+
+#include "common_types.h" // NOLINT(build/include)
+#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "test/testsupport/frame_writer.h"
+
+extern "C" {
+#if defined(USE_SYSTEM_LIBJPEG)
+#include <jpeglib.h>
+#else
+// Include directory supplied by gn
+#include "jpeglib.h" // NOLINT
+#endif
+}
+
+namespace webrtc {
+namespace test {
+
+JpegFrameWriter::JpegFrameWriter(const std::string &output_filename)
+ : frame_written_(false),
+ output_filename_(output_filename),
+ output_file_(nullptr) {}
+
+bool JpegFrameWriter::WriteFrame(const VideoFrame& input_frame, int quality) {
+ if (frame_written_) {
+ RTC_LOG(LS_ERROR) << "Only a single frame can be saved to Jpeg.";
+ return false;
+ }
+ const int kColorPlanes = 3; // R, G and B.
+ size_t rgb_len = input_frame.height() * input_frame.width() * kColorPlanes;
+ std::unique_ptr<uint8_t[]> rgb_buf(new uint8_t[rgb_len]);
+
+ // kRGB24 actually corresponds to FourCC 24BG which is 24-bit BGR.
+ if (ConvertFromI420(input_frame, VideoType::kRGB24, 0, rgb_buf.get()) < 0) {
+ RTC_LOG(LS_ERROR) << "Could not convert input frame to RGB.";
+ return false;
+ }
+ output_file_ = fopen(output_filename_.c_str(), "wb");
+ if (!output_file_) {
+ RTC_LOG(LS_ERROR) << "Couldn't open file to write jpeg frame to:"
+ << output_filename_;
+ return false;
+ }
+
+ // Invoking LIBJPEG
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPROW row_pointer[1];
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+ jpeg_stdio_dest(&cinfo, output_file_);
+
+ cinfo.image_width = input_frame.width();
+ cinfo.image_height = input_frame.height();
+ cinfo.input_components = kColorPlanes;
+ cinfo.in_color_space = JCS_EXT_BGR;
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, quality, TRUE);
+
+ jpeg_start_compress(&cinfo, TRUE);
+ int row_stride = input_frame.width() * kColorPlanes;
+ while (cinfo.next_scanline < cinfo.image_height) {
+ row_pointer[0] = &rgb_buf.get()[cinfo.next_scanline * row_stride];
+ jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+ fclose(output_file_);
+
+ frame_written_ = true;
+ return true;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer_ios.cc b/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer_ios.cc
new file mode 100644
index 0000000000..567e75e254
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer_ios.cc
@@ -0,0 +1,31 @@
+/*
+ * 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 "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "test/testsupport/frame_writer.h"
+
+
+namespace webrtc {
+namespace test {
+
+JpegFrameWriter::JpegFrameWriter(const std::string& /*output_filename*/) {}
+
+bool JpegFrameWriter::WriteFrame(const VideoFrame& /*input_frame*/,
+ int /*quality*/) {
+ RTC_LOG(LS_WARNING)
+ << "Libjpeg isn't available on IOS. Jpeg frame writer is not "
+ "supported. No frame will be saved.";
+ // Don't fail.
+ return true;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.cc b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.cc
new file mode 100644
index 0000000000..ea5d3f2b5f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.cc
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2012 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 "test/testsupport/metrics/video_metrics.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <algorithm> // min_element, max_element
+#include <memory>
+
+#include "api/video/i420_buffer.h"
+#include "api/video/video_frame.h"
+#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "test/frame_utils.h"
+#include "libyuv/convert.h"
+
+namespace webrtc {
+namespace test {
+
+// Copy here so our callers won't need to include libyuv for this constant.
+double kMetricsPerfectPSNR = kPerfectPSNR;
+
+// Used for calculating min and max values.
+static bool LessForFrameResultValue(const FrameResult& s1,
+ const FrameResult& s2) {
+ return s1.value < s2.value;
+}
+
+enum VideoMetricsType { kPSNR, kSSIM, kBoth };
+
+// Calculates metrics for a frame and adds statistics to the result for it.
+void CalculateFrame(VideoMetricsType video_metrics_type,
+ const I420BufferInterface& ref,
+ const I420BufferInterface& test,
+ int frame_number,
+ QualityMetricsResult* result) {
+ FrameResult frame_result = {0, 0};
+ frame_result.frame_number = frame_number;
+ switch (video_metrics_type) {
+ case kPSNR:
+ frame_result.value = I420PSNR(ref, test);
+ break;
+ case kSSIM:
+ frame_result.value = I420SSIM(ref, test);
+ break;
+ default:
+ assert(false);
+ }
+ result->frames.push_back(frame_result);
+}
+
+// Calculates average, min and max values for the supplied struct, if non-NULL.
+void CalculateStats(QualityMetricsResult* result) {
+ if (result == NULL || result->frames.size() == 0) {
+ return;
+ }
+ // Calculate average.
+ std::vector<FrameResult>::iterator iter;
+ double metrics_values_sum = 0.0;
+ for (iter = result->frames.begin(); iter != result->frames.end(); ++iter) {
+ metrics_values_sum += iter->value;
+ }
+ result->average = metrics_values_sum / result->frames.size();
+
+ // Calculate min/max statistics.
+ iter = std::min_element(result->frames.begin(), result->frames.end(),
+ LessForFrameResultValue);
+ result->min = iter->value;
+ result->min_frame_number = iter->frame_number;
+ iter = std::max_element(result->frames.begin(), result->frames.end(),
+ LessForFrameResultValue);
+ result->max = iter->value;
+ result->max_frame_number = iter->frame_number;
+}
+
+// Single method that handles all combinations of video metrics calculation, to
+// minimize code duplication. Either psnr_result or ssim_result may be NULL,
+// depending on which VideoMetricsType is targeted.
+int CalculateMetrics(VideoMetricsType video_metrics_type,
+ const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* psnr_result,
+ QualityMetricsResult* ssim_result) {
+ assert(ref_filename != NULL);
+ assert(test_filename != NULL);
+ assert(width > 0);
+ assert(height > 0);
+
+ FILE* ref_fp = fopen(ref_filename, "rb");
+ if (ref_fp == NULL) {
+ // Cannot open reference file.
+ fprintf(stderr, "Cannot open file %s\n", ref_filename);
+ return -1;
+ }
+ FILE* test_fp = fopen(test_filename, "rb");
+ if (test_fp == NULL) {
+ // Cannot open test file.
+ fprintf(stderr, "Cannot open file %s\n", test_filename);
+ fclose(ref_fp);
+ return -2;
+ }
+ int frame_number = 0;
+
+ // Read reference and test frames.
+ for (;;) {
+ rtc::scoped_refptr<I420Buffer> ref_i420_buffer(
+ test::ReadI420Buffer(width, height, ref_fp));
+ if (!ref_i420_buffer)
+ break;
+
+ rtc::scoped_refptr<I420Buffer> test_i420_buffer(
+ test::ReadI420Buffer(width, height, test_fp));
+
+ if (!test_i420_buffer)
+ break;
+
+ switch (video_metrics_type) {
+ case kPSNR:
+ CalculateFrame(kPSNR, *ref_i420_buffer, *test_i420_buffer, frame_number,
+ psnr_result);
+ break;
+ case kSSIM:
+ CalculateFrame(kSSIM, *ref_i420_buffer, *test_i420_buffer, frame_number,
+ ssim_result);
+ break;
+ case kBoth:
+ CalculateFrame(kPSNR, *ref_i420_buffer, *test_i420_buffer, frame_number,
+ psnr_result);
+ CalculateFrame(kSSIM, *ref_i420_buffer, *test_i420_buffer, frame_number,
+ ssim_result);
+ break;
+ }
+ frame_number++;
+ }
+ int return_code = 0;
+ if (frame_number == 0) {
+ fprintf(stderr, "Tried to measure video metrics from empty files "
+ "(reference file: %s test file: %s)\n", ref_filename,
+ test_filename);
+ return_code = -3;
+ } else {
+ CalculateStats(psnr_result);
+ CalculateStats(ssim_result);
+ }
+ fclose(ref_fp);
+ fclose(test_fp);
+ return return_code;
+}
+
+int I420MetricsFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* psnr_result,
+ QualityMetricsResult* ssim_result) {
+ assert(psnr_result != NULL);
+ assert(ssim_result != NULL);
+ return CalculateMetrics(kBoth, ref_filename, test_filename, width, height,
+ psnr_result, ssim_result);
+}
+
+int I420PSNRFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* result) {
+ assert(result != NULL);
+ return CalculateMetrics(kPSNR, ref_filename, test_filename, width, height,
+ result, NULL);
+}
+
+int I420SSIMFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* result) {
+ assert(result != NULL);
+ return CalculateMetrics(kSSIM, ref_filename, test_filename, width, height,
+ NULL, result);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.h b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.h
new file mode 100644
index 0000000000..f72ea9b7bb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.h
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#ifndef TESTSUPPORT_METRICS_VIDEO_METRICS_H_
+#define TESTSUPPORT_METRICS_VIDEO_METRICS_H_
+
+#include <limits>
+#include <vector>
+
+namespace webrtc {
+namespace test {
+
+// The highest PSNR value our algorithms will return.
+extern double kMetricsPerfectPSNR;
+
+// Contains video quality metrics result for a single frame.
+struct FrameResult {
+ int frame_number;
+ double value;
+};
+
+// Result from a PSNR/SSIM calculation operation.
+// The frames in this data structure are 0-indexed.
+struct QualityMetricsResult {
+ QualityMetricsResult() :
+ average(0.0),
+ min(std::numeric_limits<double>::max()),
+ max(std::numeric_limits<double>::min()),
+ min_frame_number(-1),
+ max_frame_number(-1)
+ {};
+ double average;
+ double min;
+ double max;
+ int min_frame_number;
+ int max_frame_number;
+ std::vector<FrameResult> frames;
+};
+
+// Calculates PSNR and SSIM values for the reference and test video files
+// (must be in I420 format). All calculated values are filled into the
+// QualityMetricsResult structs.
+//
+// PSNR values have the unit decibel (dB) where a high value means the test file
+// is similar to the reference file. The higher value, the more similar. The
+// maximum PSNR value is kMetricsInfinitePSNR. For more info about PSNR, see
+// http://en.wikipedia.org/wiki/PSNR.
+//
+// SSIM values range between -1.0 and 1.0, where 1.0 means the files are
+// identical. For more info about SSIM, see http://en.wikipedia.org/wiki/SSIM
+// This function only compares video frames up to the point when the shortest
+// video ends.
+// Return value:
+// 0 if successful, negative on errors:
+// -1 if the source file cannot be opened
+// -2 if the test file cannot be opened
+// -3 if any of the files are empty
+// -4 if any arguments are invalid.
+int I420MetricsFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* psnr_result,
+ QualityMetricsResult* ssim_result);
+
+// Calculates PSNR values for the reference and test video files (must be in
+// I420 format). All calculated values are filled into the QualityMetricsResult
+// struct.
+//
+// PSNR values have the unit decibel (dB) where a high value means the test file
+// is similar to the reference file. The higher value, the more similar. The
+// maximum PSNR value is kMetricsInfinitePSNR. For more info about PSNR, see
+// http://en.wikipedia.org/wiki/PSNR.
+//
+// This function only compares video frames up to the point when the shortest
+// video ends.
+//
+// Return value:
+// 0 if successful, negative on errors:
+// -1 if the source file cannot be opened
+// -2 if the test file cannot be opened
+// -3 if any of the files are empty
+// -4 if any arguments are invalid.
+int I420PSNRFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* result);
+
+// Calculates SSIM values for the reference and test video files (must be in
+// I420 format). All calculated values are filled into the QualityMetricsResult
+// struct.
+// SSIM values range between -1.0 and 1.0, where 1.0 means the files are
+// identical.
+// This function only compares video frames up to the point when the shortest
+// video ends.
+// For more info about SSIM, see http://en.wikipedia.org/wiki/SSIM
+//
+// Return value:
+// 0 if successful, negative on errors:
+// -1 if the source file cannot be opened
+// -2 if the test file cannot be opened
+// -3 if any of the files are empty
+// -4 if any arguments are invalid.
+int I420SSIMFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* result);
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TESTSUPPORT_METRICS_VIDEO_METRICS_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics_unittest.cc
new file mode 100644
index 0000000000..5b00458761
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics_unittest.cc
@@ -0,0 +1,147 @@
+/*
+ * 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 "test/testsupport/metrics/video_metrics.h"
+
+#include "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+
+namespace webrtc {
+
+static const int kWidth = 352;
+static const int kHeight = 288;
+
+static const int kMissingReferenceFileReturnCode = -1;
+static const int kMissingTestFileReturnCode = -2;
+static const int kEmptyFileReturnCode = -3;
+static const double kPsnrPerfectResult = 48.0;
+static const double kSsimPerfectResult = 1.0;
+
+class VideoMetricsTest: public testing::Test {
+ protected:
+ VideoMetricsTest() {
+ video_file_ = webrtc::test::ResourcePath("foreman_cif_short", "yuv");
+ }
+ virtual ~VideoMetricsTest() {}
+ void SetUp() {
+ non_existing_file_ = webrtc::test::OutputPath() +
+ "video_metrics_unittest_non_existing";
+ remove(non_existing_file_.c_str()); // To be sure it doesn't exist.
+
+ // Create an empty file:
+ empty_file_ = webrtc::test::TempFilename(
+ webrtc::test::OutputPath(), "video_metrics_unittest_empty_file");
+ FILE* dummy = fopen(empty_file_.c_str(), "wb");
+ fclose(dummy);
+ }
+ void TearDown() {
+ remove(empty_file_.c_str());
+ }
+ webrtc::test::QualityMetricsResult psnr_result_;
+ webrtc::test::QualityMetricsResult ssim_result_;
+ std::string non_existing_file_;
+ std::string empty_file_;
+ std::string video_file_;
+};
+
+// Tests that it is possible to run with the same reference as test file
+TEST_F(VideoMetricsTest, ReturnsPerfectResultForIdenticalFilesPSNR) {
+ EXPECT_EQ(0, I420PSNRFromFiles(video_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight, &psnr_result_));
+ EXPECT_EQ(kPsnrPerfectResult, psnr_result_.average);
+}
+
+TEST_F(VideoMetricsTest, ReturnsPerfectResultForIdenticalFilesSSIM) {
+ EXPECT_EQ(0, I420SSIMFromFiles(video_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+ EXPECT_EQ(kSsimPerfectResult, ssim_result_.average);
+}
+
+TEST_F(VideoMetricsTest, ReturnsPerfectResultForIdenticalFilesBothMetrics) {
+ EXPECT_EQ(0, I420MetricsFromFiles(video_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight, &psnr_result_,
+ &ssim_result_));
+ EXPECT_EQ(kPsnrPerfectResult, psnr_result_.average);
+ EXPECT_EQ(kSsimPerfectResult, ssim_result_.average);
+}
+
+// Tests that the right return code is given when the reference file is missing.
+TEST_F(VideoMetricsTest, MissingReferenceFilePSNR) {
+ EXPECT_EQ(kMissingReferenceFileReturnCode,
+ I420PSNRFromFiles(non_existing_file_.c_str(),
+ video_file_.c_str(), kWidth, kHeight,
+ &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, MissingReferenceFileSSIM) {
+ EXPECT_EQ(kMissingReferenceFileReturnCode,
+ I420SSIMFromFiles(non_existing_file_.c_str(),
+ video_file_.c_str(), kWidth, kHeight,
+ &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, MissingReferenceFileBothMetrics) {
+ EXPECT_EQ(kMissingReferenceFileReturnCode,
+ I420MetricsFromFiles(non_existing_file_.c_str(),
+ video_file_.c_str(), kWidth, kHeight,
+ &psnr_result_, &ssim_result_));
+}
+
+// Tests that the right return code is given when the test file is missing.
+TEST_F(VideoMetricsTest, MissingTestFilePSNR) {
+ EXPECT_EQ(kMissingTestFileReturnCode,
+ I420PSNRFromFiles(video_file_.c_str(), non_existing_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, MissingTestFileSSIM) {
+ EXPECT_EQ(kMissingTestFileReturnCode,
+ I420SSIMFromFiles(video_file_.c_str(), non_existing_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, MissingTestFileBothMetrics) {
+ EXPECT_EQ(kMissingTestFileReturnCode,
+ I420MetricsFromFiles(video_file_.c_str(),
+ non_existing_file_.c_str(), kWidth, kHeight,
+ &psnr_result_, &ssim_result_));
+}
+
+// Tests that the method can be executed with empty files.
+TEST_F(VideoMetricsTest, EmptyFilesPSNR) {
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420PSNRFromFiles(empty_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420PSNRFromFiles(video_file_.c_str(), empty_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, EmptyFilesSSIM) {
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420SSIMFromFiles(empty_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420SSIMFromFiles(video_file_.c_str(), empty_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, EmptyFilesBothMetrics) {
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420MetricsFromFiles(empty_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight,
+ &psnr_result_, &ssim_result_));
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420MetricsFromFiles(video_file_.c_str(), empty_file_.c_str(),
+ kWidth, kHeight,
+ &psnr_result_, &ssim_result_));
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/mock/mock_frame_reader.h b/third_party/libwebrtc/webrtc/test/testsupport/mock/mock_frame_reader.h
new file mode 100644
index 0000000000..4ba416fedf
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/mock/mock_frame_reader.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_TESTSUPPORT_MOCK_MOCK_FRAME_READER_H_
+#define TEST_TESTSUPPORT_MOCK_MOCK_FRAME_READER_H_
+
+#include "test/testsupport/frame_reader.h"
+
+#include "test/gmock.h"
+
+namespace webrtc {
+namespace test {
+
+class MockFrameReader : public FrameReader {
+ public:
+ MOCK_METHOD0(Init, bool());
+ MOCK_METHOD0(ReadFrame, rtc::scoped_refptr<I420Buffer>());
+ MOCK_METHOD0(Close, void());
+ MOCK_METHOD0(FrameLength, size_t());
+ MOCK_METHOD0(NumberOfFrames, int());
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_MOCK_MOCK_FRAME_READER_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.cc b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.cc
new file mode 100644
index 0000000000..ba52f94e57
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.cc
@@ -0,0 +1,49 @@
+/*
+ * 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 "test/testsupport/packet_reader.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <algorithm>
+
+namespace webrtc {
+namespace test {
+
+PacketReader::PacketReader()
+ : initialized_(false) {}
+
+PacketReader::~PacketReader() {}
+
+void PacketReader::InitializeReading(uint8_t* data,
+ size_t data_length_in_bytes,
+ size_t packet_size_in_bytes) {
+ assert(data);
+ assert(packet_size_in_bytes > 0);
+ data_ = data;
+ data_length_ = data_length_in_bytes;
+ packet_size_ = packet_size_in_bytes;
+ currentIndex_ = 0;
+ initialized_ = true;
+}
+
+int PacketReader::NextPacket(uint8_t** packet_pointer) {
+ if (!initialized_) {
+ fprintf(stderr, "Attempting to use uninitialized PacketReader!\n");
+ return -1;
+ }
+ *packet_pointer = data_ + currentIndex_;
+ size_t old_index = currentIndex_;
+ currentIndex_ = std::min(currentIndex_ + packet_size_, data_length_);
+ return static_cast<int>(currentIndex_ - old_index);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.h b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.h
new file mode 100644
index 0000000000..dbdb3da9e9
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_TESTSUPPORT_PACKET_READER_H_
+#define TEST_TESTSUPPORT_PACKET_READER_H_
+
+#include <cstddef>
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+// Reads chunks of data to simulate network packets from a byte array.
+class PacketReader {
+ public:
+ PacketReader();
+ virtual ~PacketReader();
+
+ // Inizializes a new reading operation. Must be done before invoking the
+ // NextPacket method.
+ // * data_length_in_bytes is the length of the data byte array.
+ // 0 length will result in no packets are read.
+ // * packet_size_in_bytes is the number of bytes to read in each NextPacket
+ // method call. Must be > 0
+ virtual void InitializeReading(uint8_t* data, size_t data_length_in_bytes,
+ size_t packet_size_in_bytes);
+
+ // Moves the supplied pointer to the beginning of the next packet.
+ // Returns:
+ // * The size of the packet ready to read (lower than the packet size for
+ // the last packet)
+ // * 0 if there are no more packets to read
+ // * -1 if InitializeReading has not been called (also prints to stderr).
+ virtual int NextPacket(uint8_t** packet_pointer);
+
+ private:
+ uint8_t* data_;
+ size_t data_length_;
+ size_t packet_size_;
+ size_t currentIndex_;
+ bool initialized_;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_PACKET_READER_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/packet_reader_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader_unittest.cc
new file mode 100644
index 0000000000..3255151d05
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader_unittest.cc
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2012 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 "test/testsupport/packet_reader.h"
+
+#include "test/gtest.h"
+#include "test/testsupport/unittest_utils.h"
+
+namespace webrtc {
+namespace test {
+
+class PacketReaderTest: public PacketRelatedTest {
+ protected:
+ PacketReaderTest() {}
+ virtual ~PacketReaderTest() {}
+ void SetUp() {
+ reader_ = new PacketReader();
+ }
+ void TearDown() {
+ delete reader_;
+ }
+ void VerifyPacketData(size_t expected_length,
+ int actual_length,
+ uint8_t* original_data_pointer,
+ uint8_t* new_data_pointer) {
+ EXPECT_EQ(static_cast<int>(expected_length), actual_length);
+ EXPECT_EQ(*original_data_pointer, *new_data_pointer);
+ EXPECT_EQ(0, memcmp(original_data_pointer, new_data_pointer,
+ actual_length));
+ }
+ PacketReader* reader_;
+};
+
+// Test lack of initialization
+TEST_F(PacketReaderTest, Uninitialized) {
+ uint8_t* data_pointer = NULL;
+ EXPECT_EQ(-1, reader_->NextPacket(&data_pointer));
+ EXPECT_EQ(NULL, data_pointer);
+}
+
+TEST_F(PacketReaderTest, InitializeZeroLengthArgument) {
+ reader_->InitializeReading(packet_data_, 0, kPacketSizeInBytes);
+ ASSERT_EQ(0, reader_->NextPacket(&packet_data_pointer_));
+}
+
+// Test with something smaller than one packet
+TEST_F(PacketReaderTest, NormalSmallData) {
+ const int kDataLengthInBytes = 1499;
+ uint8_t data[kDataLengthInBytes];
+ uint8_t* data_pointer = data;
+ memset(data, 1, kDataLengthInBytes);
+
+ reader_->InitializeReading(data, kDataLengthInBytes, kPacketSizeInBytes);
+ int length_to_read = reader_->NextPacket(&data_pointer);
+ VerifyPacketData(kDataLengthInBytes, length_to_read, data, data_pointer);
+ EXPECT_EQ(0, data_pointer - data); // pointer hasn't moved
+
+ // Reading another one shall result in 0 bytes:
+ length_to_read = reader_->NextPacket(&data_pointer);
+ EXPECT_EQ(0, length_to_read);
+ EXPECT_EQ(kDataLengthInBytes, data_pointer - data);
+}
+
+// Test with data length that exactly matches one packet
+TEST_F(PacketReaderTest, NormalOnePacketData) {
+ uint8_t data[kPacketSizeInBytes];
+ uint8_t* data_pointer = data;
+ memset(data, 1, kPacketSizeInBytes);
+
+ reader_->InitializeReading(data, kPacketSizeInBytes, kPacketSizeInBytes);
+ int length_to_read = reader_->NextPacket(&data_pointer);
+ VerifyPacketData(kPacketSizeInBytes, length_to_read, data, data_pointer);
+ EXPECT_EQ(0, data_pointer - data); // pointer hasn't moved
+
+ // Reading another one shall result in 0 bytes:
+ length_to_read = reader_->NextPacket(&data_pointer);
+ EXPECT_EQ(0, length_to_read);
+ EXPECT_EQ(kPacketSizeInBytes, static_cast<size_t>(data_pointer - data));
+}
+
+// Test with data length that will result in 3 packets
+TEST_F(PacketReaderTest, NormalLargeData) {
+ reader_->InitializeReading(packet_data_, kPacketDataLength,
+ kPacketSizeInBytes);
+
+ int length_to_read = reader_->NextPacket(&packet_data_pointer_);
+ VerifyPacketData(kPacketSizeInBytes, length_to_read,
+ packet1_, packet_data_pointer_);
+
+ length_to_read = reader_->NextPacket(&packet_data_pointer_);
+ VerifyPacketData(kPacketSizeInBytes, length_to_read,
+ packet2_, packet_data_pointer_);
+
+ length_to_read = reader_->NextPacket(&packet_data_pointer_);
+ VerifyPacketData(1u, length_to_read,
+ packet3_, packet_data_pointer_);
+
+ // Reading another one shall result in 0 bytes:
+ length_to_read = reader_->NextPacket(&packet_data_pointer_);
+ EXPECT_EQ(0, length_to_read);
+ EXPECT_EQ(kPacketDataLength,
+ static_cast<size_t>(packet_data_pointer_ - packet_data_));
+}
+
+// Test with empty data.
+TEST_F(PacketReaderTest, EmptyData) {
+ const int kDataLengthInBytes = 0;
+ // But don't really try to allocate a zero-length array...
+ uint8_t data[kPacketSizeInBytes];
+ uint8_t* data_pointer = data;
+ reader_->InitializeReading(data, kDataLengthInBytes, kPacketSizeInBytes);
+ EXPECT_EQ(kDataLengthInBytes, reader_->NextPacket(&data_pointer));
+ // Do it again to make sure nothing changes
+ EXPECT_EQ(kDataLengthInBytes, reader_->NextPacket(&data_pointer));
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/perf_test.cc b/third_party/libwebrtc/webrtc/test/testsupport/perf_test.cc
new file mode 100644
index 0000000000..b7578d101e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/perf_test.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+// A stripped-down version of Chromium's chrome/test/perf/perf_test.cc.
+// ResultsToString(), PrintResult(size_t value) and AppendResult(size_t value)
+// have been modified. The remainder are identical to the Chromium version.
+
+#include "test/testsupport/perf_test.h"
+
+#include <sstream>
+#include <stdio.h>
+#include <vector>
+
+namespace {
+
+void PrintResultsImpl(const std::string& graph_name,
+ const std::string& trace,
+ const std::string& values,
+ const std::string& units,
+ bool important) {
+ // <*>RESULT <graph_name>: <trace_name>= <value> <units>
+ // <*>RESULT <graph_name>: <trace_name>= {<mean>, <std deviation>} <units>
+ // <*>RESULT <graph_name>: <trace_name>= [<value>,value,value,...,] <units>
+
+ if (important) {
+ printf("*");
+ }
+ printf("RESULT %s: %s= %s %s\n", graph_name.c_str(), trace.c_str(),
+ values.c_str(), units.c_str());
+}
+
+} // namespace
+
+namespace webrtc {
+namespace test {
+
+void PrintResult(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const double value,
+ const std::string& units,
+ bool important) {
+ std::ostringstream value_stream;
+ value_stream << value;
+ PrintResultsImpl(measurement + modifier, trace, value_stream.str(), units,
+ important);
+}
+
+void PrintResultMeanAndError(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const double mean,
+ const double error,
+ const std::string& units,
+ bool important) {
+ std::ostringstream value_stream;
+ value_stream << '{' << mean << ',' << error << '}';
+ PrintResultsImpl(measurement + modifier, trace, value_stream.str(), units,
+ important);
+}
+
+void PrintResultList(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const std::vector<double>& values,
+ const std::string& units,
+ bool important) {
+ std::ostringstream value_stream;
+ value_stream << '[';
+ if (!values.empty()) {
+ auto it = values.begin();
+ while (true) {
+ value_stream << *it;
+ if (++it == values.end())
+ break;
+ value_stream << ',';
+ }
+ }
+ value_stream << ']';
+ PrintResultsImpl(measurement + modifier, trace, value_stream.str(), units,
+ important);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/perf_test.h b/third_party/libwebrtc/webrtc/test/testsupport/perf_test.h
new file mode 100644
index 0000000000..31b7b1345c
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/perf_test.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+// A stripped-down version of Chromium's chrome/test/perf/perf_test.h.
+// Several functions have been removed; the prototypes of the remainder have
+// not been changed.
+
+#ifndef TEST_TESTSUPPORT_PERF_TEST_H_
+#define TEST_TESTSUPPORT_PERF_TEST_H_
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace webrtc {
+namespace test {
+
+// Prints numerical information to stdout in a controlled format, for
+// post-processing. |measurement| is a description of the quantity being
+// measured, e.g. "vm_peak"; |modifier| is provided as a convenience and
+// will be appended directly to the name of the |measurement|, e.g.
+// "_browser"; |trace| is a description of the particular data point, e.g.
+// "reference"; |value| is the measured value; and |units| is a description
+// of the units of measure, e.g. "bytes". If |important| is true, the output
+// line will be specially marked, to notify the post-processor. The strings
+// may be empty. They should not contain any colons (:) or equals signs (=).
+// A typical post-processing step would be to produce graphs of the data
+// produced for various builds, using the combined |measurement| + |modifier|
+// string to specify a particular graph and the |trace| to identify a trace
+// (i.e., data series) on that graph.
+void PrintResult(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const double value,
+ const std::string& units,
+ bool important);
+
+// Like PrintResult(), but prints a (mean, standard deviation) result pair.
+// The |<values>| should be two comma-separated numbers, the mean and
+// standard deviation (or other error metric) of the measurement.
+void PrintResultMeanAndError(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const double mean,
+ const double error,
+ const std::string& units,
+ bool important);
+
+
+// Like PrintResult(), but prints an entire list of results. The |values|
+// will generally be a list of comma-separated numbers. A typical
+// post-processing step might produce plots of their mean and standard
+// deviation.
+void PrintResultList(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const std::vector<double>& values,
+ const std::string& units,
+ bool important);
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_PERF_TEST_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/perf_test_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/perf_test_unittest.cc
new file mode 100644
index 0000000000..466e2b3e69
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/perf_test_unittest.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012 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 "test/testsupport/perf_test.h"
+
+#include <string>
+
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace test {
+
+TEST(PerfTest, AppendResult) {
+ testing::internal::CaptureStdout();
+ std::string expected = "RESULT measurementmodifier: trace= 42 units\n";
+ PrintResult("measurement", "modifier", "trace", 42, "units", false);
+
+ expected += "*RESULT foobar: baz= 7 widgets\n";
+ PrintResult("foo", "bar", "baz", 7, "widgets", true);
+
+ expected += "RESULT foobar: baz= {1,2} lemurs\n";
+ PrintResultMeanAndError("foo", "bar", "baz", 1, 2, "lemurs", false);
+
+ expected += "RESULT foobar: baz= [1,2,3] units\n";
+ PrintResultList("foo", "bar", "baz", {1, 2, 3}, "units", false);
+
+ std::string output = testing::internal::GetCapturedStdout();
+ EXPECT_EQ(expected, output);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.cc b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.cc
new file mode 100644
index 0000000000..3d97a94472
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.cc
@@ -0,0 +1,70 @@
+/*
+ * 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 "test/testsupport/test_artifacts.h"
+
+#include <string.h>
+
+#include "rtc_base/file.h"
+#include "rtc_base/flags.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/pathutils.h"
+#include "test/testsupport/fileutils.h"
+
+namespace {
+const std::string& DefaultArtifactPath() {
+ static const std::string path = webrtc::test::OutputPath();
+ return path;
+}
+}
+
+DEFINE_string(test_artifacts_dir,
+ DefaultArtifactPath().c_str(),
+ "The output folder where test output should be saved.");
+
+namespace webrtc {
+namespace test {
+
+bool GetTestArtifactsDir(std::string* out_dir) {
+ if (strlen(FLAG_test_artifacts_dir) == 0) {
+ RTC_LOG(LS_WARNING) << "No test_out_dir defined.";
+ return false;
+ }
+ *out_dir = FLAG_test_artifacts_dir;
+ return true;
+}
+
+bool WriteToTestArtifactsDir(const char* filename,
+ const uint8_t* buffer,
+ size_t length) {
+ if (strlen(FLAG_test_artifacts_dir) == 0) {
+ RTC_LOG(LS_WARNING) << "No test_out_dir defined.";
+ return false;
+ }
+
+ if (filename == nullptr || strlen(filename) == 0) {
+ RTC_LOG(LS_WARNING) << "filename must be provided.";
+ return false;
+ }
+
+ rtc::File output =
+ rtc::File::Create(rtc::Pathname(FLAG_test_artifacts_dir, filename));
+
+ return output.IsOpen() && output.Write(buffer, length) == length;
+}
+
+bool WriteToTestArtifactsDir(const char* filename, const std::string& content) {
+ return WriteToTestArtifactsDir(
+ filename, reinterpret_cast<const uint8_t*>(content.c_str()),
+ content.length());
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.h b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.h
new file mode 100644
index 0000000000..ee07a9be52
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#ifndef TEST_TESTSUPPORT_TEST_ARTIFACTS_H_
+#define TEST_TESTSUPPORT_TEST_ARTIFACTS_H_
+
+#include <stdlib.h>
+
+#include <string>
+
+namespace webrtc {
+namespace test {
+
+// If the test_artifacts_dir flag is set, returns true and copies the location
+// of the dir to |out_dir|. Otherwise, return false.
+bool GetTestArtifactsDir(std::string* out_dir);
+
+// Writes a |length| bytes array |buffer| to |filename| in isolated output
+// directory defined by swarming. If the file is existing, content will be
+// appended. Otherwise a new file will be created. This function returns false
+// if isolated output directory has not been defined, or |filename| indicates an
+// invalid or non-writable file, or underlying file system errors.
+bool WriteToTestArtifactsDir(const char* filename,
+ const uint8_t* buffer,
+ size_t length);
+
+bool WriteToTestArtifactsDir(const char* filename, const std::string& content);
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_TEST_ARTIFACTS_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts_unittest.cc
new file mode 100644
index 0000000000..251c5cde88
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts_unittest.cc
@@ -0,0 +1,61 @@
+/*
+ * 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 "test/testsupport/test_artifacts.h"
+
+#include <string.h>
+
+#include <string>
+
+#include "rtc_base/file.h"
+#include "rtc_base/flags.h"
+#include "rtc_base/pathutils.h"
+#include "rtc_base/platform_file.h"
+#include "test/gtest.h"
+
+DECLARE_string(test_artifacts_dir);
+
+namespace webrtc {
+namespace test {
+
+TEST(IsolatedOutputTest, ShouldRejectInvalidIsolatedOutDir) {
+ const char* backup = FLAG_test_artifacts_dir;
+ FLAG_test_artifacts_dir = "";
+ ASSERT_FALSE(WriteToTestArtifactsDir("a-file", "some-contents"));
+ FLAG_test_artifacts_dir = backup;
+}
+
+TEST(IsolatedOutputTest, ShouldRejectInvalidFileName) {
+ ASSERT_FALSE(WriteToTestArtifactsDir(nullptr, "some-contents"));
+ ASSERT_FALSE(WriteToTestArtifactsDir("", "some-contents"));
+}
+
+// Sets isolated_out_dir=<a-writable-path> to execute this test.
+TEST(IsolatedOutputTest, ShouldBeAbleToWriteContent) {
+ const char* filename = "a-file";
+ const char* content = "some-contents";
+ if (WriteToTestArtifactsDir(filename, content)) {
+ rtc::Pathname out_file(FLAG_test_artifacts_dir, filename);
+ rtc::File input = rtc::File::Open(out_file);
+ EXPECT_TRUE(input.IsOpen());
+ EXPECT_TRUE(input.Seek(0));
+ uint8_t buffer[32];
+ EXPECT_EQ(input.Read(buffer, strlen(content)), strlen(content));
+ buffer[strlen(content)] = 0;
+ EXPECT_EQ(std::string(content),
+ std::string(reinterpret_cast<char*>(buffer)));
+ input.Close();
+
+ EXPECT_TRUE(rtc::File::Remove(out_file));
+ }
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/unittest_utils.h b/third_party/libwebrtc/webrtc/test/testsupport/unittest_utils.h
new file mode 100644
index 0000000000..5fee2ca454
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/unittest_utils.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012 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.
+ */
+
+#ifndef TEST_TESTSUPPORT_UNITTEST_UTILS_H_
+#define TEST_TESTSUPPORT_UNITTEST_UTILS_H_
+
+namespace webrtc {
+namespace test {
+
+const size_t kPacketSizeInBytes = 1500;
+const size_t kPacketDataLength = kPacketSizeInBytes * 2 + 1;
+const int kPacketDataNumberOfPackets = 3;
+
+// A base test fixture for packet related tests. Contains
+// two full prepared packets with 1s, 2s in their data and a third packet with
+// a single 3 in it (size=1).
+// A packet data structure is also available, that contains these three packets
+// in order.
+class PacketRelatedTest: public testing::Test {
+ protected:
+ // Tree packet byte arrays with data used for verification:
+ uint8_t packet1_[kPacketSizeInBytes];
+ uint8_t packet2_[kPacketSizeInBytes];
+ uint8_t packet3_[1];
+ // Construct a data structure containing these packets
+ uint8_t packet_data_[kPacketDataLength];
+ uint8_t* packet_data_pointer_;
+
+ PacketRelatedTest() {
+ packet_data_pointer_ = packet_data_;
+
+ memset(packet1_, 1, kPacketSizeInBytes);
+ memset(packet2_, 2, kPacketSizeInBytes);
+ memset(packet3_, 3, 1);
+ // Fill the packet_data:
+ memcpy(packet_data_pointer_, packet1_, kPacketSizeInBytes);
+ memcpy(packet_data_pointer_ + kPacketSizeInBytes, packet2_,
+ kPacketSizeInBytes);
+ memcpy(packet_data_pointer_ + kPacketSizeInBytes * 2, packet3_, 1);
+ }
+ virtual ~PacketRelatedTest() {}
+ void SetUp() {}
+ void TearDown() {}
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_UNITTEST_UTILS_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer.cc b/third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer.cc
new file mode 100644
index 0000000000..e0c1ed54ba
--- /dev/null
+++ b/third_party/libwebrtc/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 "rtc_base/checks.h"
+#include "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/third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer_unittest.cc
new file mode 100644
index 0000000000..d9ec09a2b7
--- /dev/null
+++ b/third_party/libwebrtc/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 "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+#include "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/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader.cc b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader.cc
new file mode 100644
index 0000000000..60f9994b14
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader.cc
@@ -0,0 +1,91 @@
+/*
+ * 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 "test/testsupport/frame_reader.h"
+
+#include "api/video/i420_buffer.h"
+#include "test/frame_utils.h"
+#include "test/testsupport/fileutils.h"
+
+namespace webrtc {
+namespace test {
+
+YuvFrameReaderImpl::YuvFrameReaderImpl(std::string input_filename,
+ int width,
+ int height)
+ : input_filename_(input_filename),
+ frame_length_in_bytes_(0),
+ width_(width),
+ height_(height),
+ number_of_frames_(-1),
+ input_file_(nullptr) {}
+
+YuvFrameReaderImpl::~YuvFrameReaderImpl() {
+ Close();
+}
+
+bool YuvFrameReaderImpl::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);
+
+ input_file_ = fopen(input_filename_.c_str(), "rb");
+ if (input_file_ == nullptr) {
+ fprintf(stderr, "Couldn't open input file for reading: %s\n",
+ input_filename_.c_str());
+ return false;
+ }
+ // Calculate total number of frames.
+ size_t source_file_size = GetFileSize(input_filename_);
+ if (source_file_size <= 0u) {
+ 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_);
+ return true;
+}
+
+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(
+ ReadI420Buffer(width_, height_, input_file_));
+ if (!buffer && ferror(input_file_)) {
+ fprintf(stderr, "Error reading from input file: %s\n",
+ input_filename_.c_str());
+ }
+ return buffer;
+}
+
+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/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader_unittest.cc
new file mode 100644
index 0000000000..dd4b980c71
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader_unittest.cc
@@ -0,0 +1,82 @@
+/*
+ * 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 "api/video/i420_buffer.h"
+#include "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+#include "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<I420BufferInterface> 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/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer.cc b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer.cc
new file mode 100644
index 0000000000..1bd343c513
--- /dev/null
+++ b/third_party/libwebrtc/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 "rtc_base/checks.h"
+#include "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/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer_unittest.cc
new file mode 100644
index 0000000000..49b595e1da
--- /dev/null
+++ b/third_party/libwebrtc/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 "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+#include "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