mirror of
https://github.com/esphome/esphome.git
synced 2026-10-01 08:50:22 +00:00
[speaker_source] Account for playback callbacks during speaker writes (#19499)
Co-authored-by: n-IA-hane <n-IA-hane@users.noreply.github.com>
This commit is contained in:
@@ -196,10 +196,19 @@ size_t SpeakerSourceMediaPlayer::handle_media_output_(uint8_t pipeline, media_so
|
||||
vTaskDelay(pdMS_TO_TICKS(timeout_ms));
|
||||
return 0;
|
||||
}
|
||||
// Reserve frames before the speaker can play them and report their progress,
|
||||
// then release the portion it did not accept.
|
||||
const uint32_t reserved_frames = stream_info.bytes_to_frames(length);
|
||||
ps.pending_frames.fetch_add(reserved_frames, std::memory_order_relaxed);
|
||||
size_t bytes_written = ps.speaker->play(data, length, pdMS_TO_TICKS(timeout_ms));
|
||||
if (bytes_written > 0) {
|
||||
// Track frames sent to speaker for this source
|
||||
ps.pending_frames.fetch_add(stream_info.bytes_to_frames(bytes_written), std::memory_order_relaxed);
|
||||
const uint32_t unused_frames = reserved_frames - stream_info.bytes_to_frames(bytes_written);
|
||||
if (unused_frames > 0) {
|
||||
// The main loop may reset pending_frames while play() is blocked.
|
||||
// Clamp the release so that a concurrent reset cannot cause underflow.
|
||||
uint32_t pending = ps.pending_frames.load(std::memory_order_relaxed);
|
||||
while (!ps.pending_frames.compare_exchange_weak(pending, pending - std::min(pending, unused_frames),
|
||||
std::memory_order_relaxed)) {
|
||||
}
|
||||
}
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
@@ -4,4 +4,4 @@ substitutions:
|
||||
packages:
|
||||
i2s_audio: !include ../../test_build_components/common/i2s_audio/esp32-idf.yaml
|
||||
|
||||
<<: !include common.yaml
|
||||
speaker_source: !include common.yaml
|
||||
|
||||
Reference in New Issue
Block a user