From ada4c130ab576120380d48f29908b6cc20ec9cf5 Mon Sep 17 00:00:00 2001 From: kwiberg Date: Thu, 17 Sep 2015 03:12:35 -0700 Subject: [PATCH] Move AudioDecoderG722 next to AudioEncoderG722 All AudioDecoder subclasses have historically lived in NetEq, but they fit better with the codec they wrap. BUG=webrtc:4557 Review URL: https://codereview.webrtc.org/1346993002 Cr-Commit-Position: refs/heads/master@{#9966} --- webrtc/modules/audio_coding/BUILD.gn | 2 + .../codecs/g722/audio_decoder_g722.cc | 138 ++++++++++++++++++ .../audio_coding/codecs/g722/g722.gypi | 2 + .../codecs/g722/include/audio_decoder_g722.h | 72 +++++++++ .../audio_coding/neteq/audio_decoder_impl.cc | 125 +--------------- .../audio_coding/neteq/audio_decoder_impl.h | 52 ------- .../neteq/audio_decoder_unittest.cc | 1 + 7 files changed, 216 insertions(+), 176 deletions(-) create mode 100644 webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc create mode 100644 webrtc/modules/audio_coding/codecs/g722/include/audio_decoder_g722.h diff --git a/webrtc/modules/audio_coding/BUILD.gn b/webrtc/modules/audio_coding/BUILD.gn index bc1c35a14d..862c6051b9 100644 --- a/webrtc/modules/audio_coding/BUILD.gn +++ b/webrtc/modules/audio_coding/BUILD.gn @@ -201,11 +201,13 @@ config("g722_config") { source_set("g722") { sources = [ + "codecs/g722/audio_decoder_g722.cc", "codecs/g722/audio_encoder_g722.cc", "codecs/g722/g722_decode.c", "codecs/g722/g722_enc_dec.h", "codecs/g722/g722_encode.c", "codecs/g722/g722_interface.c", + "codecs/g722/include/audio_decoder_g722.h", "codecs/g722/include/audio_encoder_g722.h", "codecs/g722/include/g722_interface.h", ] diff --git a/webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc b/webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc new file mode 100644 index 0000000000..55ebe7a315 --- /dev/null +++ b/webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.cc @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/audio_coding/codecs/g722/include/audio_decoder_g722.h" + +#include + +#include "webrtc/base/checks.h" +#include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h" + +namespace webrtc { + +AudioDecoderG722::AudioDecoderG722() { + WebRtcG722_CreateDecoder(&dec_state_); + WebRtcG722_DecoderInit(dec_state_); +} + +AudioDecoderG722::~AudioDecoderG722() { + WebRtcG722_FreeDecoder(dec_state_); +} + +bool AudioDecoderG722::HasDecodePlc() const { + return false; +} + +int AudioDecoderG722::DecodeInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type) { + RTC_DCHECK_EQ(sample_rate_hz, 16000); + int16_t temp_type = 1; // Default is speech. + size_t ret = + WebRtcG722_Decode(dec_state_, encoded, encoded_len, decoded, &temp_type); + *speech_type = ConvertSpeechType(temp_type); + return static_cast(ret); +} + +void AudioDecoderG722::Reset() { + WebRtcG722_DecoderInit(dec_state_); +} + +int AudioDecoderG722::PacketDuration(const uint8_t* encoded, + size_t encoded_len) const { + // 1/2 encoded byte per sample per channel. + return static_cast(2 * encoded_len / Channels()); +} + +size_t AudioDecoderG722::Channels() const { + return 1; +} + +AudioDecoderG722Stereo::AudioDecoderG722Stereo() { + WebRtcG722_CreateDecoder(&dec_state_left_); + WebRtcG722_CreateDecoder(&dec_state_right_); + WebRtcG722_DecoderInit(dec_state_left_); + WebRtcG722_DecoderInit(dec_state_right_); +} + +AudioDecoderG722Stereo::~AudioDecoderG722Stereo() { + WebRtcG722_FreeDecoder(dec_state_left_); + WebRtcG722_FreeDecoder(dec_state_right_); +} + +int AudioDecoderG722Stereo::DecodeInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type) { + RTC_DCHECK_EQ(sample_rate_hz, 16000); + int16_t temp_type = 1; // Default is speech. + // De-interleave the bit-stream into two separate payloads. + uint8_t* encoded_deinterleaved = new uint8_t[encoded_len]; + SplitStereoPacket(encoded, encoded_len, encoded_deinterleaved); + // Decode left and right. + size_t decoded_len = WebRtcG722_Decode(dec_state_left_, encoded_deinterleaved, + encoded_len / 2, decoded, &temp_type); + size_t ret = WebRtcG722_Decode( + dec_state_right_, &encoded_deinterleaved[encoded_len / 2], + encoded_len / 2, &decoded[decoded_len], &temp_type); + if (ret == decoded_len) { + ret += decoded_len; // Return total number of samples. + // Interleave output. + for (size_t k = ret / 2; k < ret; k++) { + int16_t temp = decoded[k]; + memmove(&decoded[2 * k - ret + 2], &decoded[2 * k - ret + 1], + (ret - k - 1) * sizeof(int16_t)); + decoded[2 * k - ret + 1] = temp; + } + } + *speech_type = ConvertSpeechType(temp_type); + delete[] encoded_deinterleaved; + return static_cast(ret); +} + +size_t AudioDecoderG722Stereo::Channels() const { + return 2; +} + +void AudioDecoderG722Stereo::Reset() { + WebRtcG722_DecoderInit(dec_state_left_); + WebRtcG722_DecoderInit(dec_state_right_); +} + +// Split the stereo packet and place left and right channel after each other +// in the output array. +void AudioDecoderG722Stereo::SplitStereoPacket(const uint8_t* encoded, + size_t encoded_len, + uint8_t* encoded_deinterleaved) { + // Regroup the 4 bits/sample so |l1 l2| |r1 r2| |l3 l4| |r3 r4| ..., + // where "lx" is 4 bits representing left sample number x, and "rx" right + // sample. Two samples fit in one byte, represented with |...|. + for (size_t i = 0; i + 1 < encoded_len; i += 2) { + uint8_t right_byte = ((encoded[i] & 0x0F) << 4) + (encoded[i + 1] & 0x0F); + encoded_deinterleaved[i] = (encoded[i] & 0xF0) + (encoded[i + 1] >> 4); + encoded_deinterleaved[i + 1] = right_byte; + } + + // Move one byte representing right channel each loop, and place it at the + // end of the bytestream vector. After looping the data is reordered to: + // |l1 l2| |l3 l4| ... |l(N-1) lN| |r1 r2| |r3 r4| ... |r(N-1) r(N)|, + // where N is the total number of samples. + for (size_t i = 0; i < encoded_len / 2; i++) { + uint8_t right_byte = encoded_deinterleaved[i + 1]; + memmove(&encoded_deinterleaved[i + 1], &encoded_deinterleaved[i + 2], + encoded_len - i - 2); + encoded_deinterleaved[encoded_len - 1] = right_byte; + } +} + +} // namespace webrtc diff --git a/webrtc/modules/audio_coding/codecs/g722/g722.gypi b/webrtc/modules/audio_coding/codecs/g722/g722.gypi index 14b34b7440..aad11e3685 100644 --- a/webrtc/modules/audio_coding/codecs/g722/g722.gypi +++ b/webrtc/modules/audio_coding/codecs/g722/g722.gypi @@ -24,7 +24,9 @@ ], }, 'sources': [ + 'audio_decoder_g722.cc', 'audio_encoder_g722.cc', + 'include/audio_decoder_g722.h', 'include/audio_encoder_g722.h', 'include/g722_interface.h', 'g722_interface.c', diff --git a/webrtc/modules/audio_coding/codecs/g722/include/audio_decoder_g722.h b/webrtc/modules/audio_coding/codecs/g722/include/audio_decoder_g722.h new file mode 100644 index 0000000000..4f0d8eae3a --- /dev/null +++ b/webrtc/modules/audio_coding/codecs/g722/include/audio_decoder_g722.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 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_G722_INCLUDE_AUDIO_DECODER_G722_H_ +#define WEBRTC_MODULES_AUDIO_CODING_CODECS_G722_INCLUDE_AUDIO_DECODER_G722_H_ + +#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" + +typedef struct WebRtcG722DecInst G722DecInst; + +namespace webrtc { + +class AudioDecoderG722 : public AudioDecoder { + public: + AudioDecoderG722(); + ~AudioDecoderG722() override; + bool HasDecodePlc() const override; + void Reset() override; + int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; + size_t Channels() const override; + + protected: + int DecodeInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type) override; + + private: + G722DecInst* dec_state_; + RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderG722); +}; + +class AudioDecoderG722Stereo : public AudioDecoder { + public: + AudioDecoderG722Stereo(); + ~AudioDecoderG722Stereo() override; + void Reset() override; + + protected: + int DecodeInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type) override; + size_t Channels() const override; + + private: + // Splits the stereo-interleaved payload in |encoded| into separate payloads + // for left and right channels. The separated payloads are written to + // |encoded_deinterleaved|, which must hold at least |encoded_len| samples. + // The left channel starts at offset 0, while the right channel starts at + // offset encoded_len / 2 into |encoded_deinterleaved|. + void SplitStereoPacket(const uint8_t* encoded, + size_t encoded_len, + uint8_t* encoded_deinterleaved); + + G722DecInst* dec_state_left_; + G722DecInst* dec_state_right_; + + RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderG722Stereo); +}; + +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_G722_INCLUDE_AUDIO_DECODER_G722_H_ diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc index 274eec00c3..508129841a 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc @@ -11,13 +11,12 @@ #include "webrtc/modules/audio_coding/neteq/audio_decoder_impl.h" #include -#include // memmove #include "webrtc/base/checks.h" #include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h" #include "webrtc/modules/audio_coding/codecs/g711/include/g711_interface.h" #ifdef WEBRTC_CODEC_G722 -#include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h" +#include "webrtc/modules/audio_coding/codecs/g722/include/audio_decoder_g722.h" #endif #ifdef WEBRTC_CODEC_ILBC #include "webrtc/modules/audio_coding/codecs/ilbc/interface/audio_decoder_ilbc.h" @@ -95,128 +94,6 @@ size_t AudioDecoderPcmAMultiCh::Channels() const { return channels_; } -// G.722 -#ifdef WEBRTC_CODEC_G722 -AudioDecoderG722::AudioDecoderG722() { - WebRtcG722_CreateDecoder(&dec_state_); - WebRtcG722_DecoderInit(dec_state_); -} - -AudioDecoderG722::~AudioDecoderG722() { - WebRtcG722_FreeDecoder(dec_state_); -} - -bool AudioDecoderG722::HasDecodePlc() const { - return false; -} - -int AudioDecoderG722::DecodeInternal(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - int16_t* decoded, - SpeechType* speech_type) { - RTC_DCHECK_EQ(sample_rate_hz, 16000); - int16_t temp_type = 1; // Default is speech. - size_t ret = - WebRtcG722_Decode(dec_state_, encoded, encoded_len, decoded, &temp_type); - *speech_type = ConvertSpeechType(temp_type); - return static_cast(ret); -} - -void AudioDecoderG722::Reset() { - WebRtcG722_DecoderInit(dec_state_); -} - -int AudioDecoderG722::PacketDuration(const uint8_t* encoded, - size_t encoded_len) const { - // 1/2 encoded byte per sample per channel. - return static_cast(2 * encoded_len / Channels()); -} - -size_t AudioDecoderG722::Channels() const { - return 1; -} - -AudioDecoderG722Stereo::AudioDecoderG722Stereo() { - WebRtcG722_CreateDecoder(&dec_state_left_); - WebRtcG722_CreateDecoder(&dec_state_right_); - WebRtcG722_DecoderInit(dec_state_left_); - WebRtcG722_DecoderInit(dec_state_right_); -} - -AudioDecoderG722Stereo::~AudioDecoderG722Stereo() { - WebRtcG722_FreeDecoder(dec_state_left_); - WebRtcG722_FreeDecoder(dec_state_right_); -} - -int AudioDecoderG722Stereo::DecodeInternal(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - int16_t* decoded, - SpeechType* speech_type) { - RTC_DCHECK_EQ(sample_rate_hz, 16000); - int16_t temp_type = 1; // Default is speech. - // De-interleave the bit-stream into two separate payloads. - uint8_t* encoded_deinterleaved = new uint8_t[encoded_len]; - SplitStereoPacket(encoded, encoded_len, encoded_deinterleaved); - // Decode left and right. - size_t decoded_len = WebRtcG722_Decode(dec_state_left_, encoded_deinterleaved, - encoded_len / 2, decoded, &temp_type); - size_t ret = WebRtcG722_Decode( - dec_state_right_, &encoded_deinterleaved[encoded_len / 2], - encoded_len / 2, &decoded[decoded_len], &temp_type); - if (ret == decoded_len) { - ret += decoded_len; // Return total number of samples. - // Interleave output. - for (size_t k = ret / 2; k < ret; k++) { - int16_t temp = decoded[k]; - memmove(&decoded[2 * k - ret + 2], &decoded[2 * k - ret + 1], - (ret - k - 1) * sizeof(int16_t)); - decoded[2 * k - ret + 1] = temp; - } - } - *speech_type = ConvertSpeechType(temp_type); - delete [] encoded_deinterleaved; - return static_cast(ret); -} - -size_t AudioDecoderG722Stereo::Channels() const { - return 2; -} - -void AudioDecoderG722Stereo::Reset() { - WebRtcG722_DecoderInit(dec_state_left_); - WebRtcG722_DecoderInit(dec_state_right_); -} - -// Split the stereo packet and place left and right channel after each other -// in the output array. -void AudioDecoderG722Stereo::SplitStereoPacket(const uint8_t* encoded, - size_t encoded_len, - uint8_t* encoded_deinterleaved) { - assert(encoded); - // Regroup the 4 bits/sample so |l1 l2| |r1 r2| |l3 l4| |r3 r4| ..., - // where "lx" is 4 bits representing left sample number x, and "rx" right - // sample. Two samples fit in one byte, represented with |...|. - for (size_t i = 0; i + 1 < encoded_len; i += 2) { - uint8_t right_byte = ((encoded[i] & 0x0F) << 4) + (encoded[i + 1] & 0x0F); - encoded_deinterleaved[i] = (encoded[i] & 0xF0) + (encoded[i + 1] >> 4); - encoded_deinterleaved[i + 1] = right_byte; - } - - // Move one byte representing right channel each loop, and place it at the - // end of the bytestream vector. After looping the data is reordered to: - // |l1 l2| |l3 l4| ... |l(N-1) lN| |r1 r2| |r3 r4| ... |r(N-1) r(N)|, - // where N is the total number of samples. - for (size_t i = 0; i < encoded_len / 2; i++) { - uint8_t right_byte = encoded_deinterleaved[i + 1]; - memmove(&encoded_deinterleaved[i + 1], &encoded_deinterleaved[i + 2], - encoded_len - i - 2); - encoded_deinterleaved[encoded_len - 1] = right_byte; - } -} -#endif - AudioDecoderCng::AudioDecoderCng() { RTC_CHECK_EQ(0, WebRtcCng_CreateDec(&dec_state_)); WebRtcCng_InitDec(dec_state_); diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h index ffe908b791..27f293effc 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h @@ -90,58 +90,6 @@ class AudioDecoderPcmAMultiCh : public AudioDecoderPcmA { RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderPcmAMultiCh); }; -#ifdef WEBRTC_CODEC_G722 -class AudioDecoderG722 : public AudioDecoder { - public: - AudioDecoderG722(); - ~AudioDecoderG722() override; - bool HasDecodePlc() const override; - void Reset() override; - int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; - size_t Channels() const override; - - protected: - int DecodeInternal(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - int16_t* decoded, - SpeechType* speech_type) override; - - private: - G722DecInst* dec_state_; - RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderG722); -}; - -class AudioDecoderG722Stereo : public AudioDecoder { - public: - AudioDecoderG722Stereo(); - ~AudioDecoderG722Stereo() override; - void Reset() override; - - protected: - int DecodeInternal(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - int16_t* decoded, - SpeechType* speech_type) override; - size_t Channels() const override; - - private: - // Splits the stereo-interleaved payload in |encoded| into separate payloads - // for left and right channels. The separated payloads are written to - // |encoded_deinterleaved|, which must hold at least |encoded_len| samples. - // The left channel starts at offset 0, while the right channel starts at - // offset encoded_len / 2 into |encoded_deinterleaved|. - void SplitStereoPacket(const uint8_t* encoded, size_t encoded_len, - uint8_t* encoded_deinterleaved); - - G722DecInst* dec_state_left_; - G722DecInst* dec_state_right_; - - RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderG722Stereo); -}; -#endif - // AudioDecoderCng is a special type of AudioDecoder. It inherits from // AudioDecoder just to fit in the DecoderDatabase. None of the class methods // should be used, except constructor, destructor, and accessors. diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc index 4b40dfd626..64aa6485d8 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc @@ -19,6 +19,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h" +#include "webrtc/modules/audio_coding/codecs/g722/include/audio_decoder_g722.h" #include "webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h" #include "webrtc/modules/audio_coding/codecs/ilbc/interface/audio_decoder_ilbc.h" #include "webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h"