Commit Graph
333 Commits
Author SHA1 Message Date
Brandon ThomasandClaude Opus 5.5 5d7cc4ef66 Licensing: standard LICENSE files, NOTICE, ArtCraft brand terms
- LICENSE-MIT / LICENSE-APACHE from the Crafting Apps standard (copyright "ArtCraft Team and the
  FilmCraft contributors"; Apache text in the canonical apache.org layout)
- NOTICE (new): license, brand carve-out, third-party list from ATTRIBUTION.md
- docs/brand/LICENSE-brand.txt (new): ArtCraft brand terms; brand sidecars, ATTRIBUTION.md and
  AGENTS.md §1.8 point to it (owner "ArtCraft Team"; forks and modified versions remove the marks)
- README: "## License and credits" section per the standard (absorbs "Credits and clean room"),
  badge anchor #license-and-credits, alt text "License: MIT OR Apache-2.0"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:05:12 -04:00
Brandon ThomasandClaude Opus 5.5 f3f603a934 Rules: never panic — Result<T, E> everywhere, no unchecked indexing / zero division on untrusted input, background threads catch panics, fuzz parsers (AGENTS.md §3.1, CLAUDE.md, contributing)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:13:08 -04:00
Brandon Thomas 0fb2ba99ca Merge PR #4 from storybored379
Control: screenshots and ui.elements wait for the UI to settle
2026-10-04 02:51:55 -04:00
Brandon Thomas 3b33cb36c3 Merge PR #3 from storybored379
Timeline: fit a new empty sequence again when its first clip arrives
2026-10-04 02:51:24 -04:00
Brandon Thomas 8d7503ceae Merge PR #2 from storybored379
Media: apply the container's display rotation (portrait phone video)
2026-10-04 02:51:19 -04:00
Brandon Thomas 52b51f9784 Merge PR #1 from storybored379
Sequences: refuse a zero or negative frame rate instead of panicking
2026-10-04 02:51:16 -04:00
Brandon ThomasandClaude Opus 5.5 919d54fffc Test: ui.elements answers within a few frames once the timeline is at rest, after zooming and scrolling
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 02:50:17 -04:00
Brandon ThomasandClaude Opus 5.5 969aae8fad Test: later clips keep the user's zoom once the sequence has content (only the first clip into an empty sequence re-fits)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 02:50:17 -04:00
storybored379andClaude Opus 5.5 b215bc2b46 Control: screenshots and ui.elements wait for the UI to settle
Over the control channel (MCP bridge mode) agents read the live app with
ui.screenshot / render_frame and ui.elements right after an edit, and got
pictures of a state that was still changing:

- render_frame in bridge mode moves the playhead and screenshots the
  Program monitor. After a seek the monitor shows the nearest cached
  picture until the exact frame is decoded, so a deep seek into a long
  file returned the previous picture (even the previous sequence's).
- ui.elements answered while the timeline zoom was still animating (the
  fit after opening a sequence), with clip rects that moved afterwards.

Screenshots are now taken once paused monitors show their exact frames
and the timeline zoom is at rest (at most 5 s, then whatever is there).
ui.elements retries until the zoom has been at rest for two frames: it
answers from the frame before the last one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 02:50:17 -04:00
storybored379andClaude Opus 5.5 883e2caaa4 Timeline: fit a new empty sequence again when its first clip arrives
Opening a sequence fits the timeline once, on the first frame. An empty
sequence fits its 1 s minimum duration, so clips added afterwards (File
> New Sequence then a drag, an insert, or timeline.place over the
control channel) showed at frame-level zoom: the first clip filled the
whole track and the rest were off screen.

The zoom an empty-sequence fit chose is remembered; when the sequence
gets content and the zoom is still that value, the timeline fits again.
A zoom changed in between is kept.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 02:50:17 -04:00
Brandon ThomasandClaude Opus 5.5 e2afbed6c2 Tests for display rotation: Matroska roll → quarter turns (incl. flips, odd and malformed angles), MP4 mirrored/scaled matrices
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 02:50:16 -04:00
Brandon ThomasandClaude Opus 5.5 6f4cc47716 Tests for frame-rate validation: real rates still accepted, rates that round to zero refused without side effects
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 02:50:16 -04:00
storybored379andClaude Opus 5.5 27a1f78df7 Media: apply the container's display rotation (portrait phone video)
Phones record portrait video as landscape pictures plus a rotation in the
container: the MP4/MOV tkhd matrix (ISO/IEC 14496-12 §8.3.2) or the
Matroska Projection pose roll (RFC 9559 §5.1.4.1.28.46). The matrix was
parsed but never used, so every portrait iPhone clip imported sideways
at its landscape size.

- isobmff: Track::display_rotation() reads 0/90/180/270° from the matrix
  signs (mirrored / sheared matrices are left alone).
- matroska: parse Projection (type, yaw, pitch, roll);
  VideoInfo::display_rotation() for rectangular projections.
- frame: VideoFrame::rotated() turns every plane at its own resolution
  (4:2:2 chroma is widened to 4:4:4 for quarter turns) and swaps the PAR.
- codecs: Mp4Source / MkvSource report the displayed size and PAR, and
  GopCache rotates decoded frames before caching them.
- web: the WebCodecs source configures the decoder with the coded size
  and rotates its output the same way.

Tests: a one-frame ProRes MOV built in the test with 0/90/180/270°
matrices (reported size + which half ends up on top), plane rotation for
RGBA / 4:2:0 / 4:2:2, and a synthetic Matroska file with a -90° roll.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 02:50:16 -04:00
storybored379andClaude Opus 5.5 a1f3919ffd Sequences: refuse a zero or negative frame rate instead of panicking
file.newSequence and sequence.settings accepted fps 0 (or a negative
rate). The next frame computation divided by zero; over MCP the panic
poisoned the session lock and every later call failed with "session lock
poisoned" until the server was restarted, losing unsaved work.

Both commands now reject rates whose frame duration is not positive.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 02:50:16 -04:00
Brandon Thomas 905ab40480 Merge branch 'main' into integrate2 2026-10-04 00:26:25 -04:00
Brandon ThomasandClaude Opus 5.5 fafd82b6ec Crash and blank-screen fixes (desktop + web)
Desktop/shared:
- Frame workers catch panics per job: a failing decode/render no longer kills the worker
  or leaves its frame in flight forever (blank monitors). Counted as perf.stats failedJobs.
- UI pass catches panics and shows a "FilmCraft hit an error" window (Save Project /
  Continue) instead of closing the app.
- Panic hook writes <data dir>/Logs/crash-<day>.log with thread, location and backtrace;
  a window that can't start shows an error dialog instead of exiting silently.
- GPU compositor only on adapters that render/blend Rgba16Float with >= 4096 textures;
  GPU validation errors and oversize frames switch to the CPU compositor instead of
  wgpu's default panic.
- Dock layout and Media Browser splitter no longer panic on tiny panels/windows.

Web:
- Export mode / previews / voice-over / log reveal no longer call std::env::temp_dir
  (panics on wasm32): new filmcraft_engine::temp_dir(); default export dir /exports.
- Fatal-error overlay with Reload; WebGPU device failure retries on WebGL2 (?webgl);
  cache-busted wasm/glue URLs; webcodecs entries[0] guard.

Tests: robustness_ui (worker survives injected panics, UI panic recovery, tiny windows),
crash hook, dock split, GPU plan size, default export dir; web smoke test extended.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 00:26:19 -04:00
Brandon Thomas 879be680d0 Merge branch 'worktree-agent-af7195a2c4c71a574' into integrate2 2026-10-03 19:00:14 -04:00
Brandon ThomasandClaude Opus 5.5 333cc3fdf4 M8.10: HDR metadata field in the AAF test media info from main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:52:34 -04:00
Brandon ThomasandClaude Opus 5.5 666eeab050 M4.10: merge main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:50:04 -04:00
Brandon Thomas 0948dcf682 Merge branch 'main' into M3.13/M8.10 2026-10-03 11:50:01 -04:00
Brandon ThomasandClaude Opus 5.5 a27b50aa5d ROADMAP: ~87% after AAF/OMF and MXF export; 1605 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:04:57 -04:00
Brandon ThomasandClaude Opus 5.5 eaed9dbef6 Cargo.lock: filmcraft-cfb at 0.1.1 after merging the release bump
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:03:49 -04:00
Brandon Thomas b48c558e9e Merge branch 'main' into worktree-agent-a861ca53f77717930 2026-10-03 11:02:40 -04:00
Brandon ThomasandClaude Opus 5.5 8e6b273eba M4.10: merge main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:52:21 -04:00
Brandon ThomasandClaude Opus 5.5 32f4471e7b M4.10: before / after results in docs/performance.md, crate READMEs and ROADMAP
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:51:57 -04:00
Brandon ThomasandClaude Opus 5.5 2a199425d0 M8.10: HDR-aware Lumetri, mastering metadata tone-map peak, HSL Refine, Lumetri Presets grid, Comparison View match
- Lumetri grades PQ / HLG working spaces in their own signal normalised to
  HDR White (Basic Correction) / HDR Range (Curves) in cd/m²
  (filmcraft_color::GradeSpace): exposure in stops of light, highlights above
  HDR White kept, HDR Specular scales them; Rec. 709 unchanged.
- HDR static metadata (mdcv/clli, Matroska MasteringMetadata/MaxCLL/MaxFALL)
  on VideoStreamInfo::hdr; PQ media use MaxCLL / mastering peak as the
  BT.2390 source peak; media.colorInfo reports it.
- HSL Secondary Refine: Denoise (median of the key) and Blur (Gaussian).
- Lumetri Presets (18 original looks in 4 folders) with thumbnails rendered by
  our Lumetri on a procedural preview picture; Effects panel rows and a
  thumbnail grid when wide; lumetri.presets / applyPreset / presetThumbnails.
- Color Match: Comparison View toggle; Apply Match uses its reference frame.
- Goldens lumetri_hdr_pq and lumetri_presets_grid; D-Log M stays unsupported
  (no published formula).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:31:00 -04:00
Brandon ThomasandClaude Opus 5.5 468321391f M3.13: headless test of a subclip in the Source monitor and the Project panel subclip menu
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:30:59 -04:00
Brandon ThomasandClaude Opus 5.5 e7e9ebe55e Release 0.1.1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.1.1
2026-10-03 09:55:34 -04:00
Brandon ThomasandClaude Opus 5.5 c025c42470 M3.13: multicam paging beyond 16 angles, view options, Edit Cameras thumbnails; subclip trim limits and Source monitor
Multi-Camera view: automatic / 2x2 / 3x3 / 4x4 grid layouts paged when the
angles don't fit (page arrows, keys 1-9 pick cameras on the shown page),
Multi-Camera Selection Top Down, Show Multi-Camera Preview Monitor (grid
fills the monitor when off), Auto-Adjust Multi-Camera Playback Quality
(lower cell decode scale while playing), Transmit Multi-Camera View (stored,
no device yet), Edit Cameras dialog with a thumbnail per angle. Only the
shown page's angles are decoded, at the cell scale. Engine commands
multicam.gridLayout/page/nextPage/prevPage/selectionTopDown/
showPreviewMonitor/autoAdjustQuality/transmitView/grid.

Subclips: restricted subclips limit trims, rolls, slides and slips on both
sides (EditCtx::media_start); the Source monitor shows a subclip's range
(or the whole master with the range as In/Out when unrestricted), opens at
its In and shows the master clip's markers inside it (source.inspect);
Convert to Master Clip keeps the range as In/Out and the inherited markers;
Make / Edit Subclip and Convert to Master Clip in the Project panel menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 09:42:21 -04:00
Brandon Thomas 81873deedb Merge branch 'main' into worktree-agent-a861ca53f77717930
# Conflicts:
#	Cargo.toml
#	docs/architecture.md
#	xtask/src/main.rs
2026-10-03 08:55:10 -04:00
Brandon ThomasandClaude Opus 5.5 fab3a59942 ROADMAP: ~86% after MPEG-2, TS/PS and AC-3; 1562 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 08:50:56 -04:00
Brandon Thomas a0735c98f6 M4.10: merge main 2026-10-03 08:11:28 -04:00
Brandon ThomasandClaude Opus 5.5 7ce0766744 M4.10: AV1 fixed-width MC passes, recycled planes, lean mode info, draft mode; media-stack draft test
Sub-pixel filter passes run over fixed block widths; frame / region planes are recycled
through a bounded pool (zeroed on reuse) instead of fresh calloc / munmap per frame; the
palette mode-info arrays (40 bytes per 4x4) exist only when screen content tools are allowed;
CDF adaptation is branch-free. Draft mode skips deblocking, CDEF and loop restoration of shown
frames that refresh no reference slot. Media-stack test: VP9 / HEVC / AV1 draft playback only
reaches draft requests, and an export afterwards is bit-exact with ffmpeg.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 08:02:43 -04:00
Brandon ThomasandClaude Opus 5.5 c8edb9daaf M4.10: HEVC vectorised MC, SAO and output, batched bypass bins, draft mode
Interpolation keeps its reference windows in reusable scratch (no 2 x 10 KB zeroing per block)
and filters with taps outer / outputs inner over fixed block widths; SAO edge and band offsets
select the offset per lane instead of a table lookup; uni / bi output clips with min / max; runs of
bypass bins decode with one division; context-coded bins are branch-free. Draft mode skips
deblocking and SAO of sub-layer non-reference pictures of the top sub-layer. Bit-exact with 1, 3
and all threads; draft output differs only on flagged pictures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 07:38:29 -04:00
Brandon ThomasandClaude Opus 5.5 bd5f618c01 M11.4: AAF consolidated audio as OP-Atom MXF (audioFormat mxf) using the MXF writer
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 07:14:32 -04:00
Brandon ThomasandClaude Opus 5.5 1827b71891 M4.10: VP9 vectorised loop filter, column-parallel transforms, 16-bit 8-bit MC
The loop filter's lane masks are 0 / -1 integers with bitwise selects and min / max clipping
(bool masks and clamp kept it scalar); the 2D inverse transform's column pass runs the generated
butterflies on 4 / 8 columns at once; 8-bit sub-pixel filters accumulate in 16-bit lanes (every
sum of the VP9 filters fits modulo 2^16). Branch-free bool decoder update. Bit-exact; tested
against the per-column transform on random blocks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 07:12:57 -04:00
Brandon ThomasandClaude Opus 5.5 8e7eebce41 M6.6: fix the architecture crate table after merging the MXF writer
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 07:12:07 -04:00
Brandon Thomas 9ec0c7213b Merge branch 'worktree-agent-a1a2bf10c26331f84' into worktree-agent-a861ca53f77717930
# Conflicts:
#	docs/architecture.md
2026-10-03 07:11:48 -04:00
Brandon Thomas 41942e17d8 Merge branch 'main' into worktree-agent-a3c3d94e29f8131bb 2026-10-03 07:11:09 -04:00
Brandon ThomasandClaude Opus 5.5 7e16968b3a M9.15: MPEG-2 decoded frames carry the draft flag introduced on main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 05:50:54 -04:00
Brandon ThomasandClaude Opus 5.5 842801de41 M4.10: VP9 frame threading (band-published references, per-frame post stage) and draft mode
Frames are published one superblock row at a time once loop filtered; a post stage per frame
(own thread) assembles bands from the tile strips, filters them in raster order and builds the
output picture, while the next frame's tile columns decode and wait per band for the reference
rows they read. Bit-exact with 1, 3 and all threads. Draft mode skips the loop filter of frames
that refresh no reference slot. av1dec / hevcdec bench knobs and VP9 / AV1 4K playback scenarios
in the bench.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 05:34:39 -04:00
Brandon Thomas 167f971e05 Merge branch 'main' into worktree-agent-a861ca53f77717930
# Conflicts:
#	crates/ui-egui/src/panels/dialogs.rs
2026-10-03 05:04:28 -04:00
Brandon ThomasandClaude Opus 5.5 3ce2726a24 M11.4: Cargo.lock for the ui-egui interchange dev-dependency
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 05:04:00 -04:00
Brandon ThomasandClaude Opus 5.5 a96f046b34 ROADMAP: ~85% after Project panel and Media Browser parity; 1513 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 04:59:33 -04:00
Brandon ThomasandClaude Opus 5.5 6cddaf08aa M11.4: document AAF / OMF interchange and the cfb crate
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 04:55:23 -04:00
Brandon ThomasandClaude Opus 5.5 ba3695e102 M11.4: AAF / OMF export settings dialogs (File ▸ Export), AAF/OMF in File ▸ Import
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 04:54:27 -04:00
Brandon ThomasandClaude Opus 5.5 09947712d0 M6.6: MXF OP1a / OP-Atom writer and MXF export formats
filmcraft-mxf gains a streaming writer (ST 377-1 partitions, primer, header
metadata, VBR index segments with temporal offsets, RIP; ST 378 OP1a
frame wrapping, ST 390 OP-Atom clip wrapping) for VC-3, ProRes, AVC byte
stream and PCM with start timecode and caller-supplied package UMIDs, plus
write_opatom_pcm. filmcraft-export adds mxf-op1a / mxf-opatom formats
(DNxHR, ProRes or H.264 + PCM; OP-Atom writes one mono file per channel),
presets, the engine mxfVideoCodec parameter and CLI .mxf inference.
Tests read our files back and check them against ffprobe / ffmpeg.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 04:45:27 -04:00
Brandon ThomasandClaude Opus 5.5 72425d476f M11.4: file.exportAaf / file.exportOmf / file.importAaf engine commands
Premiere's AAF and OMF export options: embedded or separate WAV/AIFF audio,
sample rate and bit depth, trim with handles, rendered clip effects, breakout
to mono, AAF video mixdown and linked media; AAF/OMF import writes embedded
audio next to the document and links it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 04:43:37 -04:00
Brandon ThomasandClaude Opus 5.5 0658967a5b M11.4: AAF (Edit Protocol) and OMF 2.0 import/export in filmcraft-interchange
Shared mob-style composition model; AAF objects in structured storage over
filmcraft-cfb; OMF objects in a Bento container; embedded / consolidated audio
supplied by the caller (essence::audio_needs, MediaOptions).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 04:23:20 -04:00
Brandon Thomas 72e0dda167 Merge main into M9.15 2026-10-03 04:16:41 -04:00