Skip to content

Conversation

@cijiugechu
Copy link

@cijiugechu cijiugechu commented Oct 12, 2025

This PR introduces a new non-blocking method try_get_next_frame to the Capturer.

The existing get_next_frame blocks the calling thread until a frame is available, which can be unsuitable for applications that need to remain responsive, such as GUI applications or game loops.

Summary by CodeRabbit

  • New Features
    • Adds a non-blocking way to retrieve the next captured frame.
    • Returns immediately when no frame is available to enable polling without stalling.
    • Distinguishes outcomes: frame delivered, no data available, or channel disconnection error.
    • Preserves existing error semantics and control flow to remain consistent with the blocking API.
    • Enables responsive polling patterns for consumers that must avoid blocking.

@cijiugechu cijiugechu changed the title Add non-blocking 'try_get_next_frame' to Capturer Add non-blocking try_get_next_frame to Capturer Oct 12, 2025
@coderabbitai
Copy link

coderabbitai bot commented Oct 12, 2025

Walkthrough

Adds a non-blocking frame retrieval method try_get_next_frame to Capturer that uses mpsc::Receiver::try_recv(), forwards received items to engine.process_channel_item, and returns Ok(Some(Frame)), Ok(None) when nothing usable is available, or Err(RecvError) on channel disconnection.

Changes

Cohort / File(s) Summary
Capturer non-blocking API
src/capturer/mod.rs
Added pub fn try_get_next_frame(&self) -> Result<Option<Frame>, mpsc::RecvError>: non-blocking try_recv, forwards items to engine.process_channel_item, returns Ok(Some(Frame)), Ok(None) when no frame is yielded or channel empty, or Err(RecvError) on disconnect.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor Caller
    participant C as Capturer
    participant RX as Channel (rx)
    participant E as Engine

    Caller->>C: try_get_next_frame()
    C->>RX: try_recv()
    alt Item available
        RX-->>C: Item
        C->>E: process_channel_item(Item)
        alt Frame produced
            E-->>C: Frame
            C-->>Caller: Ok(Some(Frame))
        else No frame yielded
            E-->>C: None
            C-->>Caller: Ok(None)
        end
    else Empty
        RX-->>C: Empty
        C-->>Caller: Ok(None)
    else Disconnected
        RX-->>C: RecvError
        C-->>Caller: Err(RecvError)
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

A twitch of whiskers, a hop, not a block,
I peek at the queue with a soft, gentle knock.
If frames are a-plenty, I nibble one quick—
If none, I dash off with a tap-tappy tick.
When lines go silent, I thump: “Channel’s out!” 🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly and concisely summarizes the primary addition of a non-blocking try_get_next_frame method to the Capturer, accurately reflecting the main change in the pull request.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0cc234 and bd8e9a4.

📒 Files selected for processing (1)
  • src/capturer/mod.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/capturer/mod.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c03f15a and 69b2344.

📒 Files selected for processing (1)
  • src/capturer/mod.rs (1 hunks)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/capturer/mod.rs (1)

143-157: Previous concern resolved: implementation now correctly mirrors get_next_frame semantics.

The loop-based implementation addresses the semantic inconsistency flagged in the previous review. By draining all available channel items until a usable frame is found or the channel is empty, try_get_next_frame now behaves consistently with get_next_frame—the only difference being blocking vs. non-blocking behavior.

Ok(None) unambiguously means "no frame currently available," not "item was filtered."

Optional: Consider expanding the doc comment.

While the implementation is clear, users might benefit from more detail:

-    /// Attempts to return the next captured frame without blocking.
+    /// Attempts to return the next captured frame without blocking.
+    ///
+    /// Processes all currently available channel items until a usable frame is found.
+    /// Returns `Ok(None)` if no frames are available at this moment (not that items were filtered).
+    /// Returns `Err(mpsc::RecvError)` if the capture channel has been disconnected.
     pub fn try_get_next_frame(&self) -> Result<Option<Frame>, mpsc::RecvError> {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 69b2344 and f454d78.

📒 Files selected for processing (1)
  • src/capturer/mod.rs (1 hunks)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f454d78 and e827130.

📒 Files selected for processing (1)
  • src/capturer/mod.rs (1 hunks)
🔇 Additional comments (1)
src/capturer/mod.rs (1)

148-161: LGTM! Non-blocking semantics correctly implemented.

The implementation correctly addresses the previous concern by looping through all available channel items until a usable frame is found. The behavior now matches get_next_frame semantics while providing non-blocking operation:

  • Drains all currently available items in the channel
  • Returns the first usable frame via Ok(Some(frame))
  • Returns Ok(None) unambiguously when the channel is empty (not because items were filtered)
  • Correctly maps TryRecvError::Disconnected to RecvError for consistency with the blocking API

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/capturer/mod.rs (1)

143-161: Implementation looks good; consider clarifying documentation.

The implementation correctly mirrors get_next_frame's semantics by looping through filtered items transparently. The previous semantic inconsistency has been resolved.

However, the documentation at line 146 is slightly ambiguous. The phrase "(note that items were filtered)" could be misread as suggesting that Ok(None) is related to filtered items, when in fact Ok(None) is returned only when the channel is empty—filtered items are handled transparently in the loop and never cause an early return.

Consider this clearer phrasing:

-    /// Returns `Ok(None)` if no frames are available at this moment (note that items were filtered).
+    /// Returns `Ok(None)` if the channel is empty; filtered items are processed transparently.

Or alternatively:

-    /// Returns `Ok(None)` if no frames are available at this moment (note that items were filtered).
+    /// Returns `Ok(None)` only when the channel is empty, not because items were filtered.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e827130 and c0cc234.

📒 Files selected for processing (1)
  • src/capturer/mod.rs (1 hunks)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant