2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
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.
10 #ifndef TEST_VIDEO_SOURCE_H_
11 #define TEST_VIDEO_SOURCE_H_
19 #include "test/acm_random.h"
20 #include "vpx/vpx_encoder.h"
22 namespace libvpx_test {
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)
31 // A simple function to encapsulate cross platform retrieval of test data path
32 static 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);
47 // Undefining stringification macros because they are not used elsewhere
51 static 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");
56 static FILE *OpenTestOutFile(const std::string& file_name) {
57 const std::string path_to_source = GetDataPath() + "/" + file_name;
58 return fopen(path_to_source.c_str(), "wb");
61 static std::string GetTempOutFilename() {
65 // Assume for now that the filename generated is unique per process
66 const UINT ret = GetTempFileNameA(
67 GetDataPath().c_str(), "lvx", 0, fname);
69 const char *slash = strrchr(fname, '\\');
70 if (slash == NULL) slash = strrchr(fname, '/');
72 basename.assign(fname);
74 basename.assign(slash + 1);
80 const std::string templ = GetDataPath() + "/libvpx_test_XXXXXX";
81 strncpy(fname, templ.c_str(), templ.size());
82 fname[templ.size()] = '\0';
83 const int fd = mkstemp(fname);
86 basename.assign(strrchr(fname, '/') + 1);
97 file_name_ = GetTempOutFilename();
98 file_ = OpenTestOutFile(file_name_);
102 if (!file_name_.empty()) {
103 const std::string path_to_source = GetDataPath() + "/" + file_name_;
104 EXPECT_EQ(0, remove(path_to_source.c_str()));
110 const std::string& file_name() {
122 std::string file_name_;
125 // Abstract base class for test video sources, which provide a stream of
126 // vpx_image_t images with associated timestamps and duration.
129 virtual ~VideoSource() {}
131 // Prepare the stream for reading, rewind/open as necessary.
132 virtual void Begin() = 0;
134 // Advance the cursor to the next frame
135 virtual void Next() = 0;
137 // Get the current video frame, or NULL on End-Of-Stream.
138 virtual vpx_image_t *img() const = 0;
140 // Get the presentation timestamp of the current frame.
141 virtual vpx_codec_pts_t pts() const = 0;
143 // Get the current frame's duration
144 virtual unsigned long duration() const = 0;
146 // Get the timebase for the stream
147 virtual vpx_rational_t timebase() const = 0;
149 // Get the current frame counter, starting at 0.
150 virtual unsigned int frame() const = 0;
152 // Get the current file limit.
153 virtual unsigned int limit() const = 0;
157 class DummyVideoSource : public VideoSource {
159 DummyVideoSource() : img_(NULL), limit_(100), width_(0), height_(0) {
163 virtual ~DummyVideoSource() { vpx_img_free(img_); }
165 virtual void Begin() {
170 virtual void Next() {
175 virtual vpx_image_t *img() const {
176 return (frame_ < limit_) ? img_ : NULL;
179 // Models a stream where Timebase = 1/FPS, so pts == frame.
180 virtual vpx_codec_pts_t pts() const { return frame_; }
182 virtual unsigned long duration() const { return 1; }
184 virtual vpx_rational_t timebase() const {
185 const vpx_rational_t t = {1, 30};
189 virtual unsigned int frame() const { return frame_; }
191 virtual unsigned int limit() const { return limit_; }
193 void set_limit(unsigned int limit) {
197 void SetSize(unsigned int width, unsigned int height) {
198 if (width != width_ || height != height_) {
200 raw_sz_ = ((width + 31)&~31) * height * 3 / 2;
201 img_ = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, width, height, 32);
208 virtual void FillFrame() { if (img_) memset(img_->img_data, 0, raw_sz_); }
215 unsigned int height_;
219 class RandomVideoSource : public DummyVideoSource {
221 RandomVideoSource(int seed = ACMRandom::DeterministicSeed())
226 // Reset the RNG to get a matching stream for the second pass
227 virtual void Begin() {
233 // 15 frames of noise, followed by 15 static frames. Reset to 0 rather
234 // than holding previous frames to encourage keyframes to be thrown.
235 virtual void FillFrame() {
237 if (frame_ % 30 < 15)
238 for (size_t i = 0; i < raw_sz_; ++i)
239 img_->img_data[i] = rnd_.Rand8();
241 memset(img_->img_data, 0, raw_sz_);
249 // Abstract base class for test video sources, which provide a stream of
250 // decompressed images to the decoder.
251 class CompressedVideoSource {
253 virtual ~CompressedVideoSource() {}
255 virtual void Init() = 0;
257 // Prepare the stream for reading, rewind/open as necessary.
258 virtual void Begin() = 0;
260 // Advance the cursor to the next frame
261 virtual void Next() = 0;
263 virtual const uint8_t *cxdata() const = 0;
265 virtual size_t frame_size() const = 0;
267 virtual unsigned int frame_number() const = 0;
270 } // namespace libvpx_test
272 #endif // TEST_VIDEO_SOURCE_H_