Add separate rendering starting and complete events - #991
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
DEBUG-only assertions can now fire on explicitly handled message-queue overruns (and a small render-path inefficiency was introduced), so the new event split needs minor tightening before it’s safe to land.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR refactors rendering notifications in AudioPlayer by splitting the previous “frames rendered” event flags into dedicated “rendering started” and “rendering complete” events, allowing the event thread to process these lifecycle transitions separately from per-buffer frame accounting.
Changes:
- Replaced
FramesRenderedEventFlagswith standalonerenderingStartedandrenderingCompleteevent commands. - Updated render-path event enqueueing to emit start / frames-rendered / complete events with appropriate host-time scheduling.
- Added new event processing handlers to update decoder state and dispatch rendering lifecycle notifications.
File summaries
| File | Description |
|---|---|
| Sources/CSFBAudioEngine/Player/AudioPlayer.mm | Splits rendering lifecycle notifications into separate events and adds dedicated processing functions. |
| Sources/CSFBAudioEngine/Player/AudioPlayer.h | Extends EventCommand and declares new event-processing entry points. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🔵 Needs a closer look
Independently queued lifecycle events can be partially accepted, producing inconsistent rendering state.
Review details
Suppressed comments (2)
Sources/CSFBAudioEngine/Player/AudioPlayer.mm:1691
- The start, frame, and completion records now fail independently. If the queue is full for
renderingStartedbut the consumer frees space beforerenderingComplete, completion is accepted without start;processRenderingCompleteEventthen asserts in debug and removes/notifies the decoder without a start in release. Preserve lifecycle atomicity by enqueueing one record or reserving and committing the required records as a batch.
if (!events_.enqueue(EventCommand::renderingComplete, eventTime,
renderingChunk_->descriptor_.sequenceNumber_,
renderingChunk_->descriptor_.playbackGeneration_)) [[unlikely]] {
setFlags(Flags::renderEventDropped);
Sources/CSFBAudioEngine/Player/AudioPlayer.mm:1734
- The two lifecycle events for an empty decoder can be only partially queued. The event consumer may free capacity after
renderingStartedfails, allowing this completion record through and violating the completion handler's requiredrenderingStartedstate. Queue both events atomically (or use one combined empty-render lifecycle record).
if (!events_.enqueue(EventCommand::renderingComplete, eventTime, chunkDescriptor.sequenceNumber_,
chunkDescriptor.playbackGeneration_)) [[unlikely]] {
setFlags(Flags::renderEventDropped);
- Files reviewed: 2/2 changed files
- Comments generated: 0 new
- Review effort level: Balanced
No description provided.