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