| Index: webrtc/media/engine/payload_type_mapper_unittest.cc
 | 
| diff --git a/webrtc/media/engine/payload_type_mapper_unittest.cc b/webrtc/media/engine/payload_type_mapper_unittest.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..70420866380fc4f171f17f1a7a16e977c8471f90
 | 
| --- /dev/null
 | 
| +++ b/webrtc/media/engine/payload_type_mapper_unittest.cc
 | 
| @@ -0,0 +1,162 @@
 | 
| +/*
 | 
| + *  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 <set>
 | 
| +#include <string>
 | 
| +
 | 
| +#include "testing/gtest/include/gtest/gtest.h"
 | 
| +#include "webrtc/media/engine/payload_type_mapper.h"
 | 
| +
 | 
| +namespace cricket {
 | 
| +
 | 
| +class PayloadTypeMapperTest : public testing::Test {
 | 
| + public:
 | 
| +  // TODO(ossu): These are to work around missing comparison operators in
 | 
| +  // rtc::Optional. They should be removed once Optional has been updated.
 | 
| +  int FindMapping(const webrtc::SdpAudioFormat& format) {
 | 
| +    auto opt_mapping = mapper_.FindMappingFor(format);
 | 
| +    if (opt_mapping)
 | 
| +      return *opt_mapping;
 | 
| +    return -1;
 | 
| +  }
 | 
| +
 | 
| +  int GetMapping(const webrtc::SdpAudioFormat& format) {
 | 
| +    auto opt_mapping = mapper_.GetMappingFor(format);
 | 
| +    if (opt_mapping)
 | 
| +      return *opt_mapping;
 | 
| +    return -1;
 | 
| +  }
 | 
| +
 | 
| + protected:
 | 
| +  PayloadTypeMapper mapper_;
 | 
| +};
 | 
| +
 | 
| +TEST_F(PayloadTypeMapperTest, StaticPayloadTypes) {
 | 
| +  EXPECT_EQ(0,  FindMapping({"pcmu",   8000, 1}));
 | 
| +  EXPECT_EQ(3,  FindMapping({"gsm",    8000, 1}));
 | 
| +  EXPECT_EQ(4,  FindMapping({"g723",   8000, 1}));
 | 
| +  EXPECT_EQ(5,  FindMapping({"dvi4",   8000, 1}));
 | 
| +  EXPECT_EQ(6,  FindMapping({"dvi4",  16000, 1}));
 | 
| +  EXPECT_EQ(7,  FindMapping({"lpc",    8000, 1}));
 | 
| +  EXPECT_EQ(8,  FindMapping({"pcma",   8000, 1}));
 | 
| +  EXPECT_EQ(9,  FindMapping({"g722",   8000, 1}));
 | 
| +  EXPECT_EQ(10, FindMapping({"l16",   44100, 2}));
 | 
| +  EXPECT_EQ(11, FindMapping({"l16",   44100, 1}));
 | 
| +  EXPECT_EQ(12, FindMapping({"qcelp",  8000, 1}));
 | 
| +  EXPECT_EQ(13, FindMapping({"cn",     8000, 1}));
 | 
| +  EXPECT_EQ(14, FindMapping({"mpa",   90000, 0}));
 | 
| +  EXPECT_EQ(14, FindMapping({"mpa",   90000, 1}));
 | 
| +  EXPECT_EQ(15, FindMapping({"g728",   8000, 1}));
 | 
| +  EXPECT_EQ(16, FindMapping({"dvi4",  11025, 1}));
 | 
| +  EXPECT_EQ(17, FindMapping({"dvi4",  22050, 1}));
 | 
| +  EXPECT_EQ(18, FindMapping({"g729",   8000, 1}));
 | 
| +}
 | 
| +
 | 
| +TEST_F(PayloadTypeMapperTest, WebRTCPayloadTypes) {
 | 
| +  // Tests that the payload mapper knows about the formats we've been using in
 | 
| +  // WebRTC, with their hard coded values.
 | 
| +  auto video_mapping = [this] (const char *name) {
 | 
| +    return FindMapping({name, kVideoCodecClockrate, 0});
 | 
| +  };
 | 
| +  EXPECT_EQ(kDefaultVp8PlType,  video_mapping(kVp8CodecName));
 | 
| +  EXPECT_EQ(kDefaultVp9PlType,  video_mapping(kVp9CodecName));
 | 
| +  EXPECT_EQ(kDefaultH264PlType, video_mapping(kH264CodecName));
 | 
| +  EXPECT_EQ(kDefaultRedPlType,  video_mapping(kRedCodecName));
 | 
| +  EXPECT_EQ(kDefaultUlpfecType, video_mapping(kUlpfecCodecName));
 | 
| +
 | 
| +  auto rtx_mapping = [this] (int payload_type) {
 | 
| +    return FindMapping({kRtxCodecName, kVideoCodecClockrate, 0,
 | 
| +        {{ kCodecParamAssociatedPayloadType, std::to_string(payload_type)}}});
 | 
| +  };
 | 
| +  EXPECT_EQ(kDefaultRtxVp8PlType,  rtx_mapping(kDefaultVp8PlType));
 | 
| +  EXPECT_EQ(kDefaultRtxVp9PlType,  rtx_mapping(kDefaultVp9PlType));
 | 
| +  EXPECT_EQ(kDefaultRtxH264PlType, rtx_mapping(kDefaultH264PlType));
 | 
| +  EXPECT_EQ(kDefaultRtxRedPlType,  rtx_mapping(kDefaultRedPlType));
 | 
| +
 | 
| +  EXPECT_EQ(102, FindMapping({kIlbcCodecName,  8000, 1}));
 | 
| +  EXPECT_EQ(103, FindMapping({kIsacCodecName, 16000, 1}));
 | 
| +  EXPECT_EQ(104, FindMapping({kIsacCodecName, 32000, 1}));
 | 
| +  EXPECT_EQ(105, FindMapping({kCnCodecName,   16000, 1}));
 | 
| +  EXPECT_EQ(106, FindMapping({kCnCodecName,   32000, 1}));
 | 
| +  EXPECT_EQ(111, FindMapping({kOpusCodecName, 48000, 2,
 | 
| +        {{"minptime", "10"}, {"useinbandfec", "1"}}}));
 | 
| +  EXPECT_EQ(126, FindMapping({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, FindMapping(format))
 | 
| +          << "Mapping must be permanent after successful call to "
 | 
| +             "GetMappingFor";
 | 
| +      EXPECT_EQ(payload_type, GetMapping(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
 | 
| 
 |