/*
 *  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 "media/engine/payload_type_mapper.h"

#include <set>
#include <string>

#include "absl/strings/string_view.h"
#include "media/base/media_constants.h"
#include "test/gtest.h"

namespace cricket {

class PayloadTypeMapperTest : public ::testing::Test {
 protected:
  PayloadTypeMapper mapper_;
};

TEST_F(PayloadTypeMapperTest, StaticPayloadTypes) {
  EXPECT_EQ(0, mapper_.FindMappingFor({"pcmu", 8000, 1}));
  EXPECT_EQ(3, mapper_.FindMappingFor({"gsm", 8000, 1}));
  EXPECT_EQ(4, mapper_.FindMappingFor({"g723", 8000, 1}));
  EXPECT_EQ(5, mapper_.FindMappingFor({"dvi4", 8000, 1}));
  EXPECT_EQ(6, mapper_.FindMappingFor({"dvi4", 16000, 1}));
  EXPECT_EQ(7, mapper_.FindMappingFor({"lpc", 8000, 1}));
  EXPECT_EQ(8, mapper_.FindMappingFor({"pcma", 8000, 1}));
  EXPECT_EQ(9, mapper_.FindMappingFor({"g722", 8000, 1}));
  EXPECT_EQ(10, mapper_.FindMappingFor({"l16", 44100, 2}));
  EXPECT_EQ(11, mapper_.FindMappingFor({"l16", 44100, 1}));
  EXPECT_EQ(12, mapper_.FindMappingFor({"qcelp", 8000, 1}));
  EXPECT_EQ(13, mapper_.FindMappingFor({"cn", 8000, 1}));
  EXPECT_EQ(14, mapper_.FindMappingFor({"mpa", 90000, 0}));
  EXPECT_EQ(14, mapper_.FindMappingFor({"mpa", 90000, 1}));
  EXPECT_EQ(15, mapper_.FindMappingFor({"g728", 8000, 1}));
  EXPECT_EQ(16, mapper_.FindMappingFor({"dvi4", 11025, 1}));
  EXPECT_EQ(17, mapper_.FindMappingFor({"dvi4", 22050, 1}));
  EXPECT_EQ(18, mapper_.FindMappingFor({"g729", 8000, 1}));
}

TEST_F(PayloadTypeMapperTest, WebRTCPayloadTypes) {
  // Tests that the payload mapper knows about the audio and data formats we've
  // been using in WebRTC, with their hard coded values.
  auto data_mapping = [this](const char* name) {
    return mapper_.FindMappingFor({name, 0, 0});
  };
  EXPECT_EQ(kGoogleRtpDataCodecPlType, data_mapping(kGoogleRtpDataCodecName));

  EXPECT_EQ(102, mapper_.FindMappingFor({kIlbcCodecName, 8000, 1}));
  EXPECT_EQ(103, mapper_.FindMappingFor({kIsacCodecName, 16000, 1}));
  EXPECT_EQ(104, mapper_.FindMappingFor({kIsacCodecName, 32000, 1}));
  EXPECT_EQ(105, mapper_.FindMappingFor({kCnCodecName, 16000, 1}));
  EXPECT_EQ(106, mapper_.FindMappingFor({kCnCodecName, 32000, 1}));
  EXPECT_EQ(111, mapper_.FindMappingFor(
                     {kOpusCodecName,
                      48000,
                      2,
                      {{"minptime", "10"}, {"useinbandfec", "1"}}}));
  // TODO(solenberg): Remove 16k, 32k, 48k DTMF checks once these payload types
  // are dynamically assigned.
  EXPECT_EQ(110, mapper_.FindMappingFor({kDtmfCodecName, 48000, 1}));
  EXPECT_EQ(112, mapper_.FindMappingFor({kDtmfCodecName, 32000, 1}));
  EXPECT_EQ(113, mapper_.FindMappingFor({kDtmfCodecName, 16000, 1}));
  EXPECT_EQ(126, mapper_.FindMappingFor({kDtmfCodecName, 8000, 1}));
}

TEST_F(PayloadTypeMapperTest, ValidDynamicPayloadTypes) {
  // RFC 3551 says:
  // "This profile reserves payload type numbers in the range 96-127
  // exclusively for dynamic assignment.  Applications SHOULD first use
  // values in this range for dynamic payload types.  Those applications
  // which need to define more than 32 dynamic payload types MAY bind
  // codes below 96, in which case it is RECOMMENDED that unassigned
  // payload type numbers be used first.  However, the statically assigned
  // payload types are default bindings and MAY be dynamically bound to
  // new encodings if needed."

  // Tests that the payload mapper uses values in the dynamic payload type range
  // (96 - 127) before any others and that the values returned are all valid.
  bool has_been_below_96 = false;
  std::set<int> used_payload_types;
  for (int i = 0; i != 256; ++i) {
    std::string format_name = "unknown_format_" + std::to_string(i);
    webrtc::SdpAudioFormat format(format_name.c_str(), i * 100, (i % 2) + 1);
    auto opt_payload_type = mapper_.GetMappingFor(format);
    bool mapper_is_full = false;

    // There's a limited number of slots for payload types. We're fine with not
    // being able to map them all.
    if (opt_payload_type) {
      int payload_type = *opt_payload_type;
      EXPECT_FALSE(mapper_is_full) << "Mapping should not fail sporadically";
      EXPECT_EQ(used_payload_types.find(payload_type), used_payload_types.end())
          << "Payload types must not be reused";
      used_payload_types.insert(payload_type);
      EXPECT_GE(payload_type, 0) << "Negative payload types are invalid";
      EXPECT_LE(payload_type, 127) << "Payload types above 127 are invalid";
      EXPECT_FALSE(payload_type >= 96 && has_been_below_96);
      if (payload_type < 96)
        has_been_below_96 = true;

      EXPECT_EQ(payload_type, mapper_.FindMappingFor(format))
          << "Mapping must be permanent after successful call to "
             "GetMappingFor";
      EXPECT_EQ(payload_type, mapper_.GetMappingFor(format))
          << "Subsequent calls to GetMappingFor must return the same value";
    } else {
      mapper_is_full = true;
    }
  }

  // Also, we must've been able to map at least one dynamic payload type.
  EXPECT_FALSE(used_payload_types.empty())
      << "Mapper must support at least one user-defined payload type";
}

TEST_F(PayloadTypeMapperTest, ToAudioCodec) {
  webrtc::SdpAudioFormat format("unknown_format", 4711, 17);
  auto opt_payload_type = mapper_.GetMappingFor(format);
  EXPECT_TRUE(opt_payload_type);
  auto opt_audio_codec = mapper_.ToAudioCodec(format);
  EXPECT_TRUE(opt_audio_codec);

  if (opt_payload_type && opt_audio_codec) {
    int payload_type = *opt_payload_type;
    const AudioCodec& codec = *opt_audio_codec;

    EXPECT_EQ(codec.id, payload_type);
    EXPECT_EQ(codec.name, format.name);
    EXPECT_EQ(codec.clockrate, format.clockrate_hz);
    EXPECT_EQ(codec.channels, format.num_channels);
    EXPECT_EQ(codec.params, format.parameters);
  }
}

}  // namespace cricket
