// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/memory/ref_counted.h"
#include "cobalt/base/wrap_main.h"
#include "cobalt/media/sandbox/fuzzer_app.h"
#include "cobalt/media/sandbox/in_memory_data_source.h"
#include "cobalt/media/sandbox/media_sandbox.h"
#include "media/base/bind_to_loop.h"
#include "media/base/pipeline_status.h"
#include "media/filters/shell_demuxer.h"

namespace cobalt {
namespace media {
namespace sandbox {
namespace {

using base::Bind;
using ::media::BindToCurrentLoop;
using ::media::DecoderBuffer;
using ::media::Demuxer;
using ::media::DemuxerHost;
using ::media::DemuxerStream;
using ::media::PipelineStatus;
using ::media::ShellDemuxer;

class ShellDemuxerFuzzer : DemuxerHost {
 public:
  explicit ShellDemuxerFuzzer(const std::vector<uint8>& content)
      : error_occurred_(false), eos_count_(0), stopped_(false) {
    demuxer_ = new ShellDemuxer(base::MessageLoopProxy::current(),
                                new InMemoryDataSource(content));
  }

  void Fuzz() {
    demuxer_->Initialize(
        this, Bind(&ShellDemuxerFuzzer::InitializeCB, base::Unretained(this)));

    // Check if there is any error or if both of the audio and video streams
    // have reached eos.
    while (!error_occurred_ && eos_count_ != 2) {
      MessageLoop::current()->RunUntilIdle();
    }

    demuxer_->Stop(Bind(&ShellDemuxerFuzzer::StopCB, base::Unretained(this)));

    while (!stopped_) {
      MessageLoop::current()->RunUntilIdle();
    }
  }

 private:
  // DataSourceHost methods (parent class of DemuxerHost)
  void SetTotalBytes(int64 total_bytes) OVERRIDE {
    UNREFERENCED_PARAMETER(total_bytes);
  }

  void AddBufferedByteRange(int64 start, int64 end) OVERRIDE {
    UNREFERENCED_PARAMETER(start);
    UNREFERENCED_PARAMETER(end);
  }

  void AddBufferedTimeRange(base::TimeDelta start,
                            base::TimeDelta end) OVERRIDE {
    UNREFERENCED_PARAMETER(start);
    UNREFERENCED_PARAMETER(end);
  }

  // DemuxerHost methods
  void SetDuration(base::TimeDelta duration) OVERRIDE {
    UNREFERENCED_PARAMETER(duration);
  }
  void OnDemuxerError(PipelineStatus error) OVERRIDE {
    UNREFERENCED_PARAMETER(error);
    error_occurred_ = true;
  }

  void InitializeCB(PipelineStatus status) {
    DCHECK(!error_occurred_);
    if (status != ::media::PIPELINE_OK) {
      error_occurred_ = true;
      return;
    }
    scoped_refptr<DemuxerStream> audio_stream =
        demuxer_->GetStream(DemuxerStream::AUDIO);
    scoped_refptr<DemuxerStream> video_stream =
        demuxer_->GetStream(DemuxerStream::VIDEO);
    if (!audio_stream || !video_stream ||
        !audio_stream->audio_decoder_config().IsValidConfig() ||
        !video_stream->video_decoder_config().IsValidConfig()) {
      error_occurred_ = true;
      return;
    }
    audio_stream->Read(BindToCurrentLoop(Bind(
        &ShellDemuxerFuzzer::ReadCB, base::Unretained(this), audio_stream)));
    video_stream->Read(BindToCurrentLoop(Bind(
        &ShellDemuxerFuzzer::ReadCB, base::Unretained(this), video_stream)));
  }

  void StopCB() { stopped_ = true; }

  void ReadCB(const scoped_refptr<DemuxerStream>& stream,
              DemuxerStream::Status status,
              const scoped_refptr<DecoderBuffer>& buffer) {
    DCHECK_NE(status, DemuxerStream::kAborted);
    if (status == DemuxerStream::kOk) {
      DCHECK(buffer);
      if (buffer->IsEndOfStream()) {
        ++eos_count_;
        return;
      }
    }
    DCHECK(!error_occurred_);
    stream->Read(BindToCurrentLoop(
        Bind(&ShellDemuxerFuzzer::ReadCB, base::Unretained(this), stream)));
  }

  bool error_occurred_;
  int eos_count_;
  bool stopped_;
  scoped_refptr<ShellDemuxer> demuxer_;
};

class ShellDemuxerFuzzerApp : public FuzzerApp {
 public:
  explicit ShellDemuxerFuzzerApp(MediaSandbox* media_sandbox)
      : media_sandbox_(media_sandbox) {}

  std::vector<uint8> ParseFileContent(
      const std::string& file_name,
      const std::vector<uint8>& file_content) OVERRIDE {
    std::string ext = FilePath(file_name).Extension();
    if (ext != ".flv" && ext != ".mp4") {
      LOG(ERROR) << "Skip unsupported file " << file_name;
      return std::vector<uint8>();
    }
    return file_content;
  }

  void Fuzz(const std::string& file_name,
            const std::vector<uint8>& fuzzing_content) OVERRIDE {
    ShellDemuxerFuzzer demuxer_fuzzer(fuzzing_content);
    demuxer_fuzzer.Fuzz();
  }

 private:
  MediaSandbox* media_sandbox_;
};

int SandboxMain(int argc, char** argv) {
  MediaSandbox media_sandbox(
      argc, argv, FilePath(FILE_PATH_LITERAL("shell_demuxer_fuzzer.json")));
  ShellDemuxerFuzzerApp fuzzer_app(&media_sandbox);

  if (fuzzer_app.Init(argc, argv)) {
    fuzzer_app.RunFuzzingLoop();
  }

  return 0;
}

}  // namespace
}  // namespace sandbox
}  // namespace media
}  // namespace cobalt

COBALT_WRAP_SIMPLE_MAIN(cobalt::media::sandbox::SandboxMain);
