Skip to content

Conversation

@emilsas
Copy link
Contributor

@emilsas emilsas commented Nov 28, 2025

No description provided.

@coderabbitai
Copy link

coderabbitai bot commented Nov 28, 2025

Walkthrough

This change replaces OnceLock<Mutex<...>> with Mutex<Option<...>> for the static IMPORT and HANDLE variables and updates all accesses to use lock guards. It adds audio support: ImportJoy::init_audio() and ImportJoy::write_audio_frame(), initializes an audio track and renditions in the catalog, and adjusts priorities (video lowered, audio set higher). New C ABI function hang_write_audio_packet_from_c() is exposed. Thread handle storage and cleanup now use Mutex-guarded Option, and video/audio packet write paths use the guarded IMPORT.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to evaluate relevance to the changeset. Add a description explaining the audio track implementation, its purpose, and any relevant context for reviewers.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Add audio track for hang-c library' clearly and specifically describes the main change: adding audio track support to the hang-c library.
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

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: 0

🧹 Nitpick comments (3)
rs/hang-c/src/lib.rs (3)

66-68: Lock poisoning silently ignored.

If the lock is poisoned, the thread handle will be leaked. While lock poisoning is rare, consider logging the error or using .expect() with a descriptive message for debugging.

Apply this diff to add error handling:

-	if let Ok(mut guard) = HANDLE.lock() {
-		*guard = Some(handle);
-	}
+	*HANDLE.lock().expect("HANDLE lock poisoned") = Some(handle);

74-81: Improved shutdown sequence.

The addition of thread join and IMPORT clearing provides cleaner shutdown behavior. However, consider that write operations (hang_write_video_packet_from_c, hang_write_audio_packet_from_c) might still execute if they acquired locks before IMPORT is cleared.

For more robust error handling, consider:

-	if let Ok(mut guard) = HANDLE.lock() {
-		if let Some(handle) = guard.take() {
-			let _ = handle.join();
-		}
-	}
-	if let Ok(mut guard) = IMPORT.lock() {
-		*guard = None;
-	}
+	if let Ok(mut guard) = HANDLE.lock() {
+		if let Some(handle) = guard.take() {
+			let _ = handle.join();
+		}
+	} else {
+		eprintln!("Warning: HANDLE lock poisoned during shutdown");
+	}
+	
+	if let Ok(mut guard) = IMPORT.lock() {
+		*guard = None;
+	} else {
+		eprintln!("Warning: IMPORT lock poisoned during shutdown");
+	}

206-223: Audio track initialization looks good.

The audio track integration follows the same pattern as video and correctly adds it to the catalog. The audio priority of 2 (vs. video priority of 1) prioritizes audio delivery.

Consider using constants or an enum for track indices instead of hardcoding 0 and 1:

const VIDEO_TRACK_ID: u32 = 0;
const AUDIO_TRACK_ID: u32 = 1;

This would make the code more maintainable and reduce the risk of index mismatches between init() and the write methods.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b2abf68 and 877bc2a.

