1 /*
2 * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "api/audio_codecs/opus/audio_encoder_multi_channel_opus.h"
12
13 #include "test/gmock.h"
14
15 namespace webrtc {
16 using ::testing::NiceMock;
17 using ::testing::Return;
18
19 namespace {
20 constexpr int kOpusPayloadType = 120;
21 } // namespace
22
TEST(AudioEncoderMultiOpusTest,CheckConfigValidity)23 TEST(AudioEncoderMultiOpusTest, CheckConfigValidity) {
24 {
25 const SdpAudioFormat sdp_format("multiopus", 48000, 2,
26 {{"channel_mapping", "3,0"},
27 {"coupled_streams", "1"},
28 {"num_streams", "2"}});
29 const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
30 AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
31 ASSERT_TRUE(encoder_config.has_value());
32
33 // Maps input channel 0 to coded channel 3, which doesn't exist.
34 EXPECT_FALSE(encoder_config->IsOk());
35 }
36
37 {
38 const SdpAudioFormat sdp_format("multiopus", 48000, 2,
39 {{"channel_mapping", "0"},
40 {"coupled_streams", "1"},
41 {"num_streams", "2"}});
42 const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
43 AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
44 ASSERT_TRUE(encoder_config.has_value());
45
46 // The mapping is too short.
47 EXPECT_FALSE(encoder_config->IsOk());
48 }
49 {
50 const SdpAudioFormat sdp_format("multiopus", 48000, 3,
51 {{"channel_mapping", "0,0,0"},
52 {"coupled_streams", "0"},
53 {"num_streams", "1"}});
54 const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
55 AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
56 ASSERT_TRUE(encoder_config.has_value());
57
58 // Coded channel 0 comes from both input channels 0, 1 and 2.
59 EXPECT_FALSE(encoder_config->IsOk());
60 }
61 {
62 const SdpAudioFormat sdp_format("multiopus", 48000, 3,
63 {{"channel_mapping", "0,255,255"},
64 {"coupled_streams", "0"},
65 {"num_streams", "1"}});
66 const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
67 AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
68 ASSERT_TRUE(encoder_config.has_value());
69
70 // This is fine, because channels 1, 2 are set to be ignored.
71 EXPECT_TRUE(encoder_config->IsOk());
72 }
73 {
74 const SdpAudioFormat sdp_format("multiopus", 48000, 3,
75 {{"channel_mapping", "0,255,255"},
76 {"coupled_streams", "0"},
77 {"num_streams", "2"}});
78 const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
79 AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
80 ASSERT_TRUE(encoder_config.has_value());
81
82 // This is NOT fine, because channels nothing says how coded channel 1
83 // should be coded.
84 EXPECT_FALSE(encoder_config->IsOk());
85 }
86 }
87
TEST(AudioEncoderMultiOpusTest,ConfigValuesAreParsedCorrectly)88 TEST(AudioEncoderMultiOpusTest, ConfigValuesAreParsedCorrectly) {
89 SdpAudioFormat sdp_format({"multiopus",
90 48000,
91 6,
92 {{"minptime", "10"},
93 {"useinbandfec", "1"},
94 {"channel_mapping", "0,4,1,2,3,5"},
95 {"num_streams", "4"},
96 {"coupled_streams", "2"}}});
97 const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
98 AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
99 ASSERT_TRUE(encoder_config.has_value());
100
101 EXPECT_EQ(encoder_config->coupled_streams, 2);
102 EXPECT_EQ(encoder_config->num_streams, 4);
103 EXPECT_THAT(
104 encoder_config->channel_mapping,
105 testing::ContainerEq(std::vector<unsigned char>({0, 4, 1, 2, 3, 5})));
106 }
107
TEST(AudioEncoderMultiOpusTest,CreateFromValidOrInvalidConfig)108 TEST(AudioEncoderMultiOpusTest, CreateFromValidOrInvalidConfig) {
109 {
110 const SdpAudioFormat sdp_format("multiopus", 48000, 3,
111 {{"channel_mapping", "0,255,255"},
112 {"coupled_streams", "0"},
113 {"num_streams", "2"}});
114 const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
115 AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
116 ASSERT_TRUE(encoder_config.has_value());
117
118 // Invalid config from the ConfigValidity test. It's not allowed by our
119 // checks, but Opus is more forgiving.
120 EXPECT_FALSE(encoder_config->IsOk());
121
122 const std::unique_ptr<AudioEncoder> opus_encoder =
123 AudioEncoderMultiChannelOpus::MakeAudioEncoder(*encoder_config,
124 kOpusPayloadType);
125
126 // Shouldn't be possible (but shouldn't result in a crash) to create an
127 // Encoder from an invalid config.
128 EXPECT_FALSE(opus_encoder);
129 }
130 {
131 const SdpAudioFormat sdp_format("multiopus", 48000, 3,
132 {{"channel_mapping", "1,255,0"},
133 {"coupled_streams", "1"},
134 {"num_streams", "1"}});
135 const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
136 AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format);
137 ASSERT_TRUE(encoder_config.has_value());
138
139 EXPECT_THAT(encoder_config->channel_mapping,
140 testing::ContainerEq(std::vector<unsigned char>({1, 255, 0})));
141
142 EXPECT_TRUE(encoder_config->IsOk());
143
144 const std::unique_ptr<AudioEncoder> opus_encoder =
145 AudioEncoderMultiChannelOpus::MakeAudioEncoder(*encoder_config,
146 kOpusPayloadType);
147
148 // Creating an encoder from a valid config should work.
149 EXPECT_TRUE(opus_encoder);
150 }
151 }
152
TEST(AudioEncoderMultiOpusTest,AdvertisedCodecsCanBeCreated)153 TEST(AudioEncoderMultiOpusTest, AdvertisedCodecsCanBeCreated) {
154 std::vector<AudioCodecSpec> specs;
155 AudioEncoderMultiChannelOpus::AppendSupportedEncoders(&specs);
156
157 EXPECT_FALSE(specs.empty());
158
159 for (const AudioCodecSpec& spec : specs) {
160 const absl::optional<AudioEncoderMultiChannelOpus::Config> encoder_config =
161 AudioEncoderMultiChannelOpus::SdpToConfig(spec.format);
162 ASSERT_TRUE(encoder_config.has_value());
163
164 const std::unique_ptr<AudioEncoder> opus_encoder =
165 AudioEncoderMultiChannelOpus::MakeAudioEncoder(*encoder_config,
166 kOpusPayloadType);
167
168 EXPECT_TRUE(opus_encoder);
169 }
170 }
171
172 } // namespace webrtc
173