audio_decoder_opus.cc (3101B)
1 /* 2 * Copyright (c) 2017 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_decoder_opus.h" 12 13 #include <map> 14 #include <memory> 15 #include <optional> 16 #include <string> 17 #include <utility> 18 #include <vector> 19 20 #include "absl/strings/match.h" 21 #include "api/audio_codecs/audio_decoder.h" 22 #include "api/audio_codecs/audio_format.h" 23 #include "api/environment/environment.h" 24 #include "api/field_trials_view.h" 25 #include "modules/audio_coding/codecs/opus/audio_decoder_opus.h" 26 #include "rtc_base/checks.h" 27 28 namespace webrtc { 29 namespace { 30 31 int GetDefaultNumChannels(const FieldTrialsView& field_trials) { 32 return field_trials.IsEnabled("WebRTC-Audio-OpusDecodeStereoByDefault") ? 2 33 : 1; 34 } 35 36 } // namespace 37 38 bool AudioDecoderOpus::Config::IsOk() const { 39 if (sample_rate_hz != 16000 && sample_rate_hz != 48000) { 40 // Unsupported sample rate. (libopus supports a few other rates as 41 // well; we can add support for them when needed.) 42 return false; 43 } 44 return !num_channels.has_value() || *num_channels == 1 || *num_channels == 2; 45 } 46 47 std::optional<AudioDecoderOpus::Config> AudioDecoderOpus::SdpToConfig( 48 const SdpAudioFormat& format) { 49 if (!absl::EqualsIgnoreCase(format.name, "opus") || 50 format.clockrate_hz != 48000 || format.num_channels != 2) { 51 return std::nullopt; 52 } 53 54 Config config; 55 56 // Parse the "stereo" codec parameter. If set, it overrides the default number 57 // of channels. 58 const auto stereo_param = format.parameters.find("stereo"); 59 if (stereo_param != format.parameters.end()) { 60 if (stereo_param->second == "0") { 61 config.num_channels = 1; 62 } else if (stereo_param->second == "1") { 63 config.num_channels = 2; 64 } else { 65 // Malformed stereo parameter. 66 return std::nullopt; 67 } 68 } 69 70 if (!config.IsOk()) { 71 RTC_DCHECK_NOTREACHED(); 72 return std::nullopt; 73 } 74 return config; 75 } 76 77 void AudioDecoderOpus::AppendSupportedDecoders( 78 std::vector<AudioCodecSpec>* specs) { 79 AudioCodecInfo opus_info{48000, 1, 64000, 6000, 510000}; 80 opus_info.allow_comfort_noise = false; 81 opus_info.supports_network_adaption = true; 82 SdpAudioFormat opus_format( 83 {"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}}); 84 specs->push_back({std::move(opus_format), opus_info}); 85 } 86 87 std::unique_ptr<AudioDecoder> AudioDecoderOpus::MakeAudioDecoder( 88 const Environment& env, 89 Config config) { 90 if (!config.IsOk()) { 91 RTC_DCHECK_NOTREACHED(); 92 return nullptr; 93 } 94 return std::make_unique<AudioDecoderOpusImpl>( 95 env.field_trials(), 96 config.num_channels.value_or(GetDefaultNumChannels(env.field_trials())), 97 config.sample_rate_hz); 98 } 99 100 } // namespace webrtc