1 /*
2  *  Copyright (c) 2014 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 VPX_TEST_YUV_VIDEO_SOURCE_H_
11 #define VPX_TEST_YUV_VIDEO_SOURCE_H_
12 
13 #include <cstdio>
14 #include <cstdlib>
15 #include <string>
16 
17 #include "test/video_source.h"
18 #include "vpx/vpx_image.h"
19 
20 namespace libvpx_test {
21 
22 // This class extends VideoSource to allow parsing of raw YUV
23 // formats of various color sampling and bit-depths so that we can
24 // do actual file encodes.
25 class YUVVideoSource : public VideoSource {
26  public:
YUVVideoSource(const std::string & file_name,vpx_img_fmt format,unsigned int width,unsigned int height,int rate_numerator,int rate_denominator,unsigned int start,int limit)27   YUVVideoSource(const std::string &file_name, vpx_img_fmt format,
28                  unsigned int width, unsigned int height, int rate_numerator,
29                  int rate_denominator, unsigned int start, int limit)
30       : file_name_(file_name), input_file_(NULL), img_(NULL), start_(start),
31         limit_(limit), frame_(0), width_(0), height_(0),
32         format_(VPX_IMG_FMT_NONE), framerate_numerator_(rate_numerator),
33         framerate_denominator_(rate_denominator) {
34     // This initializes format_, raw_size_, width_, height_ and allocates img.
35     SetSize(width, height, format);
36   }
37 
~YUVVideoSource()38   virtual ~YUVVideoSource() {
39     vpx_img_free(img_);
40     if (input_file_) fclose(input_file_);
41   }
42 
Begin()43   virtual void Begin() {
44     if (input_file_) fclose(input_file_);
45     input_file_ = OpenTestDataFile(file_name_);
46     ASSERT_TRUE(input_file_ != NULL)
47         << "Input file open failed. Filename: " << file_name_;
48     if (start_) {
49       fseek(input_file_, static_cast<unsigned>(raw_size_) * start_, SEEK_SET);
50     }
51 
52     frame_ = start_;
53     FillFrame();
54   }
55 
Next()56   virtual void Next() {
57     ++frame_;
58     FillFrame();
59   }
60 
img()61   virtual vpx_image_t *img() const { return (frame_ < limit_) ? img_ : NULL; }
62 
63   // Models a stream where Timebase = 1/FPS, so pts == frame.
pts()64   virtual vpx_codec_pts_t pts() const { return frame_; }
65 
duration()66   virtual unsigned long duration() const { return 1; }
67 
timebase()68   virtual vpx_rational_t timebase() const {
69     const vpx_rational_t t = { framerate_denominator_, framerate_numerator_ };
70     return t;
71   }
72 
frame()73   virtual unsigned int frame() const { return frame_; }
74 
limit()75   virtual unsigned int limit() const { return limit_; }
76 
SetSize(unsigned int width,unsigned int height,vpx_img_fmt format)77   virtual void SetSize(unsigned int width, unsigned int height,
78                        vpx_img_fmt format) {
79     if (width != width_ || height != height_ || format != format_) {
80       vpx_img_free(img_);
81       img_ = vpx_img_alloc(NULL, format, width, height, 1);
82       ASSERT_TRUE(img_ != NULL);
83       width_ = width;
84       height_ = height;
85       format_ = format;
86       switch (format) {
87         case VPX_IMG_FMT_I420: raw_size_ = width * height * 3 / 2; break;
88         case VPX_IMG_FMT_I422: raw_size_ = width * height * 2; break;
89         case VPX_IMG_FMT_I440: raw_size_ = width * height * 2; break;
90         case VPX_IMG_FMT_I444: raw_size_ = width * height * 3; break;
91         case VPX_IMG_FMT_I42016: raw_size_ = width * height * 3; break;
92         case VPX_IMG_FMT_I42216: raw_size_ = width * height * 4; break;
93         case VPX_IMG_FMT_I44016: raw_size_ = width * height * 4; break;
94         case VPX_IMG_FMT_I44416: raw_size_ = width * height * 6; break;
95         default: ASSERT_TRUE(0);
96       }
97     }
98   }
99 
FillFrame()100   virtual void FillFrame() {
101     ASSERT_TRUE(input_file_ != NULL);
102     // Read a frame from input_file.
103     if (fread(img_->img_data, raw_size_, 1, input_file_) == 0) {
104       limit_ = frame_;
105     }
106   }
107 
108  protected:
109   std::string file_name_;
110   FILE *input_file_;
111   vpx_image_t *img_;
112   size_t raw_size_;
113   unsigned int start_;
114   unsigned int limit_;
115   unsigned int frame_;
116   unsigned int width_;
117   unsigned int height_;
118   vpx_img_fmt format_;
119   int framerate_numerator_;
120   int framerate_denominator_;
121 };
122 
123 }  // namespace libvpx_test
124 
125 #endif  // VPX_TEST_YUV_VIDEO_SOURCE_H_
126