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 #include <cstdio> 14 #include <cstdlib> 15 #include <string> 16 #include "test/acm_random.h" 17 #include "vpx/vpx_encoder.h" 18 19 namespace libvpx_test { 20 21 // Helper macros to ensure LIBVPX_TEST_DATA_PATH is a quoted string. 22 // These are undefined right below GetDataPath 23 // NOTE: LIBVPX_TEST_DATA_PATH MUST NOT be a quoted string before 24 // Stringification or the GetDataPath will fail at runtime 25 #define TO_STRING(S) #S 26 #define STRINGIFY(S) TO_STRING(S) 27 28 // A simple function to encapsulate cross platform retrieval of test data path 29 static std::string GetDataPath() { 30 const char *const data_path = getenv("LIBVPX_TEST_DATA_PATH"); 31 if (data_path == NULL) { 32 #ifdef LIBVPX_TEST_DATA_PATH 33 // In some environments, we cannot set environment variables 34 // Instead, we set the data path by using a preprocessor symbol 35 // which can be set from make files 36 return STRINGIFY(LIBVPX_TEST_DATA_PATH); 37 #else 38 return "."; 39 #endif 40 } 41 return data_path; 42 } 43 44 // Undefining stringification macros because they are not used elsewhere 45 #undef TO_STRING 46 #undef STRINGIFY 47 48 static FILE *OpenTestDataFile(const std::string& file_name) { 49 const std::string path_to_source = GetDataPath() + "/" + file_name; 50 return fopen(path_to_source.c_str(), "rb"); 51 } 52 53 // Abstract base class for test video sources, which provide a stream of 54 // vpx_image_t images with associated timestamps and duration. 55 class VideoSource { 56 public: 57 virtual ~VideoSource() {} 58 59 // Prepare the stream for reading, rewind/open as necessary. 60 virtual void Begin() = 0; 61 62 // Advance the cursor to the next frame 63 virtual void Next() = 0; 64 65 // Get the current video frame, or NULL on End-Of-Stream. 66 virtual vpx_image_t *img() const = 0; 67 68 // Get the presentation timestamp of the current frame. 69 virtual vpx_codec_pts_t pts() const = 0; 70 71 // Get the current frame's duration 72 virtual unsigned long duration() const = 0; 73 74 // Get the timebase for the stream 75 virtual vpx_rational_t timebase() const = 0; 76 77 // Get the current frame counter, starting at 0. 78 virtual unsigned int frame() const = 0; 79 80 // Get the current file limit. 81 virtual unsigned int limit() const = 0; 82 }; 83 84 85 class DummyVideoSource : public VideoSource { 86 public: 87 DummyVideoSource() : img_(NULL), limit_(100), width_(0), height_(0) { 88 SetSize(80, 64); 89 } 90 91 virtual ~DummyVideoSource() { vpx_img_free(img_); } 92 93 virtual void Begin() { 94 frame_ = 0; 95 FillFrame(); 96 } 97 98 virtual void Next() { 99 ++frame_; 100 FillFrame(); 101 } 102 103 virtual vpx_image_t *img() const { 104 return (frame_ < limit_) ? img_ : NULL; 105 } 106 107 // Models a stream where Timebase = 1/FPS, so pts == frame. 108 virtual vpx_codec_pts_t pts() const { return frame_; } 109 110 virtual unsigned long duration() const { return 1; } 111 112 virtual vpx_rational_t timebase() const { 113 const vpx_rational_t t = {1, 30}; 114 return t; 115 } 116 117 virtual unsigned int frame() const { return frame_; } 118 119 virtual unsigned int limit() const { return limit_; } 120 121 void SetSize(unsigned int width, unsigned int height) { 122 if (width != width_ || height != height_) { 123 vpx_img_free(img_); 124 raw_sz_ = ((width + 31)&~31) * height * 3 / 2; 125 img_ = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, width, height, 32); 126 width_ = width; 127 height_ = height; 128 } 129 } 130 131 protected: 132 virtual void FillFrame() { memset(img_->img_data, 0, raw_sz_); } 133 134 vpx_image_t *img_; 135 size_t raw_sz_; 136 unsigned int limit_; 137 unsigned int frame_; 138 unsigned int width_; 139 unsigned int height_; 140 }; 141 142 143 class RandomVideoSource : public DummyVideoSource { 144 public: 145 RandomVideoSource(int seed = ACMRandom::DeterministicSeed()) 146 : rnd_(seed), 147 seed_(seed) { } 148 149 protected: 150 // Reset the RNG to get a matching stream for the second pass 151 virtual void Begin() { 152 frame_ = 0; 153 rnd_.Reset(seed_); 154 FillFrame(); 155 } 156 157 // 15 frames of noise, followed by 15 static frames. Reset to 0 rather 158 // than holding previous frames to encourage keyframes to be thrown. 159 virtual void FillFrame() { 160 if (frame_ % 30 < 15) 161 for (size_t i = 0; i < raw_sz_; ++i) 162 img_->img_data[i] = rnd_.Rand8(); 163 else 164 memset(img_->img_data, 0, raw_sz_); 165 } 166 167 ACMRandom rnd_; 168 int seed_; 169 }; 170 171 // Abstract base class for test video sources, which provide a stream of 172 // decompressed images to the decoder. 173 class CompressedVideoSource { 174 public: 175 virtual ~CompressedVideoSource() {} 176 177 virtual void Init() = 0; 178 179 // Prepare the stream for reading, rewind/open as necessary. 180 virtual void Begin() = 0; 181 182 // Advance the cursor to the next frame 183 virtual void Next() = 0; 184 185 virtual const uint8_t *cxdata() const = 0; 186 187 virtual size_t frame_size() const = 0; 188 189 virtual unsigned int frame_number() const = 0; 190 }; 191 192 } // namespace libvpx_test 193 194 #endif // TEST_VIDEO_SOURCE_H_ 195