diff --git a/src/a2dp-aac.c b/src/a2dp-aac.c index 78e707a80..fd362b2fa 100644 --- a/src/a2dp-aac.c +++ b/src/a2dp-aac.c @@ -419,7 +419,7 @@ void *a2dp_aac_enc_thread(struct ba_transport_pcm *t_pcm) { rtp_state_update(&rtp, pcm_frames); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); /* If the input buffer was not consumed, we have to append new data to * the existing one. Since we do not use ring buffer, we will simply diff --git a/src/a2dp-aptx-hd.c b/src/a2dp-aptx-hd.c index 99115963d..6ed1df1aa 100644 --- a/src/a2dp-aptx-hd.c +++ b/src/a2dp-aptx-hd.c @@ -220,7 +220,7 @@ void *a2dp_aptx_hd_enc_thread(struct ba_transport_pcm *t_pcm) { rtp.ts_pcm_frames += pcm_frames; /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); /* reinitialize output buffer */ ffb_rewind(&bt); diff --git a/src/a2dp-aptx.c b/src/a2dp-aptx.c index 9a100d213..028626232 100644 --- a/src/a2dp-aptx.c +++ b/src/a2dp-aptx.c @@ -201,7 +201,7 @@ void *a2dp_aptx_enc_thread(struct ba_transport_pcm *t_pcm) { asrsync_sync(&io.asrs, pcm_samples / channels); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); /* reinitialize output buffer */ ffb_rewind(&bt); diff --git a/src/a2dp-faststream.c b/src/a2dp-faststream.c index 5d089907c..6311dfd66 100644 --- a/src/a2dp-faststream.c +++ b/src/a2dp-faststream.c @@ -228,7 +228,7 @@ void *a2dp_fs_enc_thread(struct ba_transport_pcm *t_pcm) { asrsync_sync(&io.asrs, pcm_frames); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); /* If the input buffer was not consumed (due to codesize limit), we * have to append new data to the existing one. Since we do not use diff --git a/src/a2dp-lc3plus.c b/src/a2dp-lc3plus.c index 58fa251fe..3f80a2e4d 100644 --- a/src/a2dp-lc3plus.c +++ b/src/a2dp-lc3plus.c @@ -384,7 +384,7 @@ void *a2dp_lc3plus_enc_thread(struct ba_transport_pcm *t_pcm) { rtp_state_update(&rtp, pcm_frames); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); /* If the input buffer was not consumed (due to codesize limit), we * have to append new data to the existing one. Since we do not use diff --git a/src/a2dp-ldac.c b/src/a2dp-ldac.c index 9a4446b5e..bdeab45aa 100644 --- a/src/a2dp-ldac.c +++ b/src/a2dp-ldac.c @@ -270,7 +270,7 @@ void *a2dp_ldac_enc_thread(struct ba_transport_pcm *t_pcm) { rtp_state_update(&rtp, pcm_frames); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); } diff --git a/src/a2dp-mpeg.c b/src/a2dp-mpeg.c index fd0266b38..b420bbf23 100644 --- a/src/a2dp-mpeg.c +++ b/src/a2dp-mpeg.c @@ -323,7 +323,7 @@ void *a2dp_mp3_enc_thread(struct ba_transport_pcm *t_pcm) { rtp_state_update(&rtp, pcm_frames); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); /* If the input buffer was not consumed (due to frame alignment), we * have to append new data to the existing one. Since we do not use diff --git a/src/a2dp-opus.c b/src/a2dp-opus.c index 030f1d659..54fa4827f 100644 --- a/src/a2dp-opus.c +++ b/src/a2dp-opus.c @@ -244,7 +244,7 @@ void *a2dp_opus_enc_thread(struct ba_transport_pcm *t_pcm) { rtp_state_update(&rtp, opus_frame_pcm_frames); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); /* If the input buffer was not consumed (due to encoder frame * constraint), we have to append new data to the existing one. diff --git a/src/a2dp-sbc.c b/src/a2dp-sbc.c index 696ac1378..632cd391e 100644 --- a/src/a2dp-sbc.c +++ b/src/a2dp-sbc.c @@ -273,7 +273,7 @@ void *a2dp_sbc_enc_thread(struct ba_transport_pcm *t_pcm) { rtp_state_update(&rtp, pcm_frames); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); /* If the input buffer was not consumed (due to codesize limit), we * have to append new data to the existing one. Since we do not use diff --git a/src/ba-transport-pcm.c b/src/ba-transport-pcm.c index 3c7e19ff1..633fdc703 100644 --- a/src/ba-transport-pcm.c +++ b/src/ba-transport-pcm.c @@ -716,6 +716,22 @@ int ba_transport_pcm_get_hardware_volume( return 0; } +void ba_transport_pcm_update_processing_delay(struct ba_transport_pcm *pcm, unsigned int delay) { + if (delay == pcm->processing_delay_dms) + return; + unsigned int diff = delay > pcm->reported_processing_delay_dms ? + delay - pcm->reported_processing_delay_dms : + pcm->reported_processing_delay_dms - delay; + pcm->processing_delay_dms = delay; + + /* To avoid creating a flood of dbus signals, we only notify clients when + * the value changes by more than 10ms */ + if (diff > 100 || pcm->reported_processing_delay_dms == 0) { + pcm->reported_processing_delay_dms = delay; + bluealsa_dbus_pcm_update(pcm, BA_DBUS_PCM_UPDATE_DELAY); + } +} + int ba_transport_pcm_get_delay(const struct ba_transport_pcm *pcm) { const struct ba_transport *t = pcm->t; diff --git a/src/ba-transport-pcm.h b/src/ba-transport-pcm.h index 73d7fbe14..38545d4dc 100644 --- a/src/ba-transport-pcm.h +++ b/src/ba-transport-pcm.h @@ -129,6 +129,7 @@ struct ba_transport_pcm { * the host computational power. It is used to compensate for the time * required to encode or decode audio. */ unsigned int processing_delay_dms; + unsigned int reported_processing_delay_dms; /* Positive (or negative) delay reported by the client. */ int client_delay_dms; @@ -253,6 +254,10 @@ int ba_transport_pcm_volume_update( int ba_transport_pcm_get_hardware_volume( const struct ba_transport_pcm *pcm); +void ba_transport_pcm_update_processing_delay( + struct ba_transport_pcm *pcm, + unsigned int delay); + int ba_transport_pcm_get_delay( const struct ba_transport_pcm *pcm); diff --git a/src/bluealsa-dbus.c b/src/bluealsa-dbus.c index 27269a3f7..1adef38eb 100644 --- a/src/bluealsa-dbus.c +++ b/src/bluealsa-dbus.c @@ -538,6 +538,10 @@ static void bluealsa_pcm_open(GDBusMethodInvocation *inv, void *userdata) { goto fail; } + /* It the transport thread has updated its codec_delay value during its + * start procedure then we inform clients that the delay has changed */ + if (pcm->codec_delay_dms > 0) + bluealsa_dbus_pcm_update(pcm, BA_DBUS_PCM_UPDATE_DELAY); } pthread_mutex_lock(&pcm->mutex); diff --git a/src/sco-cvsd.c b/src/sco-cvsd.c index dea164c16..64688bc10 100644 --- a/src/sco-cvsd.c +++ b/src/sco-cvsd.c @@ -79,7 +79,7 @@ void *sco_cvsd_enc_thread(struct ba_transport_pcm *t_pcm) { /* keep data transfer at a constant bit rate */ asrsync_sync(&io.asrs, mtu_samples); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); } diff --git a/src/sco-lc3-swb.c b/src/sco-lc3-swb.c index b9efb590f..4b9d6c2b8 100644 --- a/src/sco-lc3-swb.c +++ b/src/sco-lc3-swb.c @@ -85,7 +85,7 @@ void *sco_lc3_swb_enc_thread(struct ba_transport_pcm *t_pcm) { /* keep data transfer at a constant bit rate */ asrsync_sync(&io.asrs, codec.frames * LC3_SWB_CODESAMPLES); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); /* Move unprocessed data to the front of our linear * buffer and clear the LC3-SWB frame counter. */ diff --git a/src/sco-msbc.c b/src/sco-msbc.c index 3c9ceaae7..c4a4c3341 100644 --- a/src/sco-msbc.c +++ b/src/sco-msbc.c @@ -92,7 +92,7 @@ void *sco_msbc_enc_thread(struct ba_transport_pcm *t_pcm) { /* keep data transfer at a constant bit rate */ asrsync_sync(&io.asrs, msbc.frames * MSBC_CODESAMPLES); /* update busy delay (encoding overhead) */ - t_pcm->processing_delay_dms = asrsync_get_busy_usec(&io.asrs) / 100; + ba_transport_pcm_update_processing_delay(t_pcm, asrsync_get_busy_usec(&io.asrs) / 100); /* Move unprocessed data to the front of our linear * buffer and clear the mSBC frame counter. */ diff --git a/test/test-a2dp.c b/test/test-a2dp.c index c69f9828e..277dbef57 100644 --- a/test/test-a2dp.c +++ b/test/test-a2dp.c @@ -51,6 +51,8 @@ int ba_transport_pcm_state_set(struct ba_transport_pcm *pcm, enum ba_transport_pcm_signal ba_transport_pcm_signal_recv(struct ba_transport_pcm *pcm) { (void)pcm; return -1; } void ba_transport_pcm_thread_cleanup(struct ba_transport_pcm *pcm) { (void)pcm; } +void ba_transport_pcm_update_processing_delay(struct ba_transport_pcm *pcm, unsigned int delay) { + (void)pcm; (void)delay;} CK_START_TEST(test_a2dp_codecs_codec_id_from_string) { ck_assert_uint_eq(a2dp_codecs_codec_id_from_string("SBC"), A2DP_CODEC_SBC);