/* * Copyright (c) 2017 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 "api/audio_codecs/opus/audio_decoder_opus.h" #include #include #include #include #include #include #include "absl/strings/match.h" #include "api/audio_codecs/audio_codec_pair_id.h" #include "api/audio_codecs/audio_decoder.h" #include "api/audio_codecs/audio_format.h" #include "modules/audio_coding/codecs/opus/audio_decoder_opus.h" #include "rtc_base/checks.h" namespace webrtc { namespace { int GetDefaultNumChannels(const FieldTrialsView& field_trials) { return field_trials.IsEnabled("WebRTC-Audio-OpusDecodeStereoByDefault") ? 2 : 1; } } // namespace bool AudioDecoderOpus::Config::IsOk() const { if (sample_rate_hz != 16000 && sample_rate_hz != 48000) { // Unsupported sample rate. (libopus supports a few other rates as // well; we can add support for them when needed.) return false; } return !num_channels.has_value() || *num_channels == 1 || *num_channels == 2; } std::optional AudioDecoderOpus::SdpToConfig( const SdpAudioFormat& format) { if (!absl::EqualsIgnoreCase(format.name, "opus") || format.clockrate_hz != 48000 || format.num_channels != 2) { return std::nullopt; } Config config; // Parse the "stereo" codec parameter. If set, it overrides the default number // of channels. const auto stereo_param = format.parameters.find("stereo"); if (stereo_param != format.parameters.end()) { if (stereo_param->second == "0") { config.num_channels = 1; } else if (stereo_param->second == "1") { config.num_channels = 2; } else { // Malformed stereo parameter. return std::nullopt; } } if (!config.IsOk()) { RTC_DCHECK_NOTREACHED(); return std::nullopt; } return config; } void AudioDecoderOpus::AppendSupportedDecoders( std::vector* specs) { AudioCodecInfo opus_info{48000, 1, 64000, 6000, 510000}; opus_info.allow_comfort_noise = false; opus_info.supports_network_adaption = true; SdpAudioFormat opus_format( {"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}}); specs->push_back({std::move(opus_format), opus_info}); } std::unique_ptr AudioDecoderOpus::MakeAudioDecoder( const Environment& env, Config config) { if (!config.IsOk()) { RTC_DCHECK_NOTREACHED(); return nullptr; } return std::make_unique( env.field_trials(), config.num_channels.value_or(GetDefaultNumChannels(env.field_trials())), config.sample_rate_hz); } } // namespace webrtc