/*
 *  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_);
    if (nestegg_ctx_ != NULL) {
      if (pkt_ != NULL) {
        nestegg_free_packet(pkt_);
      }
      nestegg_destroy(nestegg_ctx_);
    }
  }

  virtual void Init() {
  }

  virtual void Begin() {
    input_file_ = OpenTestDataFile(file_name_);
    ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: "
        << 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() {
    ASSERT_TRUE(input_file_ != NULL);
    if (chunk_ >= chunks_) {
      unsigned int track;

      do {
        /* End of this packet, get another. */
        if (pkt_ != NULL) {
          nestegg_free_packet(pkt_);
          pkt_ = NULL;
        }

        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 size_t frame_size() const { return buf_sz_; }
  virtual 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_
