John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 1 | /* |
Yaowu Xu | 2ab7ff0 | 2016-09-02 12:04:54 -0700 | [diff] [blame] | 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 3 | * |
Yaowu Xu | 2ab7ff0 | 2016-09-02 12:04:54 -0700 | [diff] [blame] | 4 | * This source code is subject to the terms of the BSD 2 Clause License and |
| 5 | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 6 | * was not distributed with this source code in the LICENSE file, you can |
| 7 | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 8 | * Media Patent License 1.0 was not distributed with this source code in the |
| 9 | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 10 | */ |
James Zern | e1cbb13 | 2018-08-22 14:10:36 -0700 | [diff] [blame] | 11 | #ifndef AOM_TEST_VIDEO_SOURCE_H_ |
| 12 | #define AOM_TEST_VIDEO_SOURCE_H_ |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 13 | |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 14 | #if defined(_WIN32) |
James Zern | 18bd24b | 2015-10-06 23:05:15 -0700 | [diff] [blame] | 15 | #undef NOMINMAX |
James Zern | 5d91201 | 2015-09-29 20:28:47 -0700 | [diff] [blame] | 16 | #define NOMINMAX |
| 17 | #define WIN32_LEAN_AND_MEAN |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 18 | #include <windows.h> |
| 19 | #endif |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 20 | #include <cstdio> |
| 21 | #include <cstdlib> |
| 22 | #include <string> |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 23 | #include "test/acm_random.h" |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 24 | #include "aom/aom_encoder.h" |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 25 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 26 | namespace libaom_test { |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 27 | |
Yaowu Xu | 97aa09f | 2016-10-12 08:25:39 -0700 | [diff] [blame] | 28 | // Helper macros to ensure LIBAOM_TEST_DATA_PATH is a quoted string. |
Joshua Litt | ab9160d | 2013-11-04 13:47:30 -0800 | [diff] [blame] | 29 | // These are undefined right below GetDataPath |
Yaowu Xu | 97aa09f | 2016-10-12 08:25:39 -0700 | [diff] [blame] | 30 | // NOTE: LIBAOM_TEST_DATA_PATH MUST NOT be a quoted string before |
Joshua Litt | ab9160d | 2013-11-04 13:47:30 -0800 | [diff] [blame] | 31 | // Stringification or the GetDataPath will fail at runtime |
| 32 | #define TO_STRING(S) #S |
| 33 | #define STRINGIFY(S) TO_STRING(S) |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 34 | |
Joshua Litt | ab9160d | 2013-11-04 13:47:30 -0800 | [diff] [blame] | 35 | // A simple function to encapsulate cross platform retrieval of test data path |
| 36 | static std::string GetDataPath() { |
Yaowu Xu | 97aa09f | 2016-10-12 08:25:39 -0700 | [diff] [blame] | 37 | const char *const data_path = getenv("LIBAOM_TEST_DATA_PATH"); |
Joshua Litt | ab9160d | 2013-11-04 13:47:30 -0800 | [diff] [blame] | 38 | if (data_path == NULL) { |
Yaowu Xu | 97aa09f | 2016-10-12 08:25:39 -0700 | [diff] [blame] | 39 | #ifdef LIBAOM_TEST_DATA_PATH |
Joshua Litt | ab9160d | 2013-11-04 13:47:30 -0800 | [diff] [blame] | 40 | // In some environments, we cannot set environment variables |
| 41 | // Instead, we set the data path by using a preprocessor symbol |
| 42 | // which can be set from make files |
Yaowu Xu | 97aa09f | 2016-10-12 08:25:39 -0700 | [diff] [blame] | 43 | return STRINGIFY(LIBAOM_TEST_DATA_PATH); |
Joshua Litt | ab9160d | 2013-11-04 13:47:30 -0800 | [diff] [blame] | 44 | #else |
| 45 | return "."; |
| 46 | #endif |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 47 | } |
Joshua Litt | ab9160d | 2013-11-04 13:47:30 -0800 | [diff] [blame] | 48 | return data_path; |
| 49 | } |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 50 | |
Joshua Litt | ab9160d | 2013-11-04 13:47:30 -0800 | [diff] [blame] | 51 | // Undefining stringification macros because they are not used elsewhere |
| 52 | #undef TO_STRING |
| 53 | #undef STRINGIFY |
| 54 | |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 55 | inline FILE *OpenTestDataFile(const std::string &file_name) { |
Joshua Litt | ab9160d | 2013-11-04 13:47:30 -0800 | [diff] [blame] | 56 | const std::string path_to_source = GetDataPath() + "/" + file_name; |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 57 | return fopen(path_to_source.c_str(), "rb"); |
| 58 | } |
| 59 | |
Deb Mukherjee | a463513 | 2014-08-11 13:44:27 -0700 | [diff] [blame] | 60 | static FILE *GetTempOutFile(std::string *file_name) { |
| 61 | file_name->clear(); |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 62 | #if defined(_WIN32) |
| 63 | char fname[MAX_PATH]; |
Deb Mukherjee | a463513 | 2014-08-11 13:44:27 -0700 | [diff] [blame] | 64 | char tmppath[MAX_PATH]; |
| 65 | if (GetTempPathA(MAX_PATH, tmppath)) { |
| 66 | // Assume for now that the filename generated is unique per process |
| 67 | if (GetTempFileNameA(tmppath, "lvx", 0, fname)) { |
| 68 | file_name->assign(fname); |
| 69 | return fopen(fname, "wb+"); |
| 70 | } |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 71 | } |
Deb Mukherjee | a463513 | 2014-08-11 13:44:27 -0700 | [diff] [blame] | 72 | return NULL; |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 73 | #else |
Neil Birkbeck | eb895ef | 2018-03-14 17:51:03 -0700 | [diff] [blame] | 74 | char name_template[] = "/tmp/libaomtest.XXXXXX"; |
| 75 | const int fd = mkstemp(name_template); |
| 76 | *file_name = name_template; |
| 77 | return fdopen(fd, "wb+"); |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 78 | #endif |
Deb Mukherjee | 5820c5d | 2014-06-12 16:53:13 -0700 | [diff] [blame] | 79 | } |
| 80 | |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 81 | class TempOutFile { |
| 82 | public: |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 83 | TempOutFile() { file_ = GetTempOutFile(&file_name_); } |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 84 | ~TempOutFile() { |
| 85 | CloseFile(); |
| 86 | if (!file_name_.empty()) { |
Deb Mukherjee | a463513 | 2014-08-11 13:44:27 -0700 | [diff] [blame] | 87 | EXPECT_EQ(0, remove(file_name_.c_str())); |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 88 | } |
| 89 | } |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 90 | FILE *file() { return file_; } |
| 91 | const std::string &file_name() { return file_name_; } |
Deb Mukherjee | a463513 | 2014-08-11 13:44:27 -0700 | [diff] [blame] | 92 | |
| 93 | protected: |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 94 | void CloseFile() { |
| 95 | if (file_) { |
Deb Mukherjee | 4851b99 | 2014-08-14 14:59:50 -0700 | [diff] [blame] | 96 | fclose(file_); |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 97 | file_ = NULL; |
| 98 | } |
| 99 | } |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 100 | FILE *file_; |
| 101 | std::string file_name_; |
| 102 | }; |
| 103 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 104 | // Abstract base class for test video sources, which provide a stream of |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 105 | // aom_image_t images with associated timestamps and duration. |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 106 | class VideoSource { |
| 107 | public: |
| 108 | virtual ~VideoSource() {} |
| 109 | |
| 110 | // Prepare the stream for reading, rewind/open as necessary. |
| 111 | virtual void Begin() = 0; |
| 112 | |
| 113 | // Advance the cursor to the next frame |
| 114 | virtual void Next() = 0; |
| 115 | |
| 116 | // Get the current video frame, or NULL on End-Of-Stream. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 117 | virtual aom_image_t *img() const = 0; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 118 | |
| 119 | // Get the presentation timestamp of the current frame. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 120 | virtual aom_codec_pts_t pts() const = 0; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 121 | |
| 122 | // Get the current frame's duration |
| 123 | virtual unsigned long duration() const = 0; |
| 124 | |
| 125 | // Get the timebase for the stream |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 126 | virtual aom_rational_t timebase() const = 0; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 127 | |
| 128 | // Get the current frame counter, starting at 0. |
| 129 | virtual unsigned int frame() const = 0; |
Jim Bankoski | 65d7388 | 2012-10-26 19:49:44 -0700 | [diff] [blame] | 130 | |
| 131 | // Get the current file limit. |
| 132 | virtual unsigned int limit() const = 0; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 133 | }; |
| 134 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 135 | class DummyVideoSource : public VideoSource { |
| 136 | public: |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 137 | DummyVideoSource() |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 138 | : img_(NULL), limit_(100), width_(80), height_(64), |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 139 | format_(AOM_IMG_FMT_I420) { |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 140 | ReallocImage(); |
John Koleszar | 2fb29ff | 2012-05-23 12:55:27 -0700 | [diff] [blame] | 141 | } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 142 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 143 | virtual ~DummyVideoSource() { aom_img_free(img_); } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 144 | |
| 145 | virtual void Begin() { |
| 146 | frame_ = 0; |
| 147 | FillFrame(); |
| 148 | } |
| 149 | |
| 150 | virtual void Next() { |
| 151 | ++frame_; |
| 152 | FillFrame(); |
| 153 | } |
| 154 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 155 | virtual aom_image_t *img() const { return (frame_ < limit_) ? img_ : NULL; } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 156 | |
| 157 | // Models a stream where Timebase = 1/FPS, so pts == frame. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 158 | virtual aom_codec_pts_t pts() const { return frame_; } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 159 | |
| 160 | virtual unsigned long duration() const { return 1; } |
| 161 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 162 | virtual aom_rational_t timebase() const { |
| 163 | const aom_rational_t t = { 1, 30 }; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 164 | return t; |
| 165 | } |
| 166 | |
| 167 | virtual unsigned int frame() const { return frame_; } |
| 168 | |
Jim Bankoski | 65d7388 | 2012-10-26 19:49:44 -0700 | [diff] [blame] | 169 | virtual unsigned int limit() const { return limit_; } |
| 170 | |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 171 | void set_limit(unsigned int limit) { limit_ = limit; } |
Jim Bankoski | 943e432 | 2014-07-17 06:31:50 -0700 | [diff] [blame] | 172 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 173 | void SetSize(unsigned int width, unsigned int height) { |
John Koleszar | 2fb29ff | 2012-05-23 12:55:27 -0700 | [diff] [blame] | 174 | if (width != width_ || height != height_) { |
John Koleszar | 2fb29ff | 2012-05-23 12:55:27 -0700 | [diff] [blame] | 175 | width_ = width; |
| 176 | height_ = height; |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 177 | ReallocImage(); |
| 178 | } |
| 179 | } |
| 180 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 181 | void SetImageFormat(aom_img_fmt_t format) { |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 182 | if (format_ != format) { |
| 183 | format_ = format; |
| 184 | ReallocImage(); |
John Koleszar | 2fb29ff | 2012-05-23 12:55:27 -0700 | [diff] [blame] | 185 | } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 186 | } |
| 187 | |
| 188 | protected: |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 189 | virtual void FillFrame() { |
| 190 | if (img_) memset(img_->img_data, 0, raw_sz_); |
| 191 | } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 192 | |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 193 | void ReallocImage() { |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 194 | aom_img_free(img_); |
| 195 | img_ = aom_img_alloc(NULL, format_, width_, height_, 32); |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 196 | raw_sz_ = ((img_->w + 31) & ~31) * img_->h * img_->bps / 8; |
| 197 | } |
| 198 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 199 | aom_image_t *img_; |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 200 | size_t raw_sz_; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 201 | unsigned int limit_; |
| 202 | unsigned int frame_; |
John Koleszar | 2fb29ff | 2012-05-23 12:55:27 -0700 | [diff] [blame] | 203 | unsigned int width_; |
| 204 | unsigned int height_; |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 205 | aom_img_fmt_t format_; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 206 | }; |
| 207 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 208 | class RandomVideoSource : public DummyVideoSource { |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 209 | public: |
Johann | 9ec2552 | 2012-07-23 15:06:12 -0700 | [diff] [blame] | 210 | RandomVideoSource(int seed = ACMRandom::DeterministicSeed()) |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 211 | : rnd_(seed), seed_(seed) {} |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 212 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 213 | protected: |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 214 | // Reset the RNG to get a matching stream for the second pass |
| 215 | virtual void Begin() { |
| 216 | frame_ = 0; |
Johann | 9ec2552 | 2012-07-23 15:06:12 -0700 | [diff] [blame] | 217 | rnd_.Reset(seed_); |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 218 | FillFrame(); |
| 219 | } |
| 220 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 221 | // 15 frames of noise, followed by 15 static frames. Reset to 0 rather |
| 222 | // than holding previous frames to encourage keyframes to be thrown. |
| 223 | virtual void FillFrame() { |
Deb Mukherjee | bdbaa5b | 2014-07-18 03:06:07 -0700 | [diff] [blame] | 224 | if (img_) { |
| 225 | if (frame_ % 30 < 15) |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 226 | for (size_t i = 0; i < raw_sz_; ++i) img_->img_data[i] = rnd_.Rand8(); |
Deb Mukherjee | bdbaa5b | 2014-07-18 03:06:07 -0700 | [diff] [blame] | 227 | else |
| 228 | memset(img_->img_data, 0, raw_sz_); |
| 229 | } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 230 | } |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 231 | |
| 232 | ACMRandom rnd_; |
Johann | 9ec2552 | 2012-07-23 15:06:12 -0700 | [diff] [blame] | 233 | int seed_; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 234 | }; |
| 235 | |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 236 | // Abstract base class for test video sources, which provide a stream of |
| 237 | // decompressed images to the decoder. |
| 238 | class CompressedVideoSource { |
| 239 | public: |
| 240 | virtual ~CompressedVideoSource() {} |
| 241 | |
| 242 | virtual void Init() = 0; |
| 243 | |
| 244 | // Prepare the stream for reading, rewind/open as necessary. |
| 245 | virtual void Begin() = 0; |
| 246 | |
| 247 | // Advance the cursor to the next frame |
| 248 | virtual void Next() = 0; |
| 249 | |
| 250 | virtual const uint8_t *cxdata() const = 0; |
| 251 | |
Tom Finegan | eb2325e | 2014-02-19 14:17:55 -0800 | [diff] [blame] | 252 | virtual size_t frame_size() const = 0; |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 253 | |
Tom Finegan | eb2325e | 2014-02-19 14:17:55 -0800 | [diff] [blame] | 254 | virtual unsigned int frame_number() const = 0; |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 255 | }; |
| 256 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 257 | } // namespace libaom_test |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 258 | |
James Zern | e1cbb13 | 2018-08-22 14:10:36 -0700 | [diff] [blame] | 259 | #endif // AOM_TEST_VIDEO_SOURCE_H_ |