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