xref: /aosp_15_r20/external/webrtc/api/audio_codecs/ilbc/audio_encoder_ilbc.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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/ilbc/audio_encoder_ilbc.h"
12 
13 #include <memory>
14 #include <vector>
15 
16 #include "absl/strings/match.h"
17 #include "modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
18 #include "rtc_base/numerics/safe_conversions.h"
19 #include "rtc_base/numerics/safe_minmax.h"
20 #include "rtc_base/string_to_number.h"
21 
22 namespace webrtc {
23 namespace {
GetIlbcBitrate(int ptime)24 int GetIlbcBitrate(int ptime) {
25   switch (ptime) {
26     case 20:
27     case 40:
28       // 38 bytes per frame of 20 ms => 15200 bits/s.
29       return 15200;
30     case 30:
31     case 60:
32       // 50 bytes per frame of 30 ms => (approx) 13333 bits/s.
33       return 13333;
34     default:
35       RTC_CHECK_NOTREACHED();
36   }
37 }
38 }  // namespace
39 
SdpToConfig(const SdpAudioFormat & format)40 absl::optional<AudioEncoderIlbcConfig> AudioEncoderIlbc::SdpToConfig(
41     const SdpAudioFormat& format) {
42   if (!absl::EqualsIgnoreCase(format.name.c_str(), "ILBC") ||
43       format.clockrate_hz != 8000 || format.num_channels != 1) {
44     return absl::nullopt;
45   }
46 
47   AudioEncoderIlbcConfig config;
48   auto ptime_iter = format.parameters.find("ptime");
49   if (ptime_iter != format.parameters.end()) {
50     auto ptime = rtc::StringToNumber<int>(ptime_iter->second);
51     if (ptime && *ptime > 0) {
52       const int whole_packets = *ptime / 10;
53       config.frame_size_ms = rtc::SafeClamp<int>(whole_packets * 10, 20, 60);
54     }
55   }
56   if (!config.IsOk()) {
57     RTC_DCHECK_NOTREACHED();
58     return absl::nullopt;
59   }
60   return config;
61 }
62 
AppendSupportedEncoders(std::vector<AudioCodecSpec> * specs)63 void AudioEncoderIlbc::AppendSupportedEncoders(
64     std::vector<AudioCodecSpec>* specs) {
65   const SdpAudioFormat fmt = {"ILBC", 8000, 1};
66   const AudioCodecInfo info = QueryAudioEncoder(*SdpToConfig(fmt));
67   specs->push_back({fmt, info});
68 }
69 
QueryAudioEncoder(const AudioEncoderIlbcConfig & config)70 AudioCodecInfo AudioEncoderIlbc::QueryAudioEncoder(
71     const AudioEncoderIlbcConfig& config) {
72   RTC_DCHECK(config.IsOk());
73   return {8000, 1, GetIlbcBitrate(config.frame_size_ms)};
74 }
75 
MakeAudioEncoder(const AudioEncoderIlbcConfig & config,int payload_type,absl::optional<AudioCodecPairId>,const FieldTrialsView * field_trials)76 std::unique_ptr<AudioEncoder> AudioEncoderIlbc::MakeAudioEncoder(
77     const AudioEncoderIlbcConfig& config,
78     int payload_type,
79     absl::optional<AudioCodecPairId> /*codec_pair_id*/,
80     const FieldTrialsView* field_trials) {
81   if (!config.IsOk()) {
82     RTC_DCHECK_NOTREACHED();
83     return nullptr;
84   }
85   return std::make_unique<AudioEncoderIlbcImpl>(config, payload_type);
86 }
87 
88 }  // namespace webrtc
89