Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 66 additions & 2 deletions src/internal_modules/roc_pipeline/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
*/

#include "roc_pipeline/config.h"
#include "roc_audio/sample_spec.h"
#include "roc_core/log.h"
#include "roc_core/stddefs.h"
#include "roc_core/time.h"
#include "roc_rtp/headers.h"

namespace roc {
Expand All @@ -15,15 +19,75 @@ namespace pipeline {
SenderSinkConfig::SenderSinkConfig()
: input_sample_spec(DefaultSampleSpec)
, payload_type(rtp::PayloadType_L16_Stereo)
, packet_length(DefaultPacketLength)
, packet_length(0)
, packet_mtu(0)
, enable_timing(false)
, enable_auto_duration(false)
, enable_auto_cts(false)
, enable_profiling(false)
, enable_interleaving(false) {
}

void SenderSinkConfig::deduce_defaults() {
void SenderSinkConfig::deduce_defaults(const audio::SampleSpec& encoding_sample_spec) {
// Resolve packet_length from packet_mtu if needed.
if (packet_length == 0 && packet_mtu == 0) {
// Neither set: derive packet_length from DefaultPacketMtu, then use
// min(DefaultPacketLength, mtu_derived_length).
if (encoding_sample_spec.is_valid() && encoding_sample_spec.pcm_format()
!= audio::PcmFormat_Invalid) {
const size_t payload_bytes =
DefaultPacketMtu > RtpHeaderSize ? DefaultPacketMtu - RtpHeaderSize : 0;
const core::nanoseconds_t mtu_length =
encoding_sample_spec.bytes_2_ns(payload_bytes);
if (mtu_length > 0) {
packet_length = std::min(DefaultPacketLength, mtu_length);
} else {
packet_length = DefaultPacketLength;
}
} else {
packet_length = DefaultPacketLength;
}
} else if (packet_length == 0 && packet_mtu != 0) {
// Only MTU set: derive packet_length from it.
if (encoding_sample_spec.is_valid() && encoding_sample_spec.pcm_format()
!= audio::PcmFormat_Invalid) {
const size_t payload_bytes =
packet_mtu > RtpHeaderSize ? packet_mtu - RtpHeaderSize : 0;
const core::nanoseconds_t mtu_length =
encoding_sample_spec.bytes_2_ns(payload_bytes);
packet_length = mtu_length > 0 ? mtu_length : DefaultPacketLength;
} else {
packet_length = DefaultPacketLength;
}
} else if (packet_length != 0 && packet_mtu != 0) {
// Both set: warn and pick the one that leads to smaller packet size.
if (encoding_sample_spec.is_valid() && encoding_sample_spec.pcm_format()
!= audio::PcmFormat_Invalid) {
const size_t payload_bytes =
packet_mtu > RtpHeaderSize ? packet_mtu - RtpHeaderSize : 0;
const core::nanoseconds_t mtu_length =
encoding_sample_spec.bytes_2_ns(payload_bytes);
if (mtu_length > 0 && mtu_length < packet_length) {
roc_log(LogInfo,
"sender config: both packet_length and packet_mtu are set;"
" using packet_mtu-derived length (%.3fms) since it is smaller"
" than packet_length (%.3fms)",
(double)mtu_length / core::Millisecond,
(double)packet_length / core::Millisecond);
packet_length = mtu_length;
} else {
roc_log(LogInfo,
"sender config: both packet_length and packet_mtu are set;"
" using packet_length (%.3fms) since it is smaller"
" than packet_mtu-derived length (%.3fms)",
(double)packet_length / core::Millisecond,
(double)mtu_length / core::Millisecond);
}
}
// else: can't compute mtu_length, keep packet_length as-is
}
// else: only packet_length set — use it as-is

latency.deduce_defaults(DefaultLatency, false);
resampler.deduce_defaults(latency.tuner_backend, latency.tuner_profile);
}
Expand Down
23 changes: 22 additions & 1 deletion src/internal_modules/roc_pipeline/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ static const audio::SampleSpec DefaultSampleSpec(DefaultSampleRate,
//! a lower length may be required depending on network MTU, e.g. for Internet.
const core::nanoseconds_t DefaultPacketLength = 5 * core::Millisecond;

//! Default MTU (maximum transmission unit) in bytes.
//! @remarks
//! 1200 bytes is the default MTU used in WebRTC and is safe for most networks.
//! When neither packet_length nor packet_mtu is configured by the user, the
//! effective packet length is min(DefaultPacketLength, mtu_derived_length).
const size_t DefaultPacketMtu = 1200;

//! RTP header size in bytes (fixed part, no CSRC).
const size_t RtpHeaderSize = 12;

//! Default latency.
//! @remarks
//! 200ms works well on majority Wi-Fi networks and is not too annoying. However, many
Expand All @@ -66,8 +76,17 @@ struct SenderSinkConfig {
unsigned payload_type;

//! Packet length, in nanoseconds.
//! @remarks
//! If zero and packet_mtu is also zero, derived from DefaultPacketMtu.
//! If zero and packet_mtu is set, derived from packet_mtu.
core::nanoseconds_t packet_length;

//! Maximum transmission unit (MTU) in bytes.
//! @remarks
//! If zero and packet_length is also zero, DefaultPacketMtu is used.
//! If zero and packet_length is set, packet_mtu is ignored.
size_t packet_mtu;

//! FEC writer parameters.
fec::WriterConfig fec_writer;

Expand Down Expand Up @@ -108,7 +127,9 @@ struct SenderSinkConfig {
SenderSinkConfig();

//! Fill unset values with defaults.
void deduce_defaults();
//! @p encoding_sample_spec is the packet encoding spec (rate + channels + format),
//! used to derive packet_length from packet_mtu when needed.
void deduce_defaults(const audio::SampleSpec& encoding_sample_spec);
};

//! Parameters of sender slot.
Expand Down
11 changes: 10 additions & 1 deletion src/internal_modules/roc_pipeline/sender_sink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "roc_pipeline/sender_sink.h"
#include "roc_audio/resampler_map.h"
#include "roc_audio/sample_spec.h"
#include "roc_core/log.h"
#include "roc_core/panic.h"

Expand All @@ -27,7 +28,15 @@ SenderSink::SenderSink(const SenderSinkConfig& sink_config,
, arena_(arena)
, frame_writer_(NULL)
, valid_(false) {
sink_config_.deduce_defaults();
// Resolve packet_length using encoding spec if available.
{
const rtp::Encoding* enc = encoding_map_.find_by_pt(sink_config_.payload_type);
if (enc) {
sink_config_.deduce_defaults(enc->sample_spec);
} else {
sink_config_.deduce_defaults(audio::SampleSpec());
}
}

audio::IFrameWriter* frm_writer = &fanout_;

Expand Down
15 changes: 14 additions & 1 deletion src/public_api/include/roc/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -671,10 +671,23 @@ typedef struct roc_sender_config {
* accumulated or the sender is flushed or closed. Larger number reduces
* packet overhead but also does not allow smaller latency.
*
* If zero, default value is used.
* If zero and \c packet_mtu is also zero, default value is used.
* If zero and \c packet_mtu is set, packet length is derived from MTU.
* If both are set, a warning is logged and the smaller resulting size is used.
*/
unsigned long long packet_length;

/** Maximum transmission unit (MTU) for outgoing packets, in bytes.
*
* Defines the maximum network packet size. The sender will choose a packet
* duration that fits within this MTU (accounting for RTP header overhead).
*
* If zero and \c packet_length is also zero, a default MTU of 1200 bytes is used.
* If zero and \c packet_length is set, MTU is ignored.
* If both are set, a warning is logged and the smaller resulting size is used.
*/
unsigned int packet_mtu;

/** Enable packet interleaving.
*
* If non-zero, the sender shuffles packets before sending them. This
Expand Down
4 changes: 4 additions & 0 deletions src/public_api/src/adapters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ bool sender_config_from_user(node::Context& context,
out.packet_length = (core::nanoseconds_t)in.packet_length;
}

if (in.packet_mtu != 0) {
out.packet_mtu = (size_t)in.packet_mtu;
}

if (in.target_latency != 0) {
out.latency.target_latency = (core::nanoseconds_t)in.target_latency;
}
Expand Down
Loading
Loading