/*
 *  Copyright (c) 2016 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.
 */

#include <memory>

#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "test/gtest.h"

namespace webrtc {

TEST(AudioDecoderFactoryTest, CreateUnknownDecoder) {
  rtc::scoped_refptr<AudioDecoderFactory> adf =
      CreateBuiltinAudioDecoderFactory();
  ASSERT_TRUE(adf);
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("rey", 8000, 1), absl::nullopt));
}

TEST(AudioDecoderFactoryTest, CreatePcmu) {
  rtc::scoped_refptr<AudioDecoderFactory> adf =
      CreateBuiltinAudioDecoderFactory();
  ASSERT_TRUE(adf);
  // PCMu supports 8 kHz, and any number of channels.
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 0), absl::nullopt));
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 1), absl::nullopt));
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 2), absl::nullopt));
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 8000, 3), absl::nullopt));
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("pcmu", 16000, 1), absl::nullopt));
}

TEST(AudioDecoderFactoryTest, CreatePcma) {
  rtc::scoped_refptr<AudioDecoderFactory> adf =
      CreateBuiltinAudioDecoderFactory();
  ASSERT_TRUE(adf);
  // PCMa supports 8 kHz, and any number of channels.
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 0), absl::nullopt));
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 1), absl::nullopt));
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 2), absl::nullopt));
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("pcma", 8000, 3), absl::nullopt));
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("pcma", 16000, 1), absl::nullopt));
}

TEST(AudioDecoderFactoryTest, CreateIlbc) {
  rtc::scoped_refptr<AudioDecoderFactory> adf =
      CreateBuiltinAudioDecoderFactory();
  ASSERT_TRUE(adf);
  // iLBC supports 8 kHz, 1 channel.
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 8000, 0), absl::nullopt));
#ifdef WEBRTC_CODEC_ILBC
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 8000, 1), absl::nullopt));
#endif
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 8000, 2), absl::nullopt));
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("ilbc", 16000, 1), absl::nullopt));
}

TEST(AudioDecoderFactoryTest, CreateIsac) {
  rtc::scoped_refptr<AudioDecoderFactory> adf =
      CreateBuiltinAudioDecoderFactory();
  ASSERT_TRUE(adf);
  // iSAC supports 16 kHz, 1 channel. The float implementation additionally
  // supports 32 kHz, 1 channel.
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("isac", 16000, 0), absl::nullopt));
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("isac", 16000, 1), absl::nullopt));
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("isac", 16000, 2), absl::nullopt));
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("isac", 8000, 1), absl::nullopt));
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("isac", 48000, 1), absl::nullopt));
#ifdef WEBRTC_ARCH_ARM
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("isac", 32000, 1), absl::nullopt));
#else
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("isac", 32000, 1), absl::nullopt));
#endif
}

TEST(AudioDecoderFactoryTest, CreateL16) {
  rtc::scoped_refptr<AudioDecoderFactory> adf =
      CreateBuiltinAudioDecoderFactory();
  ASSERT_TRUE(adf);
  // L16 supports any clock rate, any number of channels.
  const int clockrates[] = {8000, 16000, 32000, 48000};
  const int num_channels[] = {1, 2, 3, 4711};
  for (int clockrate : clockrates) {
    EXPECT_FALSE(adf->MakeAudioDecoder(SdpAudioFormat("l16", clockrate, 0),
                                       absl::nullopt));
    for (int channels : num_channels) {
      EXPECT_TRUE(adf->MakeAudioDecoder(
          SdpAudioFormat("l16", clockrate, channels), absl::nullopt));
    }
  }
}

TEST(AudioDecoderFactoryTest, CreateG722) {
  rtc::scoped_refptr<AudioDecoderFactory> adf =
      CreateBuiltinAudioDecoderFactory();
  ASSERT_TRUE(adf);
  // g722 supports 8 kHz, 1-2 channels.
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 0), absl::nullopt));
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 1), absl::nullopt));
  EXPECT_TRUE(
      adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 2), absl::nullopt));
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 3), absl::nullopt));
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("g722", 16000, 1), absl::nullopt));
  EXPECT_FALSE(
      adf->MakeAudioDecoder(SdpAudioFormat("g722", 32000, 1), absl::nullopt));

  // g722 actually uses a 16 kHz sample rate instead of the nominal 8 kHz.
  std::unique_ptr<AudioDecoder> dec =
      adf->MakeAudioDecoder(SdpAudioFormat("g722", 8000, 1), absl::nullopt);
  EXPECT_EQ(16000, dec->SampleRateHz());
}

TEST(AudioDecoderFactoryTest, CreateOpus) {
  rtc::scoped_refptr<AudioDecoderFactory> adf =
      CreateBuiltinAudioDecoderFactory();
  ASSERT_TRUE(adf);
  // Opus supports 48 kHz, 2 channels, and wants a "stereo" parameter whose
  // value is either "0" or "1".
  for (int hz : {8000, 16000, 32000, 48000}) {
    for (int channels : {0, 1, 2, 3}) {
      for (std::string stereo : {"XX", "0", "1", "2"}) {
        std::map<std::string, std::string> params;
        if (stereo != "XX") {
          params["stereo"] = stereo;
        }
        const bool good = (hz == 48000 && channels == 2 &&
                           (stereo == "XX" || stereo == "0" || stereo == "1"));
        EXPECT_EQ(good,
                  static_cast<bool>(adf->MakeAudioDecoder(
                      SdpAudioFormat("opus", hz, channels, std::move(params)),
                      absl::nullopt)));
      }
    }
  }
}

}  // namespace webrtc
