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