Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 14:04:28 +01:00
parent 81b91f4139
commit f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions

View file

@ -0,0 +1,95 @@
# 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:stringutils",
"../../system_wrappers:system_wrappers",
"../audio_codecs:audio_codecs_api",
]
absl_deps = [ "//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",
"../../system_wrappers:system_wrappers",
]
absl_deps = [ "//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_source_set("tick_timer_unittest") {
visibility = [ "*" ]
testonly = true
sources = [ "tick_timer_unittest.cc" ]
deps = [
":tick_timer",
"../../test:test_support",
"//testing/gtest",
]
}

View file

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

View file

@ -0,0 +1,3 @@
ivoc@webrtc.org
henrik.lundin@webrtc.org
jakobi@webrtc.org

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/neteq/custom_neteq_factory.h"
#include <utility>
#include "modules/audio_coding/neteq/neteq_impl.h"
namespace webrtc {
CustomNetEqFactory::CustomNetEqFactory(
std::unique_ptr<NetEqControllerFactory> controller_factory)
: controller_factory_(std::move(controller_factory)) {}
CustomNetEqFactory::~CustomNetEqFactory() = default;
std::unique_ptr<NetEq> CustomNetEqFactory::CreateNetEq(
const NetEq::Config& config,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
Clock* clock) const {
return std::make_unique<NetEqImpl>(
config, NetEqImpl::Dependencies(config, clock, decoder_factory,
*controller_factory_));
}
} // namespace webrtc

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_NETEQ_CUSTOM_NETEQ_FACTORY_H_
#define API_NETEQ_CUSTOM_NETEQ_FACTORY_H_
#include <memory>
#include "api/audio_codecs/audio_decoder_factory.h"
#include "api/neteq/neteq_controller_factory.h"
#include "api/neteq/neteq_factory.h"
#include "api/scoped_refptr.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
// This factory can be used to generate NetEq instances that make use of a
// custom NetEqControllerFactory.
class CustomNetEqFactory : public NetEqFactory {
public:
explicit CustomNetEqFactory(
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,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
Clock* clock) const override;
private:
std::unique_ptr<NetEqControllerFactory> controller_factory_;
};
} // namespace webrtc
#endif // API_NETEQ_CUSTOM_NETEQ_FACTORY_H_

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/neteq/default_neteq_controller_factory.h"
#include "modules/audio_coding/neteq/decision_logic.h"
namespace webrtc {
DefaultNetEqControllerFactory::DefaultNetEqControllerFactory() = default;
DefaultNetEqControllerFactory::~DefaultNetEqControllerFactory() = default;
std::unique_ptr<NetEqController>
DefaultNetEqControllerFactory::CreateNetEqController(
const NetEqController::Config& config) const {
return std::make_unique<DecisionLogic>(config);
}
} // namespace webrtc

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_NETEQ_DEFAULT_NETEQ_CONTROLLER_FACTORY_H_
#define API_NETEQ_DEFAULT_NETEQ_CONTROLLER_FACTORY_H_
#include <memory>
#include "api/neteq/neteq_controller_factory.h"
namespace webrtc {
// This NetEqControllerFactory will use WebRTC's built-in controller logic.
class DefaultNetEqControllerFactory : public NetEqControllerFactory {
public:
DefaultNetEqControllerFactory();
~DefaultNetEqControllerFactory() override;
DefaultNetEqControllerFactory(const DefaultNetEqControllerFactory&) = delete;
DefaultNetEqControllerFactory& operator=(
const DefaultNetEqControllerFactory&) = delete;
std::unique_ptr<NetEqController> CreateNetEqController(
const NetEqController::Config& config) const override;
};
} // namespace webrtc
#endif // API_NETEQ_DEFAULT_NETEQ_CONTROLLER_FACTORY_H_

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/neteq/neteq.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
NetEq::Config::Config() = default;
NetEq::Config::Config(const Config&) = default;
NetEq::Config::Config(Config&&) = default;
NetEq::Config::~Config() = default;
NetEq::Config& NetEq::Config::operator=(const Config&) = default;
NetEq::Config& NetEq::Config::operator=(Config&&) = default;
std::string NetEq::Config::ToString() const {
char buf[1024];
rtc::SimpleStringBuilder ss(buf);
ss << "sample_rate_hz=" << sample_rate_hz
<< ", max_packets_in_buffer=" << max_packets_in_buffer
<< ", min_delay_ms=" << min_delay_ms << ", enable_fast_accelerate="
<< (enable_fast_accelerate ? "true" : "false")
<< ", enable_muted_state=" << (enable_muted_state ? "true" : "false")
<< ", enable_rtx_handling=" << (enable_rtx_handling ? "true" : "false");
return ss.str();
}
} // namespace webrtc

