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 | */ |
| 11 | #ifndef TEST_VIDEO_SOURCE_H_ |
| 12 | #define 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 |
Deb Mukherjee | a463513 | 2014-08-11 13:44:27 -0700 | [diff] [blame] | 74 | return tmpfile(); |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 75 | #endif |
Deb Mukherjee | 5820c5d | 2014-06-12 16:53:13 -0700 | [diff] [blame] | 76 | } |
| 77 | |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 78 | class TempOutFile { |
| 79 | public: |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 80 | TempOutFile() { file_ = GetTempOutFile(&file_name_); } |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 81 | ~TempOutFile() { |
| 82 | CloseFile(); |
| 83 | if (!file_name_.empty()) { |
Deb Mukherjee | a463513 | 2014-08-11 13:44:27 -0700 | [diff] [blame] | 84 | EXPECT_EQ(0, remove(file_name_.c_str())); |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 85 | } |
| 86 | } |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 87 | FILE *file() { return file_; } |
| 88 | const std::string &file_name() { return file_name_; } |
Deb Mukherjee | a463513 | 2014-08-11 13:44:27 -0700 | [diff] [blame] | 89 | |
| 90 | protected: |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 91 | void CloseFile() { |
| 92 | if (file_) { |
Deb Mukherjee | 4851b99 | 2014-08-14 14:59:50 -0700 | [diff] [blame] | 93 | fclose(file_); |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 94 | file_ = NULL; |
| 95 | } |
| 96 | } |
Deb Mukherjee | 096224f | 2014-07-14 13:31:29 -0700 | [diff] [blame] | 97 | FILE *file_; |
| 98 | std::string file_name_; |
| 99 | }; |
| 100 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 101 | // Abstract base class for test video sources, which provide a stream of |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 102 | // aom_image_t images with associated timestamps and duration. |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 103 | class VideoSource { |
| 104 | public: |
| 105 | virtual ~VideoSource() {} |
| 106 | |
| 107 | // Prepare the stream for reading, rewind/open as necessary. |
| 108 | virtual void Begin() = 0; |
| 109 | |
| 110 | // Advance the cursor to the next frame |
| 111 | virtual void Next() = 0; |
| 112 | |
| 113 | // Get the current video frame, or NULL on End-Of-Stream. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 114 | virtual aom_image_t *img() const = 0; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 115 | |
| 116 | // Get the presentation timestamp of the current frame. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 117 | virtual aom_codec_pts_t pts() const = 0; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 118 | |
| 119 | // Get the current frame's duration |
| 120 | virtual unsigned long duration() const = 0; |
| 121 | |
| 122 | // Get the timebase for the stream |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 123 | virtual aom_rational_t timebase() const = 0; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 124 | |
| 125 | // Get the current frame counter, starting at 0. |
| 126 | virtual unsigned int frame() const = 0; |
Jim Bankoski | 65d7388 | 2012-10-26 19:49:44 -0700 | [diff] [blame] | 127 | |
| 128 | // Get the current file limit. |
| 129 | virtual unsigned int limit() const = 0; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 130 | }; |
| 131 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 132 | class DummyVideoSource : public VideoSource { |
| 133 | public: |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 134 | DummyVideoSource() |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 135 | : img_(NULL), limit_(100), width_(80), height_(64), |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 136 | format_(AOM_IMG_FMT_I420) { |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 137 | ReallocImage(); |
John Koleszar | 2fb29ff | 2012-05-23 12:55:27 -0700 | [diff] [blame] | 138 | } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 139 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 140 | virtual ~DummyVideoSource() { aom_img_free(img_); } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 141 | |
| 142 | virtual void Begin() { |
| 143 | frame_ = 0; |
| 144 | FillFrame(); |
| 145 | } |
| 146 | |
| 147 | virtual void Next() { |
| 148 | ++frame_; |
| 149 | FillFrame(); |
| 150 | } |
| 151 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 152 | virtual aom_image_t *img() const { return (frame_ < limit_) ? img_ : NULL; } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 153 | |
| 154 | // Models a stream where Timebase = 1/FPS, so pts == frame. |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 155 | virtual aom_codec_pts_t pts() const { return frame_; } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 156 | |
| 157 | virtual unsigned long duration() const { return 1; } |
| 158 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 159 | virtual aom_rational_t timebase() const { |
| 160 | const aom_rational_t t = { 1, 30 }; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 161 | return t; |
| 162 | } |
| 163 | |
| 164 | virtual unsigned int frame() const { return frame_; } |
| 165 | |
Jim Bankoski | 65d7388 | 2012-10-26 19:49:44 -0700 | [diff] [blame] | 166 | virtual unsigned int limit() const { return limit_; } |
| 167 | |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 168 | void set_limit(unsigned int limit) { limit_ = limit; } |
Jim Bankoski | 943e432 | 2014-07-17 06:31:50 -0700 | [diff] [blame] | 169 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 170 | void SetSize(unsigned int width, unsigned int height) { |
John Koleszar | 2fb29ff | 2012-05-23 12:55:27 -0700 | [diff] [blame] | 171 | if (width != width_ || height != height_) { |
John Koleszar | 2fb29ff | 2012-05-23 12:55:27 -0700 | [diff] [blame] | 172 | width_ = width; |
| 173 | height_ = height; |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 174 | ReallocImage(); |
| 175 | } |
| 176 | } |
| 177 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 178 | void SetImageFormat(aom_img_fmt_t format) { |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 179 | if (format_ != format) { |
| 180 | format_ = format; |
| 181 | ReallocImage(); |
John Koleszar | 2fb29ff | 2012-05-23 12:55:27 -0700 | [diff] [blame] | 182 | } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | protected: |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 186 | virtual void FillFrame() { |
| 187 | if (img_) memset(img_->img_data, 0, raw_sz_); |
| 188 | } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 189 | |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 190 | void ReallocImage() { |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 191 | aom_img_free(img_); |
| 192 | img_ = aom_img_alloc(NULL, format_, width_, height_, 32); |
Alex Converse | 797a255 | 2015-01-15 13:56:55 -0800 | [diff] [blame] | 193 | raw_sz_ = ((img_->w + 31) & ~31) * img_->h * img_->bps / 8; |
| 194 | } |
| 195 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 196 | aom_image_t *img_; |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 197 | size_t raw_sz_; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 198 | unsigned int limit_; |
| 199 | unsigned int frame_; |
John Koleszar | 2fb29ff | 2012-05-23 12:55:27 -0700 | [diff] [blame] | 200 | unsigned int width_; |
| 201 | unsigned int height_; |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 202 | aom_img_fmt_t format_; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 203 | }; |
| 204 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 205 | class RandomVideoSource : public DummyVideoSource { |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 206 | public: |
Johann | 9ec2552 | 2012-07-23 15:06:12 -0700 | [diff] [blame] | 207 | RandomVideoSource(int seed = ACMRandom::DeterministicSeed()) |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 208 | : rnd_(seed), seed_(seed) {} |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 209 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 210 | protected: |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 211 | // Reset the RNG to get a matching stream for the second pass |
| 212 | virtual void Begin() { |
| 213 | frame_ = 0; |
Johann | 9ec2552 | 2012-07-23 15:06:12 -0700 | [diff] [blame] | 214 | rnd_.Reset(seed_); |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 215 | FillFrame(); |
| 216 | } |
| 217 | |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 218 | // 15 frames of noise, followed by 15 static frames. Reset to 0 rather |
| 219 | // than holding previous frames to encourage keyframes to be thrown. |
| 220 | virtual void FillFrame() { |
Deb Mukherjee | bdbaa5b | 2014-07-18 03:06:07 -0700 | [diff] [blame] | 221 | if (img_) { |
| 222 | if (frame_ % 30 < 15) |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 223 | 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] | 224 | else |
| 225 | memset(img_->img_data, 0, raw_sz_); |
| 226 | } |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 227 | } |
Johann | e3e63fb | 2012-07-23 14:55:32 -0700 | [diff] [blame] | 228 | |
| 229 | ACMRandom rnd_; |
Johann | 9ec2552 | 2012-07-23 15:06:12 -0700 | [diff] [blame] | 230 | int seed_; |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 231 | }; |
| 232 | |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 233 | // Abstract base class for test video sources, which provide a stream of |
| 234 | // decompressed images to the decoder. |
| 235 | class CompressedVideoSource { |
| 236 | public: |
| 237 | virtual ~CompressedVideoSource() {} |
| 238 | |
| 239 | virtual void Init() = 0; |
| 240 | |
| 241 | // Prepare the stream for reading, rewind/open as necessary. |
| 242 | virtual void Begin() = 0; |
| 243 | |
| 244 | // Advance the cursor to the next frame |
| 245 | virtual void Next() = 0; |
| 246 | |
| 247 | virtual const uint8_t *cxdata() const = 0; |
| 248 | |
Tom Finegan | eb2325e | 2014-02-19 14:17:55 -0800 | [diff] [blame] | 249 | virtual size_t frame_size() const = 0; |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 250 | |
Tom Finegan | eb2325e | 2014-02-19 14:17:55 -0800 | [diff] [blame] | 251 | virtual unsigned int frame_number() const = 0; |
Yunqing Wang | 15dffcf | 2012-10-04 12:59:36 -0700 | [diff] [blame] | 252 | }; |
| 253 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 254 | } // namespace libaom_test |
John Koleszar | b9180fc | 2012-05-16 15:27:00 -0700 | [diff] [blame] | 255 | |
| 256 | #endif // TEST_VIDEO_SOURCE_H_ |