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 TEST_YUV_VIDEO_SOURCE_H_
11#define 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
20namespace 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.
25class YUVVideoSource : public VideoSource {
26 public:
27  YUVVideoSource(const std::string &file_name, vpx_img_fmt format,
28                 unsigned int width, unsigned int height,
29                 int rate_numerator, int rate_denominator,
30                 unsigned int start, int limit)
31      : file_name_(file_name),
32        input_file_(NULL),
33        img_(NULL),
34        start_(start),
35        limit_(limit),
36        frame_(0),
37        width_(0),
38        height_(0),
39        format_(VPX_IMG_FMT_NONE),
40        framerate_numerator_(rate_numerator),
41        framerate_denominator_(rate_denominator) {
42    // This initializes format_, raw_size_, width_, height_ and allocates img.
43    SetSize(width, height, format);
44  }
45
46  virtual ~YUVVideoSource() {
47    vpx_img_free(img_);
48    if (input_file_)
49      fclose(input_file_);
50  }
51
52  virtual void Begin() {
53    if (input_file_)
54      fclose(input_file_);
55    input_file_ = OpenTestDataFile(file_name_);
56    ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: "
57                                     << file_name_;
58    if (start_)
59      fseek(input_file_, static_cast<unsigned>(raw_size_) * start_, SEEK_SET);
60
61    frame_ = start_;
62    FillFrame();
63  }
64
65  virtual void Next() {
66    ++frame_;
67    FillFrame();
68  }
69
70  virtual vpx_image_t *img() const { return (frame_ < limit_) ? img_ : NULL;  }
71
72  // Models a stream where Timebase = 1/FPS, so pts == frame.
73  virtual vpx_codec_pts_t pts() const { return frame_; }
74
75  virtual unsigned long duration() const { return 1; }
76
77  virtual vpx_rational_t timebase() const {
78    const vpx_rational_t t = { framerate_denominator_, framerate_numerator_ };
79    return t;
80  }
81
82  virtual unsigned int frame() const { return frame_; }
83
84  virtual unsigned int limit() const { return limit_; }
85
86  virtual void SetSize(unsigned int width, unsigned int height,
87                       vpx_img_fmt format) {
88    if (width != width_ || height != height_ || format != format_) {
89      vpx_img_free(img_);
90      img_ = vpx_img_alloc(NULL, format, width, height, 1);
91      ASSERT_TRUE(img_ != NULL);
92      width_ = width;
93      height_ = height;
94      format_ = format;
95      switch (format) {
96        case VPX_IMG_FMT_I420:
97          raw_size_ = width * height * 3 / 2;
98          break;
99        case VPX_IMG_FMT_I422:
100          raw_size_ = width * height * 2;
101          break;
102        case VPX_IMG_FMT_I440:
103          raw_size_ = width * height * 2;
104          break;
105        case VPX_IMG_FMT_I444:
106          raw_size_ = width * height * 3;
107          break;
108        case VPX_IMG_FMT_I42016:
109          raw_size_ = width * height * 3;
110          break;
111        case VPX_IMG_FMT_I42216:
112          raw_size_ = width * height * 4;
113          break;
114        case VPX_IMG_FMT_I44016:
115          raw_size_ = width * height * 4;
116          break;
117        case VPX_IMG_FMT_I44416:
118          raw_size_ = width * height * 6;
119          break;
120        default:
121          ASSERT_TRUE(0);
122      }
123    }
124  }
125
126  virtual void FillFrame() {
127    ASSERT_TRUE(input_file_ != NULL);
128    // Read a frame from input_file.
129    if (fread(img_->img_data, raw_size_, 1, input_file_) == 0) {
130      limit_ = frame_;
131    }
132  }
133
134 protected:
135  std::string file_name_;
136  FILE *input_file_;
137  vpx_image_t *img_;
138  size_t raw_size_;
139  unsigned int start_;
140  unsigned int limit_;
141  unsigned int frame_;
142  unsigned int width_;
143  unsigned int height_;
144  vpx_img_fmt format_;
145  int framerate_numerator_;
146  int framerate_denominator_;
147};
148
149}  // namespace libvpx_test
150
151#endif  // TEST_YUV_VIDEO_SOURCE_H_
152