Commit 7d3af2f
feat(compositor): add circular crop for Loom-style webcam PIP overlays (#176)
* feat(compositor): add circular crop for Loom-style webcam PIP overlays
Add a crop_circle boolean field to compositor LayerConfig that clips
the composited layer to an ellipse inscribed in the destination rect.
When the rect is square this produces a perfect circle — ideal for
webcam PIP overlays in the style of Loom.
Backend:
- config.rs, kernel.rs, mod.rs: thread crop_circle through LayerConfig,
ResolvedLayer, LayerSnapshot, CompositeItem, and resolve_scene
- blit.rs: add ellipse-masked blit path with anti-aliased edges (~1.5px
smoothstep band) to both scale_blit_rgba and scale_blit_rgba_rotated;
disable SIMD fast-forward when crop_circle is active
- tests.rs: add 3 new tests for axis-aligned, rotated, and full
composite_frame circular crop
Frontend:
- compositor-types.ts: add crop_circle to LayerConfig and ResolvedLayer
- compositorConstants.ts: DEFAULT_CROP_CIRCLE = false
- compositorLayerParsers.ts: parse/serialize cropCircle <-> crop_circle
- compositorAtoms.ts: include cropCircle in layerEqual comparison
- compositorOverlays.ts, useCompositorLayers.ts: thread cropCircle
- compositorNodeWidgets.tsx: add Circle toggle (MirrorButton) in
CropZoomControl; include in reset
- compositorNodeInspector.tsx: pass cropCircle prop
- compositorCanvasLayers.tsx: CSS border-radius: 50% preview
- compositorServerSync.ts: sync cropCircle from server state
Demo:
- samples/pipelines/dynamic/video_moq_webcam_circle_pip.yml
Signed-off-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
* fix(compositor): disable skip_clear for crop_circle, fix mergeOverlayState comparator
Address two bugs found by Devin Review:
1. kernel.rs: The skip_clear optimization now checks crop_circle — when
true, pixels outside the ellipse must be cleared to transparent black.
Without this, pooled buffers would leak stale frame data in the corners.
Added a regression test using VideoFramePool with pre-filled garbage.
2. useCompositorLayers.ts: The hasExtraChanges comparator passed to
mergeOverlayState now includes cropCircle, so remote config updates
that only change cropCircle are no longer silently discarded.
Signed-off-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
* fix(compositor): remove overflow:hidden from crop circle preview
Remove overflow:hidden from the VideoLayer container when crop_circle
is enabled. The overflow:hidden was clipping resize handles positioned
at corners since they fall outside the inscribed ellipse. The circular
outline (via borderRadius: 50%) alone provides sufficient visual
preview of the crop circle shape.
Signed-off-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
* refactor: replace crop_circle bool with crop_shape enum across full stack
Replace the boolean crop_circle field with an extensible CropShape enum
(Rect | Circle) throughout backend and frontend. This enables future
shape variants (RoundedRect, Hexagon, etc.) without breaking changes.
Backend:
- Add CropShape enum with serde rename_all snake_case
- Replace crop_circle: bool with crop_shape: CropShape in LayerConfig,
ResolvedLayer, LayerSnapshot, CompositeItem, ResolvedSlotConfig
- Kernel converts enum to bool at blit call site
- Update all tests and benchmarks
Frontend:
- Replace cropCircle: boolean with cropShape: 'rect' | 'circle' in
LayerState, parsers, atoms, overlays, server sync, drag resize
- Replace On/Off MirrorButton toggle with segmented control
(▭ Rect / ● Circle) matching existing design patterns
- Update DEFAULT_CROP_CIRCLE to DEFAULT_CROP_SHAPE
- Update all test files
Pipeline:
- Update demo pipeline YAML to use crop_shape: rect/circle
Signed-off-by: Devin AI <devin@devin.ai>
Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
* docs(compositor): fix misleading CropShape forward-compat doc comment
The doc comment claimed unknown values deserialize as Rect, but there
was no #[serde(other)] to back that up. Corrected the comment to
accurately describe the actual behavior: field-level #[serde(default)]
handles missing keys, but unknown variant strings will error.
Signed-off-by: Devin AI <devin@devin.ai>
Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
* perf(compositor): hoist ellipse AA constants out of rotated blit hot loop
ellipse_sx, ellipse_sy, aa_band, and aa_inner only depend on the
destination rect dimensions (rw/rh) which are loop-invariant. Move
them before the per-row closure, matching the axis-aligned path which
already hoists these correctly.
Signed-off-by: Devin AI <devin@devin.ai>
Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Co-Authored-By: Claudio Costa <cstcld91@gmail.com>
---------
Signed-off-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: StreamKit Devin <devin@streamkit.dev>
Signed-off-by: Devin AI <devin@devin.ai>
Co-authored-by: StreamKit Devin <devin@streamkit.dev>
Co-authored-by: Claudio Costa <cstcld91@gmail.com>1 parent 3b5f4cd commit 7d3af2f
File tree
19 files changed
+631
-27
lines changed- crates
- engine/benches
- nodes/src/video
- compositor
- pixel_ops
- samples/pipelines/dynamic
- ui/src
- components
- hooks
- nodes
- types/generated
19 files changed
+631
-27
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
120 | 120 | | |
121 | 121 | | |
122 | 122 | | |
| 123 | + | |
123 | 124 | | |
124 | 125 | | |
125 | 126 | | |
| |||
414 | 415 | | |
415 | 416 | | |
416 | 417 | | |
| 418 | + | |
417 | 419 | | |
418 | 420 | | |
419 | 421 | | |
| |||
429 | 431 | | |
430 | 432 | | |
431 | 433 | | |
| 434 | + | |
432 | 435 | | |
433 | 436 | | |
434 | 437 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
14 | 35 | | |
15 | 36 | | |
16 | 37 | | |
| |||
204 | 225 | | |
205 | 226 | | |
206 | 227 | | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
207 | 232 | | |
208 | 233 | | |
209 | 234 | | |
| |||
218 | 243 | | |
219 | 244 | | |
220 | 245 | | |
| 246 | + | |
221 | 247 | | |
222 | 248 | | |
223 | 249 | | |
| |||
299 | 325 | | |
300 | 326 | | |
301 | 327 | | |
| 328 | + | |
| 329 | + | |
302 | 330 | | |
303 | 331 | | |
304 | 332 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
218 | 218 | | |
219 | 219 | | |
220 | 220 | | |
| 221 | + | |
| 222 | + | |
221 | 223 | | |
222 | 224 | | |
223 | 225 | | |
| |||
252 | 254 | | |
253 | 255 | | |
254 | 256 | | |
| 257 | + | |
255 | 258 | | |
256 | 259 | | |
257 | 260 | | |
| |||
269 | 272 | | |
270 | 273 | | |
271 | 274 | | |
| 275 | + | |
| 276 | + | |
272 | 277 | | |
273 | 278 | | |
274 | 279 | | |
| |||
361 | 366 | | |
362 | 367 | | |
363 | 368 | | |
364 | | - | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
365 | 373 | | |
366 | 374 | | |
367 | 375 | | |
| |||
446 | 454 | | |
447 | 455 | | |
448 | 456 | | |
| 457 | + | |
449 | 458 | | |
450 | 459 | | |
451 | 460 | | |
| |||
464 | 473 | | |
465 | 474 | | |
466 | 475 | | |
| 476 | + | |
467 | 477 | | |
468 | 478 | | |
469 | 479 | | |
| |||
482 | 492 | | |
483 | 493 | | |
484 | 494 | | |
| 495 | + | |
485 | 496 | | |
486 | 497 | | |
487 | 498 | | |
| |||
505 | 516 | | |
506 | 517 | | |
507 | 518 | | |
| 519 | + | |
508 | 520 | | |
509 | 521 | | |
510 | 522 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
| 73 | + | |
73 | 74 | | |
74 | 75 | | |
75 | 76 | | |
| |||
84 | 85 | | |
85 | 86 | | |
86 | 87 | | |
| 88 | + | |
87 | 89 | | |
88 | 90 | | |
89 | 91 | | |
| |||
152 | 154 | | |
153 | 155 | | |
154 | 156 | | |
| 157 | + | |
155 | 158 | | |
156 | 159 | | |
157 | 160 | | |
| |||
164 | 167 | | |
165 | 168 | | |
166 | 169 | | |
| 170 | + | |
167 | 171 | | |
168 | 172 | | |
169 | 173 | | |
| |||
185 | 189 | | |
186 | 190 | | |
187 | 191 | | |
| 192 | + | |
188 | 193 | | |
189 | 194 | | |
190 | | - | |
| 195 | + | |
191 | 196 | | |
192 | 197 | | |
193 | 198 | | |
| |||
219 | 224 | | |
220 | 225 | | |
221 | 226 | | |
| 227 | + | |
222 | 228 | | |
223 | 229 | | |
224 | 230 | | |
| |||
232 | 238 | | |
233 | 239 | | |
234 | 240 | | |
| 241 | + | |
235 | 242 | | |
236 | 243 | | |
237 | 244 | | |
| |||
772 | 779 | | |
773 | 780 | | |
774 | 781 | | |
| 782 | + | |
775 | 783 | | |
776 | 784 | | |
777 | 785 | | |
| |||
0 commit comments