aboutsummaryrefslogtreecommitdiff
path: root/media/engine/payload_type_mapper_unittest.cc
blob: 9c29827fa90bcf6d5816f1d272d9a42b39f03a6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 *  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 formats we've
  // been using in WebRTC, with their hard coded values.
  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"}}}));
  EXPECT_EQ(63, mapper_.FindMappingFor({kRedCodecName, 48000, 2}));
  // 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