1/* 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10#ifndef TEST_VIDEO_SOURCE_H_ 11#define TEST_VIDEO_SOURCE_H_ 12 13#if defined(_WIN32) 14#include <windows.h> 15#endif 16#include <cstdio> 17#include <cstdlib> 18#include <string> 19#include "test/acm_random.h" 20#include "vpx/vpx_encoder.h" 21 22namespace libvpx_test { 23 24// Helper macros to ensure LIBVPX_TEST_DATA_PATH is a quoted string. 25// These are undefined right below GetDataPath 26// NOTE: LIBVPX_TEST_DATA_PATH MUST NOT be a quoted string before 27// Stringification or the GetDataPath will fail at runtime 28#define TO_STRING(S) #S 29#define STRINGIFY(S) TO_STRING(S) 30 31// A simple function to encapsulate cross platform retrieval of test data path 32static std::string GetDataPath() { 33 const char *const data_path = getenv("LIBVPX_TEST_DATA_PATH"); 34 if (data_path == NULL) { 35#ifdef LIBVPX_TEST_DATA_PATH 36 // In some environments, we cannot set environment variables 37 // Instead, we set the data path by using a preprocessor symbol 38 // which can be set from make files 39 return STRINGIFY(LIBVPX_TEST_DATA_PATH); 40#else 41 return "."; 42#endif 43 } 44 return data_path; 45} 46 47// Undefining stringification macros because they are not used elsewhere 48#undef TO_STRING 49#undef STRINGIFY 50 51static FILE *OpenTestDataFile(const std::string& file_name) { 52 const std::string path_to_source = GetDataPath() + "/" + file_name; 53 return fopen(path_to_source.c_str(), "rb"); 54} 55 56static FILE *GetTempOutFile(std::string *file_name) { 57 file_name->clear(); 58#if defined(_WIN32) 59 char fname[MAX_PATH]; 60 char tmppath[MAX_PATH]; 61 if (GetTempPathA(MAX_PATH, tmppath)) { 62 // Assume for now that the filename generated is unique per process 63 if (GetTempFileNameA(tmppath, "lvx", 0, fname)) { 64 file_name->assign(fname); 65 return fopen(fname, "wb+"); 66 } 67 } 68 return NULL; 69#else 70 return tmpfile(); 71#endif 72} 73 74class TempOutFile { 75 public: 76 TempOutFile() { 77 file_ = GetTempOutFile(&file_name_); 78 } 79 ~TempOutFile() { 80 CloseFile(); 81 if (!file_name_.empty()) { 82 EXPECT_EQ(0, remove(file_name_.c_str())); 83 } 84 } 85 FILE *file() { 86 return file_; 87 } 88 const std::string& file_name() { 89 return file_name_; 90 } 91 92 protected: 93 void CloseFile() { 94 if (file_) { 95 fclose(file_); 96 file_ = NULL; 97 } 98 } 99 FILE *file_; 100 std::string file_name_; 101}; 102 103// Abstract base class for test video sources, which provide a stream of 104// vpx_image_t images with associated timestamps and duration. 105class VideoSource { 106 public: 107 virtual ~VideoSource() {} 108 109 // Prepare the stream for reading, rewind/open as necessary. 110 virtual void Begin() = 0; 111 112 // Advance the cursor to the next frame 113 virtual void Next() = 0; 114 115 // Get the current video frame, or NULL on End-Of-Stream. 116 virtual vpx_image_t *img() const = 0; 117 118 // Get the presentation timestamp of the current frame. 119 virtual vpx_codec_pts_t pts() const = 0; 120 121 // Get the current frame's duration 122 virtual unsigned long duration() const = 0; 123 124 // Get the timebase for the stream 125 virtual vpx_rational_t timebase() const = 0; 126 127 // Get the current frame counter, starting at 0. 128 virtual unsigned int frame() const = 0; 129 130 // Get the current file limit. 131 virtual unsigned int limit() const = 0; 132}; 133 134 135class DummyVideoSource : public VideoSource { 136 public: 137 DummyVideoSource() : img_(NULL), limit_(100), width_(0), height_(0) { 138 SetSize(80, 64); 139 } 140 141 virtual ~DummyVideoSource() { vpx_img_free(img_); } 142 143 virtual void Begin() { 144 frame_ = 0; 145 FillFrame(); 146 } 147 148 virtual void Next() { 149 ++frame_; 150 FillFrame(); 151 } 152 153 virtual vpx_image_t *img() const { 154 return (frame_ < limit_) ? img_ : NULL; 155 } 156 157 // Models a stream where Timebase = 1/FPS, so pts == frame. 158 virtual vpx_codec_pts_t pts() const { return frame_; } 159 160 virtual unsigned long duration() const { return 1; } 161 162 virtual vpx_rational_t timebase() const { 163 const vpx_rational_t t = {1, 30}; 164 return t; 165 } 166 167 virtual unsigned int frame() const { return frame_; } 168 169 virtual unsigned int limit() const { return limit_; } 170 171 void set_limit(unsigned int limit) { 172 limit_ = limit; 173 } 174 175 void SetSize(unsigned int width, unsigned int height) { 176 if (width != width_ || height != height_) { 177 vpx_img_free(img_); 178 raw_sz_ = ((width + 31)&~31) * height * 3 / 2; 179 img_ = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, width, height, 32); 180 width_ = width; 181 height_ = height; 182 } 183 } 184 185 protected: 186 virtual void FillFrame() { if (img_) memset(img_->img_data, 0, raw_sz_); } 187 188 vpx_image_t *img_; 189 size_t raw_sz_; 190 unsigned int limit_; 191 unsigned int frame_; 192 unsigned int width_; 193 unsigned int height_; 194}; 195 196 197class RandomVideoSource : public DummyVideoSource { 198 public: 199 RandomVideoSource(int seed = ACMRandom::DeterministicSeed()) 200 : rnd_(seed), 201 seed_(seed) { } 202 203 protected: 204 // Reset the RNG to get a matching stream for the second pass 205 virtual void Begin() { 206 frame_ = 0; 207 rnd_.Reset(seed_); 208 FillFrame(); 209 } 210 211 // 15 frames of noise, followed by 15 static frames. Reset to 0 rather 212 // than holding previous frames to encourage keyframes to be thrown. 213 virtual void FillFrame() { 214 if (img_) { 215 if (frame_ % 30 < 15) 216 for (size_t i = 0; i < raw_sz_; ++i) 217 img_->img_data[i] = rnd_.Rand8(); 218 else 219 memset(img_->img_data, 0, raw_sz_); 220 } 221 } 222 223 ACMRandom rnd_; 224 int seed_; 225}; 226 227// Abstract base class for test video sources, which provide a stream of 228// decompressed images to the decoder. 229class CompressedVideoSource { 230 public: 231 virtual ~CompressedVideoSource() {} 232 233 virtual void Init() = 0; 234 235 // Prepare the stream for reading, rewind/open as necessary. 236 virtual void Begin() = 0; 237 238 // Advance the cursor to the next frame 239 virtual void Next() = 0; 240 241 virtual const uint8_t *cxdata() const = 0; 242 243 virtual size_t frame_size() const = 0; 244 245 virtual unsigned int frame_number() const = 0; 246}; 247 248} // namespace libvpx_test 249 250#endif // TEST_VIDEO_SOURCE_H_ 251