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