View file

@ -0,0 +1,314 @@
/*
* 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 API_NETEQ_NETEQ_H_
#define API_NETEQ_NETEQ_H_
#include <stddef.h> // Provide access to size_t.
#include <map>
#include <string>
#include <vector>
#include "absl/types/optional.h"
#include "api/audio_codecs/audio_codec_pair_id.h"
#include "api/audio_codecs/audio_decoder.h"
#include "api/audio_codecs/audio_format.h"
#include "api/rtp_headers.h"
#include "api/scoped_refptr.h"
namespace webrtc {
// Forward declarations.
class AudioFrame;
class AudioDecoderFactory;
class Clock;
struct NetEqNetworkStatistics {
uint16_t current_buffer_size_ms; // Current jitter buffer size in ms.
uint16_t preferred_buffer_size_ms; // Target buffer size in ms.
uint16_t jitter_peaks_found; // 1 if adding extra delay due to peaky
// jitter; 0 otherwise.
uint16_t expand_rate; // Fraction (of original stream) of synthesized
// audio inserted through expansion (in Q14).
uint16_t speech_expand_rate; // Fraction (of original stream) of synthesized
// speech inserted through expansion (in Q14).
uint16_t preemptive_rate; // Fraction of data inserted through pre-emptive
// expansion (in Q14).
uint16_t accelerate_rate; // Fraction of data removed through acceleration
// (in Q14).
uint16_t secondary_decoded_rate; // Fraction of data coming from FEC/RED
// decoding (in Q14).
uint16_t secondary_discarded_rate; // Fraction of discarded FEC/RED data (in
// Q14).
// Statistics for packet waiting times, i.e., the time between a packet
// arrives until it is decoded.
int mean_waiting_time_ms;
int median_waiting_time_ms;
int min_waiting_time_ms;
int max_waiting_time_ms;
};
// NetEq statistics that persist over the lifetime of the class.
// These metrics are never reset.
struct NetEqLifetimeStatistics {
// Stats below correspond to similarly-named fields in the WebRTC stats spec.
// https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats
uint64_t total_samples_received = 0;
uint64_t concealed_samples = 0;
uint64_t concealment_events = 0;
uint64_t jitter_buffer_delay_ms = 0;
uint64_t jitter_buffer_emitted_count = 0;
uint64_t jitter_buffer_target_delay_ms = 0;
uint64_t jitter_buffer_minimum_delay_ms = 0;
uint64_t inserted_samples_for_deceleration = 0;
uint64_t removed_samples_for_acceleration = 0;
uint64_t silent_concealed_samples = 0;
uint64_t fec_packets_received = 0;
uint64_t fec_packets_discarded = 0;
uint64_t packets_discarded = 0;
// Below stats are not part of the spec.
uint64_t delayed_packet_outage_samples = 0;
uint64_t delayed_packet_outage_events = 0;
// This is sum of relative packet arrival delays of received packets so far.
// Since end-to-end delay of a packet is difficult to measure and is not
// necessarily useful for measuring jitter buffer performance, we report a
// relative packet arrival delay. The relative packet arrival delay of a
// packet is defined as the arrival delay compared to the first packet
// received, given that it had zero delay. To avoid clock drift, the "first"
// packet can be made dynamic.
uint64_t relative_packet_arrival_delay_ms = 0;
uint64_t jitter_buffer_packets_received = 0;
// An interruption is a loss-concealment event lasting at least 150 ms. The
// two stats below count the number os such events and the total duration of
// these events.
int32_t interruption_count = 0;
int32_t total_interruption_duration_ms = 0;
// Total number of comfort noise samples generated during DTX.
uint64_t generated_noise_samples = 0;
};
// Metrics that describe the operations performed in NetEq, and the internal
// state.
struct NetEqOperationsAndState {
// These sample counters are cumulative, and don't reset. As a reference, the
// total number of output samples can be found in
// NetEqLifetimeStatistics::total_samples_received.
uint64_t preemptive_samples = 0;
uint64_t accelerate_samples = 0;
// Count of the number of buffer flushes.
uint64_t packet_buffer_flushes = 0;
// The statistics below are not cumulative.
// The waiting time of the last decoded packet.
uint64_t last_waiting_time_ms = 0;
// The sum of the packet and jitter buffer size in ms.
uint64_t current_buffer_size_ms = 0;
// The current frame size in ms.
uint64_t current_frame_size_ms = 0;
// Flag to indicate that the next packet is available.
bool next_packet_available = false;
};
// This is the interface class for NetEq.
class NetEq {
public:
struct Config {
Config();
Config(const Config&);
Config(Config&&);
~Config();
Config& operator=(const Config&);
Config& operator=(Config&&);
std::string ToString() const;
int sample_rate_hz = 48000; // Initial value. Will change with input data.
size_t max_packets_in_buffer = 200;
int max_delay_ms = 0;
int min_delay_ms = 0;
bool enable_fast_accelerate = false;
bool enable_muted_state = false;
bool enable_rtx_handling = false;
absl::optional<AudioCodecPairId> codec_pair_id;
bool for_test_no_time_stretching = false; // Use only for testing.
};
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;
int num_channels;
SdpAudioFormat sdp_format;
};
virtual ~NetEq() {}
// Inserts a new packet into NetEq.
// Returns 0 on success, -1 on failure.
virtual int InsertPacket(const RTPHeader& rtp_header,
rtc::ArrayView<const uint8_t> payload) = 0;
// Lets NetEq know that a packet arrived with an empty payload. This typically
// happens when empty packets are used for probing the network channel, and
// these packets use RTP sequence numbers from the same series as the actual
// audio packets.
virtual void InsertEmptyPacket(const RTPHeader& rtp_header) = 0;
// Instructs NetEq to deliver 10 ms of audio data. The data is written to
// `audio_frame`. All data in `audio_frame` is wiped; `data_`, `speech_type_`,
// `num_channels_`, `sample_rate_hz_` and `samples_per_channel_` are updated
// upon success. If an error is returned, some fields may not have been
// updated, or may contain inconsistent values. If muted state is enabled
// (through Config::enable_muted_state), `muted` may be set to true after a
// prolonged expand period. When this happens, the `data_` in `audio_frame`
// is not written, but should be interpreted as being all zeros. For testing
// purposes, an override can be supplied in the `action_override` argument,
// which will cause NetEq to take this action next, instead of the action it
// would normally choose. An optional output argument for fetching the current
// sample rate can be provided, which will return the same value as
// last_output_sample_rate_hz() but will avoid additional synchronization.
// Returns kOK on success, or kFail in case of an error.
virtual int GetAudio(
AudioFrame* audio_frame,
bool* muted,
int* current_sample_rate_hz = nullptr,
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;
// Associates `rtp_payload_type` with the given codec, which NetEq will
// instantiate when it needs it. Returns true iff successful.
virtual bool RegisterPayloadType(int rtp_payload_type,
const SdpAudioFormat& audio_format) = 0;
// Removes `rtp_payload_type` from the codec database. Returns 0 on success,
// -1 on failure. Removing a payload type that is not registered is ok and
// will not result in an error.
virtual int RemovePayloadType(uint8_t rtp_payload_type) = 0;
// Removes all payload types from the codec database.
virtual void RemoveAllPayloadTypes() = 0;
// Sets a minimum delay in millisecond for packet buffer. The minimum is
// maintained unless a higher latency is dictated by channel condition.
// Returns true if the minimum is successfully applied, otherwise false is
// returned.
virtual bool SetMinimumDelay(int delay_ms) = 0;
// Sets a maximum delay in milliseconds for packet buffer. The latency will
// not exceed the given value, even required delay (given the channel
// conditions) is higher. Calling this method has the same effect as setting
// the `max_delay_ms` value in the NetEq::Config struct.
virtual bool SetMaximumDelay(int delay_ms) = 0;
// Sets a base minimum delay in milliseconds for packet buffer. The minimum
// delay which is set via `SetMinimumDelay` can't be lower than base minimum
// delay. Calling this method is similar to setting the `min_delay_ms` value
// in the NetEq::Config struct. Returns true if the base minimum is
// successfully applied, otherwise false is returned.
virtual bool SetBaseMinimumDelayMs(int delay_ms) = 0;
// Returns current value of base minimum delay in milliseconds.
virtual int GetBaseMinimumDelayMs() const = 0;
// Returns the current target delay in ms. This includes any extra delay
// requested through SetMinimumDelay.
virtual int TargetDelayMs() const = 0;
// Returns the current total delay (packet buffer and sync buffer) in ms,
// with smoothing applied to even out short-time fluctuations due to jitter.
// The packet buffer part of the delay is not updated during DTX/CNG periods.
virtual int FilteredCurrentDelayMs() const = 0;
// Writes the current network statistics to `stats`. The statistics are reset
// after the call.
virtual int NetworkStatistics(NetEqNetworkStatistics* stats) = 0;
// Current values only, not resetting any state.
virtual NetEqNetworkStatistics CurrentNetworkStatistics() const = 0;
// Returns a copy of this class's lifetime statistics. These statistics are
// never reset.
virtual NetEqLifetimeStatistics GetLifetimeStatistics() const = 0;
// Returns statistics about the performed operations and internal state. These
// statistics are never reset.
virtual NetEqOperationsAndState GetOperationsAndState() const = 0;
// Returns the RTP timestamp for the last sample delivered by GetAudio().
// The return value will be empty if no valid timestamp is available.
virtual absl::optional<uint32_t> GetPlayoutTimestamp() const = 0;
// Returns the sample rate in Hz of the audio produced in the last GetAudio
// call. If GetAudio has not been called yet, the configured sample rate
// (Config::sample_rate_hz) is returned.
virtual int last_output_sample_rate_hz() const = 0;
// Returns the decoder info for the given payload type. Returns empty if no
// such payload type was registered.
virtual absl::optional<DecoderFormat> GetDecoderFormat(
int payload_type) const = 0;
// Flushes both the packet buffer and the sync buffer.
virtual void FlushBuffers() = 0;
// Enables NACK and sets the maximum size of the NACK list, which should be
// positive and no larger than Nack::kNackListSizeLimit. If NACK is already
// enabled then the maximum NACK list size is modified accordingly.
virtual void EnableNack(size_t max_nack_list_size) = 0;
virtual void DisableNack() = 0;
// Returns a list of RTP sequence numbers corresponding to packets to be
// retransmitted, given an estimate of the round-trip time in milliseconds.
virtual std::vector<uint16_t> GetNackList(
int64_t round_trip_time_ms) const = 0;
// Returns the length of the audio yet to play in the sync buffer.
// Mainly intended for testing.
virtual int SyncBufferSizeMs() const = 0;
};
} // namespace webrtc
#endif // API_NETEQ_NETEQ_H_

View file

@ -0,0 +1,189 @@
/*
* 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_H_
#define API_NETEQ_NETEQ_CONTROLLER_H_
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include "absl/types/optional.h"
#include "api/neteq/neteq.h"
#include "api/neteq/tick_timer.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
// Decides the actions that NetEq should take. This affects the behavior of the
// jitter buffer, and how it reacts to network conditions.
// This class will undergo substantial refactoring in the near future, and the
// API is expected to undergo significant changes. A target API is given below:
//
// class NetEqController {
// public:
// // Resets object to a clean state.
// void Reset();
// // Given NetEq status, make a decision.
// Operation GetDecision(NetEqStatus neteq_status);
// // Register every packet received.
// void RegisterPacket(PacketInfo packet_info);
// // Register empty packet.
// void RegisterEmptyPacket();
// // Register a codec switching.
// void CodecSwithed();
// // Sets the sample rate.
// void SetSampleRate(int fs_hz);
// // Sets the packet length in samples.
// void SetPacketLengthSamples();
// // Sets maximum delay.
// void SetMaximumDelay(int delay_ms);
// // Sets mininum delay.
// void SetMinimumDelay(int delay_ms);
// // Sets base mininum delay.
// void SetBaseMinimumDelay(int delay_ms);
// // Gets target buffer level.
// int GetTargetBufferLevelMs() const;
// // Gets filtered buffer level.
// int GetFilteredBufferLevel() const;
// // Gets base minimum delay.
// int GetBaseMinimumDelay() const;
// }
class NetEqController {
public:
// This struct is used to create a NetEqController.
struct Config {
bool allow_time_stretching;
bool enable_rtx_handling;
int max_packets_in_buffer;
int base_min_delay_ms;
TickTimer* tick_timer;
webrtc::Clock* clock = nullptr;
};
struct PacketInfo {
uint32_t timestamp;
bool is_dtx;
bool is_cng;
};
struct PacketBufferInfo {
bool dtx_or_cng;
size_t num_samples;
size_t span_samples;
size_t span_samples_wait_time;
size_t num_packets;
};
struct NetEqStatus {
uint32_t target_timestamp;
int16_t expand_mutefactor;
size_t last_packet_samples;
absl::optional<PacketInfo> next_packet;
NetEq::Mode last_mode;
bool play_dtmf;
size_t generated_noise_samples;
PacketBufferInfo packet_buffer_info;
size_t sync_buffer_samples;
};
struct PacketArrivedInfo {
size_t packet_length_samples;
uint32_t main_timestamp;
uint16_t main_sequence_number;
bool is_cng_or_dtmf;
bool is_dtx;
bool buffer_flush;
};
virtual ~NetEqController() = default;
// Resets object to a clean state.
virtual void Reset() = 0;
// Resets parts of the state. Typically done when switching codecs.
virtual void SoftReset() = 0;
// Given info about the latest received packet, and current jitter buffer
// status, returns the operation. `target_timestamp` and `expand_mutefactor`
// are provided for reference. `last_packet_samples` is the number of samples
// obtained from the last decoded frame. If there is a packet available, it
// should be supplied in `packet`. The mode resulting from the last call to
// NetEqImpl::GetAudio is supplied in `last_mode`. If there is a DTMF event to
// 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 NetEq::Operation GetDecision(const NetEqStatus& status,
bool* reset_decoder) = 0;
// Inform NetEqController that an empty packet has arrived.
virtual void RegisterEmptyPacket() = 0;
// Sets the sample rate and the output block size.
virtual void SetSampleRate(int fs_hz, size_t output_size_samples) = 0;
// Sets a minimum or maximum delay in millisecond.
// Returns true if the delay bound is successfully applied, otherwise false.
virtual bool SetMaximumDelay(int delay_ms) = 0;
virtual bool SetMinimumDelay(int delay_ms) = 0;
// Sets a base minimum delay in milliseconds for packet buffer. The effective
// minimum delay can't be lower than base minimum delay, even if a lower value
// is set using SetMinimumDelay.
// Returns true if the base minimum is successfully applied, otherwise false.
virtual bool SetBaseMinimumDelay(int delay_ms) = 0;
virtual int GetBaseMinimumDelay() const = 0;
// Reports back to DecisionLogic whether the decision to do expand remains or
// 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(NetEq::Operation operation) = 0;
// Adds `value` to `sample_memory_`.
virtual void AddSampleMemory(int32_t value) = 0;
// Returns the target buffer level in ms.
virtual int TargetLevelMs() const = 0;
// Returns the target buffer level in ms as it would be if no minimum or
// maximum delay was set.
// TODO(bugs.webrtc.org/14270): Make pure virtual once all implementations are
// updated.
virtual int UnlimitedTargetLevelMs() const { return 0; }
// Notify the NetEqController that a packet has arrived. Returns the relative
// arrival delay, if it can be computed.
virtual absl::optional<int> PacketArrived(int fs_hz,
bool should_update_stats,
const PacketArrivedInfo& info) = 0;
// Notify the NetEqController that we are currently in muted state.
// TODO(bugs.webrtc.org/14270): Make pure virtual when downstream is updated.
virtual void NotifyMutedState() {}
// Returns true if a peak was found.
virtual bool PeakFound() const = 0;
// Get the filtered buffer level in samples.
virtual int GetFilteredBufferLevel() const = 0;
// Accessors and mutators.
virtual void set_sample_memory(int32_t value) = 0;
virtual size_t noise_fast_forward() const = 0;
virtual size_t packet_length_samples() const = 0;
virtual void set_packet_length_samples(size_t value) = 0;
virtual void set_prev_time_scale(bool value) = 0;
};
} // namespace webrtc
#endif // API_NETEQ_NETEQ_CONTROLLER_H_

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_NETEQ_NETEQ_CONTROLLER_FACTORY_H_
#define API_NETEQ_NETEQ_CONTROLLER_FACTORY_H_
#include <memory>
#include "api/neteq/neteq_controller.h"
namespace webrtc {
// Creates NetEqController instances using the settings provided in the config
// struct.
class NetEqControllerFactory {
public:
virtual ~NetEqControllerFactory() = default;
// Creates a new NetEqController object, with parameters set in `config`.
virtual std::unique_ptr<NetEqController> CreateNetEqController(
const NetEqController::Config& config) const = 0;
};
} // namespace webrtc
#endif // API_NETEQ_NETEQ_CONTROLLER_FACTORY_H_

View file

@ -0,0 +1,37 @@
/*
* 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/audio_codecs/audio_decoder_factory.h"
#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,
const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory,
Clock* clock) const = 0;
};
} // namespace webrtc
#endif // API_NETEQ_NETEQ_FACTORY_H_

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2016 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/tick_timer.h"
namespace webrtc {
TickTimer::Stopwatch::Stopwatch(const TickTimer& ticktimer)
: ticktimer_(ticktimer), starttick_(ticktimer.ticks()) {}
TickTimer::Countdown::Countdown(const TickTimer& ticktimer,
uint64_t ticks_to_count)
: stopwatch_(ticktimer.GetNewStopwatch()),
ticks_to_count_(ticks_to_count) {}
TickTimer::Countdown::~Countdown() = default;
} // namespace webrtc

View file

@ -0,0 +1,112 @@
/*
* Copyright (c) 2016 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_TICK_TIMER_H_
#define API_NETEQ_TICK_TIMER_H_
#include <stdint.h>
#include <memory>
#include "rtc_base/checks.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" of the counter corresponds to 10 ms.
// A TickTimer object can provide two types of associated time-measuring
// objects: Stopwatch and Countdown.
class TickTimer {
public:
// Stopwatch measures time elapsed since it was started, by querying the
// associated TickTimer for the current time. The intended use is to request a
// new Stopwatch object from a TickTimer object with the GetNewStopwatch()
// method. Note: since the Stopwatch object contains a reference to the
// TickTimer it is associated with, it cannot outlive the TickTimer.
class Stopwatch {
public:
explicit Stopwatch(const TickTimer& ticktimer);
uint64_t ElapsedTicks() const { return ticktimer_.ticks() - starttick_; }
uint64_t ElapsedMs() const {
const uint64_t elapsed_ticks = ticktimer_.ticks() - starttick_;
const int ms_per_tick = ticktimer_.ms_per_tick();
return elapsed_ticks < UINT64_MAX / ms_per_tick
? elapsed_ticks * ms_per_tick
: UINT64_MAX;
}
private:
const TickTimer& ticktimer_;
const uint64_t starttick_;
};
// Countdown counts down from a given start value with each tick of the
// associated TickTimer, until zero is reached. The Finished() method will
// return true if zero has been reached, false otherwise. The intended use is
// to request a new Countdown object from a TickTimer object with the
// GetNewCountdown() method. Note: since the Countdown object contains a
// reference to the TickTimer it is associated with, it cannot outlive the
// TickTimer.
class Countdown {
public:
Countdown(const TickTimer& ticktimer, uint64_t ticks_to_count);
~Countdown();
bool Finished() const {
return stopwatch_->ElapsedTicks() >= ticks_to_count_;
}
private:
const std::unique_ptr<Stopwatch> stopwatch_;
const uint64_t ticks_to_count_;
};
TickTimer() : TickTimer(10) {}
explicit TickTimer(int ms_per_tick) : ms_per_tick_(ms_per_tick) {
RTC_DCHECK_GT(ms_per_tick_, 0);
}
TickTimer(const TickTimer&) = delete;
TickTimer& operator=(const TickTimer&) = delete;
void Increment() { ++ticks_; }
// Mainly intended for testing.
void Increment(uint64_t x) { ticks_ += x; }
uint64_t ticks() const { return ticks_; }
int ms_per_tick() const { return ms_per_tick_; }
// Returns a new Stopwatch object, based on the current TickTimer. Note that
// the new Stopwatch object contains a reference to the current TickTimer,
// and must therefore not outlive the TickTimer.
std::unique_ptr<Stopwatch> GetNewStopwatch() const {
return std::unique_ptr<Stopwatch>(new Stopwatch(*this));
}
// Returns a new Countdown object, based on the current TickTimer. Note that
// the new Countdown object contains a reference to the current TickTimer,
// and must therefore not outlive the TickTimer.
std::unique_ptr<Countdown> GetNewCountdown(uint64_t ticks_to_count) const {
return std::unique_ptr<Countdown>(new Countdown(*this, ticks_to_count));
}
private:
uint64_t ticks_ = 0;
const int ms_per_tick_;
};
} // namespace webrtc
#endif // API_NETEQ_TICK_TIMER_H_

View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2016 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/tick_timer.h"
#include <memory>
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
// Verify that the default value for ms_per_tick is 10.
TEST(TickTimer, DefaultMsPerTick) {
TickTimer tt;
EXPECT_EQ(10, tt.ms_per_tick());
}
TEST(TickTimer, CustomMsPerTick) {
TickTimer tt(17);
EXPECT_EQ(17, tt.ms_per_tick());
}
TEST(TickTimer, Increment) {
TickTimer tt;
EXPECT_EQ(0u, tt.ticks());
tt.Increment();
EXPECT_EQ(1u, tt.ticks());
for (int i = 0; i < 17; ++i) {
tt.Increment();
}
EXPECT_EQ(18u, tt.ticks());
tt.Increment(17);
EXPECT_EQ(35u, tt.ticks());
}
TEST(TickTimer, WrapAround) {
TickTimer tt;
tt.Increment(UINT64_MAX);
EXPECT_EQ(UINT64_MAX, tt.ticks());
tt.Increment();
EXPECT_EQ(0u, tt.ticks());
}
TEST(TickTimer, Stopwatch) {
TickTimer tt;
// Increment it a "random" number of steps.
tt.Increment(17);
std::unique_ptr<TickTimer::Stopwatch> sw = tt.GetNewStopwatch();
ASSERT_TRUE(sw);
EXPECT_EQ(0u, sw->ElapsedTicks()); // Starts at zero.
EXPECT_EQ(0u, sw->ElapsedMs());
tt.Increment();
EXPECT_EQ(1u, sw->ElapsedTicks()); // Increases with the TickTimer.
EXPECT_EQ(10u, sw->ElapsedMs());
}
TEST(TickTimer, StopwatchWrapAround) {
TickTimer tt;
tt.Increment(UINT64_MAX);
std::unique_ptr<TickTimer::Stopwatch> sw = tt.GetNewStopwatch();
ASSERT_TRUE(sw);
tt.Increment();
EXPECT_EQ(0u, tt.ticks());
EXPECT_EQ(1u, sw->ElapsedTicks());
EXPECT_EQ(10u, sw->ElapsedMs());
tt.Increment();
EXPECT_EQ(1u, tt.ticks());
EXPECT_EQ(2u, sw->ElapsedTicks());
EXPECT_EQ(20u, sw->ElapsedMs());
}
TEST(TickTimer, StopwatchMsOverflow) {
TickTimer tt;
std::unique_ptr<TickTimer::Stopwatch> sw = tt.GetNewStopwatch();
ASSERT_TRUE(sw);
tt.Increment(UINT64_MAX / 10);
EXPECT_EQ(UINT64_MAX, sw->ElapsedMs());
tt.Increment();
EXPECT_EQ(UINT64_MAX, sw->ElapsedMs());
tt.Increment(UINT64_MAX - tt.ticks());
EXPECT_EQ(UINT64_MAX, tt.ticks());
EXPECT_EQ(UINT64_MAX, sw->ElapsedMs());
}
TEST(TickTimer, StopwatchWithCustomTicktime) {
const int kMsPerTick = 17;
TickTimer tt(kMsPerTick);
std::unique_ptr<TickTimer::Stopwatch> sw = tt.GetNewStopwatch();
ASSERT_TRUE(sw);
EXPECT_EQ(0u, sw->ElapsedMs());
tt.Increment();
EXPECT_EQ(static_cast<uint64_t>(kMsPerTick), sw->ElapsedMs());
}
TEST(TickTimer, Countdown) {
TickTimer tt;
// Increment it a "random" number of steps.
tt.Increment(4711);
std::unique_ptr<TickTimer::Countdown> cd = tt.GetNewCountdown(17);
ASSERT_TRUE(cd);
EXPECT_FALSE(cd->Finished());
tt.Increment();
EXPECT_FALSE(cd->Finished());
tt.Increment(16); // Total increment is now 17.
EXPECT_TRUE(cd->Finished());
// Further increments do not change the state.
tt.Increment();
EXPECT_TRUE(cd->Finished());
tt.Increment(1234);
EXPECT_TRUE(cd->Finished());
}
} // namespace webrtc