/*
 *  Copyright (c) 2019 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 "api/audio_codecs/opus/audio_decoder_multi_channel_opus.h"

#include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
#include "test/gmock.h"
#include "test/gtest.h"

namespace webrtc {
using ::testing::NiceMock;
using ::testing::Return;

TEST(AudioDecoderMultiOpusTest, GetFormatParameter) {
  const SdpAudioFormat sdp_format("multiopus", 48000, 4,
                                  {{"channel_mapping", "0,1,2,3"},
                                   {"coupled_streams", "2"},
                                   {"num_streams", "2"}});

  EXPECT_EQ(GetFormatParameter(sdp_format, "channel_mapping"),
            absl::optional<std::string>("0,1,2,3"));

  EXPECT_EQ(GetFormatParameter<int>(sdp_format, "coupled_streams"),
            absl::optional<int>(2));

  EXPECT_EQ(GetFormatParameter(sdp_format, "missing"), absl::nullopt);

  EXPECT_EQ(GetFormatParameter<int>(sdp_format, "channel_mapping"),
            absl::nullopt);
}

TEST(AudioDecoderMultiOpusTest, InvalidChannelMappings) {
  {
    // Can't use channel 3 if there are only 2 channels.
    const SdpAudioFormat sdp_format("multiopus", 48000, 2,
                                    {{"channel_mapping", "3,0"},
                                     {"coupled_streams", "1"},
                                     {"num_streams", "2"}});
    const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
        AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);
    ASSERT_TRUE(decoder_config.has_value());
    EXPECT_FALSE(decoder_config->IsOk());

    const std::unique_ptr<AudioDecoder> opus_decoder =
        AudioDecoderMultiChannelOpus::MakeAudioDecoder(*decoder_config);

    EXPECT_FALSE(opus_decoder);
  }
  {
    // The mapping is too long. There are only 5 channels, but 6 elements in the
    // mapping.
    const SdpAudioFormat sdp_format("multiopus", 48000, 5,
                                    {{"channel_mapping", "0,1,2,3,4,5"},
                                     {"coupled_streams", "0"},
                                     {"num_streams", "2"}});
    const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
        AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);
    ASSERT_TRUE(decoder_config.has_value());
    EXPECT_FALSE(decoder_config->IsOk());

    const std::unique_ptr<AudioDecoder> opus_decoder =
        AudioDecoderMultiChannelOpus::MakeAudioDecoder(*decoder_config);

    EXPECT_FALSE(opus_decoder);
  }
  {
    // The mapping doesn't parse correctly.
    const SdpAudioFormat sdp_format(
        "multiopus", 48000, 5,
        {{"channel_mapping", "0,1,two,3,4"}, {"coupled_streams", "0"}});
    const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
        AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);
    EXPECT_FALSE(decoder_config.has_value());
  }
}

TEST(AudioDecoderMultiOpusTest, ValidSdpToConfigProducesCorrectConfig) {
  const SdpAudioFormat sdp_format("multiopus", 48000, 4,
                                  {{"channel_mapping", "3,1,2,0"},
                                   {"coupled_streams", "2"},
                                   {"num_streams", "2"}});

  const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
      AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);

  ASSERT_TRUE(decoder_config.has_value());
  EXPECT_TRUE(decoder_config->IsOk());
  EXPECT_EQ(decoder_config->coupled_streams, 2);
  EXPECT_THAT(decoder_config->channel_mapping,
              ::testing::ContainerEq(std::vector<unsigned char>({3, 1, 2, 0})));
}

TEST(AudioDecoderMultiOpusTest, InvalidSdpToConfigDoesNotProduceConfig) {
  {
    const SdpAudioFormat sdp_format("multiopus", 48000, 4,
                                    {{"channel_mapping", "0,1,2,3"},
                                     {"coupled_stream", "2"},
                                     {"num_streams", "2"}});

    const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
        AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);

    EXPECT_FALSE(decoder_config.has_value());
  }

  {
    const SdpAudioFormat sdp_format("multiopus", 48000, 4,
                                    {{"channel_mapping", "0,1,2 3"},
                                     {"coupled_streams", "2"},
                                     {"num_streams", "2"}});

    const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
        AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);

    EXPECT_FALSE(decoder_config.has_value());
  }
}

TEST(AudioDecoderMultiOpusTest, CodecsCanBeCreated) {
  const SdpAudioFormat sdp_format("multiopus", 48000, 4,
                                  {{"channel_mapping", "0,1,2,3"},
                                   {"coupled_streams", "2"},
                                   {"num_streams", "2"}});

  const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
      AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format);

  ASSERT_TRUE(decoder_config.has_value());

  const std::unique_ptr<AudioDecoder> opus_decoder =
      AudioDecoderMultiChannelOpus::MakeAudioDecoder(*decoder_config);

  EXPECT_TRUE(opus_decoder);
}

TEST(AudioDecoderMultiOpusTest, AdvertisedCodecsCanBeCreated) {
  std::vector<AudioCodecSpec> specs;
  AudioDecoderMultiChannelOpus::AppendSupportedDecoders(&specs);

  EXPECT_FALSE(specs.empty());

  for (const AudioCodecSpec& spec : specs) {
    const absl::optional<AudioDecoderMultiChannelOpus::Config> decoder_config =
        AudioDecoderMultiChannelOpus::SdpToConfig(spec.format);
    ASSERT_TRUE(decoder_config.has_value());

    const std::unique_ptr<AudioDecoder> opus_decoder =
        AudioDecoderMultiChannelOpus::MakeAudioDecoder(*decoder_config);

    EXPECT_TRUE(opus_decoder);
  }
}
}  // namespace webrtc