📒 Files selected for processing (1)
  • rs/hang-c/src/lib.rs (8 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Rust tests should be integrated within source files

Files:

  • rs/hang-c/src/lib.rs
rs/**/*.{rs,toml}

📄 CodeRabbit inference engine (CLAUDE.md)

Use the Rust workspace configured in rs/Cargo.toml for Rust development

Files:

  • rs/hang-c/src/lib.rs
🔇 Additional comments (8)
rs/hang-c/src/lib.rs (8)

5-5: LGTM!

The additional imports for audio support (Audio, AudioConfig, AAC) are appropriate and used throughout the file.


96-101: LGTM!

The lock-based access is consistent with the refactor and correctly uses as_mut() to obtain a mutable reference for writing video frames.


104-122: LGTM!

The new audio packet function is well-structured with proper safety documentation, input validation, and consistent locking patterns matching the video counterpart.


137-139: LGTM!

The lock-based assignment is consistent with the synchronization refactor.


187-187: Priority adjustments prioritize audio over video.

The priority changes (video: 2→1, audio: 2) ensure audio is delivered with higher priority than video. This is a sensible choice for media streaming, as audio interruptions are typically more disruptive to user experience than video frame drops.

Also applies to: 198-198, 209-209, 220-220


299-319: LGTM!

The audio frame writing implementation correctly:

  • Includes safety documentation
  • Retrieves the audio track (index 1)
  • Copies data to prevent use-after-free
  • Sets keyframe: false (appropriate for audio frames)
  • Mirrors the video frame writing pattern

16-17: I'll help you verify the race condition concern in this review. Let me start by examining the current code and understanding the synchronization mechanisms.
<function_calls>


#!/bin/bash

Read the file to see lines 16-17 and surrounding context

cat -n rs/hang-c/src/lib.rs | head -50


</function_calls>

Let me also check the git history to understand if this was changed from OnceLock:
<function_calls>


#!/bin/bash

Check recent git history on this file

git log --oneline -10 -- rs/hang-c/src/lib.rs


</function_calls>

Now let me examine the implementation of hang_start_from_c() and the RUNNING flag:
<function_calls>


#!/bin/bash

Search for hang_start_from_c and RUNNING flag

echo "=== Searching for hang_start_from_c implementation ==="
rg -n 'hang_start_from_c' rs/hang-c/src/lib.rs -A 15

echo -e "\n=== Searching for RUNNING flag usage ==="
rg -n 'RUNNING' rs/hang-c/src/lib.rs -B 2 -A 2


</function_calls>

Let me also check the complete file to understand the full context:
<function_calls>


#!/bin/bash

Check file size and read the entire file

wc -l rs/hang-c/src/lib.rs
echo "---"
cat -n rs/hang-c/src/lib.rs


</function_calls>

Let me check the git diff to see what changed from previous version:
<function_calls>


#!/bin/bash

Show the recent diff or changes to understand what was modified

git diff HEAD1 rs/hang-c/src/lib.rs 2>/dev/null || echo "Could not get diff from HEAD1"

echo -e "\n=== Show current HEAD commit ==="
git log -1 --oneline rs/hang-c/src/lib.rs


</function_calls>


252-267: AAC profile 2 is correctly specified as AAC-LC. Per ISO/IEC 14496-3, audio object type 2 corresponds to AAC Low Complexity (AAC-LC), which is the standard baseline profile for general-purpose audio streaming and broadcast. The audio configuration is appropriate: 48 kHz sample rate, stereo (2 channels), and 128 kbps bitrate are all reasonable values for AAC-LC encoding.

@kixelated
Copy link
Owner

Can you run just fix then we can merge this. There's a lot of things I want to improve with the rust code, but I can do that in a separate PR.

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 (3)
rs/hang-c/src/lib.rs (3)

12-17: Global Mutex<Option<...>> usage can silently ignore poisoning and has slightly fuzzy restart semantics

Using Mutex<Option<ImportJoy>> / Mutex<Option<JoinHandle<()>>> is fine, but the repeated if let Ok(mut guard) = ... pattern means any panic while the mutex is held will poison it and make all later hang_write_* / hang_stop_from_c calls effectively no‑ops (lock returns Err, branch is skipped, and IMPORT/HANDLE never get updated or cleared). Also, calling hang_start_from_c multiple times before a matching stop drops the previous JoinHandle without joining it, so only the most recent client is tracked explicitly. If you expect panics/restarts in real usage, consider matching on Ok/Err(poisoned) and always updating the inner Option via poisoned.into_inner(), and/or guarding hang_start_from_c to be idempotent while a client is already running (e.g., check RUNNING/existing HANDLE and early‑return).

Also applies to: 66-68, 74-81, 96-101, 116-121, 137-139


104-122: Audio FFI path and track wiring look good; consider de‑magicking track IDs and double‑check priority semantics

The new audio flow (hang_write_audio_packet_from_cImportJoy::write_audio_frame plus init_audio wiring) mirrors the video path nicely: pointers are validated, data is copied into owned Bytes, and timestamps use Timestamp::from_micros(dts) consistently. Two small maintainability/nastiness points:

  • The self.tracks keys 0 (video) and 1 (audio) are magic numbers. Defining shared constants and using them in both init* and write_* would make future changes safer:
+const VIDEO_TRACK_ID: u32 = 0;
+const AUDIO_TRACK_ID: u32 = 1;
@@
-        self.tracks.insert(0, track_produce.producer.into());
+        self.tracks.insert(VIDEO_TRACK_ID, track_produce.producer.into());
@@
-        self.tracks.insert(1, track_produce.producer.into());
+        self.tracks.insert(AUDIO_TRACK_ID, track_produce.producer.into());
@@
-        let Some(track) = self.tracks.get_mut(&0) else {
+        let Some(track) = self.tracks.get_mut(&VIDEO_TRACK_ID) else {
@@
-        let Some(track) = self.tracks.get_mut(&1) else {
+        let Some(track) = self.tracks.get_mut(&AUDIO_TRACK_ID) else {
  • Audio gets priority: 2 while video is priority: 1 on both the Track and {Video, Audio} configs. If “higher number = higher preference” is the intended contract for the hang catalog/player, this is fine but might be worth a short comment to document that audio is intentionally preferred over video for selection.

Also applies to: 179-223, 252-264, 295-315


252-264: Add minimal in‑source tests for new audio behavior

The new audio initialization and write path (init_audio / write_audio_frame) are untested. A small #[cfg(test)] module that constructs an ImportJoy, calls init(), and exercises write_audio_frame (asserting that frames are accepted for the audio track and timestamp units are respected) would help catch regressions in track IDs, codec config, or timestamp handling without relying only on C‑side integration tests. As per coding guidelines, Rust tests should be integrated within source files.

Also applies to: 295-315

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 877bc2a and 16f9856.

📒 Files selected for processing (1)
  • rs/hang-c/src/lib.rs (8 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Rust tests should be integrated within source files

Files:

  • rs/hang-c/src/lib.rs
rs/**/*.{rs,toml}

📄 CodeRabbit inference engine (CLAUDE.md)

Use the Rust workspace configured in rs/Cargo.toml for Rust development

Files:

  • rs/hang-c/src/lib.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Check

@kixelated kixelated merged commit d01382b into kixelated:main Dec 1, 2025
1 check passed
@moq-bot moq-bot bot mentioned this pull request Dec 1, 2025
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.

2 participants