summaryrefslogtreecommitdiff
path: root/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h')
-rw-r--r--webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h190
1 files changed, 190 insertions, 0 deletions
diff --git a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
new file mode 100644
index 0000000..279f80d
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
+
+#include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
+
+#include "webrtc/base/checks.h"
+
+namespace webrtc {
+
+template <typename T>
+typename AudioEncoderIsacT<T>::Config CreateIsacConfig(
+ const CodecInst& codec_inst,
+ LockedIsacBandwidthInfo* bwinfo) {
+ typename AudioEncoderIsacT<T>::Config config;
+ config.bwinfo = bwinfo;
+ config.payload_type = codec_inst.pltype;
+ config.sample_rate_hz = codec_inst.plfreq;
+ config.frame_size_ms =
+ rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz);
+ config.adaptive_mode = (codec_inst.rate == -1);
+ if (codec_inst.rate != -1)
+ config.bit_rate = codec_inst.rate;
+ return config;
+}
+
+template <typename T>
+bool AudioEncoderIsacT<T>::Config::IsOk() const {
+ if (max_bit_rate < 32000 && max_bit_rate != -1)
+ return false;
+ if (max_payload_size_bytes < 120 && max_payload_size_bytes != -1)
+ return false;
+ if (adaptive_mode && !bwinfo)
+ return false;
+ switch (sample_rate_hz) {
+ case 16000:
+ if (max_bit_rate > 53400)
+ return false;
+ if (max_payload_size_bytes > 400)
+ return false;
+ return (frame_size_ms == 30 || frame_size_ms == 60) &&
+ (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 32000));
+ case 32000:
+ if (max_bit_rate > 160000)
+ return false;
+ if (max_payload_size_bytes > 600)
+ return false;
+ return T::has_swb &&
+ (frame_size_ms == 30 &&
+ (bit_rate == 0 || (bit_rate >= 10000 && bit_rate <= 56000)));
+ default:
+ return false;
+ }
+}
+
+template <typename T>
+AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config) {
+ RecreateEncoderInstance(config);
+}
+
+template <typename T>
+AudioEncoderIsacT<T>::AudioEncoderIsacT(const CodecInst& codec_inst,
+ LockedIsacBandwidthInfo* bwinfo)
+ : AudioEncoderIsacT(CreateIsacConfig<T>(codec_inst, bwinfo)) {}
+
+template <typename T>
+AudioEncoderIsacT<T>::~AudioEncoderIsacT() {
+ RTC_CHECK_EQ(0, T::Free(isac_state_));
+}
+
+template <typename T>
+size_t AudioEncoderIsacT<T>::MaxEncodedBytes() const {
+ return kSufficientEncodeBufferSizeBytes;
+}
+
+template <typename T>
+int AudioEncoderIsacT<T>::SampleRateHz() const {
+ return T::EncSampRate(isac_state_);
+}
+
+template <typename T>
+int AudioEncoderIsacT<T>::NumChannels() const {
+ return 1;
+}
+
+template <typename T>
+size_t AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const {
+ const int samples_in_next_packet = T::GetNewFrameLen(isac_state_);
+ return static_cast<size_t>(
+ rtc::CheckedDivExact(samples_in_next_packet,
+ rtc::CheckedDivExact(SampleRateHz(), 100)));
+}
+
+template <typename T>
+size_t AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const {
+ return 6; // iSAC puts at most 60 ms in a packet.
+}
+
+template <typename T>
+int AudioEncoderIsacT<T>::GetTargetBitrate() const {
+ if (config_.adaptive_mode)
+ return -1;
+ return config_.bit_rate == 0 ? kDefaultBitRate : config_.bit_rate;
+}
+
+template <typename T>
+AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeInternal(
+ uint32_t rtp_timestamp,
+ const int16_t* audio,
+ size_t max_encoded_bytes,
+ uint8_t* encoded) {
+ if (!packet_in_progress_) {
+ // Starting a new packet; remember the timestamp for later.
+ packet_in_progress_ = true;
+ packet_timestamp_ = rtp_timestamp;
+ }
+ if (bwinfo_) {
+ IsacBandwidthInfo bwinfo = bwinfo_->Get();
+ T::SetBandwidthInfo(isac_state_, &bwinfo);
+ }
+ int r = T::Encode(isac_state_, audio, encoded);
+ RTC_CHECK_GE(r, 0) << "Encode failed (error code "
+ << T::GetErrorCode(isac_state_) << ")";
+
+ // T::Encode doesn't allow us to tell it the size of the output
+ // buffer. All we can do is check for an overrun after the fact.
+ RTC_CHECK_LE(static_cast<size_t>(r), max_encoded_bytes);
+
+ if (r == 0)
+ return EncodedInfo();
+
+ // Got enough input to produce a packet. Return the saved timestamp from
+ // the first chunk of input that went into the packet.
+ packet_in_progress_ = false;
+ EncodedInfo info;
+ info.encoded_bytes = r;
+ info.encoded_timestamp = packet_timestamp_;
+ info.payload_type = config_.payload_type;
+ return info;
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::Reset() {
+ RecreateEncoderInstance(config_);
+}
+
+template <typename T>
+void AudioEncoderIsacT<T>::RecreateEncoderInstance(const Config& config) {
+ RTC_CHECK(config.IsOk());
+ packet_in_progress_ = false;
+ bwinfo_ = config.bwinfo;
+ if (isac_state_)
+ RTC_CHECK_EQ(0, T::Free(isac_state_));
+ RTC_CHECK_EQ(0, T::Create(&isac_state_));
+ RTC_CHECK_EQ(0, T::EncoderInit(isac_state_, config.adaptive_mode ? 0 : 1));
+ RTC_CHECK_EQ(0, T::SetEncSampRate(isac_state_, config.sample_rate_hz));
+ const int bit_rate = config.bit_rate == 0 ? kDefaultBitRate : config.bit_rate;
+ if (config.adaptive_mode) {
+ RTC_CHECK_EQ(0, T::ControlBwe(isac_state_, bit_rate, config.frame_size_ms,
+ config.enforce_frame_size));
+ } else {
+ RTC_CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms));
+ }
+ if (config.max_payload_size_bytes != -1)
+ RTC_CHECK_EQ(
+ 0, T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes));
+ if (config.max_bit_rate != -1)
+ RTC_CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate));
+
+ // Set the decoder sample rate even though we just use the encoder. This
+ // doesn't appear to be necessary to produce a valid encoding, but without it
+ // we get an encoding that isn't bit-for-bit identical with what a combined
+ // encoder+decoder object produces.
+ RTC_CHECK_EQ(0, T::SetDecSampRate(isac_state_, config.sample_rate_hz));
+
+ config_ = config;
+}
+
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_