11b362b15af34006e6a11974088a46d42b903418eJohann/*
21b362b15af34006e6a11974088a46d42b903418eJohann *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
31b362b15af34006e6a11974088a46d42b903418eJohann *
41b362b15af34006e6a11974088a46d42b903418eJohann *  Use of this source code is governed by a BSD-style license
51b362b15af34006e6a11974088a46d42b903418eJohann *  that can be found in the LICENSE file in the root of the source
61b362b15af34006e6a11974088a46d42b903418eJohann *  tree. An additional intellectual property rights grant can be found
71b362b15af34006e6a11974088a46d42b903418eJohann *  in the file PATENTS.  All contributing project authors may
81b362b15af34006e6a11974088a46d42b903418eJohann *  be found in the AUTHORS file in the root of the source tree.
91b362b15af34006e6a11974088a46d42b903418eJohann */
101b362b15af34006e6a11974088a46d42b903418eJohann#ifndef TEST_VIDEO_SOURCE_H_
111b362b15af34006e6a11974088a46d42b903418eJohann#define TEST_VIDEO_SOURCE_H_
121b362b15af34006e6a11974088a46d42b903418eJohann
131b362b15af34006e6a11974088a46d42b903418eJohann#include <cstdio>
141b362b15af34006e6a11974088a46d42b903418eJohann#include <cstdlib>
151b362b15af34006e6a11974088a46d42b903418eJohann#include <string>
161b362b15af34006e6a11974088a46d42b903418eJohann#include "test/acm_random.h"
171b362b15af34006e6a11974088a46d42b903418eJohann#include "vpx/vpx_encoder.h"
181b362b15af34006e6a11974088a46d42b903418eJohann
191b362b15af34006e6a11974088a46d42b903418eJohannnamespace libvpx_test {
201b362b15af34006e6a11974088a46d42b903418eJohann
215ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang// Helper macros to ensure LIBVPX_TEST_DATA_PATH is a quoted string.
225ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang// These are undefined right below GetDataPath
235ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang// NOTE: LIBVPX_TEST_DATA_PATH MUST NOT be a quoted string before
245ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang// Stringification or the GetDataPath will fail at runtime
255ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#define TO_STRING(S) #S
265ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#define STRINGIFY(S) TO_STRING(S)
271b362b15af34006e6a11974088a46d42b903418eJohann
285ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang// A simple function to encapsulate cross platform retrieval of test data path
295ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic std::string GetDataPath() {
305ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang  const char *const data_path = getenv("LIBVPX_TEST_DATA_PATH");
315ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang  if (data_path == NULL) {
325ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#ifdef LIBVPX_TEST_DATA_PATH
335ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    // In some environments, we cannot set environment variables
345ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    // Instead, we set the data path by using a preprocessor symbol
355ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    // which can be set from make files
365ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    return STRINGIFY(LIBVPX_TEST_DATA_PATH);
375ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#else
385ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    return ".";
395ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#endif
401b362b15af34006e6a11974088a46d42b903418eJohann  }
415ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang  return data_path;
425ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang}
431b362b15af34006e6a11974088a46d42b903418eJohann
445ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang// Undefining stringification macros because they are not used elsewhere
455ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#undef TO_STRING
465ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang#undef STRINGIFY
475ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
485ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuangstatic FILE *OpenTestDataFile(const std::string& file_name) {
495ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang  const std::string path_to_source = GetDataPath() + "/" + file_name;
501b362b15af34006e6a11974088a46d42b903418eJohann  return fopen(path_to_source.c_str(), "rb");
511b362b15af34006e6a11974088a46d42b903418eJohann}
521b362b15af34006e6a11974088a46d42b903418eJohann
531b362b15af34006e6a11974088a46d42b903418eJohann// Abstract base class for test video sources, which provide a stream of
541b362b15af34006e6a11974088a46d42b903418eJohann// vpx_image_t images with associated timestamps and duration.
551b362b15af34006e6a11974088a46d42b903418eJohannclass VideoSource {
561b362b15af34006e6a11974088a46d42b903418eJohann public:
571b362b15af34006e6a11974088a46d42b903418eJohann  virtual ~VideoSource() {}
581b362b15af34006e6a11974088a46d42b903418eJohann
591b362b15af34006e6a11974088a46d42b903418eJohann  // Prepare the stream for reading, rewind/open as necessary.
601b362b15af34006e6a11974088a46d42b903418eJohann  virtual void Begin() = 0;
611b362b15af34006e6a11974088a46d42b903418eJohann
621b362b15af34006e6a11974088a46d42b903418eJohann  // Advance the cursor to the next frame
631b362b15af34006e6a11974088a46d42b903418eJohann  virtual void Next() = 0;
641b362b15af34006e6a11974088a46d42b903418eJohann
651b362b15af34006e6a11974088a46d42b903418eJohann  // Get the current video frame, or NULL on End-Of-Stream.
661b362b15af34006e6a11974088a46d42b903418eJohann  virtual vpx_image_t *img() const = 0;
671b362b15af34006e6a11974088a46d42b903418eJohann
681b362b15af34006e6a11974088a46d42b903418eJohann  // Get the presentation timestamp of the current frame.
691b362b15af34006e6a11974088a46d42b903418eJohann  virtual vpx_codec_pts_t pts() const = 0;
701b362b15af34006e6a11974088a46d42b903418eJohann
711b362b15af34006e6a11974088a46d42b903418eJohann  // Get the current frame's duration
721b362b15af34006e6a11974088a46d42b903418eJohann  virtual unsigned long duration() const = 0;
731b362b15af34006e6a11974088a46d42b903418eJohann
741b362b15af34006e6a11974088a46d42b903418eJohann  // Get the timebase for the stream
751b362b15af34006e6a11974088a46d42b903418eJohann  virtual vpx_rational_t timebase() const = 0;
761b362b15af34006e6a11974088a46d42b903418eJohann
771b362b15af34006e6a11974088a46d42b903418eJohann  // Get the current frame counter, starting at 0.
781b362b15af34006e6a11974088a46d42b903418eJohann  virtual unsigned int frame() const = 0;
791b362b15af34006e6a11974088a46d42b903418eJohann
801b362b15af34006e6a11974088a46d42b903418eJohann  // Get the current file limit.
811b362b15af34006e6a11974088a46d42b903418eJohann  virtual unsigned int limit() const = 0;
821b362b15af34006e6a11974088a46d42b903418eJohann};
831b362b15af34006e6a11974088a46d42b903418eJohann
841b362b15af34006e6a11974088a46d42b903418eJohann
851b362b15af34006e6a11974088a46d42b903418eJohannclass DummyVideoSource : public VideoSource {
861b362b15af34006e6a11974088a46d42b903418eJohann public:
871b362b15af34006e6a11974088a46d42b903418eJohann  DummyVideoSource() : img_(NULL), limit_(100), width_(0), height_(0) {
881b362b15af34006e6a11974088a46d42b903418eJohann    SetSize(80, 64);
891b362b15af34006e6a11974088a46d42b903418eJohann  }
901b362b15af34006e6a11974088a46d42b903418eJohann
911b362b15af34006e6a11974088a46d42b903418eJohann  virtual ~DummyVideoSource() { vpx_img_free(img_); }
921b362b15af34006e6a11974088a46d42b903418eJohann
931b362b15af34006e6a11974088a46d42b903418eJohann  virtual void Begin() {
941b362b15af34006e6a11974088a46d42b903418eJohann    frame_ = 0;
951b362b15af34006e6a11974088a46d42b903418eJohann    FillFrame();
961b362b15af34006e6a11974088a46d42b903418eJohann  }
971b362b15af34006e6a11974088a46d42b903418eJohann
981b362b15af34006e6a11974088a46d42b903418eJohann  virtual void Next() {
991b362b15af34006e6a11974088a46d42b903418eJohann    ++frame_;
1001b362b15af34006e6a11974088a46d42b903418eJohann    FillFrame();
1011b362b15af34006e6a11974088a46d42b903418eJohann  }
1021b362b15af34006e6a11974088a46d42b903418eJohann
1031b362b15af34006e6a11974088a46d42b903418eJohann  virtual vpx_image_t *img() const {
1041b362b15af34006e6a11974088a46d42b903418eJohann    return (frame_ < limit_) ? img_ : NULL;
1051b362b15af34006e6a11974088a46d42b903418eJohann  }
1061b362b15af34006e6a11974088a46d42b903418eJohann
1071b362b15af34006e6a11974088a46d42b903418eJohann  // Models a stream where Timebase = 1/FPS, so pts == frame.
1081b362b15af34006e6a11974088a46d42b903418eJohann  virtual vpx_codec_pts_t pts() const { return frame_; }
1091b362b15af34006e6a11974088a46d42b903418eJohann
1101b362b15af34006e6a11974088a46d42b903418eJohann  virtual unsigned long duration() const { return 1; }
1111b362b15af34006e6a11974088a46d42b903418eJohann
1121b362b15af34006e6a11974088a46d42b903418eJohann  virtual vpx_rational_t timebase() const {
1131b362b15af34006e6a11974088a46d42b903418eJohann    const vpx_rational_t t = {1, 30};
1141b362b15af34006e6a11974088a46d42b903418eJohann    return t;
1151b362b15af34006e6a11974088a46d42b903418eJohann  }
1161b362b15af34006e6a11974088a46d42b903418eJohann
1171b362b15af34006e6a11974088a46d42b903418eJohann  virtual unsigned int frame() const { return frame_; }
1181b362b15af34006e6a11974088a46d42b903418eJohann
1191b362b15af34006e6a11974088a46d42b903418eJohann  virtual unsigned int limit() const { return limit_; }
1201b362b15af34006e6a11974088a46d42b903418eJohann
1211b362b15af34006e6a11974088a46d42b903418eJohann  void SetSize(unsigned int width, unsigned int height) {
1221b362b15af34006e6a11974088a46d42b903418eJohann    if (width != width_ || height != height_) {
1231b362b15af34006e6a11974088a46d42b903418eJohann      vpx_img_free(img_);
1241b362b15af34006e6a11974088a46d42b903418eJohann      raw_sz_ = ((width + 31)&~31) * height * 3 / 2;
125ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      img_ = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, width, height, 32);
1261b362b15af34006e6a11974088a46d42b903418eJohann      width_ = width;
1271b362b15af34006e6a11974088a46d42b903418eJohann      height_ = height;
1281b362b15af34006e6a11974088a46d42b903418eJohann    }
1291b362b15af34006e6a11974088a46d42b903418eJohann  }
1301b362b15af34006e6a11974088a46d42b903418eJohann
1311b362b15af34006e6a11974088a46d42b903418eJohann protected:
1321b362b15af34006e6a11974088a46d42b903418eJohann  virtual void FillFrame() { memset(img_->img_data, 0, raw_sz_); }
1331b362b15af34006e6a11974088a46d42b903418eJohann
1341b362b15af34006e6a11974088a46d42b903418eJohann  vpx_image_t *img_;
1351b362b15af34006e6a11974088a46d42b903418eJohann  size_t       raw_sz_;
1361b362b15af34006e6a11974088a46d42b903418eJohann  unsigned int limit_;
1371b362b15af34006e6a11974088a46d42b903418eJohann  unsigned int frame_;
1381b362b15af34006e6a11974088a46d42b903418eJohann  unsigned int width_;
1391b362b15af34006e6a11974088a46d42b903418eJohann  unsigned int height_;
1401b362b15af34006e6a11974088a46d42b903418eJohann};
1411b362b15af34006e6a11974088a46d42b903418eJohann
1421b362b15af34006e6a11974088a46d42b903418eJohann
1431b362b15af34006e6a11974088a46d42b903418eJohannclass RandomVideoSource : public DummyVideoSource {
1441b362b15af34006e6a11974088a46d42b903418eJohann public:
1451b362b15af34006e6a11974088a46d42b903418eJohann  RandomVideoSource(int seed = ACMRandom::DeterministicSeed())
1461b362b15af34006e6a11974088a46d42b903418eJohann      : rnd_(seed),
1471b362b15af34006e6a11974088a46d42b903418eJohann        seed_(seed) { }
1481b362b15af34006e6a11974088a46d42b903418eJohann
1491b362b15af34006e6a11974088a46d42b903418eJohann protected:
1501b362b15af34006e6a11974088a46d42b903418eJohann  // Reset the RNG to get a matching stream for the second pass
1511b362b15af34006e6a11974088a46d42b903418eJohann  virtual void Begin() {
1521b362b15af34006e6a11974088a46d42b903418eJohann    frame_ = 0;
1531b362b15af34006e6a11974088a46d42b903418eJohann    rnd_.Reset(seed_);
1541b362b15af34006e6a11974088a46d42b903418eJohann    FillFrame();
1551b362b15af34006e6a11974088a46d42b903418eJohann  }
1561b362b15af34006e6a11974088a46d42b903418eJohann
1571b362b15af34006e6a11974088a46d42b903418eJohann  // 15 frames of noise, followed by 15 static frames. Reset to 0 rather
1581b362b15af34006e6a11974088a46d42b903418eJohann  // than holding previous frames to encourage keyframes to be thrown.
1591b362b15af34006e6a11974088a46d42b903418eJohann  virtual void FillFrame() {
1601b362b15af34006e6a11974088a46d42b903418eJohann    if (frame_ % 30 < 15)
1611b362b15af34006e6a11974088a46d42b903418eJohann      for (size_t i = 0; i < raw_sz_; ++i)
1621b362b15af34006e6a11974088a46d42b903418eJohann        img_->img_data[i] = rnd_.Rand8();
1631b362b15af34006e6a11974088a46d42b903418eJohann    else
1641b362b15af34006e6a11974088a46d42b903418eJohann      memset(img_->img_data, 0, raw_sz_);
1651b362b15af34006e6a11974088a46d42b903418eJohann  }
1661b362b15af34006e6a11974088a46d42b903418eJohann
1671b362b15af34006e6a11974088a46d42b903418eJohann  ACMRandom rnd_;
1681b362b15af34006e6a11974088a46d42b903418eJohann  int seed_;
1691b362b15af34006e6a11974088a46d42b903418eJohann};
1701b362b15af34006e6a11974088a46d42b903418eJohann
1711b362b15af34006e6a11974088a46d42b903418eJohann// Abstract base class for test video sources, which provide a stream of
1721b362b15af34006e6a11974088a46d42b903418eJohann// decompressed images to the decoder.
1731b362b15af34006e6a11974088a46d42b903418eJohannclass CompressedVideoSource {
1741b362b15af34006e6a11974088a46d42b903418eJohann public:
1751b362b15af34006e6a11974088a46d42b903418eJohann  virtual ~CompressedVideoSource() {}
1761b362b15af34006e6a11974088a46d42b903418eJohann
1771b362b15af34006e6a11974088a46d42b903418eJohann  virtual void Init() = 0;
1781b362b15af34006e6a11974088a46d42b903418eJohann
1791b362b15af34006e6a11974088a46d42b903418eJohann  // Prepare the stream for reading, rewind/open as necessary.
1801b362b15af34006e6a11974088a46d42b903418eJohann  virtual void Begin() = 0;
1811b362b15af34006e6a11974088a46d42b903418eJohann
1821b362b15af34006e6a11974088a46d42b903418eJohann  // Advance the cursor to the next frame
1831b362b15af34006e6a11974088a46d42b903418eJohann  virtual void Next() = 0;
1841b362b15af34006e6a11974088a46d42b903418eJohann
1851b362b15af34006e6a11974088a46d42b903418eJohann  virtual const uint8_t *cxdata() const = 0;
1861b362b15af34006e6a11974088a46d42b903418eJohann
187b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  virtual size_t frame_size() const = 0;
1881b362b15af34006e6a11974088a46d42b903418eJohann
189b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  virtual unsigned int frame_number() const = 0;
1901b362b15af34006e6a11974088a46d42b903418eJohann};
1911b362b15af34006e6a11974088a46d42b903418eJohann
1921b362b15af34006e6a11974088a46d42b903418eJohann}  // namespace libvpx_test
1931b362b15af34006e6a11974088a46d42b903418eJohann
1941b362b15af34006e6a11974088a46d42b903418eJohann#endif  // TEST_VIDEO_SOURCE_H_
195