// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cobalt/media/base/mock_filters.h"

#include <memory>

#include "base/logging.h"

using ::testing::_;
using ::testing::Invoke;
using ::testing::NotNull;
using ::testing::Return;

namespace cobalt {
namespace media {

MockPipelineClient::MockPipelineClient() {}
MockPipelineClient::~MockPipelineClient() {}

MockPipeline::MockPipeline() {}
MockPipeline::~MockPipeline() {}

void MockPipeline::Start(Demuxer* demuxer, std::unique_ptr<Renderer> renderer,
                         Client* client, const PipelineStatusCB& seek_cb) {
  Start(demuxer, &renderer, client, seek_cb);
}

void MockPipeline::Resume(std::unique_ptr<Renderer> renderer,
                          base::TimeDelta timestamp,
                          const PipelineStatusCB& seek_cb) {
  Resume(&renderer, timestamp, seek_cb);
}

MockDemuxer::MockDemuxer() {}

MockDemuxer::~MockDemuxer() {}

std::string MockDemuxer::GetDisplayName() const { return "MockDemuxer"; }

MockDemuxerStream::MockDemuxerStream(DemuxerStream::Type type)
    : type_(type), liveness_(LIVENESS_UNKNOWN) {}

MockDemuxerStream::~MockDemuxerStream() {}

DemuxerStream::Type MockDemuxerStream::type() const { return type_; }

DemuxerStream::Liveness MockDemuxerStream::liveness() const {
  return liveness_;
}

AudioDecoderConfig MockDemuxerStream::audio_decoder_config() {
  DCHECK_EQ(type_, DemuxerStream::AUDIO);
  return audio_decoder_config_;
}

VideoDecoderConfig MockDemuxerStream::video_decoder_config() {
  DCHECK_EQ(type_, DemuxerStream::VIDEO);
  return video_decoder_config_;
}

void MockDemuxerStream::set_audio_decoder_config(
    const AudioDecoderConfig& config) {
  DCHECK_EQ(type_, DemuxerStream::AUDIO);
  audio_decoder_config_ = config;
}

void MockDemuxerStream::set_video_decoder_config(
    const VideoDecoderConfig& config) {
  DCHECK_EQ(type_, DemuxerStream::VIDEO);
  video_decoder_config_ = config;
}

void MockDemuxerStream::set_liveness(DemuxerStream::Liveness liveness) {
  liveness_ = liveness;
}

VideoRotation MockDemuxerStream::video_rotation() { return VIDEO_ROTATION_0; }

std::string MockVideoDecoder::GetDisplayName() const {
  return "MockVideoDecoder";
}

MockVideoDecoder::MockVideoDecoder() {
  ON_CALL(*this, CanReadWithoutStalling()).WillByDefault(Return(true));
}

std::string MockAudioDecoder::GetDisplayName() const {
  return "MockAudioDecoder";
}

MockVideoDecoder::~MockVideoDecoder() {}

MockAudioDecoder::MockAudioDecoder() {}

MockAudioDecoder::~MockAudioDecoder() {}

MockRendererClient::MockRendererClient() {}

MockRendererClient::~MockRendererClient() {}

MockVideoRenderer::MockVideoRenderer() {}

MockVideoRenderer::~MockVideoRenderer() {}

MockAudioRenderer::MockAudioRenderer() {}

MockAudioRenderer::~MockAudioRenderer() {}

MockRenderer::MockRenderer() {}

MockRenderer::~MockRenderer() {}

MockTimeSource::MockTimeSource() {}

MockTimeSource::~MockTimeSource() {}

MockTextTrack::MockTextTrack() {}

MockTextTrack::~MockTextTrack() {}

MockDecryptor::MockDecryptor() {}

MockDecryptor::~MockDecryptor() {}

MockCdmContext::MockCdmContext() {}

MockCdmContext::~MockCdmContext() {}

int MockCdmContext::GetCdmId() const { return cdm_id_; }

void MockCdmContext::set_cdm_id(int cdm_id) { cdm_id_ = cdm_id; }

MockStreamParser::MockStreamParser() {}

MockStreamParser::~MockStreamParser() {}

}  // namespace media
}  // namespace cobalt
