Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(323)

Side by Side Diff: webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc

Issue 2951873002: Expose ILBC codec in webrtc/api/audio_codecs/ (Closed)
Patch Set: Fix tests Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h" 11 #include "webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h"
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <limits> 14 #include <limits>
15 #include "webrtc/base/checks.h" 15 #include "webrtc/base/checks.h"
16 #include "webrtc/base/safe_conversions.h" 16 #include "webrtc/base/safe_conversions.h"
17 #include "webrtc/base/string_to_number.h" 17 #include "webrtc/base/string_to_number.h"
18 #include "webrtc/common_types.h" 18 #include "webrtc/common_types.h"
19 #include "webrtc/modules/audio_coding/codecs/ilbc/ilbc.h" 19 #include "webrtc/modules/audio_coding/codecs/ilbc/ilbc.h"
20 20
21 namespace webrtc { 21 namespace webrtc {
22 22
23 namespace { 23 namespace {
24 24
25 const int kSampleRateHz = 8000; 25 const int kSampleRateHz = 8000;
26 26
27 AudioEncoderIlbc::Config CreateConfig(const CodecInst& codec_inst) { 27 AudioEncoderIlbcConfig CreateConfig(const CodecInst& codec_inst) {
28 AudioEncoderIlbc::Config config; 28 AudioEncoderIlbcConfig config;
29 config.frame_size_ms = codec_inst.pacsize / 8; 29 config.frame_size_ms = codec_inst.pacsize / 8;
30 config.payload_type = codec_inst.pltype;
31 return config;
32 }
33
34 AudioEncoderIlbc::Config CreateConfig(int payload_type,
35 const SdpAudioFormat& format) {
36 AudioEncoderIlbc::Config config;
37 config.payload_type = payload_type;
38 auto ptime_iter = format.parameters.find("ptime");
39 if (ptime_iter != format.parameters.end()) {
40 auto ptime = rtc::StringToNumber<int>(ptime_iter->second);
41 if (ptime && *ptime > 0) {
42 const int whole_packets = *ptime / 10;
43 config.frame_size_ms = std::max(20, std::min(whole_packets * 10, 60));
44 }
45 }
46 return config; 30 return config;
47 } 31 }
48 32
49 int GetIlbcBitrate(int ptime) { 33 int GetIlbcBitrate(int ptime) {
50 switch (ptime) { 34 switch (ptime) {
51 case 20: case 40: 35 case 20:
36 case 40:
52 // 38 bytes per frame of 20 ms => 15200 bits/s. 37 // 38 bytes per frame of 20 ms => 15200 bits/s.
53 return 15200; 38 return 15200;
54 case 30: case 60: 39 case 30:
40 case 60:
55 // 50 bytes per frame of 30 ms => (approx) 13333 bits/s. 41 // 50 bytes per frame of 30 ms => (approx) 13333 bits/s.
56 return 13333; 42 return 13333;
57 default: 43 default:
58 FATAL(); 44 FATAL();
59 } 45 }
60 } 46 }
61 47
62 } // namespace 48 } // namespace
63 49
64 // static 50 rtc::Optional<AudioEncoderIlbcConfig> AudioEncoderIlbcImpl::SdpToConfig(
65 const size_t AudioEncoderIlbc::kMaxSamplesPerPacket; 51 const SdpAudioFormat& format) {
52 if (STR_CASE_CMP(format.name.c_str(), "ilbc") != 0 ||
53 format.clockrate_hz != 8000 || format.num_channels != 1) {
54 return rtc::Optional<AudioEncoderIlbcConfig>();
55 }
66 56
67 bool AudioEncoderIlbc::Config::IsOk() const { 57 AudioEncoderIlbcConfig config;
68 return (frame_size_ms == 20 || frame_size_ms == 30 || frame_size_ms == 40 || 58 auto ptime_iter = format.parameters.find("ptime");
69 frame_size_ms == 60) && 59 if (ptime_iter != format.parameters.end()) {
70 static_cast<size_t>(kSampleRateHz / 100 * (frame_size_ms / 10)) <= 60 auto ptime = rtc::StringToNumber<int>(ptime_iter->second);
71 kMaxSamplesPerPacket; 61 if (ptime && *ptime > 0) {
62 const int whole_packets = *ptime / 10;
63 config.frame_size_ms = std::max(20, std::min(whole_packets * 10, 60));
64 }
65 }
66 return config.IsOk() ? rtc::Optional<AudioEncoderIlbcConfig>(config)
67 : rtc::Optional<AudioEncoderIlbcConfig>();
72 } 68 }
73 69
74 AudioEncoderIlbc::AudioEncoderIlbc(const Config& config) 70 AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(const AudioEncoderIlbcConfig& config,
75 : config_(config), 71 int payload_type)
72 : frame_size_ms_(config.frame_size_ms),
73 payload_type_(payload_type),
76 num_10ms_frames_per_packet_( 74 num_10ms_frames_per_packet_(
77 static_cast<size_t>(config.frame_size_ms / 10)), 75 static_cast<size_t>(config.frame_size_ms / 10)),
78 encoder_(nullptr) { 76 encoder_(nullptr) {
77 RTC_CHECK(config.IsOk());
79 Reset(); 78 Reset();
80 } 79 }
81 80
82 AudioEncoderIlbc::AudioEncoderIlbc(const CodecInst& codec_inst) 81 AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(const CodecInst& codec_inst)
83 : AudioEncoderIlbc(CreateConfig(codec_inst)) {} 82 : AudioEncoderIlbcImpl(CreateConfig(codec_inst), codec_inst.pltype) {}
84 83
85 AudioEncoderIlbc::AudioEncoderIlbc(int payload_type, 84 AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(int payload_type,
86 const SdpAudioFormat& format) 85 const SdpAudioFormat& format)
87 : AudioEncoderIlbc(CreateConfig(payload_type, format)) {} 86 : AudioEncoderIlbcImpl(*SdpToConfig(format), payload_type) {}
88 87
89 rtc::Optional<AudioCodecInfo> AudioEncoderIlbc::QueryAudioEncoder( 88 AudioEncoderIlbcImpl::~AudioEncoderIlbcImpl() {
89 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
90 }
91
92 rtc::Optional<AudioCodecInfo> AudioEncoderIlbcImpl::QueryAudioEncoder(
90 const SdpAudioFormat& format) { 93 const SdpAudioFormat& format) {
91 if (STR_CASE_CMP(format.name.c_str(), GetPayloadName()) == 0 && 94 if (STR_CASE_CMP(format.name.c_str(), GetPayloadName()) == 0) {
92 format.clockrate_hz == 8000 && format.num_channels == 1) { 95 const auto config_opt = SdpToConfig(format);
93 Config config = CreateConfig(0, format); 96 if (format.clockrate_hz == 8000 && format.num_channels == 1 &&
94 if (config.IsOk()) { 97 config_opt) {
98 RTC_DCHECK(config_opt->IsOk());
95 return rtc::Optional<AudioCodecInfo>( 99 return rtc::Optional<AudioCodecInfo>(
96 {kSampleRateHz, 1, GetIlbcBitrate(config.frame_size_ms)}); 100 {rtc::dchecked_cast<int>(kSampleRateHz), 1,
101 GetIlbcBitrate(config_opt->frame_size_ms)});
97 } 102 }
98 } 103 }
99
100 return rtc::Optional<AudioCodecInfo>(); 104 return rtc::Optional<AudioCodecInfo>();
101 } 105 }
102 106
103 AudioEncoderIlbc::~AudioEncoderIlbc() { 107 int AudioEncoderIlbcImpl::SampleRateHz() const {
104 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
105 }
106
107 int AudioEncoderIlbc::SampleRateHz() const {
108 return kSampleRateHz; 108 return kSampleRateHz;
109 } 109 }
110 110
111 size_t AudioEncoderIlbc::NumChannels() const { 111 size_t AudioEncoderIlbcImpl::NumChannels() const {
112 return 1; 112 return 1;
113 } 113 }
114 114
115 size_t AudioEncoderIlbc::Num10MsFramesInNextPacket() const { 115 size_t AudioEncoderIlbcImpl::Num10MsFramesInNextPacket() const {
116 return num_10ms_frames_per_packet_; 116 return num_10ms_frames_per_packet_;
117 } 117 }
118 118
119 size_t AudioEncoderIlbc::Max10MsFramesInAPacket() const { 119 size_t AudioEncoderIlbcImpl::Max10MsFramesInAPacket() const {
120 return num_10ms_frames_per_packet_; 120 return num_10ms_frames_per_packet_;
121 } 121 }
122 122
123 int AudioEncoderIlbc::GetTargetBitrate() const { 123 int AudioEncoderIlbcImpl::GetTargetBitrate() const {
124 return GetIlbcBitrate(rtc::dchecked_cast<int>(num_10ms_frames_per_packet_) * 124 return GetIlbcBitrate(rtc::dchecked_cast<int>(num_10ms_frames_per_packet_) *
125 10); 125 10);
126 } 126 }
127 127
128 AudioEncoder::EncodedInfo AudioEncoderIlbc::EncodeImpl( 128 AudioEncoder::EncodedInfo AudioEncoderIlbcImpl::EncodeImpl(
129 uint32_t rtp_timestamp, 129 uint32_t rtp_timestamp,
130 rtc::ArrayView<const int16_t> audio, 130 rtc::ArrayView<const int16_t> audio,
131 rtc::Buffer* encoded) { 131 rtc::Buffer* encoded) {
132 132
133 // Save timestamp if starting a new packet. 133 // Save timestamp if starting a new packet.
134 if (num_10ms_frames_buffered_ == 0) 134 if (num_10ms_frames_buffered_ == 0)
135 first_timestamp_in_buffer_ = rtp_timestamp; 135 first_timestamp_in_buffer_ = rtp_timestamp;
136 136
137 // Buffer input. 137 // Buffer input.
138 std::copy(audio.cbegin(), audio.cend(), 138 std::copy(audio.cbegin(), audio.cend(),
(...skipping 20 matching lines...) Expand all
159 RTC_CHECK_GE(r, 0); 159 RTC_CHECK_GE(r, 0);
160 160
161 return static_cast<size_t>(r); 161 return static_cast<size_t>(r);
162 }); 162 });
163 163
164 RTC_DCHECK_EQ(encoded_bytes, RequiredOutputSizeBytes()); 164 RTC_DCHECK_EQ(encoded_bytes, RequiredOutputSizeBytes());
165 165
166 EncodedInfo info; 166 EncodedInfo info;
167 info.encoded_bytes = encoded_bytes; 167 info.encoded_bytes = encoded_bytes;
168 info.encoded_timestamp = first_timestamp_in_buffer_; 168 info.encoded_timestamp = first_timestamp_in_buffer_;
169 info.payload_type = config_.payload_type; 169 info.payload_type = payload_type_;
170 info.encoder_type = CodecType::kIlbc; 170 info.encoder_type = CodecType::kIlbc;
171 return info; 171 return info;
172 } 172 }
173 173
174 void AudioEncoderIlbc::Reset() { 174 void AudioEncoderIlbcImpl::Reset() {
175 if (encoder_) 175 if (encoder_)
176 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_)); 176 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
177 RTC_CHECK(config_.IsOk());
178 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderCreate(&encoder_)); 177 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderCreate(&encoder_));
179 const int encoder_frame_size_ms = config_.frame_size_ms > 30 178 const int encoder_frame_size_ms = frame_size_ms_ > 30
180 ? config_.frame_size_ms / 2 179 ? frame_size_ms_ / 2
181 : config_.frame_size_ms; 180 : frame_size_ms_;
182 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderInit(encoder_, encoder_frame_size_ms)); 181 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderInit(encoder_, encoder_frame_size_ms));
183 num_10ms_frames_buffered_ = 0; 182 num_10ms_frames_buffered_ = 0;
184 } 183 }
185 184
186 size_t AudioEncoderIlbc::RequiredOutputSizeBytes() const { 185 size_t AudioEncoderIlbcImpl::RequiredOutputSizeBytes() const {
187 switch (num_10ms_frames_per_packet_) { 186 switch (num_10ms_frames_per_packet_) {
188 case 2: return 38; 187 case 2: return 38;
189 case 3: return 50; 188 case 3: return 50;
190 case 4: return 2 * 38; 189 case 4: return 2 * 38;
191 case 6: return 2 * 50; 190 case 6: return 2 * 50;
192 default: FATAL(); 191 default: FATAL();
193 } 192 }
194 } 193 }
195 194
196 } // namespace webrtc 195 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698