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
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 4aa372f..fe2b547 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 @@
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<uint32_t>(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 @@
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 @@
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 @@
(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<uint16_t>(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<uint16_t>(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 @@
{
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 @@
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 a06d877..df9e334 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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
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<ACMGenericCodec> 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 8826194..a16b005 100644
--- a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
+++ b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
@@ -245,33 +245,6 @@
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.
//
@@ -285,19 +258,6 @@
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 9b960af..0000000
--- 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<AudioCodingModule> acm_dual_stream_;
- scoped_ptr<AudioCodingModule> acm_ref_primary_;
- scoped_ptr<AudioCodingModule> 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 5d11aee..92a7721 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',