xref: /aosp_15_r20/external/webrtc/api/audio_codecs/opus/audio_encoder_multi_channel_opus_config.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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_config.h"
12 
13 namespace webrtc {
14 
15 namespace {
16 constexpr int kDefaultComplexity = 9;
17 }  // namespace
18 
AudioEncoderMultiChannelOpusConfig()19 AudioEncoderMultiChannelOpusConfig::AudioEncoderMultiChannelOpusConfig()
20     : frame_size_ms(kDefaultFrameSizeMs),
21       num_channels(1),
22       application(ApplicationMode::kVoip),
23       bitrate_bps(32000),
24       fec_enabled(false),
25       cbr_enabled(false),
26       dtx_enabled(false),
27       max_playback_rate_hz(48000),
28       complexity(kDefaultComplexity),
29       num_streams(-1),
30       coupled_streams(-1) {}
31 AudioEncoderMultiChannelOpusConfig::AudioEncoderMultiChannelOpusConfig(
32     const AudioEncoderMultiChannelOpusConfig&) = default;
33 AudioEncoderMultiChannelOpusConfig::~AudioEncoderMultiChannelOpusConfig() =
34     default;
35 AudioEncoderMultiChannelOpusConfig& AudioEncoderMultiChannelOpusConfig::
36 operator=(const AudioEncoderMultiChannelOpusConfig&) = default;
37 
IsOk() const38 bool AudioEncoderMultiChannelOpusConfig::IsOk() const {
39   if (frame_size_ms <= 0 || frame_size_ms % 10 != 0)
40     return false;
41   if (num_channels >= 255) {
42     return false;
43   }
44   if (bitrate_bps < kMinBitrateBps || bitrate_bps > kMaxBitrateBps)
45     return false;
46   if (complexity < 0 || complexity > 10)
47     return false;
48 
49   // Check the lengths:
50   if (num_streams < 0 || coupled_streams < 0) {
51     return false;
52   }
53   if (num_streams < coupled_streams) {
54     return false;
55   }
56   if (channel_mapping.size() != static_cast<size_t>(num_channels)) {
57     return false;
58   }
59 
60   // Every mono stream codes one channel, every coupled stream codes two. This
61   // is the total coded channel count:
62   const int max_coded_channel = num_streams + coupled_streams;
63   for (const auto& x : channel_mapping) {
64     // Coded channels >= max_coded_channel don't exist. Except for 255, which
65     // tells Opus to ignore input channel x.
66     if (x >= max_coded_channel && x != 255) {
67       return false;
68     }
69   }
70 
71   // Inverse mapping.
72   constexpr int kNotSet = -1;
73   std::vector<int> coded_channels_to_input_channels(max_coded_channel, kNotSet);
74   for (size_t i = 0; i < num_channels; ++i) {
75     if (channel_mapping[i] == 255) {
76       continue;
77     }
78 
79     // If it's not ignored, put it in the inverted mapping. But first check if
80     // we've told Opus to use another input channel for this coded channel:
81     const int coded_channel = channel_mapping[i];
82     if (coded_channels_to_input_channels[coded_channel] != kNotSet) {
83       // Coded channel `coded_channel` comes from both input channels
84       // `coded_channels_to_input_channels[coded_channel]` and `i`.
85       return false;
86     }
87 
88     coded_channels_to_input_channels[coded_channel] = i;
89   }
90 
91   // Check that we specified what input the encoder should use to produce
92   // every coded channel.
93   for (int i = 0; i < max_coded_channel; ++i) {
94     if (coded_channels_to_input_channels[i] == kNotSet) {
95       // Coded channel `i` has unspecified input channel.
96       return false;
97     }
98   }
99 
100   if (num_channels > 255 || max_coded_channel >= 255) {
101     return false;
102   }
103   return true;
104 }
105 
106 }  // namespace webrtc
107