1ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/*
2ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *
4ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  Use of this source code is governed by a BSD-style license
5ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  that can be found in the LICENSE file in the root of the source
6ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  tree. An additional intellectual property rights grant can be found
7ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  in the file PATENTS.  All contributing project authors may
8ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  be found in the AUTHORS file in the root of the source tree.
9ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#ifndef TEST_WEBM_VIDEO_SOURCE_H_
11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#define TEST_WEBM_VIDEO_SOURCE_H_
12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <cstdarg>
13ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <cstdio>
14ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <cstdlib>
15ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <new>
16ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <string>
17b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include "third_party/nestegg/include/nestegg/nestegg.h"
18ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "test/video_source.h"
19ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
20ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangnamespace libvpx_test {
21ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
22ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic int
23ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangnestegg_read_cb(void *buffer, size_t length, void *userdata) {
24ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  FILE *f = reinterpret_cast<FILE *>(userdata);
25ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
26ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (fread(buffer, 1, length, f) < length) {
27ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (ferror(f))
28ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return -1;
29ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (feof(f))
30ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return 0;
31ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
32ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return 1;
33ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
34ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
35ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
36ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic int
37ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangnestegg_seek_cb(int64_t offset, int whence, void *userdata) {
38ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  FILE *f = reinterpret_cast<FILE *>(userdata);
39ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  switch (whence) {
40ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    case NESTEGG_SEEK_SET:
41ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      whence = SEEK_SET;
42ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      break;
43ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    case NESTEGG_SEEK_CUR:
44ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      whence = SEEK_CUR;
45ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      break;
46ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    case NESTEGG_SEEK_END:
47ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      whence = SEEK_END;
48ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      break;
49ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  };
50ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return fseek(f, (long)offset, whence) ? -1 : 0;
51ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
52ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
53ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
54ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic int64_t
55ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangnestegg_tell_cb(void *userdata) {
56ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  FILE *f = reinterpret_cast<FILE *>(userdata);
57ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return ftell(f);
58ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
59ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
60ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
61ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic void
62ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangnestegg_log_cb(nestegg *context, unsigned int severity, char const *format,
63ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               ...) {
64ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  va_list ap;
65ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
66ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  va_start(ap, format);
67ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  vfprintf(stderr, format, ap);
68ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  fprintf(stderr, "\n");
69ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  va_end(ap);
70ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
71ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
72ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang// This class extends VideoSource to allow parsing of WebM files,
73ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang// so that we can do actual file decodes.
74ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass WebMVideoSource : public CompressedVideoSource {
75ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang public:
76ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  explicit WebMVideoSource(const std::string &file_name)
77ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      : file_name_(file_name),
78ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        input_file_(NULL),
79ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        nestegg_ctx_(NULL),
80ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        pkt_(NULL),
81ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        video_track_(0),
82ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        chunk_(0),
83ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        chunks_(0),
84ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        buf_(NULL),
85ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        buf_sz_(0),
86ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        frame_(0),
87ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        end_of_file_(false) {
88ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
89ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
90ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  virtual ~WebMVideoSource() {
91ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (input_file_)
92ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      fclose(input_file_);
93b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (nestegg_ctx_ != NULL) {
94b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if (pkt_ != NULL) {
95b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        nestegg_free_packet(pkt_);
96b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      }
97ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      nestegg_destroy(nestegg_ctx_);
98b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
99ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  virtual void Init() {
102ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
103ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
104ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  virtual void Begin() {
105ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    input_file_ = OpenTestDataFile(file_name_);
10691037db265ecdd914a26e056cf69207b4f50924ehkuang    ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: "
107ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << file_name_;
108ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
109ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb,
110ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                     input_file_};
111b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    ASSERT_FALSE(nestegg_init(&nestegg_ctx_, io, NULL, -1))
112ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << "nestegg_init failed";
113ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
114ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    unsigned int n;
115ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ASSERT_FALSE(nestegg_track_count(nestegg_ctx_, &n))
116ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << "failed to get track count";
117ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for (unsigned int i = 0; i < n; i++) {
119ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      int track_type = nestegg_track_type(nestegg_ctx_, i);
120ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ASSERT_GE(track_type, 0) << "failed to get track type";
121ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
122ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (track_type == NESTEGG_TRACK_VIDEO) {
123ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        video_track_ = i;
124ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        break;
125ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
126ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
127ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
128ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    FillFrame();
129ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
131ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  virtual void Next() {
132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ++frame_;
133ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    FillFrame();
134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  void FillFrame() {
13791037db265ecdd914a26e056cf69207b4f50924ehkuang    ASSERT_TRUE(input_file_ != NULL);
138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (chunk_ >= chunks_) {
139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      unsigned int track;
140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      do {
142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        /* End of this packet, get another. */
143b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if (pkt_ != NULL) {
144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          nestegg_free_packet(pkt_);
145b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          pkt_ = NULL;
146b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        }
147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        int again = nestegg_read_packet(nestegg_ctx_, &pkt_);
149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        ASSERT_GE(again, 0) << "nestegg_read_packet failed";
150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if (!again) {
151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          end_of_file_ = true;
152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          return;
153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        }
154ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
155ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        ASSERT_FALSE(nestegg_packet_track(pkt_, &track))
156ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            << "nestegg_packet_track failed";
157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      } while (track != video_track_);
158ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
159ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ASSERT_FALSE(nestegg_packet_count(pkt_, &chunks_))
160ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          << "nestegg_packet_count failed";
161ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      chunk_ = 0;
162ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ASSERT_FALSE(nestegg_packet_data(pkt_, chunk_, &buf_, &buf_sz_))
165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        << "nestegg_packet_data failed";
166ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    chunk_++;
167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
168ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  virtual const uint8_t *cxdata() const {
170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return end_of_file_ ? NULL : buf_;
171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
172b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  virtual size_t frame_size() const { return buf_sz_; }
173b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  virtual unsigned int frame_number() const { return frame_; }
174ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang protected:
176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  std::string file_name_;
177ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  FILE *input_file_;
178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  nestegg *nestegg_ctx_;
179ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  nestegg_packet *pkt_;
180ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int video_track_;
181ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int chunk_;
182ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int chunks_;
183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  uint8_t *buf_;
184ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  size_t buf_sz_;
185ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int frame_;
186ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  bool end_of_file_;
187ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang};
188ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
189ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}  // namespace libvpx_test
190ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif  // TEST_WEBM_VIDEO_SOURCE_H_
192