ReviewOS

also looking at this

home-lang/home

feat(media): add bounded PCM capture, owned snapshots and A/V streaming

#917
Merged chris wants to merge feat/pcm-av-streaming into main
11 files +683 -0

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

packages/audio/src/io/native_capture.zigmodified+1-2
Changes to packages/audio/src/io/native_capture.zig
@@ -1,6 +1,5 @@
11//! Home opaque, header-checked ALSA capture. Build C boundary and link libasound.
22//! Calls serialize; close only after read returns. S16LE mono/stereo, BOOTTIME ns.
3const std = ;
43const Handle = opaque {};
54pub const Config = extern struct { sample_rate: u32, channels: u32, block_frames: u32 };
65extern fn home_audio_open(*const Config, [*:0]const u8, *?*Handle) c_int;
@@ -23,7 +22,7 @@ pub const Capture = struct {
2322 if (s.failed) return error.CaptureFailed;
2423 if (data.len < @as(u64, s.config.block_frames) * s.config.channels * 2 or timeout_ms > 1000) return error.InvalidConfiguration;
2524 var block: Block = undefined;
26 const rc = home_audio_read(s.handle, data.ptr, @intCast(data.len / (s.config.channels * 2)), timeout_ms, &block.frames, &block.timestamp_ns, &block.clock_error_ns);
25 const rc = home_audio_read(s.handle, data.ptr, @intCast(s.config.block_frames), timeout_ms, &block.frames, &block.timestamp_ns, &block.clock_error_ns);
2726 if (rc == 1) return null;
2827 check(rc) catch |err| {
2928 s.failed = true;
packages/video/src/core/pcm_timeline.zigmodified+5-7
Changes to packages/video/src/core/pcm_timeline.zig
@@ -42,13 +42,8 @@ pub const Queue = struct {
4242 if (data.len == 0 or data.len % stride != 0) return error.InvalidPcm;
4343 const frames = data.len / stride;
4444 if (frames > s.capacity - s.used or s.count == s.entries.len) return error.BufferFull;
45 var ts = timestamp;
46 if (s.last_end) |end| {
47 if (ts < end) {
48 if (end - ts > (1_000_000_000 + s.rate - 1) / s.rate) return error.InvalidTimestamp;
49 ts = end;
50 }
51 }
45 const ts = timestamp;
46 if (s.last_end) |end| if (ts < end) return error.InvalidTimestamp;
5247 const end = try at(ts, frames, s.rate);
5348 const first = @min(frames, s.capacity - s.write_pos);
5449 @memcpy(s.data[s.write_pos * stride ..][0 .. first * stride], data[0 .. first * stride]);
@@ -115,6 +110,9 @@ test "PCM rejects full queues, invalid inputs and overflow before modifying hist
115110 try std.testing.expectError(error.InvalidPcm, q.push(&.{1}, 2000000));
116111 try std.testing.expectError(error.InvalidTimestamp, q.push(&.{ 1, 0 }, 1));
117112 try std.testing.expectError(error.TimestampOverflow, at(std.math.maxInt(u64), 1, 48000));
113 const previous = q.last_end.?;
114 try std.testing.expectError(error.InvalidTimestamp, q.push(&.{ 1, 0 }, previous - 1));
115 try std.testing.expectEqual(previous, q.last_end.?);
118116 try std.testing.expectEqual(@as(u64, 1_000_000_000), try at(0, 44100, 44100));
119117}
120118test "PCM partial allocation failure cleanup" {