webm_video_source.h 4.58 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
/*
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#ifndef TEST_WEBM_VIDEO_SOURCE_H_
#define TEST_WEBM_VIDEO_SOURCE_H_
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <new>
#include <string>
#include "nestegg/include/nestegg/nestegg.h"
#include "test/video_source.h"

namespace libvpx_test {

static int
nestegg_read_cb(void *buffer, size_t length, void *userdata) {
  FILE *f = reinterpret_cast<FILE *>(userdata);

  if (fread(buffer, 1, length, f) < length) {
    if (ferror(f))
      return -1;
    if (feof(f))
      return 0;
  }
  return 1;
}


static int
nestegg_seek_cb(int64_t offset, int whence, void *userdata) {
  FILE *f = reinterpret_cast<FILE *>(userdata);
  switch (whence) {
    case NESTEGG_SEEK_SET:
      whence = SEEK_SET;
      break;
    case NESTEGG_SEEK_CUR:
      whence = SEEK_CUR;
      break;
    case NESTEGG_SEEK_END:
      whence = SEEK_END;
      break;
  };
  return fseek(f, (long)offset, whence) ? -1 : 0;
}


static int64_t
nestegg_tell_cb(void *userdata) {
  FILE *f = reinterpret_cast<FILE *>(userdata);
  return ftell(f);
}


static void
nestegg_log_cb(nestegg *context, unsigned int severity, char const *format,
               ...) {
  va_list ap;

  va_start(ap, format);
  vfprintf(stderr, format, ap);
  fprintf(stderr, "\n");
  va_end(ap);
}

// This class extends VideoSource to allow parsing of WebM files,
// so that we can do actual file decodes.
class WebMVideoSource : public CompressedVideoSource {
 public:
  explicit WebMVideoSource(const std::string &file_name)
      : file_name_(file_name),
        input_file_(NULL),
        nestegg_ctx_(NULL),
        pkt_(NULL),
        video_track_(0),
        chunk_(0),
        chunks_(0),
        buf_(NULL),
        buf_sz_(0),
        frame_(0),
        end_of_file_(false) {
  }

  virtual ~WebMVideoSource() {
    if (input_file_)
      fclose(input_file_);
93 94 95 96
    if (nestegg_ctx_ != NULL) {
      if (pkt_ != NULL) {
        nestegg_free_packet(pkt_);
      }
97
      nestegg_destroy(nestegg_ctx_);
98
    }
99 100 101 102 103 104 105
  }

  virtual void Init() {
  }

  virtual void Begin() {
    input_file_ = OpenTestDataFile(file_name_);
106
    ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: "
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
        << file_name_;

    nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb,
                     input_file_};
    ASSERT_FALSE(nestegg_init(&nestegg_ctx_, io, NULL))
        << "nestegg_init failed";

    unsigned int n;
    ASSERT_FALSE(nestegg_track_count(nestegg_ctx_, &n))
        << "failed to get track count";

    for (unsigned int i = 0; i < n; i++) {
      int track_type = nestegg_track_type(nestegg_ctx_, i);
      ASSERT_GE(track_type, 0) << "failed to get track type";

      if (track_type == NESTEGG_TRACK_VIDEO) {
        video_track_ = i;
        break;
      }
    }

    FillFrame();
  }

  virtual void Next() {
    ++frame_;
    FillFrame();
  }

  void FillFrame() {
137
    ASSERT_TRUE(input_file_ != NULL);
138 139 140 141 142
    if (chunk_ >= chunks_) {
      unsigned int track;

      do {
        /* End of this packet, get another. */
143
        if (pkt_ != NULL) {
144
          nestegg_free_packet(pkt_);
145 146
          pkt_ = NULL;
        }
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

        int again = nestegg_read_packet(nestegg_ctx_, &pkt_);
        ASSERT_GE(again, 0) << "nestegg_read_packet failed";
        if (!again) {
          end_of_file_ = true;
          return;
        }

        ASSERT_FALSE(nestegg_packet_track(pkt_, &track))
            << "nestegg_packet_track failed";
      } while (track != video_track_);

      ASSERT_FALSE(nestegg_packet_count(pkt_, &chunks_))
          << "nestegg_packet_count failed";
      chunk_ = 0;
    }

    ASSERT_FALSE(nestegg_packet_data(pkt_, chunk_, &buf_, &buf_sz_))
        << "nestegg_packet_data failed";
    chunk_++;
  }

  virtual const uint8_t *cxdata() const {
    return end_of_file_ ? NULL : buf_;
  }
  virtual const unsigned int frame_size() const { return buf_sz_; }
  virtual const unsigned int frame_number() const { return frame_; }

 protected:
  std::string file_name_;
  FILE *input_file_;
  nestegg *nestegg_ctx_;
  nestegg_packet *pkt_;
  unsigned int video_track_;
  unsigned int chunk_;
  unsigned int chunks_;
  uint8_t *buf_;
  size_t buf_sz_;
  unsigned int frame_;
  bool end_of_file_;
};

}  // namespace libvpx_test

#endif  // TEST_WEBM_VIDEO_SOURCE_H_