Chromium Code Reviews| Index: webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h |
| 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 |
| index d2b20e3b941c932cf736489b17cf4455154a9d32..ce70db455b511c9508d650855d0bc998fd4339ba 100644 |
| --- 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 |
| @@ -17,7 +17,6 @@ |
| #include "webrtc/base/checks.h" |
| #include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h" |
| -#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" |
| namespace webrtc { |
| @@ -25,8 +24,9 @@ const int kIsacPayloadType = 103; |
| const int kDefaultBitRate = 32000; |
| template <typename T> |
| -AudioEncoderDecoderIsacT<T>::Config::Config() |
| - : payload_type(kIsacPayloadType), |
| +AudioEncoderIsacT<T>::Config::Config() |
| + : bwinfo(nullptr), |
| + payload_type(kIsacPayloadType), |
| sample_rate_hz(16000), |
| frame_size_ms(30), |
| bit_rate(kDefaultBitRate), |
| @@ -37,11 +37,13 @@ AudioEncoderDecoderIsacT<T>::Config::Config() |
| } |
| template <typename T> |
| -bool AudioEncoderDecoderIsacT<T>::Config::IsOk() const { |
| +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) |
| @@ -65,11 +67,9 @@ bool AudioEncoderDecoderIsacT<T>::Config::IsOk() const { |
| } |
| template <typename T> |
| -AudioEncoderDecoderIsacT<T>::AudioEncoderDecoderIsacT(const Config& config) |
| +AudioEncoderIsacT<T>::AudioEncoderIsacT(const Config& config) |
| : payload_type_(config.payload_type), |
| - state_lock_(CriticalSectionWrapper::CreateCriticalSection()), |
| - decoder_sample_rate_hz_(0), |
| - lock_(CriticalSectionWrapper::CreateCriticalSection()), |
| + bwinfo_(config.bwinfo), |
| packet_in_progress_(false), |
| target_bitrate_bps_(config.adaptive_mode ? -1 : (config.bit_rate == 0 |
| ? kDefaultBitRate |
| @@ -85,80 +85,82 @@ AudioEncoderDecoderIsacT<T>::AudioEncoderDecoderIsacT(const Config& config) |
| } else { |
| CHECK_EQ(0, T::Control(isac_state_, bit_rate, config.frame_size_ms)); |
| } |
| - // When config.sample_rate_hz is set to 48000 Hz (iSAC-fb), the decoder is |
| - // still set to 32000 Hz, since there is no full-band mode in the decoder. |
| - CHECK_EQ(0, T::SetDecSampRate(isac_state_, |
| - std::min(config.sample_rate_hz, 32000))); |
| if (config.max_payload_size_bytes != -1) |
| CHECK_EQ(0, |
| T::SetMaxPayloadSize(isac_state_, config.max_payload_size_bytes)); |
| if (config.max_bit_rate != -1) |
| CHECK_EQ(0, T::SetMaxRate(isac_state_, config.max_bit_rate)); |
| - CHECK_EQ(0, T::DecoderInit(isac_state_)); |
| + |
| + // When config.sample_rate_hz is set to 48000 Hz (iSAC-fb), the decoder is |
| + // still set to 32000 Hz, since there is no full-band mode in the decoder. |
| + const int decoder_sample_rate_hz = std::min(config.sample_rate_hz, 32000); |
| + |
| + // 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. |
| + CHECK_EQ(0, T::SetDecSampRate(isac_state_, decoder_sample_rate_hz)); |
| } |
| template <typename T> |
| -AudioEncoderDecoderIsacT<T>::~AudioEncoderDecoderIsacT() { |
| +AudioEncoderIsacT<T>::~AudioEncoderIsacT() { |
| CHECK_EQ(0, T::Free(isac_state_)); |
| } |
| template <typename T> |
| -int AudioEncoderDecoderIsacT<T>::SampleRateHz() const { |
| - CriticalSectionScoped cs(state_lock_.get()); |
| +int AudioEncoderIsacT<T>::SampleRateHz() const { |
| return T::EncSampRate(isac_state_); |
| } |
| template <typename T> |
| -int AudioEncoderDecoderIsacT<T>::NumChannels() const { |
| +int AudioEncoderIsacT<T>::NumChannels() const { |
| return 1; |
| } |
| template <typename T> |
| -size_t AudioEncoderDecoderIsacT<T>::MaxEncodedBytes() const { |
| +size_t AudioEncoderIsacT<T>::MaxEncodedBytes() const { |
| return kSufficientEncodeBufferSizeBytes; |
| } |
| template <typename T> |
| -int AudioEncoderDecoderIsacT<T>::Num10MsFramesInNextPacket() const { |
| - CriticalSectionScoped cs(state_lock_.get()); |
| +int AudioEncoderIsacT<T>::Num10MsFramesInNextPacket() const { |
| const int samples_in_next_packet = T::GetNewFrameLen(isac_state_); |
| return rtc::CheckedDivExact(samples_in_next_packet, |
| rtc::CheckedDivExact(SampleRateHz(), 100)); |
| } |
| template <typename T> |
| -int AudioEncoderDecoderIsacT<T>::Max10MsFramesInAPacket() const { |
| +int AudioEncoderIsacT<T>::Max10MsFramesInAPacket() const { |
| return 6; // iSAC puts at most 60 ms in a packet. |
| } |
| template <typename T> |
| -int AudioEncoderDecoderIsacT<T>::GetTargetBitrate() const { |
| +int AudioEncoderIsacT<T>::GetTargetBitrate() const { |
| return target_bitrate_bps_; |
| } |
| template <typename T> |
| -AudioEncoder::EncodedInfo AudioEncoderDecoderIsacT<T>::EncodeInternal( |
| +AudioEncoder::EncodedInfo AudioEncoderIsacT<T>::EncodeInternal( |
| uint32_t rtp_timestamp, |
| const int16_t* audio, |
| size_t max_encoded_bytes, |
| uint8_t* encoded) { |
| - CriticalSectionScoped cs_lock(lock_.get()); |
| if (!packet_in_progress_) { |
| // Starting a new packet; remember the timestamp for later. |
| packet_in_progress_ = true; |
| packet_timestamp_ = rtp_timestamp; |
| } |
| - int r; |
| - { |
| - CriticalSectionScoped cs(state_lock_.get()); |
| - r = T::Encode(isac_state_, audio, encoded); |
| - CHECK_GE(r, 0) << "Encode failed (error code " |
| - << T::GetErrorCode(isac_state_) << ")"; |
| + if (bwinfo_) { |
| + IsacBandwidthInfo bwinfo = bwinfo_->Get(); |
| + T::SetBandwidthInfo(isac_state_, &bwinfo); |
| } |
| + int r = T::Encode(isac_state_, audio, encoded); |
| + 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. |
| - CHECK(static_cast<size_t>(r) <= max_encoded_bytes); |
| + CHECK_LE(static_cast<size_t>(r), max_encoded_bytes); |
| if (r == 0) |
| return EncodedInfo(); |
| @@ -174,12 +176,33 @@ AudioEncoder::EncodedInfo AudioEncoderDecoderIsacT<T>::EncodeInternal( |
| } |
| template <typename T> |
| -int AudioEncoderDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded, |
| - size_t encoded_len, |
| - int sample_rate_hz, |
| - int16_t* decoded, |
| - SpeechType* speech_type) { |
| - CriticalSectionScoped cs(state_lock_.get()); |
| +AudioDecoderIsacT<T>::AudioDecoderIsacT() |
| + : AudioDecoderIsacT(nullptr) { |
| +} |
| + |
| +template <typename T> |
| +AudioDecoderIsacT<T>::AudioDecoderIsacT(LockedIsacBandwidthInfo* bwinfo) |
| + : bwinfo_(bwinfo), decoder_sample_rate_hz_(-1) { |
| + CHECK_EQ(0, T::Create(&isac_state_)); |
| + CHECK_EQ(0, T::DecoderInit(isac_state_)); |
| + if (bwinfo_) { |
| + IsacBandwidthInfo bwinfo; |
|
brucedawson
2015/08/26 18:45:57
This variable shadows the function parameter bwinf
kwiberg-webrtc
2015/08/27 09:01:48
Good idea. CL here: https://codereview.webrtc.org/
|
| + T::GetBandwidthInfo(isac_state_, &bwinfo); |
| + bwinfo_->Set(bwinfo); |
| + } |
| +} |
| + |
| +template <typename T> |
| +AudioDecoderIsacT<T>::~AudioDecoderIsacT() { |
| + CHECK_EQ(0, T::Free(isac_state_)); |
| +} |
| + |
| +template <typename T> |
| +int AudioDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded, |
| + size_t encoded_len, |
| + int sample_rate_hz, |
| + int16_t* decoded, |
| + SpeechType* speech_type) { |
| // We want to crate the illusion that iSAC supports 48000 Hz decoding, while |
| // in fact it outputs 32000 Hz. This is the iSAC fullband mode. |
| if (sample_rate_hz == 48000) |
| @@ -199,40 +222,47 @@ int AudioEncoderDecoderIsacT<T>::DecodeInternal(const uint8_t* encoded, |
| } |
| template <typename T> |
| -bool AudioEncoderDecoderIsacT<T>::HasDecodePlc() const { |
| +bool AudioDecoderIsacT<T>::HasDecodePlc() const { |
| return false; |
| } |
| template <typename T> |
| -int AudioEncoderDecoderIsacT<T>::DecodePlc(int num_frames, int16_t* decoded) { |
| - CriticalSectionScoped cs(state_lock_.get()); |
| +int AudioDecoderIsacT<T>::DecodePlc(int num_frames, int16_t* decoded) { |
| return T::DecodePlc(isac_state_, decoded, num_frames); |
| } |
| template <typename T> |
| -int AudioEncoderDecoderIsacT<T>::Init() { |
| - CriticalSectionScoped cs(state_lock_.get()); |
| +int AudioDecoderIsacT<T>::Init() { |
| return T::DecoderInit(isac_state_); |
| } |
| template <typename T> |
| -int AudioEncoderDecoderIsacT<T>::IncomingPacket(const uint8_t* payload, |
| - size_t payload_len, |
| - uint16_t rtp_sequence_number, |
| - uint32_t rtp_timestamp, |
| - uint32_t arrival_timestamp) { |
| - CriticalSectionScoped cs(state_lock_.get()); |
| - return T::UpdateBwEstimate( |
| +int AudioDecoderIsacT<T>::IncomingPacket(const uint8_t* payload, |
| + size_t payload_len, |
| + uint16_t rtp_sequence_number, |
| + uint32_t rtp_timestamp, |
| + uint32_t arrival_timestamp) { |
| + int ret = T::UpdateBwEstimate( |
| isac_state_, payload, static_cast<int32_t>(payload_len), |
| rtp_sequence_number, rtp_timestamp, arrival_timestamp); |
| + if (bwinfo_) { |
| + IsacBandwidthInfo bwinfo; |
| + T::GetBandwidthInfo(isac_state_, &bwinfo); |
| + bwinfo_->Set(bwinfo); |
| + } |
| + return ret; |
| } |
| template <typename T> |
| -int AudioEncoderDecoderIsacT<T>::ErrorCode() { |
| - CriticalSectionScoped cs(state_lock_.get()); |
| +int AudioDecoderIsacT<T>::ErrorCode() { |
| return T::GetErrorCode(isac_state_); |
| } |
| +template <typename T> |
| +size_t AudioDecoderIsacT<T>::Channels() const { |
| + return 1; |
| +} |
| + |
| } // namespace webrtc |
| #endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ |