From 1f67b53c888c6305b60fba327c0a422c8884ff53 Mon Sep 17 00:00:00 2001 From: "henrik.lundin@webrtc.org" Date: Thu, 15 Jan 2015 09:36:30 +0000 Subject: [PATCH] Remove dual stream functionality in ACM This is old code that is no longer in use. The clean-up is part of the ACM redesign work. With this change, there is no longer need for the ProcessDualStream method, which is removed. Consequently, the method ProcessSingleStream is renamed to Process. BUG=3520 R=kwiberg@webrtc.org Review URL: https://webrtc-codereview.appspot.com/39489004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@8074 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../main/acm2/audio_coding_module_impl.cc | 360 +----------- .../main/acm2/audio_coding_module_impl.h | 30 +- .../main/interface/audio_coding_module.h | 40 -- .../main/test/dual_stream_unittest.cc | 542 ------------------ webrtc/modules/modules.gyp | 1 - 5 files changed, 8 insertions(+), 965 deletions(-) delete mode 100644 webrtc/modules/audio_coding/main/test/dual_stream_unittest.cc diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc index 4aa372fe24..fe2b5474f6 100644 --- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc +++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc @@ -96,23 +96,6 @@ int UpMix(const AudioFrame& frame, int length_out_buff, int16_t* out_buff) { return 0; } -// Return 1 if timestamp t1 is less than timestamp t2, while compensating for -// wrap-around. -static int TimestampLessThan(uint32_t t1, uint32_t t2) { - uint32_t kHalfFullRange = static_cast(0xFFFFFFFF) / 2; - if (t1 == t2) { - return 0; - } else if (t1 < t2) { - if (t2 - t1 < kHalfFullRange) - return 1; - return 0; - } else { - if (t1 - t2 < kHalfFullRange) - return 0; - return 1; - } -} - } // namespace AudioCodingModuleImpl::AudioCodingModuleImpl( @@ -141,7 +124,6 @@ AudioCodingModuleImpl::AudioCodingModuleImpl( previous_pltype_(255), aux_rtp_header_(NULL), receiver_initialized_(false), - secondary_send_codec_inst_(), codec_timestamp_(expected_codec_ts_), first_10ms_data_(false), callback_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), @@ -154,10 +136,6 @@ AudioCodingModuleImpl::AudioCodingModuleImpl( strncpy(send_codec_inst_.plname, no_name, RTP_PAYLOAD_NAME_SIZE - 1); send_codec_inst_.pltype = -1; - strncpy(secondary_send_codec_inst_.plname, no_name, - RTP_PAYLOAD_NAME_SIZE - 1); - secondary_send_codec_inst_.pltype = -1; - for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) { codecs_[i] = NULL; mirror_codec_idx_[i] = -1; @@ -272,218 +250,8 @@ int64_t AudioCodingModuleImpl::TimeUntilNextProcess() { (send_codec_inst_.plfreq / 1000); } -int32_t AudioCodingModuleImpl::Process() { - bool dual_stream; - { - CriticalSectionScoped lock(acm_crit_sect_); - dual_stream = (secondary_encoder_.get() != NULL); - } - if (dual_stream) { - return ProcessDualStream(); - } - return ProcessSingleStream(); -} - -int AudioCodingModuleImpl::EncodeFragmentation(int fragmentation_index, - int payload_type, - uint32_t current_timestamp, - ACMGenericCodec* encoder, - uint8_t* stream) { - int16_t len_bytes = MAX_PAYLOAD_SIZE_BYTE; - uint32_t rtp_timestamp; - WebRtcACMEncodingType encoding_type; - if (encoder->Encode(stream, &len_bytes, &rtp_timestamp, &encoding_type) < 0) { - return -1; - } - assert(encoding_type == kActiveNormalEncoded); - assert(len_bytes > 0); - - fragmentation_.fragmentationLength[fragmentation_index] = len_bytes; - fragmentation_.fragmentationPlType[fragmentation_index] = payload_type; - fragmentation_.fragmentationTimeDiff[fragmentation_index] = - static_cast(current_timestamp - rtp_timestamp); - fragmentation_.fragmentationVectorSize++; - return len_bytes; -} - -// Primary payloads are sent immediately, whereas a single secondary payload is -// buffered to be combined with "the next payload." -// Normally "the next payload" would be a primary payload. In case two -// consecutive secondary payloads are generated with no primary payload in -// between, then two secondary payloads are packed in one RED. -int AudioCodingModuleImpl::ProcessDualStream() { - uint8_t stream[kMaxNumFragmentationVectors * MAX_PAYLOAD_SIZE_BYTE]; - uint32_t current_timestamp; - size_t length_bytes = 0; - RTPFragmentationHeader my_fragmentation; - - uint8_t my_red_payload_type; - - { - CriticalSectionScoped lock(acm_crit_sect_); - // Check if there is an encoder before. - if (!HaveValidEncoder("ProcessDualStream") || - secondary_encoder_.get() == NULL) { - return -1; - } - ACMGenericCodec* primary_encoder = codecs_[current_send_codec_idx_]; - // If primary encoder has a full frame of audio to generate payload. - bool primary_ready_to_encode = primary_encoder->HasFrameToEncode(); - // If the secondary encoder has a frame of audio to generate a payload. - bool secondary_ready_to_encode = secondary_encoder_->HasFrameToEncode(); - - if (!primary_ready_to_encode && !secondary_ready_to_encode) { - // Nothing to send. - return 0; - } - size_t len_bytes_previous_secondary = fragmentation_.fragmentationLength[2]; - assert(len_bytes_previous_secondary <= MAX_PAYLOAD_SIZE_BYTE); - bool has_previous_payload = len_bytes_previous_secondary > 0; - - uint32_t primary_timestamp = primary_encoder->EarliestTimestamp(); - uint32_t secondary_timestamp = secondary_encoder_->EarliestTimestamp(); - - if (!has_previous_payload && !primary_ready_to_encode && - secondary_ready_to_encode) { - // Secondary payload will be the ONLY bit-stream. Encode by secondary - // encoder, store the payload, and return. No packet is sent. - int16_t len_bytes = MAX_PAYLOAD_SIZE_BYTE; - WebRtcACMEncodingType encoding_type; - if (secondary_encoder_->Encode(red_buffer_, &len_bytes, - &last_red_timestamp_, - &encoding_type) < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_, - "ProcessDual(): Encoding of secondary encoder Failed"); - return -1; - } - assert(len_bytes > 0); - assert(encoding_type == kActiveNormalEncoded); - assert(len_bytes <= MAX_PAYLOAD_SIZE_BYTE); - fragmentation_.fragmentationLength[2] = len_bytes; - return 0; - } - - // Initialize with invalid but different values, so later can have sanity - // check if they are different. - int index_primary = -1; - int index_secondary = -2; - int index_previous_secondary = -3; - - if (primary_ready_to_encode) { - index_primary = secondary_ready_to_encode ? - TimestampLessThan(primary_timestamp, secondary_timestamp) : 0; - index_primary += has_previous_payload ? - TimestampLessThan(primary_timestamp, last_red_timestamp_) : 0; - } - - if (secondary_ready_to_encode) { - // Timestamp of secondary payload can only be less than primary payload, - // but is always larger than the timestamp of previous secondary payload. - index_secondary = primary_ready_to_encode ? - (1 - TimestampLessThan(primary_timestamp, secondary_timestamp)) : 0; - } - - if (has_previous_payload) { - index_previous_secondary = primary_ready_to_encode ? - (1 - TimestampLessThan(primary_timestamp, last_red_timestamp_)) : 0; - // If secondary is ready it always have a timestamp larger than previous - // secondary. So the index is either 0 or 1. - index_previous_secondary += secondary_ready_to_encode ? 1 : 0; - } - - // Indices must not be equal. - assert(index_primary != index_secondary); - assert(index_primary != index_previous_secondary); - assert(index_secondary != index_previous_secondary); - - // One of the payloads has to be at position zero. - assert(index_primary == 0 || index_secondary == 0 || - index_previous_secondary == 0); - - // Timestamp of the RED payload. - if (index_primary == 0) { - current_timestamp = primary_timestamp; - } else if (index_secondary == 0) { - current_timestamp = secondary_timestamp; - } else { - current_timestamp = last_red_timestamp_; - } - - fragmentation_.fragmentationVectorSize = 0; - if (has_previous_payload) { - assert(index_previous_secondary >= 0 && - index_previous_secondary < kMaxNumFragmentationVectors); - assert(len_bytes_previous_secondary <= MAX_PAYLOAD_SIZE_BYTE); - memcpy(&stream[index_previous_secondary * MAX_PAYLOAD_SIZE_BYTE], - red_buffer_, sizeof(stream[0]) * len_bytes_previous_secondary); - fragmentation_.fragmentationLength[index_previous_secondary] = - len_bytes_previous_secondary; - fragmentation_.fragmentationPlType[index_previous_secondary] = - secondary_send_codec_inst_.pltype; - fragmentation_.fragmentationTimeDiff[index_previous_secondary] = - static_cast(current_timestamp - last_red_timestamp_); - fragmentation_.fragmentationVectorSize++; - } - - if (primary_ready_to_encode) { - assert(index_primary >= 0 && index_primary < kMaxNumFragmentationVectors); - int i = index_primary * MAX_PAYLOAD_SIZE_BYTE; - if (EncodeFragmentation(index_primary, send_codec_inst_.pltype, - current_timestamp, primary_encoder, - &stream[i]) < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_, - "ProcessDualStream(): Encoding of primary encoder Failed"); - return -1; - } - } - - if (secondary_ready_to_encode) { - assert(index_secondary >= 0 && - index_secondary < kMaxNumFragmentationVectors - 1); - int i = index_secondary * MAX_PAYLOAD_SIZE_BYTE; - if (EncodeFragmentation(index_secondary, - secondary_send_codec_inst_.pltype, - current_timestamp, secondary_encoder_.get(), - &stream[i]) < 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_, - "ProcessDualStream(): Encoding of secondary encoder " - "Failed"); - return -1; - } - } - // Copy to local variable, as it will be used outside the ACM lock. - my_fragmentation.CopyFrom(fragmentation_); - my_red_payload_type = red_pltype_; - length_bytes = 0; - for (int n = 0; n < fragmentation_.fragmentationVectorSize; n++) { - length_bytes += fragmentation_.fragmentationLength[n]; - } - } - - { - CriticalSectionScoped lock(callback_crit_sect_); - if (packetization_callback_ != NULL) { - // Callback with payload data, including redundant data (RED). - if (packetization_callback_->SendData(kAudioFrameSpeech, - my_red_payload_type, - current_timestamp, stream, - length_bytes, - &my_fragmentation) < 0) { - return -1; - } - } - } - - { - CriticalSectionScoped lock(acm_crit_sect_); - // Now that data is sent, clean up fragmentation. - ResetFragmentation(0); - } - return 0; -} - // Process any pending tasks such as timeouts. -int AudioCodingModuleImpl::ProcessSingleStream() { +int32_t AudioCodingModuleImpl::Process() { // Make room for 1 RED payload. uint8_t stream[2 * MAX_PAYLOAD_SIZE_BYTE]; // TODO(turajs): |length_bytes| & |red_length_bytes| can be of type int if @@ -503,7 +271,7 @@ int AudioCodingModuleImpl::ProcessSingleStream() { { CriticalSectionScoped lock(acm_crit_sect_); // Check if there is an encoder before. - if (!HaveValidEncoder("ProcessSingleStream")) { + if (!HaveValidEncoder("Process")) { return -1; } status = codecs_[current_send_codec_idx_]->Encode(stream, &length_bytes, @@ -512,7 +280,7 @@ int AudioCodingModuleImpl::ProcessSingleStream() { if (status < 0) { // Encode failed. WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_, - "ProcessSingleStream(): Encoding Failed"); + "Process(): Encoding Failed"); length_bytes = 0; return -1; } else if (status == 0) { @@ -716,15 +484,11 @@ int AudioCodingModuleImpl::InitializeSender() { // Initialize RED. is_first_red_ = true; - if (red_enabled_ || secondary_encoder_.get() != NULL) { + if (red_enabled_) { if (red_buffer_ != NULL) { memset(red_buffer_, 0, MAX_PAYLOAD_SIZE_BYTE); } - if (red_enabled_) { - ResetFragmentation(kNumRedFragmentationVectors); - } else { - ResetFragmentation(0); - } + ResetFragmentation(kNumRedFragmentationVectors); } return 0; @@ -820,69 +584,6 @@ static int IsValidSendCodec(const CodecInst& send_codec, return codec_id; } -int AudioCodingModuleImpl::RegisterSecondarySendCodec( - const CodecInst& send_codec) { - CriticalSectionScoped lock(acm_crit_sect_); - if (!send_codec_registered_) { - return -1; - } - // Primary and Secondary codecs should have the same sampling rates. - if (send_codec.plfreq != send_codec_inst_.plfreq) { - return -1; - } - int mirror_id; - int codec_id = IsValidSendCodec(send_codec, false, id_, &mirror_id); - if (codec_id < 0) { - return -1; - } - ACMGenericCodec* encoder = CreateCodec(send_codec); - WebRtcACMCodecParams codec_params; - // Initialize the codec before registering. For secondary codec VAD & DTX are - // disabled. - memcpy(&(codec_params.codec_inst), &send_codec, sizeof(CodecInst)); - codec_params.enable_vad = false; - codec_params.enable_dtx = false; - codec_params.vad_mode = VADNormal; - // Force initialization. - if (encoder->InitEncoder(&codec_params, true) < 0) { - // Could not initialize, therefore cannot be registered. - delete encoder; - return -1; - } - secondary_encoder_.reset(encoder); - memcpy(&secondary_send_codec_inst_, &send_codec, sizeof(send_codec)); - - // Disable VAD & DTX. - SetVADSafe(false, false, VADNormal); - - // Cleaning. - if (red_buffer_) { - memset(red_buffer_, 0, MAX_PAYLOAD_SIZE_BYTE); - } - ResetFragmentation(0); - return 0; -} - -void AudioCodingModuleImpl::UnregisterSecondarySendCodec() { - CriticalSectionScoped lock(acm_crit_sect_); - if (secondary_encoder_.get() == NULL) { - return; - } - secondary_encoder_.reset(); - ResetFragmentation(0); -} - -int AudioCodingModuleImpl::SecondarySendCodec( - CodecInst* secondary_codec) const { - CriticalSectionScoped lock(acm_crit_sect_); - if (secondary_encoder_.get() == NULL) { - return -1; - } - memcpy(secondary_codec, &secondary_send_codec_inst_, - sizeof(secondary_send_codec_inst_)); - return 0; -} - // Can be called multiple times for Codec, CNG, RED. int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) { int mirror_id; @@ -973,15 +674,6 @@ int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) { is_send_codec = false; } - // If there is secondary codec registered and the new send codec has a - // sampling rate different than that of secondary codec, then unregister the - // secondary codec. - if (secondary_encoder_.get() != NULL && - secondary_send_codec_inst_.plfreq != send_codec.plfreq) { - secondary_encoder_.reset(); - ResetFragmentation(0); - } - // If new codec, or new settings, register. if (!is_send_codec) { if (codecs_[mirror_id] == NULL) { @@ -1265,10 +957,6 @@ int AudioCodingModuleImpl::Add10MsData( // Check whether we need an up-mix or down-mix? bool remix = ptr_frame->num_channels_ != send_codec_inst_.channels; - if (secondary_encoder_.get() != NULL) { - remix = remix || - (ptr_frame->num_channels_ != secondary_send_codec_inst_.channels); - } // If a re-mix is required (up or down), this buffer will store re-mixed // version of the input. @@ -1296,18 +984,6 @@ int AudioCodingModuleImpl::Add10MsData( send_codec_inst_.channels) < 0) return -1; - if (secondary_encoder_.get() != NULL) { - // For pushing data to secondary, point the |ptr_audio| to correct buffer. - ptr_audio = ptr_frame->data_; - if (secondary_send_codec_inst_.channels != ptr_frame->num_channels_) - ptr_audio = buffer; - - if (secondary_encoder_->Add10MsData( - ptr_frame->timestamp_, ptr_audio, ptr_frame->samples_per_channel_, - secondary_send_codec_inst_.channels) < 0) - return -1; - } - return 0; } @@ -1318,23 +994,12 @@ int AudioCodingModuleImpl::Add10MsData( // is required, |*ptr_out| points to |in_frame|. int AudioCodingModuleImpl::PreprocessToAddData(const AudioFrame& in_frame, const AudioFrame** ptr_out) { - // Primary and secondary (if exists) should have the same sampling rate. - assert((secondary_encoder_.get() != NULL) ? - secondary_send_codec_inst_.plfreq == send_codec_inst_.plfreq : true); - bool resample = (in_frame.sample_rate_hz_ != send_codec_inst_.plfreq); // This variable is true if primary codec and secondary codec (if exists) // are both mono and input is stereo. - bool down_mix; - if (secondary_encoder_.get() != NULL) { - down_mix = (in_frame.num_channels_ == 2) && - (send_codec_inst_.channels == 1) && - (secondary_send_codec_inst_.channels == 1); - } else { - down_mix = (in_frame.num_channels_ == 2) && - (send_codec_inst_.channels == 1); - } + bool down_mix = + (in_frame.num_channels_ == 2) && (send_codec_inst_.channels == 1); if (!first_10ms_data_) { expected_in_ts_ = in_frame.timestamp_; @@ -1520,17 +1185,6 @@ int AudioCodingModuleImpl::SetVADSafe(bool enable_dtx, return -1; } - // We don't support VAD/DTX when dual-streaming is enabled, i.e. - // secondary-encoder is registered. - if ((enable_dtx || enable_vad) && secondary_encoder_.get() != NULL) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_, - "VAD/DTX not supported when dual-streaming is enabled."); - dtx_enabled_ = false; - vad_enabled_ = false; - vad_mode_ = mode; - return -1; - } - // Store VAD/DTX settings. Values can be changed in the call to "SetVAD" // below. dtx_enabled_ = enable_dtx; diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h index a06d87778b..df9e334773 100644 --- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h +++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h @@ -58,17 +58,6 @@ class AudioCodingModuleImpl : public AudioCodingModule { // Can be called multiple times for Codec, CNG, RED. virtual int RegisterSendCodec(const CodecInst& send_codec) OVERRIDE; - // Register Secondary codec for dual-streaming. Dual-streaming is activated - // right after the secondary codec is registered. - virtual int RegisterSecondarySendCodec(const CodecInst& send_codec) OVERRIDE; - - // Unregister the secondary codec. Dual-streaming is deactivated right after - // deregistering secondary codec. - virtual void UnregisterSecondarySendCodec() OVERRIDE; - - // Get the secondary codec. - virtual int SecondarySendCodec(CodecInst* secondary_codec) const OVERRIDE; - // Get current send codec. virtual int SendCodec(CodecInst* current_codec) const OVERRIDE; @@ -266,14 +255,6 @@ class AudioCodingModuleImpl : public AudioCodingModule { int SetVADSafe(bool enable_dtx, bool enable_vad, ACMVADMode mode) EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); - // Process buffered audio when dual-streaming is not enabled (When RED is - // enabled still this function is used.) - int ProcessSingleStream(); - - // Process buffered audio when dual-streaming is enabled, i.e. secondary send - // codec is registered. - int ProcessDualStream(); - // Preprocessing of input audio, including resampling and down-mixing if // required, before pushing audio into encoder's buffer. // @@ -293,13 +274,6 @@ class AudioCodingModuleImpl : public AudioCodingModule { // to |index|. int UpdateUponReceivingCodec(int index); - int EncodeFragmentation(int fragmentation_index, - int payload_type, - uint32_t current_timestamp, - ACMGenericCodec* encoder, - uint8_t* stream) - EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); - void ResetFragmentation(int vector_size) EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); @@ -348,7 +322,7 @@ class AudioCodingModuleImpl : public AudioCodingModule { // TODO(turajs): |red_buffer_| is allocated in constructor, why having them // as pointers and not an array. If concerned about the memory, then make a // set-up function to allocate them only when they are going to be used, i.e. - // RED or Dual-streaming is enabled. + // RED is enabled. uint8_t* red_buffer_ GUARDED_BY(acm_crit_sect_); // TODO(turajs): we actually don't need |fragmentation_| as a member variable. @@ -374,8 +348,6 @@ class AudioCodingModuleImpl : public AudioCodingModule { bool receiver_initialized_ GUARDED_BY(acm_crit_sect_); AudioFrame preprocess_frame_ GUARDED_BY(acm_crit_sect_); - CodecInst secondary_send_codec_inst_ GUARDED_BY(acm_crit_sect_); - scoped_ptr secondary_encoder_ GUARDED_BY(acm_crit_sect_); uint32_t codec_timestamp_ GUARDED_BY(acm_crit_sect_); bool first_10ms_data_ GUARDED_BY(acm_crit_sect_); diff --git a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h index 88261940c5..a16b005897 100644 --- a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h +++ b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h @@ -244,33 +244,6 @@ class AudioCodingModule: public Module { // virtual int32_t RegisterSendCodec(const CodecInst& send_codec) = 0; - /////////////////////////////////////////////////////////////////////////// - // int RegisterSecondarySendCodec() - // Register a secondary encoder to enable dual-streaming. If a secondary - // codec is already registered, it will be removed before the new one is - // registered. - // - // Note: The secondary encoder will be unregistered if a primary codec - // is set with a sampling rate which does not match that of the existing - // secondary codec. - // - // Input: - // -send_codec : Parameters of the codec to be registered, c.f. - // common_types.h for the definition of - // CodecInst. - // - // Return value: - // -1 if failed to register, - // 0 if succeeded. - // - virtual int RegisterSecondarySendCodec(const CodecInst& send_codec) = 0; - - /////////////////////////////////////////////////////////////////////////// - // void UnregisterSecondarySendCodec() - // Unregister the secondary encoder to disable dual-streaming. - // - virtual void UnregisterSecondarySendCodec() = 0; - /////////////////////////////////////////////////////////////////////////// // int32_t SendCodec() // Get parameters for the codec currently registered as send codec. @@ -284,19 +257,6 @@ class AudioCodingModule: public Module { // virtual int32_t SendCodec(CodecInst* current_send_codec) const = 0; - /////////////////////////////////////////////////////////////////////////// - // int SecondarySendCodec() - // Get the codec parameters for the current secondary send codec. - // - // Output: - // -secondary_codec : parameters of the secondary send codec. - // - // Return value: - // -1 if failed to get send codec, - // 0 if succeeded. - // - virtual int SecondarySendCodec(CodecInst* secondary_codec) const = 0; - /////////////////////////////////////////////////////////////////////////// // int32_t SendFrequency() // Get the sampling frequency of the current encoder in Hertz. diff --git a/webrtc/modules/audio_coding/main/test/dual_stream_unittest.cc b/webrtc/modules/audio_coding/main/test/dual_stream_unittest.cc deleted file mode 100644 index 9b960afa82..0000000000 --- a/webrtc/modules/audio_coding/main/test/dual_stream_unittest.cc +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Copyright (c) 2012 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 "testing/gtest/include/gtest/gtest.h" -#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h" -#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h" -#include "webrtc/modules/audio_coding/main/test/PCMFile.h" -#include "webrtc/modules/audio_coding/main/test/utility.h" -#include "webrtc/modules/interface/module_common_types.h" -#include "webrtc/system_wrappers/interface/scoped_ptr.h" -#include "webrtc/typedefs.h" -#include "webrtc/test/testsupport/fileutils.h" -#include "webrtc/test/testsupport/gtest_disable.h" - -namespace webrtc { - -class DualStreamTest : public AudioPacketizationCallback, - public ::testing::Test { - protected: - DualStreamTest(); - ~DualStreamTest(); - - void RunTest(int frame_size_primary_samples, - int num_channels_primary, - int sampling_rate, - bool start_in_sync, - int num_channels_input); - - void ApiTest(); - - virtual int32_t SendData( - FrameType frameType, - uint8_t payload_type, - uint32_t timestamp, - const uint8_t* payload_data, - size_t payload_size, - const RTPFragmentationHeader* fragmentation) OVERRIDE; - - void Perform(bool start_in_sync, int num_channels_input); - - void InitializeSender(int frame_size_primary_samples, - int num_channels_primary, int sampling_rate); - - void PopulateCodecInstances(int frame_size_primary_ms, - int num_channels_primary, int sampling_rate); - - void Validate(bool start_in_sync, size_t tolerance); - bool EqualTimestamp(int stream, int position); - size_t EqualPayloadLength(int stream, int position); - bool EqualPayloadData(int stream, int position); - - static const int kMaxNumStoredPayloads = 2; - - enum { - kPrimary = 0, - kSecondary, - kMaxNumStreams - }; - - scoped_ptr acm_dual_stream_; - scoped_ptr acm_ref_primary_; - scoped_ptr acm_ref_secondary_; - - CodecInst primary_encoder_; - CodecInst secondary_encoder_; - - CodecInst red_encoder_; - - int payload_ref_is_stored_[kMaxNumStreams][kMaxNumStoredPayloads]; - int payload_dual_is_stored_[kMaxNumStreams][kMaxNumStoredPayloads]; - - uint32_t timestamp_ref_[kMaxNumStreams][kMaxNumStoredPayloads]; - uint32_t timestamp_dual_[kMaxNumStreams][kMaxNumStoredPayloads]; - - size_t payload_len_ref_[kMaxNumStreams][kMaxNumStoredPayloads]; - size_t payload_len_dual_[kMaxNumStreams][kMaxNumStoredPayloads]; - - uint8_t payload_data_ref_[kMaxNumStreams][MAX_PAYLOAD_SIZE_BYTE - * kMaxNumStoredPayloads]; - uint8_t payload_data_dual_[kMaxNumStreams][MAX_PAYLOAD_SIZE_BYTE - * kMaxNumStoredPayloads]; - int num_received_payloads_dual_[kMaxNumStreams]; - int num_received_payloads_ref_[kMaxNumStreams]; - - int num_compared_payloads_[kMaxNumStreams]; - uint32_t last_timestamp_[kMaxNumStreams]; - bool received_payload_[kMaxNumStreams]; -}; - -DualStreamTest::DualStreamTest() - : acm_dual_stream_(AudioCodingModule::Create(0)), - acm_ref_primary_(AudioCodingModule::Create(1)), - acm_ref_secondary_(AudioCodingModule::Create(2)), - payload_ref_is_stored_(), - payload_dual_is_stored_(), - timestamp_ref_(), - num_received_payloads_dual_(), - num_received_payloads_ref_(), - num_compared_payloads_(), - last_timestamp_(), - received_payload_() {} - -DualStreamTest::~DualStreamTest() {} - -void DualStreamTest::PopulateCodecInstances(int frame_size_primary_ms, - int num_channels_primary, - int sampling_rate) { - CodecInst my_codec; - - // Invalid values. To check later on if the codec are found in the database. - primary_encoder_.pltype = -1; - secondary_encoder_.pltype = -1; - red_encoder_.pltype = -1; - - for (int n = 0; n < AudioCodingModule::NumberOfCodecs(); n++) { - AudioCodingModule::Codec(n, &my_codec); - if (strcmp(my_codec.plname, "ISAC") == 0 - && my_codec.plfreq == sampling_rate) { - my_codec.rate = 32000; - my_codec.pacsize = 30 * sampling_rate / 1000; - memcpy(&secondary_encoder_, &my_codec, sizeof(my_codec)); - } else if (strcmp(my_codec.plname, "L16") == 0 - && my_codec.channels == num_channels_primary - && my_codec.plfreq == sampling_rate) { - my_codec.pacsize = frame_size_primary_ms * sampling_rate / 1000; - memcpy(&primary_encoder_, &my_codec, sizeof(my_codec)); - } else if (strcmp(my_codec.plname, "red") == 0) { - memcpy(&red_encoder_, &my_codec, sizeof(my_codec)); - } - } - - ASSERT_GE(primary_encoder_.pltype, 0); - ASSERT_GE(secondary_encoder_.pltype, 0); - ASSERT_GE(red_encoder_.pltype, 0); -} - -void DualStreamTest::InitializeSender(int frame_size_primary_samples, - int num_channels_primary, - int sampling_rate) { - ASSERT_TRUE(acm_dual_stream_.get() != NULL); - ASSERT_TRUE(acm_ref_primary_.get() != NULL); - ASSERT_TRUE(acm_ref_secondary_.get() != NULL); - - ASSERT_EQ(0, acm_dual_stream_->InitializeSender()); - ASSERT_EQ(0, acm_ref_primary_->InitializeSender()); - ASSERT_EQ(0, acm_ref_secondary_->InitializeSender()); - - PopulateCodecInstances(frame_size_primary_samples, num_channels_primary, - sampling_rate); - - ASSERT_EQ(0, acm_ref_primary_->RegisterSendCodec(primary_encoder_)); - ASSERT_EQ(0, acm_ref_secondary_->RegisterSendCodec(secondary_encoder_)); - ASSERT_EQ(0, acm_dual_stream_->RegisterSendCodec(primary_encoder_)); - ASSERT_EQ(0, - acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_)); - - ASSERT_EQ(0, acm_ref_primary_->RegisterTransportCallback(this)); - ASSERT_EQ(0, acm_ref_secondary_->RegisterTransportCallback(this)); - ASSERT_EQ(0, acm_dual_stream_->RegisterTransportCallback(this)); -} - -void DualStreamTest::Perform(bool start_in_sync, int num_channels_input) { - PCMFile pcm_file; - std::string file_name = test::ResourcePath( - (num_channels_input == 1) ? - "audio_coding/testfile32kHz" : "audio_coding/teststereo32kHz", - "pcm"); - pcm_file.Open(file_name, 32000, "rb"); - pcm_file.ReadStereo(num_channels_input == 2); - AudioFrame audio_frame; - - size_t tolerance = 0; - if (num_channels_input == 2 && primary_encoder_.channels == 2 - && secondary_encoder_.channels == 1) { - tolerance = 12; - } - - if (!start_in_sync) { - pcm_file.Read10MsData(audio_frame); - // Unregister secondary codec and feed only the primary - acm_dual_stream_->UnregisterSecondarySendCodec(); - EXPECT_EQ(0, acm_dual_stream_->Add10MsData(audio_frame)); - EXPECT_EQ(0, acm_ref_primary_->Add10MsData(audio_frame)); - ASSERT_EQ(0, - acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_)); - } - - const int kNumFramesToProcess = 100; - int frame_cntr = 0; - while (!pcm_file.EndOfFile() && frame_cntr < kNumFramesToProcess) { - pcm_file.Read10MsData(audio_frame); - frame_cntr++; - EXPECT_EQ(0, acm_dual_stream_->Add10MsData(audio_frame)); - EXPECT_EQ(0, acm_ref_primary_->Add10MsData(audio_frame)); - EXPECT_EQ(0, acm_ref_secondary_->Add10MsData(audio_frame)); - - EXPECT_GE(acm_dual_stream_->Process(), 0); - EXPECT_GE(acm_ref_primary_->Process(), 0); - EXPECT_GE(acm_ref_secondary_->Process(), 0); - - if (start_in_sync || frame_cntr > 7) { - // If we haven't started in sync the first few audio frames might - // slightly differ due to the difference in the state of the resamplers - // of dual-ACM and reference-ACM. - Validate(start_in_sync, tolerance); - } else { - // SendData stores the payloads, if we are not comparing we have to free - // the space by resetting these flags. - memset(payload_ref_is_stored_, 0, sizeof(payload_ref_is_stored_)); - memset(payload_dual_is_stored_, 0, sizeof(payload_dual_is_stored_)); - } - } - pcm_file.Close(); - - // Make sure that number of received payloads match. In case of secondary - // encoder, the dual-stream might deliver one lesser payload. The reason is - // that some secondary payloads are stored to be sent with a payload generated - // later and the input file may end before the "next" payload . - EXPECT_EQ(num_received_payloads_ref_[kPrimary], - num_received_payloads_dual_[kPrimary]); - EXPECT_TRUE( - num_received_payloads_ref_[kSecondary] - == num_received_payloads_dual_[kSecondary] - || num_received_payloads_ref_[kSecondary] - == (num_received_payloads_dual_[kSecondary] + 1)); - - // Make sure all received payloads are compared. - if (start_in_sync) { - EXPECT_EQ(num_received_payloads_dual_[kPrimary], - num_compared_payloads_[kPrimary]); - EXPECT_EQ(num_received_payloads_dual_[kSecondary], - num_compared_payloads_[kSecondary]); - } else { - // In asynchronous test we don't compare couple of first frames, so we - // should account for them in our counting. - EXPECT_GE(num_compared_payloads_[kPrimary], - num_received_payloads_dual_[kPrimary] - 4); - EXPECT_GE(num_compared_payloads_[kSecondary], - num_received_payloads_dual_[kSecondary] - 4); - } -} - -bool DualStreamTest::EqualTimestamp(int stream_index, int position) { - if (timestamp_dual_[stream_index][position] - != timestamp_ref_[stream_index][position]) { - return false; - } - return true; -} - -size_t DualStreamTest::EqualPayloadLength(int stream_index, int position) { - size_t dual = payload_len_dual_[stream_index][position]; - size_t ref = payload_len_ref_[stream_index][position]; - return (dual > ref) ? (dual - ref) : (ref - dual); -} - -bool DualStreamTest::EqualPayloadData(int stream_index, int position) { - assert( - payload_len_dual_[stream_index][position] - == payload_len_ref_[stream_index][position]); - int offset = position * MAX_PAYLOAD_SIZE_BYTE; - for (size_t n = 0; n < payload_len_dual_[stream_index][position]; n++) { - if (payload_data_dual_[stream_index][offset + n] - != payload_data_ref_[stream_index][offset + n]) { - return false; - } - } - return true; -} - -void DualStreamTest::Validate(bool start_in_sync, size_t tolerance) { - for (int stream_index = 0; stream_index < kMaxNumStreams; stream_index++) { - size_t my_tolerance = stream_index == kPrimary ? 0 : tolerance; - for (int position = 0; position < kMaxNumStoredPayloads; position++) { - if (payload_ref_is_stored_[stream_index][position] == 1 - && payload_dual_is_stored_[stream_index][position] == 1) { - // Check timestamps only if codecs started in sync or it is primary. - if (start_in_sync || stream_index == 0) - EXPECT_TRUE(EqualTimestamp(stream_index, position)); - EXPECT_LE(EqualPayloadLength(stream_index, position), my_tolerance); - if (my_tolerance == 0) - EXPECT_TRUE(EqualPayloadData(stream_index, position)); - num_compared_payloads_[stream_index]++; - payload_ref_is_stored_[stream_index][position] = 0; - payload_dual_is_stored_[stream_index][position] = 0; - } - } - } -} - -int32_t DualStreamTest::SendData(FrameType frameType, uint8_t payload_type, - uint32_t timestamp, - const uint8_t* payload_data, - size_t payload_size, - const RTPFragmentationHeader* fragmentation) { - int position; - int stream_index; - - if (payload_type == red_encoder_.pltype) { - if (fragmentation == NULL) { - assert(false); - return -1; - } - // As the oldest payloads are in the higher indices of fragmentation, - // to be able to check the increment of timestamps are correct we loop - // backward. - for (int n = fragmentation->fragmentationVectorSize - 1; n >= 0; --n) { - if (fragmentation->fragmentationPlType[n] == primary_encoder_.pltype) { - // Received primary payload from dual stream. - stream_index = kPrimary; - } else if (fragmentation->fragmentationPlType[n] - == secondary_encoder_.pltype) { - // Received secondary payload from dual stream. - stream_index = kSecondary; - } else { - assert(false); - return -1; - } - num_received_payloads_dual_[stream_index]++; - if (payload_dual_is_stored_[stream_index][0] == 0) { - position = 0; - } else if (payload_dual_is_stored_[stream_index][1] == 0) { - position = 1; - } else { - assert(false); - return -1; - } - timestamp_dual_[stream_index][position] = timestamp - - fragmentation->fragmentationTimeDiff[n]; - payload_len_dual_[stream_index][position] = fragmentation - ->fragmentationLength[n]; - memcpy( - &payload_data_dual_[stream_index][position * MAX_PAYLOAD_SIZE_BYTE], - &payload_data[fragmentation->fragmentationOffset[n]], - fragmentation->fragmentationLength[n]); - payload_dual_is_stored_[stream_index][position] = 1; - // Check if timestamps are incremented correctly. - if (received_payload_[stream_index]) { - int t = timestamp_dual_[stream_index][position] - - last_timestamp_[stream_index]; - if ((stream_index == kPrimary) && (t != primary_encoder_.pacsize)) { - assert(false); - return -1; - } - if ((stream_index == kSecondary) && (t != secondary_encoder_.pacsize)) { - assert(false); - return -1; - } - } else { - received_payload_[stream_index] = true; - } - last_timestamp_[stream_index] = timestamp_dual_[stream_index][position]; - } - } else { - if (fragmentation != NULL) { - assert(false); - return -1; - } - if (payload_type == primary_encoder_.pltype) { - stream_index = kPrimary; - } else if (payload_type == secondary_encoder_.pltype) { - stream_index = kSecondary; - } else { - assert(false); - return -1; - } - num_received_payloads_ref_[stream_index]++; - if (payload_ref_is_stored_[stream_index][0] == 0) { - position = 0; - } else if (payload_ref_is_stored_[stream_index][1] == 0) { - position = 1; - } else { - assert(false); - return -1; - } - timestamp_ref_[stream_index][position] = timestamp; - payload_len_ref_[stream_index][position] = payload_size; - memcpy(&payload_data_ref_[stream_index][position * MAX_PAYLOAD_SIZE_BYTE], - payload_data, payload_size); - payload_ref_is_stored_[stream_index][position] = 1; - } - return 0; -} - -// Mono input, mono primary WB 20 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimaryWb20Ms)) { - InitializeSender(20, 1, 16000); - Perform(true, 1); -} - -// Mono input, stereo primary WB 20 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncMonoInput_StereoPrimaryWb20Ms)) { - InitializeSender(20, 2, 16000); - Perform(true, 1); -} - -// Mono input, mono primary SWB 20 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimarySwb20Ms)) { - InitializeSender(20, 1, 32000); - Perform(true, 1); -} - -// Mono input, stereo primary SWB 20 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncMonoInputStereoPrimarySwb20Ms)) { - InitializeSender(20, 2, 32000); - Perform(true, 1); -} - -// Mono input, mono primary WB 40 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimaryWb40Ms)) { - InitializeSender(40, 1, 16000); - Perform(true, 1); -} - -// Mono input, stereo primary WB 40 ms frame -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncMonoInputStereoPrimaryWb40Ms)) { - InitializeSender(40, 2, 16000); - Perform(true, 1); -} - -// Stereo input, mono primary WB 20 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimaryWb20Ms)) { - InitializeSender(20, 1, 16000); - Perform(true, 2); -} - -// Stereo input, stereo primary WB 20 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimaryWb20Ms)) { - InitializeSender(20, 2, 16000); - Perform(true, 2); -} - -// Stereo input, mono primary SWB 20 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimarySwb20Ms)) { - InitializeSender(20, 1, 32000); - Perform(true, 2); -} - -// Stereo input, stereo primary SWB 20 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimarySwb20Ms)) { - InitializeSender(20, 2, 32000); - Perform(true, 2); -} - -// Stereo input, mono primary WB 40 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimaryWb40Ms)) { - InitializeSender(40, 1, 16000); - Perform(true, 2); -} - -// Stereo input, stereo primary WB 40 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimaryWb40Ms)) { - InitializeSender(40, 2, 16000); - Perform(true, 2); -} - -// Asynchronous test, ACM is fed with data then secondary coder is registered. -// Mono input, mono primary WB 20 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactAsyncMonoInputMonoPrimaryWb20Ms)) { - InitializeSender(20, 1, 16000); - Perform(false, 1); -} - -// Mono input, mono primary WB 20 ms frame. -TEST_F(DualStreamTest, - DISABLED_ON_ANDROID(BitExactAsyncMonoInputMonoPrimaryWb40Ms)) { - InitializeSender(40, 1, 16000); - Perform(false, 1); -} - -TEST_F(DualStreamTest, DISABLED_ON_ANDROID(Api)) { - PopulateCodecInstances(20, 1, 16000); - CodecInst my_codec; - ASSERT_EQ(0, acm_dual_stream_->InitializeSender()); - ASSERT_EQ(-1, acm_dual_stream_->SecondarySendCodec(&my_codec)); - - // Not allowed to register secondary codec if primary is not registered yet. - ASSERT_EQ(-1, - acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_)); - ASSERT_EQ(-1, acm_dual_stream_->SecondarySendCodec(&my_codec)); - - ASSERT_EQ(0, acm_dual_stream_->RegisterSendCodec(primary_encoder_)); - - ASSERT_EQ(0, acm_dual_stream_->SetVAD(true, true, VADNormal)); - - // Make sure vad is activated. - bool vad_status; - bool dtx_status; - ACMVADMode vad_mode; - EXPECT_EQ(0, acm_dual_stream_->VAD(&vad_status, &dtx_status, &vad_mode)); - EXPECT_TRUE(vad_status); - EXPECT_TRUE(dtx_status); - EXPECT_EQ(VADNormal, vad_mode); - - ASSERT_EQ(0, - acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_)); - - ASSERT_EQ(0, acm_dual_stream_->SecondarySendCodec(&my_codec)); - ASSERT_EQ(0, memcmp(&my_codec, &secondary_encoder_, sizeof(my_codec))); - - // Test if VAD get disabled after registering secondary codec. - EXPECT_EQ(0, acm_dual_stream_->VAD(&vad_status, &dtx_status, &vad_mode)); - EXPECT_FALSE(vad_status); - EXPECT_FALSE(dtx_status); - - // Activating VAD should fail. - ASSERT_EQ(-1, acm_dual_stream_->SetVAD(true, true, VADNormal)); - - // Unregister secondary encoder and it should be possible to activate VAD. - acm_dual_stream_->UnregisterSecondarySendCodec(); - // Should fail. - ASSERT_EQ(-1, acm_dual_stream_->SecondarySendCodec(&my_codec)); - - ASSERT_EQ(0, acm_dual_stream_->SetVAD(true, true, VADVeryAggr)); - // Make sure VAD is activated. - EXPECT_EQ(0, acm_dual_stream_->VAD(&vad_status, &dtx_status, &vad_mode)); - EXPECT_TRUE(vad_status); - EXPECT_TRUE(dtx_status); - EXPECT_EQ(VADVeryAggr, vad_mode); -} - -} // namespace webrtc diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index 5d11aee0f1..92a7721b74 100644 --- a/webrtc/modules/modules.gyp +++ b/webrtc/modules/modules.gyp @@ -388,7 +388,6 @@ 'audio_coding/main/test/Tester.cc', 'audio_coding/main/test/TimedTrace.cc', 'audio_coding/main/test/TwoWayCommunication.cc', - 'audio_coding/main/test/dual_stream_unittest.cc', 'audio_coding/main/test/iSACTest.cc', 'audio_coding/main/test/initial_delay_unittest.cc', 'audio_coding/main/test/opus_test.cc',