Move NetEq headers to api/

This CL also introduces NetEqFactory and NetEqControllerFactory
interfaces, as well as several convenience classes for working with
them: DefaultNetEqFactory, DefaultNetEqControllerFactory and
CustomNetEqFactory.

Bug: webrtc:11005
Change-Id: I1e8fc5154636ac2aad1a856828f80a2a758ad392
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/156945
Commit-Queue: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29671}
This commit is contained in:
Ivo Creusen 2019-10-31 14:38:11 +01:00 committed by Commit Bot
parent 739a5b3692
commit 3ce44a3540
50 changed files with 851 additions and 389 deletions

View File

@ -597,6 +597,26 @@ rtc_library("neteq_simulator_api") {
]
}
rtc_source_set("neteq_factory_with_codecs") {
visibility = [ "*" ]
testonly = true
sources = [
"test/neteq_factory_with_codecs.cc",
"test/neteq_factory_with_codecs.h",
]
deps = [
":scoped_refptr",
"../modules/audio_coding:neteq",
"../system_wrappers:system_wrappers",
"audio_codecs:audio_codecs_api",
"audio_codecs:builtin_audio_decoder_factory",
"neteq:default_neteq_controller_factory",
"neteq:neteq_api",
"neteq:neteq_controller_api",
]
}
rtc_source_set("function_view") {
visibility = [ "*" ]
sources = [

98
api/neteq/BUILD.gn Normal file
View File

@ -0,0 +1,98 @@
# Copyright (c) 2019 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.
import("../../webrtc.gni")
rtc_source_set("neteq_api") {
visibility = [ "*" ]
sources = [
"neteq.cc",
"neteq.h",
"neteq_factory.h",
]
deps = [
"..:rtp_headers",
"..:rtp_packet_info",
"..:scoped_refptr",
"../../rtc_base:rtc_base_approved",
"../../system_wrappers:system_wrappers",
"../audio_codecs:audio_codecs_api",
"//third_party/abseil-cpp/absl/types:optional",
]
}
rtc_source_set("custom_neteq_factory") {
visibility = [ "*" ]
sources = [
"custom_neteq_factory.cc",
"custom_neteq_factory.h",
]
deps = [
":neteq_api",
":neteq_controller_api",
"..:scoped_refptr",
"../../modules/audio_coding:neteq",
"../../system_wrappers:system_wrappers",
"../audio_codecs:audio_codecs_api",
]
}
rtc_source_set("neteq_controller_api") {
visibility = [ "*" ]
sources = [
"neteq_controller.h",
"neteq_controller_factory.h",
]
deps = [
":neteq_api",
":tick_timer",
"../../rtc_base:rtc_base_approved",
"//third_party/abseil-cpp/absl/types:optional",
]
}
rtc_source_set("default_neteq_controller_factory") {
visibility = [ "*" ]
sources = [
"default_neteq_controller_factory.cc",
"default_neteq_controller_factory.h",
]
deps = [
":neteq_controller_api",
"../../modules/audio_coding:neteq",
]
}
rtc_source_set("tick_timer") {
visibility = [ "*" ]
sources = [
"tick_timer.cc",
"tick_timer.h",
]
deps = [
"../../rtc_base:checks",
"../../rtc_base:rtc_base_approved",
]
}
rtc_source_set("tick_timer_unittest") {
visibility = [ "*" ]
testonly = true
sources = [
"tick_timer_unittest.cc",
]
deps = [
":tick_timer",
"../../test:test_support",
"//testing/gtest",
]
}

8
api/neteq/DEPS Normal file
View File

@ -0,0 +1,8 @@
specific_include_rules = {
"neteq_factory\.h": [
"+system_wrappers/include/clock.h",
],
"custom_neteq_factory\.h": [
"+system_wrappers/include/clock.h",
],
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019 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 "api/neteq/custom_neteq_factory.h"
#include <utility>
#include "modules/audio_coding/neteq/neteq_impl.h"
namespace webrtc {
CustomNetEqFactory::CustomNetEqFactory(
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
std::unique_ptr<NetEqControllerFactory> controller_factory)
: decoder_factory_(decoder_factory),
controller_factory_(std::move(controller_factory)) {}
CustomNetEqFactory::~CustomNetEqFactory() = default;
std::unique_ptr<NetEq> CustomNetEqFactory::CreateNetEq(
const NetEq::Config& config,
Clock* clock) const {
return std::make_unique<NetEqImpl>(
config, NetEqImpl::Dependencies(config, clock, decoder_factory_,
*controller_factory_));
}
} // namespace webrtc

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2019 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 API_NETEQ_CUSTOM_NETEQ_FACTORY_H_
#define API_NETEQ_CUSTOM_NETEQ_FACTORY_H_
#include <memory>
#include "api/audio_codecs/audio_decoder_factory.h"
#include "api/neteq/neteq_controller_factory.h"
#include "api/neteq/neteq_factory.h"
#include "api/scoped_refptr.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
// This factory can be used to generate NetEq instances that make use of a
// custom AudioDecoderFactory and/or NetEqControllerFactory.
class CustomNetEqFactory : public NetEqFactory {
public:
CustomNetEqFactory(
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
std::unique_ptr<NetEqControllerFactory> controller_factory);
~CustomNetEqFactory() override;
CustomNetEqFactory(const CustomNetEqFactory&) = delete;
CustomNetEqFactory& operator=(const CustomNetEqFactory&) = delete;
std::unique_ptr<NetEq> CreateNetEq(const NetEq::Config& config,
Clock* clock) const override;
private:
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
std::unique_ptr<NetEqControllerFactory> controller_factory_;
};
} // namespace webrtc
#endif // API_NETEQ_CUSTOM_NETEQ_FACTORY_H_

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2019 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 "api/neteq/default_neteq_controller_factory.h"
#include "modules/audio_coding/neteq/decision_logic.h"
namespace webrtc {
DefaultNetEqControllerFactory::DefaultNetEqControllerFactory() = default;
DefaultNetEqControllerFactory::~DefaultNetEqControllerFactory() = default;
std::unique_ptr<NetEqController>
DefaultNetEqControllerFactory::CreateNetEqController(
const NetEqController::Config& config) const {
return std::make_unique<DecisionLogic>(config);
}
} // namespace webrtc

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019 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 API_NETEQ_DEFAULT_NETEQ_CONTROLLER_FACTORY_H_
#define API_NETEQ_DEFAULT_NETEQ_CONTROLLER_FACTORY_H_
#include <memory>
#include "api/neteq/neteq_controller_factory.h"
namespace webrtc {
// This NetEqControllerFactory will use WebRTC's built-in controller logic.
class DefaultNetEqControllerFactory : public NetEqControllerFactory {
public:
DefaultNetEqControllerFactory();
~DefaultNetEqControllerFactory() override;
DefaultNetEqControllerFactory(const DefaultNetEqControllerFactory&) = delete;
DefaultNetEqControllerFactory& operator=(
const DefaultNetEqControllerFactory&) = delete;
std::unique_ptr<NetEqController> CreateNetEqController(
const NetEqController::Config& config) const override;
};
} // namespace webrtc
#endif // API_NETEQ_DEFAULT_NETEQ_CONTROLLER_FACTORY_H_

View File

@ -8,9 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/audio_coding/neteq/include/neteq.h"
#include "api/neteq/neteq.h"
#include "modules/audio_coding/neteq/neteq_impl.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
@ -35,14 +34,4 @@ std::string NetEq::Config::ToString() const {
return ss.str();
}
// Creates all classes needed and inject them into a new NetEqImpl object.
// Return the new object.
NetEq* NetEq::Create(
const NetEq::Config& config,
Clock* clock,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
return new NetEqImpl(config,
NetEqImpl::Dependencies(config, clock, decoder_factory));
}
} // namespace webrtc

View File

@ -8,10 +8,10 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_AUDIO_CODING_NETEQ_INCLUDE_NETEQ_H_
#define MODULES_AUDIO_CODING_NETEQ_INCLUDE_NETEQ_H_
#ifndef API_NETEQ_NETEQ_H_
#define API_NETEQ_NETEQ_H_
#include <string.h> // Provide access to size_t.
#include <stddef.h> // Provide access to size_t.
#include <map>
#include <string>
@ -23,8 +23,6 @@
#include "api/audio_codecs/audio_format.h"
#include "api/rtp_headers.h"
#include "api/scoped_refptr.h"
#include "modules/audio_coding/neteq/defines.h"
#include "rtc_base/constructor_magic.h"
namespace webrtc {
@ -143,6 +141,38 @@ class NetEq {
enum ReturnCodes { kOK = 0, kFail = -1 };
enum class Operation {
kNormal,
kMerge,
kExpand,
kAccelerate,
kFastAccelerate,
kPreemptiveExpand,
kRfc3389Cng,
kRfc3389CngNoPacket,
kCodecInternalCng,
kDtmf,
kUndefined,
};
enum class Mode {
kNormal,
kExpand,
kMerge,
kAccelerateSuccess,
kAccelerateLowEnergy,
kAccelerateFail,
kPreemptiveExpandSuccess,
kPreemptiveExpandLowEnergy,
kPreemptiveExpandFail,
kRfc3389Cng,
kCodecInternalCng,
kCodecPlc,
kDtmf,
kError,
kUndefined,
};
// Return type for GetDecoderFormat.
struct DecoderFormat {
int sample_rate_hz;
@ -193,7 +223,7 @@ class NetEq {
virtual int GetAudio(
AudioFrame* audio_frame,
bool* muted,
absl::optional<Operations> action_override = absl::nullopt) = 0;
absl::optional<Operation> action_override = absl::nullopt) = 0;
// Replaces the current set of decoders with the given one.
virtual void SetCodecs(const std::map<int, SdpAudioFormat>& codecs) = 0;
@ -299,13 +329,7 @@ class NetEq {
// Returns the length of the audio yet to play in the sync buffer.
// Mainly intended for testing.
virtual int SyncBufferSizeMs() const = 0;
protected:
NetEq() {}
private:
RTC_DISALLOW_COPY_AND_ASSIGN(NetEq);
};
} // namespace webrtc
#endif // MODULES_AUDIO_CODING_NETEQ_INCLUDE_NETEQ_H_
#endif // API_NETEQ_NETEQ_H_

View File

@ -8,8 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_AUDIO_CODING_NETEQ_NETEQ_CONTROLLER_H_
#define MODULES_AUDIO_CODING_NETEQ_NETEQ_CONTROLLER_H_
#ifndef API_NETEQ_NETEQ_CONTROLLER_H_
#define API_NETEQ_NETEQ_CONTROLLER_H_
#include <cstddef>
#include <cstdint>
@ -18,8 +18,8 @@
#include <memory>
#include "absl/types/optional.h"
#include "modules/audio_coding/neteq/defines.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "api/neteq/neteq.h"
#include "api/neteq/tick_timer.h"
namespace webrtc {
@ -88,7 +88,7 @@ class NetEqController {
int16_t expand_mutefactor;
size_t last_packet_samples;
absl::optional<PacketInfo> next_packet;
Modes last_mode;
NetEq::Mode last_mode;
bool play_dtmf;
size_t generated_noise_samples;
PacketBufferInfo packet_buffer_info;
@ -111,8 +111,8 @@ class NetEqController {
// play, |play_dtmf| should be set to true. The output variable
// |reset_decoder| will be set to true if a reset is required; otherwise it is
// left unchanged (i.e., it can remain true if it was true before the call).
virtual Operations GetDecision(const NetEqStatus& status,
bool* reset_decoder) = 0;
virtual NetEq::Operation GetDecision(const NetEqStatus& status,
bool* reset_decoder) = 0;
// Inform NetEqController that an empty packet has arrived.
virtual void RegisterEmptyPacket() = 0;
@ -143,7 +143,7 @@ class NetEqController {
// not. Note that this is necessary, since an expand decision can be changed
// to kNormal in NetEqImpl::GetDecision if there is still enough data in the
// sync buffer.
virtual void ExpandDecision(Operations operation) = 0;
virtual void ExpandDecision(NetEq::Operation operation) = 0;
// Adds |value| to |sample_memory_|.
virtual void AddSampleMemory(int32_t value) = 0;
@ -175,4 +175,4 @@ class NetEqController {
};
} // namespace webrtc
#endif // MODULES_AUDIO_CODING_NETEQ_NETEQ_CONTROLLER_H_
#endif // API_NETEQ_NETEQ_CONTROLLER_H_

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2019 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 API_NETEQ_NETEQ_CONTROLLER_FACTORY_H_
#define API_NETEQ_NETEQ_CONTROLLER_FACTORY_H_
#include <memory>
#include "api/neteq/neteq_controller.h"
namespace webrtc {
// Creates NetEqController instances using the settings provided in the config
// struct.
class NetEqControllerFactory {
public:
virtual ~NetEqControllerFactory() = default;
// Creates a new NetEqController object, with parameters set in |config|.
virtual std::unique_ptr<NetEqController> CreateNetEqController(
const NetEqController::Config& config) const = 0;
};
} // namespace webrtc
#endif // API_NETEQ_NETEQ_CONTROLLER_FACTORY_H_

34
api/neteq/neteq_factory.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019 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 API_NETEQ_NETEQ_FACTORY_H_
#define API_NETEQ_NETEQ_FACTORY_H_
#include <memory>
#include "api/neteq/neteq.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
// Creates NetEq instances using the settings provided in the config struct.
class NetEqFactory {
public:
virtual ~NetEqFactory() = default;
// Creates a new NetEq object, with parameters set in |config|. The |config|
// object will only have to be valid for the duration of the call to this
// method.
virtual std::unique_ptr<NetEq> CreateNetEq(const NetEq::Config& config,
Clock* clock) const = 0;
};
} // namespace webrtc
#endif // API_NETEQ_NETEQ_FACTORY_H_

View File

@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/audio_coding/neteq/tick_timer.h"
#include "api/neteq/tick_timer.h"
namespace webrtc {

View File

@ -8,21 +8,20 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_AUDIO_CODING_NETEQ_TICK_TIMER_H_
#define MODULES_AUDIO_CODING_NETEQ_TICK_TIMER_H_
#ifndef API_NETEQ_TICK_TIMER_H_
#define API_NETEQ_TICK_TIMER_H_
#include <stdint.h>
#include <memory>
#include "rtc_base/checks.h"
#include "rtc_base/constructor_magic.h"
namespace webrtc {
// Implements a time counter. The counter is advanced with the Increment()
// methods, and is queried with the ticks() accessor. It is assumed that one
// "tick" och the counter corresponds to 10 ms.
// "tick" of the counter corresponds to 10 ms.
// A TickTimer object can provide two types of associated time-measuring
// objects: Stopwatch and Countdown.
class TickTimer {
@ -78,6 +77,9 @@ class TickTimer {
RTC_DCHECK_GT(ms_per_tick_, 0);
}
TickTimer(const TickTimer&) = delete;
TickTimer& operator=(const TickTimer&) = delete;
void Increment() { ++ticks_; }
// Mainly intended for testing.
@ -104,8 +106,7 @@ class TickTimer {
private:
uint64_t ticks_ = 0;
const int ms_per_tick_;
RTC_DISALLOW_COPY_AND_ASSIGN(TickTimer);
};
} // namespace webrtc
#endif // MODULES_AUDIO_CODING_NETEQ_TICK_TIMER_H_
#endif // API_NETEQ_TICK_TIMER_H_

View File

@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/audio_coding/neteq/tick_timer.h"
#include "api/neteq/tick_timer.h"
#include <memory>

View File

@ -17,6 +17,9 @@ specific_include_rules = {
"+rtc_base/thread.h",
"+rtc_base/thread_checker.h",
],
"neteq_factory_with_codecs\.h": [
"+system_wrappers/include/clock.h",
],
"network_emulation_manager\.h": [
"+rtc_base/thread.h",
"+rtc_base/network.h",

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2019 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 "api/test/neteq_factory_with_codecs.h"
#include "api/audio_codecs/audio_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/neteq/default_neteq_controller_factory.h"
#include "api/neteq/neteq_controller_factory.h"
#include "api/neteq/neteq_factory.h"
#include "modules/audio_coding/neteq/decision_logic.h"
#include "modules/audio_coding/neteq/neteq_impl.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
namespace {
class NetEqFactoryWithCodecs final : public NetEqFactory {
public:
std::unique_ptr<NetEq> CreateNetEq(const NetEq::Config& config,
Clock* clock) const override {
return std::make_unique<NetEqImpl>(
config, NetEqImpl::Dependencies(config, clock, decoder_factory_,
*controller_factory_));
}
private:
const rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_ =
CreateBuiltinAudioDecoderFactory();
const std::unique_ptr<NetEqControllerFactory> controller_factory_ =
std::make_unique<DefaultNetEqControllerFactory>();
};
} // namespace
std::unique_ptr<NetEqFactory> CreateNetEqFactoryWithCodecs() {
return std::make_unique<NetEqFactoryWithCodecs>();
}
} // namespace webrtc

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2019 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 API_TEST_NETEQ_FACTORY_WITH_CODECS_H_
#define API_TEST_NETEQ_FACTORY_WITH_CODECS_H_
#include <memory>
#include "api/neteq/neteq_factory.h"
namespace webrtc {
// This NetEq factory will use WebRTC's built-in AudioDecoders as well as the
// built-in NetEqController logic.
std::unique_ptr<NetEqFactory> CreateNetEqFactoryWithCodecs();
} // namespace webrtc
#endif // API_TEST_NETEQ_FACTORY_WITH_CODECS_H_

View File

@ -48,6 +48,9 @@ rtc_library("audio_coding") {
"../../api:function_view",
"../../api/audio:audio_frame_api",
"../../api/audio_codecs:audio_codecs_api",
"../../api/neteq:custom_neteq_factory",
"../../api/neteq:default_neteq_controller_factory",
"../../api/neteq:neteq_api",
"../../common_audio",
"../../common_audio:common_audio_c",
"../../rtc_base:audio_format_to_string",
@ -944,7 +947,6 @@ rtc_library("neteq") {
"neteq/decision_logic.h",
"neteq/decoder_database.cc",
"neteq/decoder_database.h",
"neteq/defines.h",
"neteq/delay_manager.cc",
"neteq/delay_manager.h",
"neteq/delay_peak_detector.cc",
@ -961,13 +963,10 @@ rtc_library("neteq") {
"neteq/expand_uma_logger.h",
"neteq/histogram.cc",
"neteq/histogram.h",
"neteq/include/neteq.h",
"neteq/merge.cc",
"neteq/merge.h",
"neteq/nack_tracker.cc",
"neteq/nack_tracker.h",
"neteq/neteq.cc",
"neteq/neteq_controller.h",
"neteq/neteq_impl.cc",
"neteq/neteq_impl.h",
"neteq/normal.cc",
@ -988,8 +987,6 @@ rtc_library("neteq") {
"neteq/statistics_calculator.h",
"neteq/sync_buffer.cc",
"neteq/sync_buffer.h",
"neteq/tick_timer.cc",
"neteq/tick_timer.h",
"neteq/time_stretch.cc",
"neteq/time_stretch.h",
"neteq/timestamp_scaler.cc",
@ -1007,6 +1004,9 @@ rtc_library("neteq") {
"../../api:scoped_refptr",
"../../api/audio:audio_frame_api",
"../../api/audio_codecs:audio_codecs_api",
"../../api/neteq:neteq_api",
"../../api/neteq:neteq_controller_api",
"../../api/neteq:tick_timer",
"../../common_audio",
"../../common_audio:common_audio_c",
"../../rtc_base:audio_format_to_string",
@ -1052,6 +1052,9 @@ rtc_library("neteq_tools_minimal") {
"../../api:rtp_headers",
"../../api/audio:audio_frame_api",
"../../api/audio_codecs:audio_codecs_api",
"../../api/neteq:custom_neteq_factory",
"../../api/neteq:default_neteq_controller_factory",
"../../api/neteq:neteq_api",
"../../rtc_base:checks",
"../../rtc_base:rtc_base_approved",
"../../system_wrappers",
@ -1467,6 +1470,7 @@ if (rtc_include_tests) {
":neteq",
":neteq_test_tools",
"../../api/audio_codecs:builtin_audio_decoder_factory",
"../../api/neteq:neteq_api",
"../../rtc_base:rtc_base_approved",
"../../test:audio_codec_mocks",
"../../test:field_trial",
@ -1558,9 +1562,11 @@ if (rtc_include_tests) {
":neteq",
":neteq_test_tools",
":pcm16b",
"../../api:neteq_factory_with_codecs",
"../../api/audio:audio_frame_api",
"../../api/audio_codecs:audio_codecs_api",
"../../api/audio_codecs:builtin_audio_decoder_factory",
"../../api/neteq:neteq_api",
"../../rtc_base:checks",
"../../rtc_base:rtc_base_approved",
"../../system_wrappers",
@ -1581,6 +1587,9 @@ if (rtc_include_tests) {
":neteq",
":neteq_test_tools",
"../../api/audio_codecs:builtin_audio_decoder_factory",
"../../api/neteq:custom_neteq_factory",
"../../api/neteq:default_neteq_controller_factory",
"../../api/neteq:neteq_api",
"../../rtc_base:checks",
"../../system_wrappers",
"../../test:fileutils",
@ -1976,7 +1985,6 @@ if (rtc_include_tests) {
"neteq/red_payload_splitter_unittest.cc",
"neteq/statistics_calculator_unittest.cc",
"neteq/sync_buffer_unittest.cc",
"neteq/tick_timer_unittest.cc",
"neteq/time_stretch_unittest.cc",
"neteq/timestamp_scaler_unittest.cc",
"neteq/tools/input_audio_file_unittest.cc",
@ -2007,6 +2015,7 @@ if (rtc_include_tests) {
":webrtc_opus",
"..:module_api",
"..:module_api_public",
"../../api:neteq_factory_with_codecs",
"../../api/audio:audio_frame_api",
"../../api/audio_codecs:audio_codecs_api",
"../../api/audio_codecs:builtin_audio_decoder_factory",
@ -2015,6 +2024,12 @@ if (rtc_include_tests) {
"../../api/audio_codecs/opus:audio_decoder_opus",
"../../api/audio_codecs/opus:audio_encoder_multiopus",
"../../api/audio_codecs/opus:audio_encoder_opus",
"../../api/neteq:custom_neteq_factory",
"../../api/neteq:default_neteq_controller_factory",
"../../api/neteq:neteq_api",
"../../api/neteq:neteq_controller_api",
"../../api/neteq:tick_timer",
"../../api/neteq:tick_timer_unittest",
"../../api/rtc_event_log",
"../../common_audio",
"../../common_audio:common_audio_c",

View File

@ -19,9 +19,11 @@
#include "absl/strings/match.h"
#include "api/audio/audio_frame.h"
#include "api/audio_codecs/audio_decoder.h"
#include "api/neteq/custom_neteq_factory.h"
#include "api/neteq/default_neteq_controller_factory.h"
#include "api/neteq/neteq.h"
#include "modules/audio_coding/acm2/acm_resampler.h"
#include "modules/audio_coding/acm2/call_statistics.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
@ -32,11 +34,24 @@ namespace webrtc {
namespace acm2 {
namespace {
std::unique_ptr<NetEq> CreateNetEq(
const NetEq::Config& config,
Clock* clock,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
CustomNetEqFactory neteq_factory(
decoder_factory, std::make_unique<DefaultNetEqControllerFactory>());
return neteq_factory.CreateNetEq(config, clock);
}
} // namespace
AcmReceiver::AcmReceiver(const AudioCodingModule::Config& config)
: last_audio_buffer_(new int16_t[AudioFrame::kMaxDataSizeSamples]),
neteq_(NetEq::Create(config.neteq_config,
config.clock,
config.decoder_factory)),
neteq_(CreateNetEq(config.neteq_config,
config.clock,
config.decoder_factory)),
clock_(config.clock),
resampled_last_output_frame_(true) {
RTC_DCHECK(clock_);

View File

@ -20,8 +20,8 @@
#include "api/audio_codecs/audio_decoder_factory.h"
#include "api/audio_codecs/audio_encoder.h"
#include "api/function_view.h"
#include "api/neteq/neteq.h"
#include "modules/audio_coding/include/audio_coding_module_typedefs.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {

View File

@ -91,42 +91,43 @@ void DecisionLogic::SetSampleRate(int fs_hz, size_t output_size_samples) {
output_size_samples_ = output_size_samples;
}
Operations DecisionLogic::GetDecision(const NetEqStatus& status,
bool* reset_decoder) {
NetEq::Operation DecisionLogic::GetDecision(const NetEqStatus& status,
bool* reset_decoder) {
// If last mode was CNG (or Expand, since this could be covering up for
// a lost CNG packet), remember that CNG is on. This is needed if comfort
// noise is interrupted by DTMF.
if (status.last_mode == kModeRfc3389Cng) {
if (status.last_mode == NetEq::Mode::kRfc3389Cng) {
cng_state_ = kCngRfc3389On;
} else if (status.last_mode == kModeCodecInternalCng) {
} else if (status.last_mode == NetEq::Mode::kCodecInternalCng) {
cng_state_ = kCngInternalOn;
}
size_t cur_size_samples = estimate_dtx_delay_
? status.packet_buffer_info.span_samples
: status.packet_buffer_info.num_samples;
prev_time_scale_ =
prev_time_scale_ && (status.last_mode == kModeAccelerateSuccess ||
status.last_mode == kModeAccelerateLowEnergy ||
status.last_mode == kModePreemptiveExpandSuccess ||
status.last_mode == kModePreemptiveExpandLowEnergy);
prev_time_scale_ &&
(status.last_mode == NetEq::Mode::kAccelerateSuccess ||
status.last_mode == NetEq::Mode::kAccelerateLowEnergy ||
status.last_mode == NetEq::Mode::kPreemptiveExpandSuccess ||
status.last_mode == NetEq::Mode::kPreemptiveExpandLowEnergy);
// Do not update buffer history if currently playing CNG since it will bias
// the filtered buffer level.
if (status.last_mode != kModeRfc3389Cng &&
status.last_mode != kModeCodecInternalCng &&
if (status.last_mode != NetEq::Mode::kRfc3389Cng &&
status.last_mode != NetEq::Mode::kCodecInternalCng &&
!(status.next_packet && status.next_packet->is_dtx &&
!estimate_dtx_delay_)) {
FilterBufferLevel(cur_size_samples);
}
// Guard for errors, to avoid getting stuck in error mode.
if (status.last_mode == kModeError) {
if (status.last_mode == NetEq::Mode::kError) {
if (!status.next_packet) {
return kExpand;
return NetEq::Operation::kExpand;
} else {
return kUndefined; // Use kUndefined to flag for a reset.
// Use kUndefined to flag for a reset.
return NetEq::Operation::kUndefined;
}
}
@ -145,7 +146,7 @@ Operations DecisionLogic::GetDecision(const NetEqStatus& status,
// sender was restarted.
if (num_consecutive_expands_ > kReinitAfterExpands) {
*reset_decoder = true;
return kNormal;
return NetEq::Operation::kNormal;
}
// Make sure we don't restart audio too soon after an expansion to avoid
@ -158,13 +159,14 @@ Operations DecisionLogic::GetDecision(const NetEqStatus& status,
const size_t current_span =
estimate_dtx_delay_ ? status.packet_buffer_info.span_samples
: status.packet_buffer_info.span_samples_no_dtx;
if ((status.last_mode == kModeExpand || status.last_mode == kModeCodecPlc) &&
if ((status.last_mode == NetEq::Mode::kExpand ||
status.last_mode == NetEq::Mode::kCodecPlc) &&
status.expand_mutefactor < 16384 / 2 &&
current_span<static_cast<size_t>(delay_manager_->TargetLevel() *
packet_length_samples_ *
kPostponeDecodingLevel / 100)>> 8 &&
!status.packet_buffer_info.dtx_or_cng) {
return kExpand;
return NetEq::Operation::kExpand;
}
const uint32_t five_seconds_samples = static_cast<uint32_t>(5 * sample_rate_);
@ -182,12 +184,12 @@ Operations DecisionLogic::GetDecision(const NetEqStatus& status,
} else {
// This implies that available_timestamp < target_timestamp, which can
// happen when a new stream or codec is received. Signal for a reset.
return kUndefined;
return NetEq::Operation::kUndefined;
}
}
void DecisionLogic::ExpandDecision(Operations operation) {
if (operation == kExpand) {
void DecisionLogic::ExpandDecision(NetEq::Operation operation) {
if (operation == NetEq::Operation::kExpand) {
num_consecutive_expands_++;
} else {
num_consecutive_expands_ = 0;
@ -241,10 +243,10 @@ void DecisionLogic::FilterBufferLevel(size_t buffer_size_samples) {
time_stretched_cn_samples_ = 0;
}
Operations DecisionLogic::CngOperation(Modes prev_mode,
uint32_t target_timestamp,
uint32_t available_timestamp,
size_t generated_noise_samples) {
NetEq::Operation DecisionLogic::CngOperation(NetEq::Mode prev_mode,
uint32_t target_timestamp,
uint32_t available_timestamp,
size_t generated_noise_samples) {
// Signed difference between target and available timestamp.
int32_t timestamp_diff = static_cast<int32_t>(
static_cast<uint32_t>(generated_noise_samples + target_timestamp) -
@ -264,35 +266,36 @@ Operations DecisionLogic::CngOperation(Modes prev_mode,
rtc::saturated_cast<int32_t>(timestamp_diff + excess_waiting_time_samp);
}
if (timestamp_diff < 0 && prev_mode == kModeRfc3389Cng) {
if (timestamp_diff < 0 && prev_mode == NetEq::Mode::kRfc3389Cng) {
// Not time to play this packet yet. Wait another round before using this
// packet. Keep on playing CNG from previous CNG parameters.
return kRfc3389CngNoPacket;
return NetEq::Operation::kRfc3389CngNoPacket;
} else {
// Otherwise, go for the CNG packet now.
noise_fast_forward_ = 0;
return kRfc3389Cng;
return NetEq::Operation::kRfc3389Cng;
}
}
Operations DecisionLogic::NoPacket(bool play_dtmf) {
NetEq::Operation DecisionLogic::NoPacket(bool play_dtmf) {
if (cng_state_ == kCngRfc3389On) {
// Keep on playing comfort noise.
return kRfc3389CngNoPacket;
return NetEq::Operation::kRfc3389CngNoPacket;
} else if (cng_state_ == kCngInternalOn) {
// Keep on playing codec internal comfort noise.
return kCodecInternalCng;
return NetEq::Operation::kCodecInternalCng;
} else if (play_dtmf) {
return kDtmf;
return NetEq::Operation::kDtmf;
} else {
// Nothing to play, do expand.
return kExpand;
return NetEq::Operation::kExpand;
}
}
Operations DecisionLogic::ExpectedPacketAvailable(Modes prev_mode,
bool play_dtmf) {
if (!disallow_time_stretching_ && prev_mode != kModeExpand && !play_dtmf) {
NetEq::Operation DecisionLogic::ExpectedPacketAvailable(NetEq::Mode prev_mode,
bool play_dtmf) {
if (!disallow_time_stretching_ && prev_mode != NetEq::Mode::kExpand &&
!play_dtmf) {
// Check criterion for time-stretching. The values are in number of packets
// in Q8.
int low_limit, high_limit;
@ -304,20 +307,20 @@ Operations DecisionLogic::ExpectedPacketAvailable(Modes prev_mode,
packet_length_samples_;
}
if (buffer_level_packets >= high_limit << 2)
return kFastAccelerate;
return NetEq::Operation::kFastAccelerate;
if (TimescaleAllowed()) {
if (buffer_level_packets >= high_limit)
return kAccelerate;
return NetEq::Operation::kAccelerate;
if (buffer_level_packets < low_limit)
return kPreemptiveExpand;
return NetEq::Operation::kPreemptiveExpand;
}
}
return kNormal;
return NetEq::Operation::kNormal;
}
Operations DecisionLogic::FuturePacketAvailable(
NetEq::Operation DecisionLogic::FuturePacketAvailable(
size_t decoder_frame_length,
Modes prev_mode,
NetEq::Mode prev_mode,
uint32_t target_timestamp,
uint32_t available_timestamp,
bool play_dtmf,
@ -328,24 +331,26 @@ Operations DecisionLogic::FuturePacketAvailable(
// Check if we should continue with an ongoing expand because the new packet
// is too far into the future.
uint32_t timestamp_leap = available_timestamp - target_timestamp;
if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) &&
if ((prev_mode == NetEq::Mode::kExpand ||
prev_mode == NetEq::Mode::kCodecPlc) &&
!ReinitAfterExpands(timestamp_leap) && !MaxWaitForPacket() &&
PacketTooEarly(timestamp_leap) && UnderTargetLevel()) {
if (play_dtmf) {
// Still have DTMF to play, so do not do expand.
return kDtmf;
return NetEq::Operation::kDtmf;
} else {
// Nothing to play.
return kExpand;
return NetEq::Operation::kExpand;
}
}
if (prev_mode == kModeCodecPlc) {
return kNormal;
if (prev_mode == NetEq::Mode::kCodecPlc) {
return NetEq::Operation::kNormal;
}
// If previous was comfort noise, then no merge is needed.
if (prev_mode == kModeRfc3389Cng || prev_mode == kModeCodecInternalCng) {
if (prev_mode == NetEq::Mode::kRfc3389Cng ||
prev_mode == NetEq::Mode::kCodecInternalCng) {
size_t cur_size_samples =
estimate_dtx_delay_
? cur_size_samples = span_samples_in_packet_buffer
@ -370,7 +375,7 @@ Operations DecisionLogic::FuturePacketAvailable(
if ((generated_enough_noise && !below_target_window) ||
above_target_window) {
time_stretched_cn_samples_ = timestamp_leap - generated_noise_samples;
return kNormal;
return NetEq::Operation::kNormal;
}
} else {
// Keep the same delay as before the CNG, but make sure that the number of
@ -378,26 +383,26 @@ Operations DecisionLogic::FuturePacketAvailable(
if (generated_enough_noise ||
cur_size_samples > target_level_samples * 4) {
// Time to play this new packet.
return kNormal;
return NetEq::Operation::kNormal;
}
}
// Too early to play this new packet; keep on playing comfort noise.
if (prev_mode == kModeRfc3389Cng) {
return kRfc3389CngNoPacket;
if (prev_mode == NetEq::Mode::kRfc3389Cng) {
return NetEq::Operation::kRfc3389CngNoPacket;
}
// prevPlayMode == kModeCodecInternalCng.
return kCodecInternalCng;
return NetEq::Operation::kCodecInternalCng;
}
// Do not merge unless we have done an expand before.
if (prev_mode == kModeExpand) {
return kMerge;
if (prev_mode == NetEq::Mode::kExpand) {
return NetEq::Operation::kMerge;
} else if (play_dtmf) {
// Play DTMF instead of expand.
return kDtmf;
return NetEq::Operation::kDtmf;
} else {
return kExpand;
return NetEq::Operation::kExpand;
}
}

View File

@ -11,12 +11,12 @@
#ifndef MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_
#define MODULES_AUDIO_CODING_NETEQ_DECISION_LOGIC_H_
#include "api/neteq/neteq.h"
#include "api/neteq/neteq_controller.h"
#include "api/neteq/tick_timer.h"
#include "modules/audio_coding/neteq/buffer_level_filter.h"
#include "modules/audio_coding/neteq/defines.h"
#include "modules/audio_coding/neteq/delay_manager.h"
#include "modules/audio_coding/neteq/delay_peak_detector.h"
#include "modules/audio_coding/neteq/neteq_controller.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "rtc_base/constructor_magic.h"
#include "rtc_base/experiments/field_trial_parser.h"
@ -52,8 +52,8 @@ class DecisionLogic : public NetEqController {
// true. The output variable |reset_decoder| will be set to true if a reset is
// required; otherwise it is left unchanged (i.e., it can remain true if it
// was true before the call).
Operations GetDecision(const NetEqStatus& status,
bool* reset_decoder) override;
NetEq::Operation GetDecision(const NetEqController::NetEqStatus& status,
bool* reset_decoder) override;
// These methods test the |cng_state_| for different conditions.
bool CngRfc3389On() const override { return cng_state_ == kCngRfc3389On; }
@ -66,7 +66,7 @@ class DecisionLogic : public NetEqController {
// not. Note that this is necessary, since an expand decision can be changed
// to kNormal in NetEqImpl::GetDecision if there is still enough data in the
// sync buffer.
void ExpandDecision(Operations operation) override;
void ExpandDecision(NetEq::Operation operation) override;
// Adds |value| to |sample_memory_|.
void AddSampleMemory(int32_t value) override { sample_memory_ += value; }
@ -126,28 +126,29 @@ class DecisionLogic : public NetEqController {
// Returns the operation given that the next available packet is a comfort
// noise payload (RFC 3389 only, not codec-internal).
Operations CngOperation(Modes prev_mode,
uint32_t target_timestamp,
uint32_t available_timestamp,
size_t generated_noise_samples);
NetEq::Operation CngOperation(NetEq::Mode prev_mode,
uint32_t target_timestamp,
uint32_t available_timestamp,
size_t generated_noise_samples);
// Returns the operation given that no packets are available (except maybe
// a DTMF event, flagged by setting |play_dtmf| true).
Operations NoPacket(bool play_dtmf);
NetEq::Operation NoPacket(bool play_dtmf);
// Returns the operation to do given that the expected packet is available.
Operations ExpectedPacketAvailable(Modes prev_mode, bool play_dtmf);
NetEq::Operation ExpectedPacketAvailable(NetEq::Mode prev_mode,
bool play_dtmf);
// Returns the operation to do given that the expected packet is not
// available, but a packet further into the future is at hand.
Operations FuturePacketAvailable(size_t decoder_frame_length,
Modes prev_mode,
uint32_t target_timestamp,
uint32_t available_timestamp,
bool play_dtmf,
size_t generated_noise_samples,
size_t span_samples_in_packet_buffer,
size_t num_packets_in_packet_buffer);
NetEq::Operation FuturePacketAvailable(size_t decoder_frame_length,
NetEq::Mode prev_mode,
uint32_t target_timestamp,
uint32_t available_timestamp,
bool play_dtmf,
size_t generated_noise_samples,
size_t span_samples_in_packet_buffer,
size_t num_packets_in_packet_buffer);
// Checks if enough time has elapsed since the last successful timescale
// operation was done (i.e., accelerate or preemptive expand).

View File

@ -12,14 +12,14 @@
#include "modules/audio_coding/neteq/decision_logic.h"
#include "api/neteq/neteq_controller.h"
#include "api/neteq/tick_timer.h"
#include "modules/audio_coding/neteq/buffer_level_filter.h"
#include "modules/audio_coding/neteq/decoder_database.h"
#include "modules/audio_coding/neteq/delay_manager.h"
#include "modules/audio_coding/neteq/delay_peak_detector.h"
#include "modules/audio_coding/neteq/neteq_controller.h"
#include "modules/audio_coding/neteq/packet_buffer.h"
#include "modules/audio_coding/neteq/statistics_calculator.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "test/gtest.h"
#include "test/mock_audio_decoder_factory.h"

View File

@ -1,49 +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.
*/
#ifndef MODULES_AUDIO_CODING_NETEQ_DEFINES_H_
#define MODULES_AUDIO_CODING_NETEQ_DEFINES_H_
namespace webrtc {
enum Operations {
kNormal = 0,
kMerge,
kExpand,
kAccelerate,
kFastAccelerate,
kPreemptiveExpand,
kRfc3389Cng,
kRfc3389CngNoPacket,
kCodecInternalCng,
kDtmf,
kUndefined = -1
};
enum Modes {
kModeNormal = 0,
kModeExpand,
kModeMerge,
kModeAccelerateSuccess,
kModeAccelerateLowEnergy,
kModeAccelerateFail,
kModePreemptiveExpandSuccess,
kModePreemptiveExpandLowEnergy,
kModePreemptiveExpandFail,
kModeRfc3389Cng,
kModeCodecInternalCng,
kModeCodecPlc,
kModeDtmf,
kModeError,
kModeUndefined = -1
};
} // namespace webrtc
#endif // MODULES_AUDIO_CODING_NETEQ_DEFINES_H_

View File

@ -17,8 +17,8 @@
#include <memory>
#include "absl/types/optional.h"
#include "api/neteq/tick_timer.h"
#include "modules/audio_coding/neteq/histogram.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "rtc_base/constructor_magic.h"
namespace webrtc {

View File

@ -17,7 +17,7 @@
#include <list>
#include <memory>
#include "modules/audio_coding/neteq/tick_timer.h"
#include "api/neteq/tick_timer.h"
#include "rtc_base/constructor_magic.h"
namespace webrtc {

View File

@ -16,7 +16,7 @@
#include <string>
#include "absl/types/optional.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "api/neteq/tick_timer.h"
#include "rtc_base/constructor_magic.h"
namespace webrtc {

View File

@ -11,7 +11,7 @@
#ifndef MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_NETEQ_CONTROLLER_H_
#define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_NETEQ_CONTROLLER_H_
#include "modules/audio_coding/neteq/neteq_controller.h"
#include "api/neteq/neteq_controller.h"
#include "test/gmock.h"
namespace webrtc {
@ -24,8 +24,8 @@ class MockNetEqController : public NetEqController {
MOCK_METHOD0(Reset, void());
MOCK_METHOD0(SoftReset, void());
MOCK_METHOD2(GetDecision,
Operations(const NetEqStatus& neteq_status,
bool* reset_decoder));
NetEq::Operation(const NetEqStatus& neteq_status,
bool* reset_decoder));
MOCK_METHOD6(Update,
void(uint16_t sequence_number,
uint32_t timestamp,
@ -42,7 +42,7 @@ class MockNetEqController : public NetEqController {
MOCK_CONST_METHOD0(CngRfc3389On, bool());
MOCK_CONST_METHOD0(CngOff, bool());
MOCK_METHOD0(SetCngOff, void());
MOCK_METHOD1(ExpandDecision, void(Operations operation));
MOCK_METHOD1(ExpandDecision, void(NetEq::Operation operation));
MOCK_METHOD1(AddSampleMemory, void(int32_t value));
MOCK_METHOD0(TargetLevelMs, int());
MOCK_METHOD6(PacketArrived,

View File

@ -21,6 +21,7 @@
#include <vector>
#include "api/audio_codecs/audio_decoder.h"
#include "api/neteq/tick_timer.h"
#include "common_audio/signal_processing/include/signal_processing_library.h"
#include "modules/audio_coding/codecs/cng/webrtc_cng.h"
#include "modules/audio_coding/neteq/accelerate.h"
@ -28,7 +29,6 @@
#include "modules/audio_coding/neteq/comfort_noise.h"
#include "modules/audio_coding/neteq/decision_logic.h"
#include "modules/audio_coding/neteq/decoder_database.h"
#include "modules/audio_coding/neteq/defines.h"
#include "modules/audio_coding/neteq/dtmf_buffer.h"
#include "modules/audio_coding/neteq/dtmf_tone_generator.h"
#include "modules/audio_coding/neteq/expand.h"
@ -42,7 +42,6 @@
#include "modules/audio_coding/neteq/red_payload_splitter.h"
#include "modules/audio_coding/neteq/statistics_calculator.h"
#include "modules/audio_coding/neteq/sync_buffer.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "modules/audio_coding/neteq/time_stretch.h"
#include "modules/audio_coding/neteq/timestamp_scaler.h"
#include "rtc_base/checks.h"
@ -57,6 +56,7 @@ namespace webrtc {
namespace {
std::unique_ptr<NetEqController> CreateNetEqController(
const NetEqControllerFactory& controller_factory,
int base_min_delay,
int max_packets_in_buffer,
bool enable_rtx_handling,
@ -68,7 +68,7 @@ std::unique_ptr<NetEqController> CreateNetEqController(
config.enable_rtx_handling = enable_rtx_handling;
config.allow_time_stretching = allow_time_stretching;
config.tick_timer = tick_timer;
return std::make_unique<DecisionLogic>(std::move(config));
return controller_factory.CreateNetEqController(config);
}
} // namespace
@ -76,7 +76,8 @@ std::unique_ptr<NetEqController> CreateNetEqController(
NetEqImpl::Dependencies::Dependencies(
const NetEq::Config& config,
Clock* clock,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory)
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
const NetEqControllerFactory& controller_factory)
: clock(clock),
tick_timer(new TickTimer),
stats(new StatisticsCalculator),
@ -87,7 +88,8 @@ NetEqImpl::Dependencies::Dependencies(
packet_buffer(
new PacketBuffer(config.max_packets_in_buffer, tick_timer.get())),
neteq_controller(
CreateNetEqController(config.min_delay_ms,
CreateNetEqController(controller_factory,
config.min_delay_ms,
config.max_packets_in_buffer,
config.enable_rtx_handling,
!config.for_test_no_time_stretching,
@ -117,7 +119,7 @@ NetEqImpl::NetEqImpl(const NetEq::Config& config,
preemptive_expand_factory_(std::move(deps.preemptive_expand_factory)),
stats_(std::move(deps.stats)),
controller_(std::move(deps.neteq_controller)),
last_mode_(kModeNormal),
last_mode_(Mode::kNormal),
decoded_buffer_length_(kMaxFrameSize),
decoded_buffer_(new int16_t[decoded_buffer_length_]),
playout_timestamp_(0),
@ -230,7 +232,7 @@ void SetAudioFrameActivityAndType(bool vad_enabled,
int NetEqImpl::GetAudio(AudioFrame* audio_frame,
bool* muted,
absl::optional<Operations> action_override) {
absl::optional<Operation> action_override) {
TRACE_EVENT0("webrtc", "NetEqImpl::GetAudio");
rtc::CritScope lock(&crit_sect_);
if (GetAudioInternal(audio_frame, muted, action_override) != 0) {
@ -381,8 +383,8 @@ void NetEqImpl::DisableVad() {
absl::optional<uint32_t> NetEqImpl::GetPlayoutTimestamp() const {
rtc::CritScope lock(&crit_sect_);
if (first_packet_ || last_mode_ == kModeRfc3389Cng ||
last_mode_ == kModeCodecInternalCng) {
if (first_packet_ || last_mode_ == Mode::kRfc3389Cng ||
last_mode_ == Mode::kCodecInternalCng) {
// We don't have a valid RTP timestamp until we have decoded our first
// RTP packet. Also, the RTP timestamp is not accurate while playing CNG,
// which is indicated by returning an empty value.
@ -470,7 +472,7 @@ const SyncBuffer* NetEqImpl::sync_buffer_for_test() const {
return sync_buffer_.get();
}
Operations NetEqImpl::last_operation_for_test() const {
NetEq::Operation NetEqImpl::last_operation_for_test() const {
rtc::CritScope lock(&crit_sect_);
return last_operation_;
}
@ -743,10 +745,10 @@ int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header,
int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
bool* muted,
absl::optional<Operations> action_override) {
absl::optional<Operation> action_override) {
PacketList packet_list;
DtmfEvent dtmf_event;
Operations operation;
Operation operation;
bool play_dtmf;
*muted = false;
last_decoded_timestamps_.clear();
@ -763,7 +765,7 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
// Check for muted state.
if (enable_muted_state_ && expand_->Muted() && packet_buffer_->Empty()) {
RTC_DCHECK_EQ(last_mode_, kModeExpand);
RTC_DCHECK_EQ(last_mode_, Mode::kExpand);
audio_frame->Reset();
RTC_DCHECK(audio_frame->muted()); // Reset() should mute the frame.
playout_timestamp_ += static_cast<uint32_t>(output_size_samples_);
@ -782,7 +784,7 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
int return_value = GetDecision(&operation, &packet_list, &dtmf_event,
&play_dtmf, action_override);
if (return_value != 0) {
last_mode_ = kModeError;
last_mode_ = Mode::kError;
return return_value;
}
@ -793,7 +795,8 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
Decode(&packet_list, &operation, &length, &speech_type);
assert(vad_.get());
bool sid_frame_available = (operation == kRfc3389Cng && !packet_list.empty());
bool sid_frame_available =
(operation == Operation::kRfc3389Cng && !packet_list.empty());
vad_->Update(decoded_buffer_.get(), static_cast<size_t>(length), speech_type,
sid_frame_available, fs_hz_);
@ -810,18 +813,18 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
algorithm_buffer_->Clear();
switch (operation) {
case kNormal: {
case Operation::kNormal: {
DoNormal(decoded_buffer_.get(), length, speech_type, play_dtmf);
if (length > 0) {
stats_->DecodedOutputPlayed();
}
break;
}
case kMerge: {
case Operation::kMerge: {
DoMerge(decoded_buffer_.get(), length, speech_type, play_dtmf);
break;
}
case kExpand: {
case Operation::kExpand: {
RTC_DCHECK_EQ(return_value, 0);
if (!current_rtp_payload_type_ || !DoCodecPlc()) {
return_value = DoExpand(play_dtmf);
@ -830,40 +833,40 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
output_size_samples_);
break;
}
case kAccelerate:
case kFastAccelerate: {
case Operation::kAccelerate:
case Operation::kFastAccelerate: {
const bool fast_accelerate =
enable_fast_accelerate_ && (operation == kFastAccelerate);
enable_fast_accelerate_ && (operation == Operation::kFastAccelerate);
return_value = DoAccelerate(decoded_buffer_.get(), length, speech_type,
play_dtmf, fast_accelerate);
break;
}
case kPreemptiveExpand: {
case Operation::kPreemptiveExpand: {
return_value = DoPreemptiveExpand(decoded_buffer_.get(), length,
speech_type, play_dtmf);
break;
}
case kRfc3389Cng:
case kRfc3389CngNoPacket: {
case Operation::kRfc3389Cng:
case Operation::kRfc3389CngNoPacket: {
return_value = DoRfc3389Cng(&packet_list, play_dtmf);
break;
}
case kCodecInternalCng: {
case Operation::kCodecInternalCng: {
// This handles the case when there is no transmission and the decoder
// should produce internal comfort noise.
// TODO(hlundin): Write test for codec-internal CNG.
DoCodecInternalCng(decoded_buffer_.get(), length);
break;
}
case kDtmf: {
case Operation::kDtmf: {
// TODO(hlundin): Write test for this.
return_value = DoDtmf(dtmf_event, &play_dtmf);
break;
}
case kUndefined: {
case Operation::kUndefined: {
RTC_LOG(LS_ERROR) << "Invalid operation kUndefined.";
assert(false); // This should not happen.
last_mode_ = kModeError;
last_mode_ = Mode::kError;
return kInvalidOperation;
}
} // End of switch.
@ -872,7 +875,7 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
return return_value;
}
if (last_mode_ != kModeRfc3389Cng) {
if (last_mode_ != Mode::kRfc3389Cng) {
comfort_noise_->Reset();
}
@ -941,20 +944,20 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
// Update the background noise parameters if last operation wrote data
// straight from the decoder to the |sync_buffer_|. That is, none of the
// operations that modify the signal can be followed by a parameter update.
if ((last_mode_ == kModeNormal) || (last_mode_ == kModeAccelerateFail) ||
(last_mode_ == kModePreemptiveExpandFail) ||
(last_mode_ == kModeRfc3389Cng) ||
(last_mode_ == kModeCodecInternalCng)) {
if ((last_mode_ == Mode::kNormal) || (last_mode_ == Mode::kAccelerateFail) ||
(last_mode_ == Mode::kPreemptiveExpandFail) ||
(last_mode_ == Mode::kRfc3389Cng) ||
(last_mode_ == Mode::kCodecInternalCng)) {
background_noise_->Update(*sync_buffer_, *vad_.get());
}
if (operation == kDtmf) {
if (operation == Operation::kDtmf) {
// DTMF data was written the end of |sync_buffer_|.
// Update index to end of DTMF data in |sync_buffer_|.
sync_buffer_->set_dtmf_index(sync_buffer_->Size());
}
if (last_mode_ != kModeExpand && last_mode_ != kModeCodecPlc) {
if (last_mode_ != Mode::kExpand && last_mode_ != Mode::kCodecPlc) {
// If last operation was not expand, calculate the |playout_timestamp_| from
// the |sync_buffer_|. However, do not update the |playout_timestamp_| if it
// would be moved "backwards".
@ -978,8 +981,9 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
: timestamp_scaler_->ToExternal(playout_timestamp_) -
static_cast<uint32_t>(audio_frame->samples_per_channel_);
if (!(last_mode_ == kModeRfc3389Cng || last_mode_ == kModeCodecInternalCng ||
last_mode_ == kModeExpand || last_mode_ == kModeCodecPlc)) {
if (!(last_mode_ == Mode::kRfc3389Cng ||
last_mode_ == Mode::kCodecInternalCng || last_mode_ == Mode::kExpand ||
last_mode_ == Mode::kCodecPlc)) {
generated_noise_stopwatch_.reset();
}
@ -988,14 +992,14 @@ int NetEqImpl::GetAudioInternal(AudioFrame* audio_frame,
return return_value;
}
int NetEqImpl::GetDecision(Operations* operation,
int NetEqImpl::GetDecision(Operation* operation,
PacketList* packet_list,
DtmfEvent* dtmf_event,
bool* play_dtmf,
absl::optional<Operations> action_override) {
absl::optional<Operation> action_override) {
// Initialize output variables.
*play_dtmf = false;
*operation = kUndefined;
*operation = Operation::kUndefined;
assert(sync_buffer_.get());
uint32_t end_timestamp = sync_buffer_->end_timestamp();
@ -1014,7 +1018,7 @@ int NetEqImpl::GetDecision(Operations* operation,
controller_->noise_fast_forward()
: 0;
if (controller_->CngRfc3389On() || last_mode_ == kModeRfc3389Cng) {
if (controller_->CngRfc3389On() || last_mode_ == Mode::kRfc3389Cng) {
// Because of timestamp peculiarities, we have to "manually" disallow using
// a CNG packet with the same timestamp as the one that was last played.
// This can happen when using redundancy and will cause the timing to shift.
@ -1038,10 +1042,10 @@ int NetEqImpl::GetDecision(Operations* operation,
assert(expand_.get());
const int samples_left = static_cast<int>(sync_buffer_->FutureLength() -
expand_->overlap_length());
if (last_mode_ == kModeAccelerateSuccess ||
last_mode_ == kModeAccelerateLowEnergy ||
last_mode_ == kModePreemptiveExpandSuccess ||
last_mode_ == kModePreemptiveExpandLowEnergy) {
if (last_mode_ == Mode::kAccelerateSuccess ||
last_mode_ == Mode::kAccelerateLowEnergy ||
last_mode_ == Mode::kPreemptiveExpandSuccess ||
last_mode_ == Mode::kPreemptiveExpandLowEnergy) {
// Subtract (samples_left + output_size_samples_) from sampleMemory.
controller_->AddSampleMemory(
-(samples_left + rtc::dchecked_cast<int>(output_size_samples_)));
@ -1091,9 +1095,11 @@ int NetEqImpl::GetDecision(Operations* operation,
// during DTX. When we have a better way to update buffer level during DTX,
// this can be discarded.
if (packet && packet->frame && packet->frame->IsDtxPacket() &&
(*operation == kMerge || *operation == kAccelerate ||
*operation == kFastAccelerate || *operation == kPreemptiveExpand)) {
*operation = kNormal;
(*operation == Operation::kMerge ||
*operation == Operation::kAccelerate ||
*operation == Operation::kFastAccelerate ||
*operation == Operation::kPreemptiveExpand)) {
*operation = Operation::kNormal;
}
if (action_override) {
@ -1104,16 +1110,17 @@ int NetEqImpl::GetDecision(Operations* operation,
// change decision to normal, unless the decision was merge, accelerate, or
// preemptive expand.
if (samples_left >= rtc::dchecked_cast<int>(output_size_samples_) &&
*operation != kMerge && *operation != kAccelerate &&
*operation != kFastAccelerate && *operation != kPreemptiveExpand) {
*operation = kNormal;
*operation != Operation::kMerge && *operation != Operation::kAccelerate &&
*operation != Operation::kFastAccelerate &&
*operation != Operation::kPreemptiveExpand) {
*operation = Operation::kNormal;
return 0;
}
controller_->ExpandDecision(*operation);
// Check conditions for reset.
if (new_codec_ || *operation == kUndefined) {
if (new_codec_ || *operation == Operation::kUndefined) {
// The only valid reason to get kUndefined is that new_codec_ is set.
assert(new_codec_);
if (*play_dtmf && !packet) {
@ -1124,13 +1131,13 @@ int NetEqImpl::GetDecision(Operations* operation,
return -1;
}
timestamp_ = packet->timestamp;
if (*operation == kRfc3389CngNoPacket &&
if (*operation == Operation::kRfc3389CngNoPacket &&
decoder_database_->IsComfortNoise(packet->payload_type)) {
// Change decision to CNG packet, since we do have a CNG packet, but it
// was considered too early to use. Now, use it anyway.
*operation = kRfc3389Cng;
} else if (*operation != kRfc3389Cng) {
*operation = kNormal;
*operation = Operation::kRfc3389Cng;
} else if (*operation != Operation::kRfc3389Cng) {
*operation = Operation::kNormal;
}
}
// Adjust |sync_buffer_| timestamp before setting |end_timestamp| to the
@ -1148,15 +1155,15 @@ int NetEqImpl::GetDecision(Operations* operation,
const size_t samples_30_ms = 3 * samples_10_ms;
switch (*operation) {
case kExpand: {
case Operation::kExpand: {
timestamp_ = end_timestamp;
return 0;
}
case kRfc3389CngNoPacket:
case kCodecInternalCng: {
case Operation::kRfc3389CngNoPacket:
case Operation::kCodecInternalCng: {
return 0;
}
case kDtmf: {
case Operation::kDtmf: {
// TODO(hlundin): Write test for this.
// Update timestamp.
timestamp_ = end_timestamp;
@ -1166,7 +1173,7 @@ int NetEqImpl::GetDecision(Operations* operation,
output_size_samples_ +
controller_->noise_fast_forward()
: 0;
if (generated_noise_samples > 0 && last_mode_ != kModeDtmf) {
if (generated_noise_samples > 0 && last_mode_ != Mode::kDtmf) {
// Make a jump in timestamp due to the recently played comfort noise.
uint32_t timestamp_jump =
static_cast<uint32_t>(generated_noise_samples);
@ -1175,8 +1182,8 @@ int NetEqImpl::GetDecision(Operations* operation,
}
return 0;
}
case kAccelerate:
case kFastAccelerate: {
case Operation::kAccelerate:
case Operation::kFastAccelerate: {
// In order to do an accelerate we need at least 30 ms of audio data.
if (samples_left >= static_cast<int>(samples_30_ms)) {
// Already have enough data, so we do not need to extract any more.
@ -1186,7 +1193,7 @@ int NetEqImpl::GetDecision(Operations* operation,
} else if (samples_left >= static_cast<int>(samples_10_ms) &&
decoder_frame_length_ >= samples_30_ms) {
// Avoid decoding more data as it might overflow the playout buffer.
*operation = kNormal;
*operation = Operation::kNormal;
return 0;
} else if (samples_left < static_cast<int>(samples_20_ms) &&
decoder_frame_length_ < samples_30_ms) {
@ -1194,7 +1201,7 @@ int NetEqImpl::GetDecision(Operations* operation,
// not perform accelerate yet, but wait until we only need to do one
// decoding.
required_samples = 2 * output_size_samples_;
*operation = kNormal;
*operation = Operation::kNormal;
}
// If none of the above is true, we have one of two possible situations:
// (1) 20 ms <= samples_left < 30 ms and decoder_frame_length_ < 30 ms; or
@ -1203,7 +1210,7 @@ int NetEqImpl::GetDecision(Operations* operation,
// frame now.
break;
}
case kPreemptiveExpand: {
case Operation::kPreemptiveExpand: {
// In order to do a preemptive expand we need at least 30 ms of decoded
// audio data.
if ((samples_left >= static_cast<int>(samples_30_ms)) ||
@ -1225,7 +1232,7 @@ int NetEqImpl::GetDecision(Operations* operation,
// Move on with the preemptive expand decision.
break;
}
case kMerge: {
case Operation::kMerge: {
required_samples =
std::max(merge_->RequiredFutureSamples(), required_samples);
break;
@ -1247,7 +1254,7 @@ int NetEqImpl::GetDecision(Operations* operation,
stats_->LostSamples(packet->timestamp - end_timestamp);
}
if (*operation != kRfc3389Cng) {
if (*operation != Operation::kRfc3389Cng) {
// We are about to decode and use a non-CNG packet.
controller_->SetCngOff();
}
@ -1258,18 +1265,20 @@ int NetEqImpl::GetDecision(Operations* operation,
}
}
if (*operation == kAccelerate || *operation == kFastAccelerate ||
*operation == kPreemptiveExpand) {
if (*operation == Operation::kAccelerate ||
*operation == Operation::kFastAccelerate ||
*operation == Operation::kPreemptiveExpand) {
controller_->set_sample_memory(samples_left + extracted_samples);
controller_->set_prev_time_scale(true);
}
if (*operation == kAccelerate || *operation == kFastAccelerate) {
if (*operation == Operation::kAccelerate ||
*operation == Operation::kFastAccelerate) {
// Check that we have enough data (30ms) to do accelerate.
if (extracted_samples + samples_left < static_cast<int>(samples_30_ms)) {
// TODO(hlundin): Write test for this.
// Not enough, do normal operation instead.
*operation = kNormal;
*operation = Operation::kNormal;
}
}
@ -1278,7 +1287,7 @@ int NetEqImpl::GetDecision(Operations* operation,
}
int NetEqImpl::Decode(PacketList* packet_list,
Operations* operation,
Operation* operation,
int* decoded_length,
AudioDecoder::SpeechType* speech_type) {
*speech_type = AudioDecoder::kSpeech;
@ -1341,12 +1350,12 @@ int NetEqImpl::Decode(PacketList* packet_list,
*decoded_length = 0;
// Update codec-internal PLC state.
if ((*operation == kMerge) && decoder && decoder->HasDecodePlc()) {
if ((*operation == Operation::kMerge) && decoder && decoder->HasDecodePlc()) {
decoder->DecodePlc(1, &decoded_buffer_[*decoded_length]);
}
int return_value;
if (*operation == kCodecInternalCng) {
if (*operation == Operation::kCodecInternalCng) {
RTC_DCHECK(packet_list->empty());
return_value = DecodeCng(decoder, decoded_length, speech_type);
} else {
@ -1371,7 +1380,7 @@ int NetEqImpl::Decode(PacketList* packet_list,
return_value = kOtherDecoderError;
RTC_LOG(LS_WARNING) << "Decoder error (no error code)";
}
*operation = kExpand; // Do expansion to get data instead.
*operation = Operation::kExpand; // Do expansion to get data instead.
}
if (*speech_type != AudioDecoder::kComfortNoise) {
// Don't increment timestamp if codec returned CNG speech type
@ -1417,7 +1426,7 @@ int NetEqImpl::DecodeCng(AudioDecoder* decoder,
}
int NetEqImpl::DecodeLoop(PacketList* packet_list,
const Operations& operation,
const Operation& operation,
AudioDecoder* decoder,
int* decoded_length,
AudioDecoder::SpeechType* speech_type) {
@ -1432,9 +1441,11 @@ int NetEqImpl::DecodeLoop(PacketList* packet_list,
// number decoder channels.
assert(sync_buffer_->Channels() == decoder->Channels());
assert(decoded_buffer_length_ >= kMaxFrameSize * decoder->Channels());
assert(operation == kNormal || operation == kAccelerate ||
operation == kFastAccelerate || operation == kMerge ||
operation == kPreemptiveExpand);
assert(operation == Operation::kNormal ||
operation == Operation::kAccelerate ||
operation == Operation::kFastAccelerate ||
operation == Operation::kMerge ||
operation == Operation::kPreemptiveExpand);
auto opt_result = packet_list->front().frame->Decode(
rtc::ArrayView<int16_t>(&decoded_buffer_[*decoded_length],
@ -1485,14 +1496,14 @@ void NetEqImpl::DoNormal(const int16_t* decoded_buffer,
normal_->Process(decoded_buffer, decoded_length, last_mode_,
algorithm_buffer_.get());
if (decoded_length != 0) {
last_mode_ = kModeNormal;
last_mode_ = Mode::kNormal;
}
// If last packet was decoded as an inband CNG, set mode to CNG instead.
if ((speech_type == AudioDecoder::kComfortNoise) ||
((last_mode_ == kModeCodecInternalCng) && (decoded_length == 0))) {
((last_mode_ == Mode::kCodecInternalCng) && (decoded_length == 0))) {
// TODO(hlundin): Remove second part of || statement above.
last_mode_ = kModeCodecInternalCng;
last_mode_ = Mode::kCodecInternalCng;
}
if (!play_dtmf) {
@ -1521,10 +1532,10 @@ void NetEqImpl::DoMerge(int16_t* decoded_buffer,
stats_->ExpandedVoiceSamplesCorrection(expand_length_correction);
}
last_mode_ = kModeMerge;
last_mode_ = Mode::kMerge;
// If last packet was decoded as an inband CNG, set mode to CNG instead.
if (speech_type == AudioDecoder::kComfortNoise) {
last_mode_ = kModeCodecInternalCng;
last_mode_ = Mode::kCodecInternalCng;
}
expand_->Reset();
if (!play_dtmf) {
@ -1555,7 +1566,7 @@ bool NetEqImpl::DoCodecPlc() {
concealment_audio_.size() / channels;
// Update in-call and post-call statistics.
const bool is_new_concealment_event = (last_mode_ != kModeCodecPlc);
const bool is_new_concealment_event = (last_mode_ != Mode::kCodecPlc);
if (std::all_of(concealment_audio_.cbegin(), concealment_audio_.cend(),
[](int16_t i) { return i == 0; })) {
// Expand operation generates only noise.
@ -1566,7 +1577,7 @@ bool NetEqImpl::DoCodecPlc() {
stats_->ExpandedVoiceSamples(concealed_samples_per_channel,
is_new_concealment_event);
}
last_mode_ = kModeCodecPlc;
last_mode_ = Mode::kCodecPlc;
if (!generated_noise_stopwatch_) {
// Start a new stopwatch since we may be covering for a lost CNG packet.
generated_noise_stopwatch_ = tick_timer_->GetNewStopwatch();
@ -1580,7 +1591,7 @@ int NetEqImpl::DoExpand(bool play_dtmf) {
algorithm_buffer_->Clear();
int return_value = expand_->Process(algorithm_buffer_.get());
size_t length = algorithm_buffer_->Size();
bool is_new_concealment_event = (last_mode_ != kModeExpand);
bool is_new_concealment_event = (last_mode_ != Mode::kExpand);
// Update in-call and post-call statistics.
if (expand_->MuteFactor(0) == 0) {
@ -1591,7 +1602,7 @@ int NetEqImpl::DoExpand(bool play_dtmf) {
stats_->ExpandedVoiceSamples(length, is_new_concealment_event);
}
last_mode_ = kModeExpand;
last_mode_ = Mode::kExpand;
if (return_value < 0) {
return return_value;
@ -1640,17 +1651,17 @@ int NetEqImpl::DoAccelerate(int16_t* decoded_buffer,
stats_->AcceleratedSamples(samples_removed);
switch (return_code) {
case Accelerate::kSuccess:
last_mode_ = kModeAccelerateSuccess;
last_mode_ = Mode::kAccelerateSuccess;
break;
case Accelerate::kSuccessLowEnergy:
last_mode_ = kModeAccelerateLowEnergy;
last_mode_ = Mode::kAccelerateLowEnergy;
break;
case Accelerate::kNoStretch:
last_mode_ = kModeAccelerateFail;
last_mode_ = Mode::kAccelerateFail;
break;
case Accelerate::kError:
// TODO(hlundin): Map to kModeError instead?
last_mode_ = kModeAccelerateFail;
// TODO(hlundin): Map to Modes::kError instead?
last_mode_ = Mode::kAccelerateFail;
return kAccelerateError;
}
@ -1676,7 +1687,7 @@ int NetEqImpl::DoAccelerate(int16_t* decoded_buffer,
// If last packet was decoded as an inband CNG, set mode to CNG instead.
if (speech_type == AudioDecoder::kComfortNoise) {
last_mode_ = kModeCodecInternalCng;
last_mode_ = Mode::kCodecInternalCng;
}
if (!play_dtmf) {
dtmf_tone_generator_->Reset();
@ -1718,17 +1729,17 @@ int NetEqImpl::DoPreemptiveExpand(int16_t* decoded_buffer,
stats_->PreemptiveExpandedSamples(samples_added);
switch (return_code) {
case PreemptiveExpand::kSuccess:
last_mode_ = kModePreemptiveExpandSuccess;
last_mode_ = Mode::kPreemptiveExpandSuccess;
break;
case PreemptiveExpand::kSuccessLowEnergy:
last_mode_ = kModePreemptiveExpandLowEnergy;
last_mode_ = Mode::kPreemptiveExpandLowEnergy;
break;
case PreemptiveExpand::kNoStretch:
last_mode_ = kModePreemptiveExpandFail;
last_mode_ = Mode::kPreemptiveExpandFail;
break;
case PreemptiveExpand::kError:
// TODO(hlundin): Map to kModeError instead?
last_mode_ = kModePreemptiveExpandFail;
// TODO(hlundin): Map to Modes::kError instead?
last_mode_ = Mode::kPreemptiveExpandFail;
return kPreemptiveExpandError;
}
@ -1742,7 +1753,7 @@ int NetEqImpl::DoPreemptiveExpand(int16_t* decoded_buffer,
// If last packet was decoded as an inband CNG, set mode to CNG instead.
if (speech_type == AudioDecoder::kComfortNoise) {
last_mode_ = kModeCodecInternalCng;
last_mode_ = Mode::kCodecInternalCng;
}
if (!play_dtmf) {
dtmf_tone_generator_->Reset();
@ -1769,7 +1780,7 @@ int NetEqImpl::DoRfc3389Cng(PacketList* packet_list, bool play_dtmf) {
int cn_return =
comfort_noise_->Generate(output_size_samples_, algorithm_buffer_.get());
expand_->Reset();
last_mode_ = kModeRfc3389Cng;
last_mode_ = Mode::kRfc3389Cng;
if (!play_dtmf) {
dtmf_tone_generator_->Reset();
}
@ -1788,7 +1799,7 @@ void NetEqImpl::DoCodecInternalCng(const int16_t* decoded_buffer,
RTC_DCHECK(normal_.get());
normal_->Process(decoded_buffer, decoded_length, last_mode_,
algorithm_buffer_.get());
last_mode_ = kModeCodecInternalCng;
last_mode_ = Mode::kCodecInternalCng;
expand_->Reset();
}
@ -1803,7 +1814,8 @@ int NetEqImpl::DoDtmf(const DtmfEvent& dtmf_event, bool* play_dtmf) {
// switch from audio to DTMF. Issue 1545 is filed to track this.
//
// bool dtmf_switch = false;
// if ((last_mode_ != kModeDtmf) && dtmf_tone_generator_->initialized()) {
// if ((last_mode_ != Modes::kDtmf) &&
// dtmf_tone_generator_->initialized()) {
// // Special case; see below.
// // We must catch this before calling Generate, since |initialized| is
// // modified in that call.
@ -1865,7 +1877,7 @@ int NetEqImpl::DoDtmf(const DtmfEvent& dtmf_event, bool* play_dtmf) {
sync_buffer_->IncreaseEndTimestamp(
static_cast<uint32_t>(output_size_samples_));
expand_->Reset();
last_mode_ = kModeDtmf;
last_mode_ = Mode::kDtmf;
// Set to false because the DTMF is already in the algorithm buffer.
*play_dtmf = false;
@ -2024,7 +2036,7 @@ void NetEqImpl::SetSampleRateAndChannels(int fs_hz, size_t channels) {
output_size_samples_ = static_cast<size_t>(kOutputSizeMs * 8 * fs_mult_);
decoder_frame_length_ = 3 * output_size_samples_; // Initialize to 30ms.
last_mode_ = kModeNormal;
last_mode_ = Mode::kNormal;
ComfortNoiseDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
if (cng_decoder)
@ -2076,16 +2088,17 @@ void NetEqImpl::SetSampleRateAndChannels(int fs_hz, size_t channels) {
NetEqImpl::OutputType NetEqImpl::LastOutputType() {
assert(vad_.get());
assert(expand_.get());
if (last_mode_ == kModeCodecInternalCng || last_mode_ == kModeRfc3389Cng) {
if (last_mode_ == Mode::kCodecInternalCng ||
last_mode_ == Mode::kRfc3389Cng) {
return OutputType::kCNG;
} else if (last_mode_ == kModeExpand && expand_->MuteFactor(0) == 0) {
} else if (last_mode_ == Mode::kExpand && expand_->MuteFactor(0) == 0) {
// Expand mode has faded down to background noise only (very long expand).
return OutputType::kPLCCNG;
} else if (last_mode_ == kModeExpand) {
} else if (last_mode_ == Mode::kExpand) {
return OutputType::kPLC;
} else if (vad_->running() && !vad_->active_speech()) {
return OutputType::kVadPassive;
} else if (last_mode_ == kModeCodecPlc) {
} else if (last_mode_ == Mode::kCodecPlc) {
return OutputType::kCodecPLC;
} else {
return OutputType::kNormalSpeech;

View File

@ -19,16 +19,16 @@
#include "absl/types/optional.h"
#include "api/audio/audio_frame.h"
#include "api/neteq/neteq.h"
#include "api/neteq/neteq_controller.h"
#include "api/neteq/neteq_controller_factory.h"
#include "api/neteq/tick_timer.h"
#include "api/rtp_packet_info.h"
#include "modules/audio_coding/neteq/audio_multi_vector.h"
#include "modules/audio_coding/neteq/defines.h" // Modes, Operations
#include "modules/audio_coding/neteq/expand_uma_logger.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "modules/audio_coding/neteq/neteq_controller.h"
#include "modules/audio_coding/neteq/packet.h"
#include "modules/audio_coding/neteq/random_vector.h"
#include "modules/audio_coding/neteq/statistics_calculator.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "rtc_base/constructor_magic.h"
#include "rtc_base/critical_section.h"
#include "rtc_base/thread_annotations.h"
@ -96,10 +96,10 @@ class NetEqImpl : public webrtc::NetEq {
// before sending the struct to the NetEqImpl constructor. However, there
// are dependencies between some of the classes inside the struct, so
// swapping out one may make it necessary to re-create another one.
Dependencies(
const NetEq::Config& config,
Clock* clock,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory);
Dependencies(const NetEq::Config& config,
Clock* clock,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
const NetEqControllerFactory& controller_factory);
~Dependencies();
Clock* const clock;
@ -133,7 +133,7 @@ class NetEqImpl : public webrtc::NetEq {
int GetAudio(
AudioFrame* audio_frame,
bool* muted,
absl::optional<Operations> action_override = absl::nullopt) override;
absl::optional<Operation> action_override = absl::nullopt) override;
void SetCodecs(const std::map<int, SdpAudioFormat>& codecs) override;
@ -195,7 +195,7 @@ class NetEqImpl : public webrtc::NetEq {
// This accessor method is only intended for testing purposes.
const SyncBuffer* sync_buffer_for_test() const;
Operations last_operation_for_test() const;
Operation last_operation_for_test() const;
protected:
static const int kOutputSizeMs = 10;
@ -216,7 +216,7 @@ class NetEqImpl : public webrtc::NetEq {
// Returns 0 on success, otherwise an error code.
int GetAudioInternal(AudioFrame* audio_frame,
bool* muted,
absl::optional<Operations> action_override)
absl::optional<Operation> action_override)
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
// Provides a decision to the GetAudioInternal method. The decision what to
@ -224,11 +224,11 @@ class NetEqImpl : public webrtc::NetEq {
// |packet_list|, and a DTMF event to play is written to |dtmf_event|. When
// DTMF should be played, |play_dtmf| is set to true by the method.
// Returns 0 on success, otherwise an error code.
int GetDecision(Operations* operation,
int GetDecision(Operation* operation,
PacketList* packet_list,
DtmfEvent* dtmf_event,
bool* play_dtmf,
absl::optional<Operations> action_override)
absl::optional<Operation> action_override)
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
// Decodes the speech packets in |packet_list|, and writes the results to
@ -238,7 +238,7 @@ class NetEqImpl : public webrtc::NetEq {
// to |speech_type|. If |packet_list| contains any SID frames for RFC 3389
// comfort noise, those are not decoded.
int Decode(PacketList* packet_list,
Operations* operation,
Operation* operation,
int* decoded_length,
AudioDecoder::SpeechType* speech_type)
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
@ -251,7 +251,7 @@ class NetEqImpl : public webrtc::NetEq {
// Sub-method to Decode(). Performs the actual decoding.
int DecodeLoop(PacketList* packet_list,
const Operations& operation,
const Operation& operation,
AudioDecoder* decoder,
int* decoded_length,
AudioDecoder::SpeechType* speech_type)
@ -374,8 +374,8 @@ class NetEqImpl : public webrtc::NetEq {
int last_output_sample_rate_hz_ RTC_GUARDED_BY(crit_sect_);
size_t output_size_samples_ RTC_GUARDED_BY(crit_sect_);
size_t decoder_frame_length_ RTC_GUARDED_BY(crit_sect_);
Modes last_mode_ RTC_GUARDED_BY(crit_sect_);
Operations last_operation_ RTC_GUARDED_BY(crit_sect_);
Mode last_mode_ RTC_GUARDED_BY(crit_sect_);
Operation last_operation_ RTC_GUARDED_BY(crit_sect_);
size_t decoded_buffer_length_ RTC_GUARDED_BY(crit_sect_);
std::unique_ptr<int16_t[]> decoded_buffer_ RTC_GUARDED_BY(crit_sect_);
uint32_t playout_timestamp_ RTC_GUARDED_BY(crit_sect_);

View File

@ -15,18 +15,20 @@
#include <vector>
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/neteq/default_neteq_controller_factory.h"
#include "api/neteq/neteq.h"
#include "api/neteq/neteq_controller.h"
#include "api/test/neteq_factory_with_codecs.h"
#include "modules/audio_coding/neteq/accelerate.h"
#include "modules/audio_coding/neteq/decision_logic.h"
#include "modules/audio_coding/neteq/expand.h"
#include "modules/audio_coding/neteq/histogram.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
#include "modules/audio_coding/neteq/mock/mock_dtmf_buffer.h"
#include "modules/audio_coding/neteq/mock/mock_dtmf_tone_generator.h"
#include "modules/audio_coding/neteq/mock/mock_neteq_controller.h"
#include "modules/audio_coding/neteq/mock/mock_packet_buffer.h"
#include "modules/audio_coding/neteq/mock/mock_red_payload_splitter.h"
#include "modules/audio_coding/neteq/neteq_controller.h"
#include "modules/audio_coding/neteq/preemptive_expand.h"
#include "modules/audio_coding/neteq/statistics_calculator.h"
#include "modules/audio_coding/neteq/sync_buffer.h"
@ -73,7 +75,8 @@ class NetEqImplTest : public ::testing::Test {
void CreateInstance(
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
ASSERT_TRUE(decoder_factory);
NetEqImpl::Dependencies deps(config_, &clock_, decoder_factory);
NetEqImpl::Dependencies deps(config_, &clock_, decoder_factory,
DefaultNetEqControllerFactory());
// Get a local pointer to NetEq's TickTimer object.
tick_timer_ = deps.tick_timer.get();
@ -249,9 +252,8 @@ class NetEqImplTest : public ::testing::Test {
TEST(NetEq, CreateAndDestroy) {
NetEq::Config config;
SimulatedClock clock(0);
NetEq* neteq =
NetEq::Create(config, &clock, CreateBuiltinAudioDecoderFactory());
delete neteq;
std::unique_ptr<NetEqFactory> neteq_factory = CreateNetEqFactoryWithCodecs();
std::unique_ptr<NetEq> neteq = neteq_factory->CreateNetEq(config, &clock);
}
TEST_F(NetEqImplTest, RegisterPayloadType) {
@ -1378,7 +1380,7 @@ TEST_F(NetEqImplTest, EnableRtxHandling) {
CreateInstance();
EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
.Times(1)
.WillOnce(Return(kNormal));
.WillOnce(Return(NetEq::Operation::kNormal));
const int kPayloadLengthSamples = 80;
const size_t kPayloadLengthBytes = 2 * kPayloadLengthSamples; // PCM 16-bit.
@ -1518,7 +1520,8 @@ TEST_F(NetEqImplTest120ms, CodecInternalCng) {
bool muted;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
EXPECT_EQ(kCodecInternalCng, neteq_->last_operation_for_test());
EXPECT_EQ(NetEq::Operation::kCodecInternalCng,
neteq_->last_operation_for_test());
}
TEST_F(NetEqImplTest120ms, Normal) {
@ -1528,7 +1531,7 @@ TEST_F(NetEqImplTest120ms, Normal) {
InsertPacket(first_timestamp());
GetFirstPacket();
EXPECT_EQ(kNormal, neteq_->last_operation_for_test());
EXPECT_EQ(NetEq::Operation::kNormal, neteq_->last_operation_for_test());
}
TEST_F(NetEqImplTest120ms, Merge) {
@ -1541,16 +1544,16 @@ TEST_F(NetEqImplTest120ms, Merge) {
GetFirstPacket();
bool muted;
EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
.WillOnce(Return(kExpand));
.WillOnce(Return(NetEq::Operation::kExpand));
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
InsertPacket(first_timestamp() + 2 * timestamp_diff_between_packets());
EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
.WillOnce(Return(kMerge));
.WillOnce(Return(NetEq::Operation::kMerge));
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
EXPECT_EQ(kMerge, neteq_->last_operation_for_test());
EXPECT_EQ(NetEq::Operation::kMerge, neteq_->last_operation_for_test());
}
TEST_F(NetEqImplTest120ms, Expand) {
@ -1562,7 +1565,7 @@ TEST_F(NetEqImplTest120ms, Expand) {
bool muted;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
EXPECT_EQ(kExpand, neteq_->last_operation_for_test());
EXPECT_EQ(NetEq::Operation::kExpand, neteq_->last_operation_for_test());
}
TEST_F(NetEqImplTest120ms, FastAccelerate) {
@ -1575,11 +1578,12 @@ TEST_F(NetEqImplTest120ms, FastAccelerate) {
EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
.Times(1)
.WillOnce(Return(kFastAccelerate));
.WillOnce(Return(NetEq::Operation::kFastAccelerate));
bool muted;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
EXPECT_EQ(kFastAccelerate, neteq_->last_operation_for_test());
EXPECT_EQ(NetEq::Operation::kFastAccelerate,
neteq_->last_operation_for_test());
}
TEST_F(NetEqImplTest120ms, PreemptiveExpand) {
@ -1593,11 +1597,12 @@ TEST_F(NetEqImplTest120ms, PreemptiveExpand) {
EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
.Times(1)
.WillOnce(Return(kPreemptiveExpand));
.WillOnce(Return(NetEq::Operation::kPreemptiveExpand));
bool muted;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
EXPECT_EQ(kPreemptiveExpand, neteq_->last_operation_for_test());
EXPECT_EQ(NetEq::Operation::kPreemptiveExpand,
neteq_->last_operation_for_test());
}
TEST_F(NetEqImplTest120ms, Accelerate) {
@ -1611,11 +1616,11 @@ TEST_F(NetEqImplTest120ms, Accelerate) {
EXPECT_CALL(*mock_neteq_controller_, GetDecision(_, _))
.Times(1)
.WillOnce(Return(kAccelerate));
.WillOnce(Return(NetEq::Operation::kAccelerate));
bool muted;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_, &muted));
EXPECT_EQ(kAccelerate, neteq_->last_operation_for_test());
EXPECT_EQ(NetEq::Operation::kAccelerate, neteq_->last_operation_for_test());
}
} // namespace webrtc

View File

@ -13,7 +13,9 @@
#include "absl/memory/memory.h"
#include "api/audio/audio_frame.h"
#include "api/audio_codecs/audio_decoder.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "api/neteq/custom_neteq_factory.h"
#include "api/neteq/default_neteq_controller_factory.h"
#include "api/neteq/neteq.h"
#include "modules/audio_coding/neteq/tools/rtp_generator.h"
#include "rtc_base/ref_counted_object.h"
#include "system_wrappers/include/clock.h"
@ -23,6 +25,19 @@
namespace webrtc {
namespace test {
namespace {
std::unique_ptr<NetEq> CreateNetEq(
const NetEq::Config& config,
Clock* clock,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
CustomNetEqFactory neteq_factory(
decoder_factory, std::make_unique<DefaultNetEqControllerFactory>());
return neteq_factory.CreateNetEq(config, clock);
}
} // namespace
using ::testing::_;
using ::testing::Return;
using ::testing::SetArgPointee;
@ -162,8 +177,7 @@ class NetEqNetworkStatsTest {
packet_loss_interval_(0xffffffff) {
NetEq::Config config;
config.sample_rate_hz = format.clockrate_hz;
neteq_ = absl::WrapUnique(
NetEq::Create(config, Clock::GetRealTimeClock(), decoder_factory_));
neteq_ = CreateNetEq(config, Clock::GetRealTimeClock(), decoder_factory_);
neteq_->RegisterPayloadType(kPayloadType, format);
}

View File

@ -17,8 +17,9 @@
#include "api/audio/audio_frame.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/neteq/neteq.h"
#include "api/test/neteq_factory_with_codecs.h"
#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "modules/audio_coding/neteq/tools/input_audio_file.h"
#include "modules/audio_coding/neteq/tools/rtp_generator.h"
#include "rtc_base/strings/string_builder.h"
@ -67,10 +68,10 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
last_arrival_time_(0) {
NetEq::Config config;
config.sample_rate_hz = sample_rate_hz_;
rtc::scoped_refptr<AudioDecoderFactory> factory =
CreateBuiltinAudioDecoderFactory();
neteq_mono_ = NetEq::Create(config, &clock_, factory);
neteq_ = NetEq::Create(config, &clock_, factory);
std::unique_ptr<NetEqFactory> neteq_factory =
CreateNetEqFactoryWithCodecs();
neteq_mono_ = neteq_factory->CreateNetEq(config, &clock_);
neteq_ = neteq_factory->CreateNetEq(config, &clock_);
input_ = new int16_t[frame_size_samples_];
encoded_ = new uint8_t[2 * frame_size_samples_];
input_multi_channel_ = new int16_t[frame_size_samples_ * num_channels_];
@ -79,8 +80,6 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
}
~NetEqStereoTest() {
delete neteq_mono_;
delete neteq_;
delete[] input_;
delete[] encoded_;
delete[] input_multi_channel_;
@ -206,8 +205,8 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> {
const size_t frame_size_samples_;
const size_t output_size_samples_;
SimulatedClock clock_;
NetEq* neteq_mono_;
NetEq* neteq_;
std::unique_ptr<NetEq> neteq_mono_;
std::unique_ptr<NetEq> neteq_;
test::RtpGenerator rtp_generator_mono_;
test::RtpGenerator rtp_generator_;
int16_t* input_;

View File

@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/audio_coding/neteq/include/neteq.h"
#include "api/neteq/neteq.h"
#include <math.h>
#include <stdlib.h>
@ -23,6 +23,7 @@
#include "absl/flags/flag.h"
#include "api/audio/audio_frame.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/test/neteq_factory_with_codecs.h"
#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
#include "modules/audio_coding/neteq/tools/audio_loop.h"
#include "modules/audio_coding/neteq/tools/neteq_packet_source_input.h"
@ -287,7 +288,7 @@ class NetEqDecodingTest : public ::testing::Test {
void DuplicateCng();
SimulatedClock clock_;
NetEq* neteq_;
std::unique_ptr<NetEq> neteq_;
NetEq::Config config_;
std::unique_ptr<test::RtpFileSource> rtp_source_;
std::unique_ptr<test::Packet> packet_;
@ -305,7 +306,6 @@ const int NetEqDecodingTest::kInitSampleRateHz;
NetEqDecodingTest::NetEqDecodingTest()
: clock_(0),
neteq_(NULL),
config_(),
output_sample_rate_(kInitSampleRateHz),
algorithmic_delay_ms_(0) {
@ -313,17 +313,16 @@ NetEqDecodingTest::NetEqDecodingTest()
}
void NetEqDecodingTest::SetUp() {
neteq_ = NetEq::Create(config_, &clock_, CreateBuiltinAudioDecoderFactory());
std::unique_ptr<NetEqFactory> neteq_factory = CreateNetEqFactoryWithCodecs();
neteq_ = neteq_factory->CreateNetEq(config_, &clock_);
NetEqNetworkStatistics stat;
ASSERT_EQ(0, neteq_->NetworkStatistics(&stat));
algorithmic_delay_ms_ = stat.current_buffer_size_ms;
ASSERT_TRUE(neteq_);
LoadDecoders(neteq_);
LoadDecoders(neteq_.get());
}
void NetEqDecodingTest::TearDown() {
delete neteq_;
}
void NetEqDecodingTest::TearDown() {}
void NetEqDecodingTest::OpenInputFile(const std::string& rtp_file) {
rtp_source_.reset(test::RtpFileSource::Create(rtp_file));
@ -1366,8 +1365,9 @@ class NetEqDecodingTestTwoInstances : public NetEqDecodingTest {
}
void CreateSecondInstance() {
neteq2_.reset(
NetEq::Create(config2_, &clock_, CreateBuiltinAudioDecoderFactory()));
std::unique_ptr<NetEqFactory> neteq_factory =
CreateNetEqFactoryWithCodecs();
neteq2_ = neteq_factory->CreateNetEq(config2_, &clock_);
ASSERT_TRUE(neteq2_);
LoadDecoders(neteq2_.get());
}
@ -1658,7 +1658,7 @@ TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithAcceleration) {
// We have two packets in the buffer and kAccelerate operation will
// extract 20 ms of data.
neteq_->GetAudio(&out_frame_, &muted, Operations::kAccelerate);
neteq_->GetAudio(&out_frame_, &muted, NetEq::Operation::kAccelerate);
// Check jitter buffer delay.
NetEqLifetimeStatistics stats = neteq_->GetLifetimeStatistics();

View File

@ -26,7 +26,7 @@ namespace webrtc {
int Normal::Process(const int16_t* input,
size_t length,
Modes last_mode,
NetEq::Mode last_mode,
AudioMultiVector* output) {
if (length == 0) {
// Nothing to process.
@ -52,7 +52,7 @@ int Normal::Process(const int16_t* input,
// Check if last RecOut call resulted in an Expand. If so, we have to take
// care of some cross-fading and unmuting.
if (last_mode == kModeExpand) {
if (last_mode == NetEq::Mode::kExpand) {
// Generate interpolation data using Expand.
// First, set Expand parameters to appropriate values.
expand_->SetParametersForNormalAfterExpand();
@ -144,7 +144,7 @@ int Normal::Process(const int16_t* input,
RTC_DCHECK_GT(win_up_Q14,
(1 << 14) - 32); // Worst case rouding is a length of 34
}
} else if (last_mode == kModeRfc3389Cng) {
} else if (last_mode == NetEq::Mode::kRfc3389Cng) {
RTC_DCHECK_EQ(output->Channels(), 1); // Not adapted for multi-channel yet.
static const size_t kCngLength = 48;
RTC_DCHECK_LE(8 * fs_mult, kCngLength);

View File

@ -14,7 +14,7 @@
#include <stdint.h>
#include <string.h> // Access to size_t.
#include "modules/audio_coding/neteq/defines.h"
#include "api/neteq/neteq.h"
#include "rtc_base/checks.h"
#include "rtc_base/constructor_magic.h"
#include "rtc_base/numerics/safe_conversions.h"
@ -54,7 +54,7 @@ class Normal {
// GetAudio call (i.e., not the current one).
int Process(const int16_t* input,
size_t length,
Modes last_mode,
NetEq::Mode last_mode,
AudioMultiVector* output);
private:

View File

@ -70,7 +70,7 @@ TEST(Normal, AvoidDivideByZero) {
AudioMultiVector output(channels);
// Zero input length.
EXPECT_EQ(0, normal.Process(input, 0, kModeExpand, &output));
EXPECT_EQ(0, normal.Process(input, 0, NetEq::Mode::kExpand, &output));
EXPECT_EQ(0u, output.Size());
// Try to make energy_length >> scaling = 0;
@ -82,8 +82,8 @@ TEST(Normal, AvoidDivideByZero) {
// will be zero, and scaling will be >= 6. Thus, energy_length >> scaling = 0,
// and using this as a denominator would lead to problems.
int input_size_samples = 63;
EXPECT_EQ(input_size_samples,
normal.Process(input, input_size_samples, kModeExpand, &output));
EXPECT_EQ(input_size_samples, normal.Process(input, input_size_samples,
NetEq::Mode::kExpand, &output));
EXPECT_CALL(db, Die()); // Called when |db| goes out of scope.
EXPECT_CALL(expand, Die()); // Called when |expand| goes out of scope.
@ -106,7 +106,7 @@ TEST(Normal, InputLengthAndChannelsDoNotMatch) {
// Let the number of samples be one sample less than 80 samples per channel.
size_t input_len = 80 * channels - 1;
EXPECT_EQ(0, normal.Process(input, input_len, kModeExpand, &output));
EXPECT_EQ(0, normal.Process(input, input_len, NetEq::Mode::kExpand, &output));
EXPECT_EQ(0u, output.Size());
EXPECT_CALL(db, Die()); // Called when |db| goes out of scope.
@ -132,8 +132,9 @@ TEST(Normal, LastModeExpand120msPacket) {
EXPECT_CALL(expand, SetParametersForNormalAfterExpand());
EXPECT_CALL(expand, Process(_)).WillOnce(Invoke(ExpandProcess120ms));
EXPECT_CALL(expand, Reset());
EXPECT_EQ(static_cast<int>(kPacketsizeBytes),
normal.Process(input, kPacketsizeBytes, kModeExpand, &output));
EXPECT_EQ(
static_cast<int>(kPacketsizeBytes),
normal.Process(input, kPacketsizeBytes, NetEq::Mode::kExpand, &output));
EXPECT_EQ(kPacketsizeBytes, output.Size());

View File

@ -17,8 +17,8 @@
#include <memory>
#include "api/audio_codecs/audio_decoder.h"
#include "api/neteq/tick_timer.h"
#include "api/rtp_packet_info.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"

View File

@ -21,9 +21,9 @@
#include <utility>
#include "api/audio_codecs/audio_decoder.h"
#include "api/neteq/tick_timer.h"
#include "modules/audio_coding/neteq/decoder_database.h"
#include "modules/audio_coding/neteq/statistics_calculator.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"

View File

@ -15,10 +15,10 @@
#include <memory>
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/neteq/tick_timer.h"
#include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
#include "modules/audio_coding/neteq/mock/mock_statistics_calculator.h"
#include "modules/audio_coding/neteq/packet.h"
#include "modules/audio_coding/neteq/tick_timer.h"
#include "test/gmock.h"
#include "test/gtest.h"

View File

@ -14,7 +14,7 @@
#include <deque>
#include <string>
#include "modules/audio_coding/neteq/include/neteq.h"
#include "api/neteq/neteq.h"
#include "rtc_base/constructor_magic.h"
namespace webrtc {

View File

@ -11,9 +11,9 @@
#include "modules/audio_coding/neteq/tools/neteq_performance_test.h"
#include "api/audio/audio_frame.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/neteq/neteq.h"
#include "api/test/neteq_factory_with_codecs.h"
#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "modules/audio_coding/neteq/tools/audio_loop.h"
#include "modules/audio_coding/neteq/tools/rtp_generator.h"
#include "rtc_base/checks.h"
@ -40,8 +40,8 @@ int64_t NetEqPerformanceTest::Run(int runtime_ms,
NetEq::Config config;
config.sample_rate_hz = kSampRateHz;
webrtc::Clock* clock = webrtc::Clock::GetRealTimeClock();
NetEq* neteq =
NetEq::Create(config, clock, CreateBuiltinAudioDecoderFactory());
std::unique_ptr<NetEqFactory> neteq_factory = CreateNetEqFactoryWithCodecs();
auto neteq = neteq_factory->CreateNetEq(config, clock);
// Register decoder in |neteq|.
if (!neteq->RegisterPayloadType(kPayloadType,
SdpAudioFormat("l16", kSampRateHz, 1)))
@ -119,7 +119,6 @@ int64_t NetEqPerformanceTest::Run(int runtime_ms,
}
}
int64_t end_time_ms = clock->TimeInMilliseconds();
delete neteq;
return end_time_ms - start_time_ms;
}

View File

@ -15,6 +15,8 @@
#include <cmath>
#include "absl/flags/flag.h"
#include "api/neteq/custom_neteq_factory.h"
#include "api/neteq/default_neteq_controller_factory.h"
#include "modules/audio_coding/neteq/tools/neteq_quality_test.h"
#include "modules/audio_coding/neteq/tools/output_audio_file.h"
#include "modules/audio_coding/neteq/tools/output_wav_file.h"
@ -87,6 +89,19 @@ ABSL_FLAG(std::string,
namespace webrtc {
namespace test {
namespace {
std::unique_ptr<NetEq> CreateNetEq(
const NetEq::Config& config,
Clock* clock,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
CustomNetEqFactory neteq_factory(
decoder_factory, std::make_unique<DefaultNetEqControllerFactory>());
return neteq_factory.CreateNetEq(config, clock);
}
} // namespace
const uint8_t kPayloadType = 95;
const int kOutputSizeMs = 10;
const int kInitSeed = 0x12345678;
@ -228,8 +243,7 @@ NetEqQualityTest::NetEqQualityTest(
NetEq::Config config;
config.sample_rate_hz = out_sampling_khz_ * 1000;
neteq_.reset(
NetEq::Create(config, Clock::GetRealTimeClock(), decoder_factory));
neteq_ = CreateNetEq(config, Clock::GetRealTimeClock(), decoder_factory);
max_payload_bytes_ = in_size_samples_ * channels_ * sizeof(int16_t);
in_data_.reset(new int16_t[in_size_samples_ * channels_]);
}

View File

@ -15,7 +15,7 @@
#include <memory>
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "api/neteq/neteq.h"
#include "modules/audio_coding/neteq/tools/audio_sink.h"
#include "modules/audio_coding/neteq/tools/input_audio_file.h"
#include "modules/audio_coding/neteq/tools/rtp_generator.h"

View File

@ -13,6 +13,8 @@
#include <iomanip>
#include <iostream>
#include "api/neteq/custom_neteq_factory.h"
#include "api/neteq/default_neteq_controller_factory.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "system_wrappers/include/clock.h"
@ -20,23 +22,32 @@ namespace webrtc {
namespace test {
namespace {
absl::optional<Operations> ActionToOperations(
absl::optional<NetEq::Operation> ActionToOperations(
absl::optional<NetEqSimulator::Action> a) {
if (!a) {
return absl::nullopt;
}
switch (*a) {
case NetEqSimulator::Action::kAccelerate:
return absl::make_optional(kAccelerate);
return absl::make_optional(NetEq::Operation::kAccelerate);
case NetEqSimulator::Action::kExpand:
return absl::make_optional(kExpand);
return absl::make_optional(NetEq::Operation::kExpand);
case NetEqSimulator::Action::kNormal:
return absl::make_optional(kNormal);
return absl::make_optional(NetEq::Operation::kNormal);
case NetEqSimulator::Action::kPreemptiveExpand:
return absl::make_optional(kPreemptiveExpand);
return absl::make_optional(NetEq::Operation::kPreemptiveExpand);
}
}
std::unique_ptr<NetEq> CreateNetEq(
const NetEq::Config& config,
Clock* clock,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
CustomNetEqFactory neteq_factory(
decoder_factory, std::make_unique<DefaultNetEqControllerFactory>());
return neteq_factory.CreateNetEq(config, clock);
}
} // namespace
void DefaultNetEqTestErrorCallback::OnInsertPacketError(
@ -59,7 +70,7 @@ NetEqTest::NetEqTest(const NetEq::Config& config,
std::unique_ptr<AudioSink> output,
Callbacks callbacks)
: clock_(0),
neteq_(NetEq::Create(config, &clock_, decoder_factory)),
neteq_(CreateNetEq(config, &clock_, decoder_factory)),
input_(std::move(input)),
output_(std::move(output)),
callbacks_(callbacks),

View File

@ -19,8 +19,8 @@
#include "absl/types/optional.h"
#include "api/audio_codecs/audio_decoder_factory.h"
#include "api/neteq/neteq.h"
#include "api/test/neteq_simulator.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "modules/audio_coding/neteq/tools/audio_sink.h"
#include "modules/audio_coding/neteq/tools/neteq_input.h"
#include "system_wrappers/include/clock.h"

View File

@ -23,7 +23,7 @@
#include <utility>
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "api/neteq/neteq.h"
#include "modules/audio_coding/neteq/tools/audio_sink.h"
#include "modules/audio_coding/neteq/tools/fake_decode_from_file.h"
#include "modules/audio_coding/neteq/tools/initial_packet_inserter_neteq_input.h"

View File

@ -324,6 +324,7 @@ if (rtc_include_tests) {
defines = [ "ENABLE_RTC_EVENT_LOG" ]
deps = [
":event_log_visualizer_utils",
"../api/neteq:neteq_api",
"../api/rtc_event_log",
"../logging:rtc_event_log_parser",
"../modules/audio_coding:neteq",

View File

@ -24,9 +24,9 @@
#include "absl/flags/usage.h"
#include "absl/flags/usage_config.h"
#include "absl/strings/match.h"
#include "api/neteq/neteq.h"
#include "api/rtc_event_log/rtc_event_log.h"
#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "modules/audio_coding/neteq/include/neteq.h"
#include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
#include "rtc_base/checks.h"
#include "rtc_tools/rtc_event_log_visualizer/analyzer.h"