diff --git a/spa/include/spa/utils/keys.h b/spa/include/spa/utils/keys.h index 59dfc1139..f60d3a3ec 100644 --- a/spa/include/spa/utils/keys.h +++ b/spa/include/spa/utils/keys.h @@ -121,6 +121,8 @@ extern "C" { #define SPA_KEY_API_BLUEZ5_CLASS "api.bluez5.class" /**< a bluetooth class */ #define SPA_KEY_API_BLUEZ5_ICON "api.bluez5.icon" /**< a bluetooth icon */ #define SPA_KEY_API_BLUEZ5_ROLE "api.bluez5.role" /**< "client" or "server" */ +#define SPA_KEY_API_BLUEZ5_MIN_LATENCY_MS \ + "api.bluez5.min-latency-ms" /**< minimum possible latency, in milliseconds */ /** keys for jack api */ #define SPA_KEY_API_JACK "api.jack" /**< key for the JACK api */ diff --git a/spa/plugins/bluez5/decode-buffer.h b/spa/plugins/bluez5/decode-buffer.h index 776c2a0ce..beb34cfe0 100644 --- a/spa/plugins/bluez5/decode-buffer.h +++ b/spa/plugins/bluez5/decode-buffer.h @@ -85,6 +85,8 @@ struct spa_bt_decode_buffer int64_t duration_ns; int64_t next_nsec; + int32_t min_latency; + int32_t delay; int32_t delay_frac; uint32_t prev_samples; @@ -252,6 +254,11 @@ static inline void spa_bt_decode_buffer_set_max_extra_latency(struct spa_bt_deco this->max_extra = samples; } +static inline void spa_bt_decode_buffer_set_min_latency(struct spa_bt_decode_buffer *this, int32_t samples) +{ + this->min_latency = samples; +} + static inline int32_t spa_bt_decode_buffer_get_auto_latency(struct spa_bt_decode_buffer *this) { const int32_t duration = this->duration_ns * this->rate / SPA_NSEC_PER_SEC; @@ -264,6 +271,7 @@ static inline int32_t spa_bt_decode_buffer_get_auto_latency(struct spa_bt_decode SPA_CLAMP((int)this->rate / 50, 1, INT32_MAX)), duration, max_buf - 2*packet_size); + target = SPA_MAX(target, this->min_latency); return SPA_MIN(target, duration + SPA_CLAMP(this->max_extra, 0, INT32_MAX - duration)); } diff --git a/spa/plugins/bluez5/media-source.c b/spa/plugins/bluez5/media-source.c index 01bb4f2fd..73ea6c44e 100644 --- a/spa/plugins/bluez5/media-source.c +++ b/spa/plugins/bluez5/media-source.c @@ -148,6 +148,7 @@ struct impl { unsigned int decode_buffer_target; unsigned int node_latency; + uint32_t min_latency_ms; int fd; struct spa_source source; @@ -1039,6 +1040,11 @@ static int transport_start(struct impl *this) port->current_format.info.raw.rate * 80 / 1000); } + if (this->min_latency_ms) { + spa_bt_decode_buffer_set_min_latency(&port->buffer, + this->min_latency_ms * port->current_format.info.raw.rate / 1000); + } + this->delay.buffer = -1; this->delay.duration = 0; this->update_delay_event = spa_loop_utils_add_event(this->loop_utils, update_delay_event, this); @@ -2249,6 +2255,8 @@ impl_init(const struct spa_handle_factory *factory, spa_scnprintf(this->props.rate, sizeof(this->props.rate), "%s", str); this->props.has_rate = true; } + if ((str = spa_dict_lookup(info, SPA_KEY_API_BLUEZ5_MIN_LATENCY_MS)) != NULL) + spa_atou32(str, &this->min_latency_ms, 0); } if (this->is_duplex) {