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:
parent
739a5b3692
commit
3ce44a3540
20
api/BUILD.gn
20
api/BUILD.gn
@ -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
98
api/neteq/BUILD.gn
Normal 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
8
api/neteq/DEPS
Normal 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",
|
||||
],
|
||||
}
|
||||
34
api/neteq/custom_neteq_factory.cc
Normal file
34
api/neteq/custom_neteq_factory.cc
Normal 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
|
||||
44
api/neteq/custom_neteq_factory.h
Normal file
44
api/neteq/custom_neteq_factory.h
Normal 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_
|
||||
25
api/neteq/default_neteq_controller_factory.cc
Normal file
25
api/neteq/default_neteq_controller_factory.cc
Normal 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
|
||||
34
api/neteq/default_neteq_controller_factory.h
Normal file
34
api/neteq/default_neteq_controller_factory.h
Normal 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_
|
||||
@ -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
|
||||
@ -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_
|
||||
@ -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_
|
||||
32
api/neteq/neteq_controller_factory.h
Normal file
32
api/neteq/neteq_controller_factory.h
Normal 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
34
api/neteq/neteq_factory.h
Normal 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_
|
||||
@ -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 {
|
||||
|
||||
@ -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_
|
||||
@ -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>
|
||||
|
||||
@ -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",
|
||||
|
||||
47
api/test/neteq_factory_with_codecs.cc
Normal file
47
api/test/neteq_factory_with_codecs.cc
Normal 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
|
||||
25
api/test/neteq_factory_with_codecs.h
Normal file
25
api/test/neteq_factory_with_codecs.h
Normal 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_
|
||||
@ -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",
|
||||
|
||||
@ -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_);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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).
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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_
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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_);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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());
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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_]);
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user