Set the maximum number of audio channels to 24
The number of audio channels can be configured in SDP, and can thus be set to arbitrary values. However, the audio code has limitations that prevent a high number of channels from working well in practice. Bug: chromium:1265806 Change-Id: I6f6c3f68a3791bb189a614eece6bd0ed7874f252 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/237807 Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Ivo Creusen <ivoc@webrtc.org> Cr-Commit-Position: refs/heads/main@{#35359}
This commit is contained in:
committed by
WebRTC LUCI CQ
parent
584e3f9f8e
commit
d823259c7f
@ -29,7 +29,8 @@ struct RTC_EXPORT AudioDecoderL16 {
|
|||||||
bool IsOk() const {
|
bool IsOk() const {
|
||||||
return (sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
|
return (sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
|
||||||
sample_rate_hz == 32000 || sample_rate_hz == 48000) &&
|
sample_rate_hz == 32000 || sample_rate_hz == 48000) &&
|
||||||
num_channels >= 1;
|
(num_channels >= 1 &&
|
||||||
|
num_channels <= AudioDecoder::kMaxNumberOfChannels);
|
||||||
}
|
}
|
||||||
int sample_rate_hz = 8000;
|
int sample_rate_hz = 8000;
|
||||||
int num_channels = 1;
|
int num_channels = 1;
|
||||||
|
|||||||
@ -29,7 +29,9 @@ struct RTC_EXPORT AudioEncoderL16 {
|
|||||||
bool IsOk() const {
|
bool IsOk() const {
|
||||||
return (sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
|
return (sample_rate_hz == 8000 || sample_rate_hz == 16000 ||
|
||||||
sample_rate_hz == 32000 || sample_rate_hz == 48000) &&
|
sample_rate_hz == 32000 || sample_rate_hz == 48000) &&
|
||||||
num_channels >= 1 && frame_size_ms > 0 && frame_size_ms <= 120 &&
|
num_channels >= 1 &&
|
||||||
|
num_channels <= AudioEncoder::kMaxNumberOfChannels &&
|
||||||
|
frame_size_ms > 0 && frame_size_ms <= 120 &&
|
||||||
frame_size_ms % 10 == 0;
|
frame_size_ms % 10 == 0;
|
||||||
}
|
}
|
||||||
int sample_rate_hz = 8000;
|
int sample_rate_hz = 8000;
|
||||||
|
|||||||
@ -166,4 +166,5 @@ AudioDecoder::SpeechType AudioDecoder::ConvertSpeechType(int16_t type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr int AudioDecoder::kMaxNumberOfChannels;
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -170,6 +170,9 @@ class AudioDecoder {
|
|||||||
// during the lifetime of the decoder.
|
// during the lifetime of the decoder.
|
||||||
virtual size_t Channels() const = 0;
|
virtual size_t Channels() const = 0;
|
||||||
|
|
||||||
|
// The maximum number of audio channels supported by WebRTC decoders.
|
||||||
|
static constexpr int kMaxNumberOfChannels = 24;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static SpeechType ConvertSpeechType(int16_t type);
|
static SpeechType ConvertSpeechType(int16_t type);
|
||||||
|
|
||||||
|
|||||||
@ -110,4 +110,5 @@ ANAStats AudioEncoder::GetANAStats() const {
|
|||||||
return ANAStats();
|
return ANAStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr int AudioEncoder::kMaxNumberOfChannels;
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -246,6 +246,9 @@ class AudioEncoder {
|
|||||||
virtual absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
|
virtual absl::optional<std::pair<TimeDelta, TimeDelta>> GetFrameLengthRange()
|
||||||
const = 0;
|
const = 0;
|
||||||
|
|
||||||
|
// The maximum number of audio channels supported by WebRTC encoders.
|
||||||
|
static constexpr int kMaxNumberOfChannels = 24;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Subclasses implement this to perform the actual encoding. Called by
|
// Subclasses implement this to perform the actual encoding. Called by
|
||||||
// Encode().
|
// Encode().
|
||||||
|
|||||||
@ -28,7 +28,9 @@ struct RTC_EXPORT AudioDecoderG711 {
|
|||||||
struct Config {
|
struct Config {
|
||||||
enum class Type { kPcmU, kPcmA };
|
enum class Type { kPcmU, kPcmA };
|
||||||
bool IsOk() const {
|
bool IsOk() const {
|
||||||
return (type == Type::kPcmU || type == Type::kPcmA) && num_channels >= 1;
|
return (type == Type::kPcmU || type == Type::kPcmA) &&
|
||||||
|
num_channels >= 1 &&
|
||||||
|
num_channels <= AudioDecoder::kMaxNumberOfChannels;
|
||||||
}
|
}
|
||||||
Type type;
|
Type type;
|
||||||
int num_channels;
|
int num_channels;
|
||||||
|
|||||||
@ -29,7 +29,9 @@ struct RTC_EXPORT AudioEncoderG711 {
|
|||||||
enum class Type { kPcmU, kPcmA };
|
enum class Type { kPcmU, kPcmA };
|
||||||
bool IsOk() const {
|
bool IsOk() const {
|
||||||
return (type == Type::kPcmU || type == Type::kPcmA) &&
|
return (type == Type::kPcmU || type == Type::kPcmA) &&
|
||||||
frame_size_ms > 0 && frame_size_ms % 10 == 0 && num_channels >= 1;
|
frame_size_ms > 0 && frame_size_ms % 10 == 0 &&
|
||||||
|
num_channels >= 1 &&
|
||||||
|
num_channels <= AudioEncoder::kMaxNumberOfChannels;
|
||||||
}
|
}
|
||||||
Type type = Type::kPcmU;
|
Type type = Type::kPcmU;
|
||||||
int num_channels = 1;
|
int num_channels = 1;
|
||||||
|
|||||||
@ -15,7 +15,8 @@ namespace webrtc {
|
|||||||
|
|
||||||
struct AudioEncoderG722Config {
|
struct AudioEncoderG722Config {
|
||||||
bool IsOk() const {
|
bool IsOk() const {
|
||||||
return frame_size_ms > 0 && frame_size_ms % 10 == 0 && num_channels >= 1;
|
return frame_size_ms > 0 && frame_size_ms % 10 == 0 && num_channels >= 1 &&
|
||||||
|
num_channels <= AudioEncoder::kMaxNumberOfChannels;
|
||||||
}
|
}
|
||||||
int frame_size_ms = 20;
|
int frame_size_ms = 20;
|
||||||
int num_channels = 1;
|
int num_channels = 1;
|
||||||
|
|||||||
@ -30,7 +30,8 @@ struct AudioDecoderMultiChannelOpusConfig {
|
|||||||
std::vector<unsigned char> channel_mapping;
|
std::vector<unsigned char> channel_mapping;
|
||||||
|
|
||||||
bool IsOk() const {
|
bool IsOk() const {
|
||||||
if (num_channels < 0 || num_streams < 0 || coupled_streams < 0) {
|
if (num_channels < 1 || num_channels > AudioDecoder::kMaxNumberOfChannels ||
|
||||||
|
num_streams < 0 || coupled_streams < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (num_streams < coupled_streams) {
|
if (num_streams < coupled_streams) {
|
||||||
|
|||||||
@ -104,9 +104,9 @@ TEST(AudioDecoderFactoryTest, CreateL16) {
|
|||||||
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||||
CreateBuiltinAudioDecoderFactory();
|
CreateBuiltinAudioDecoderFactory();
|
||||||
ASSERT_TRUE(adf);
|
ASSERT_TRUE(adf);
|
||||||
// L16 supports any clock rate, any number of channels.
|
// L16 supports any clock rate and any number of channels up to 24.
|
||||||
const int clockrates[] = {8000, 16000, 32000, 48000};
|
const int clockrates[] = {8000, 16000, 32000, 48000};
|
||||||
const int num_channels[] = {1, 2, 3, 4711};
|
const int num_channels[] = {1, 2, 3, 24};
|
||||||
for (int clockrate : clockrates) {
|
for (int clockrate : clockrates) {
|
||||||
EXPECT_FALSE(adf->MakeAudioDecoder(SdpAudioFormat("l16", clockrate, 0),
|
EXPECT_FALSE(adf->MakeAudioDecoder(SdpAudioFormat("l16", clockrate, 0),
|
||||||
absl::nullopt));
|
absl::nullopt));
|
||||||
@ -117,6 +117,34 @@ TEST(AudioDecoderFactoryTest, CreateL16) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that using more channels than the maximum does not work
|
||||||
|
TEST(AudioDecoderFactoryTest, MaxNrOfChannels) {
|
||||||
|
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||||
|
CreateBuiltinAudioDecoderFactory();
|
||||||
|
std::vector<std::string> codecs = {
|
||||||
|
#ifdef WEBRTC_CODEC_OPUS
|
||||||
|
"opus",
|
||||||
|
#endif
|
||||||
|
#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
|
||||||
|
"isac",
|
||||||
|
#endif
|
||||||
|
#ifdef WEBRTC_CODEC_ILBC
|
||||||
|
"ilbc",
|
||||||
|
#endif
|
||||||
|
"pcmu",
|
||||||
|
"pcma",
|
||||||
|
"l16",
|
||||||
|
"G722",
|
||||||
|
"G711",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto codec : codecs) {
|
||||||
|
EXPECT_FALSE(adf->MakeAudioDecoder(
|
||||||
|
SdpAudioFormat(codec, 32000, AudioDecoder::kMaxNumberOfChannels + 1),
|
||||||
|
absl::nullopt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(AudioDecoderFactoryTest, CreateG722) {
|
TEST(AudioDecoderFactoryTest, CreateG722) {
|
||||||
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
rtc::scoped_refptr<AudioDecoderFactory> adf =
|
||||||
CreateBuiltinAudioDecoderFactory();
|
CreateBuiltinAudioDecoderFactory();
|
||||||
|
|||||||
@ -144,4 +144,35 @@ TEST(BuiltinAudioEncoderFactoryTest, SupportsTheExpectedFormats) {
|
|||||||
|
|
||||||
ASSERT_THAT(supported_formats, ElementsAreArray(expected_formats));
|
ASSERT_THAT(supported_formats, ElementsAreArray(expected_formats));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that using more channels than the maximum does not work.
|
||||||
|
TEST(BuiltinAudioEncoderFactoryTest, MaxNrOfChannels) {
|
||||||
|
rtc::scoped_refptr<AudioEncoderFactory> aef =
|
||||||
|
CreateBuiltinAudioEncoderFactory();
|
||||||
|
std::vector<std::string> codecs = {
|
||||||
|
#ifdef WEBRTC_CODEC_OPUS
|
||||||
|
"opus",
|
||||||
|
#endif
|
||||||
|
#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
|
||||||
|
"isac",
|
||||||
|
#endif
|
||||||
|
#ifdef WEBRTC_CODEC_ILBC
|
||||||
|
"ilbc",
|
||||||
|
#endif
|
||||||
|
"pcmu",
|
||||||
|
"pcma",
|
||||||
|
"l16",
|
||||||
|
"G722",
|
||||||
|
"G711",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto codec : codecs) {
|
||||||
|
EXPECT_FALSE(aef->MakeAudioEncoder(
|
||||||
|
/*payload_type=*/111,
|
||||||
|
/*format=*/
|
||||||
|
SdpAudioFormat(codec, 32000, AudioEncoder::kMaxNumberOfChannels + 1),
|
||||||
|
/*codec_pair_id=*/absl::nullopt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
Reference in New Issue
Block a user