/*
 *  Copyright (c) 2018 The WebRTC 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_AUDIO_DECODER_PROXY_FACTORY_H_
#define TEST_AUDIO_DECODER_PROXY_FACTORY_H_

#include <memory>
#include <utility>
#include <vector>

#include "api/audio_codecs/audio_decoder.h"
#include "api/audio_codecs/audio_decoder_factory.h"

namespace webrtc {
namespace test {

// A decoder factory with a single underlying AudioDecoder object, intended for
// test purposes. Each call to MakeAudioDecoder returns a proxy for the same
// decoder, typically a mock or fake decoder.
class AudioDecoderProxyFactory : public AudioDecoderFactory {
 public:
  explicit AudioDecoderProxyFactory(AudioDecoder* decoder)
      : decoder_(decoder) {}

  // Unused by tests.
  std::vector<AudioCodecSpec> GetSupportedDecoders() override {
    RTC_NOTREACHED();
    return {};
  }

  bool IsSupportedDecoder(const SdpAudioFormat& format) override {
    return true;
  }

  std::unique_ptr<AudioDecoder> MakeAudioDecoder(
      const SdpAudioFormat& /* format */,
      absl::optional<AudioCodecPairId> /* codec_pair_id */) override {
    return std::make_unique<DecoderProxy>(decoder_);
  }

 private:
  // Wrapper class, since CreateAudioDecoder needs to surrender
  // ownership to the object it returns.
  class DecoderProxy final : public AudioDecoder {
   public:
    explicit DecoderProxy(AudioDecoder* decoder) : decoder_(decoder) {}

   private:
    std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
                                          uint32_t timestamp) override {
      return decoder_->ParsePayload(std::move(payload), timestamp);
    }

    bool HasDecodePlc() const override { return decoder_->HasDecodePlc(); }

    int ErrorCode() override { return decoder_->ErrorCode(); }

    void Reset() override { decoder_->Reset(); }

    int SampleRateHz() const override { return decoder_->SampleRateHz(); }

    size_t Channels() const override { return decoder_->Channels(); }

    int DecodeInternal(const uint8_t* encoded,
                       size_t encoded_len,
                       int sample_rate_hz,
                       int16_t* decoded,
                       SpeechType* speech_type) override {
      // Needed for tests of NetEqImpl::DecodeCng, which calls the deprecated
      // Decode method.
      size_t max_decoded_bytes =
          decoder_->PacketDuration(encoded, encoded_len) *
          decoder_->Channels() * sizeof(int16_t);
      return decoder_->Decode(encoded, encoded_len, sample_rate_hz,
                              max_decoded_bytes, decoded, speech_type);
    }

    void GeneratePlc(size_t requested_samples_per_channel,
                     rtc::BufferT<int16_t>* concealment_audio) override {
      decoder_->GeneratePlc(requested_samples_per_channel, concealment_audio);
    }

    AudioDecoder* const decoder_;
  };

  AudioDecoder* const decoder_;
};

}  // namespace test
}  // namespace webrtc

#endif  // TEST_AUDIO_DECODER_PROXY_FACTORY_H_
