Commit Graph
25 Commits
Author SHA1 Message Date
JonRC d0e7e09ecb Export: write a colr atom in ProRes MOVs (#2801)
ProRes renders had no colr atom, so the stream reported no primaries,
transfer or matrix. Write an nclc atom, as FilmCraft does for MOV, with
the codes of what the render path makes: the project's output space when
it has a working space, BT.709 otherwise.

sRGB output stays at transfer 1, which is still open on #340 and #464.
The frames don't change, so the pinned ProRes bytes move by exactly the
atom's 18 bytes.
2026-11-01 22:28:23 -03:00
bflatastic a3f9e0d024 Merge remote-tracking branch 'origin/main' into HEAD 2026-10-30 09:01:05 +07:00
bflatastic 1b6cc9a1f1 Merge remote-tracking branch 'pr/2623' into HEAD 2026-10-30 08:58:42 +07:00
erythrofr f6222ff5d5 Tests: document crop/resize regressions
Describe the dimension, pixel-preservation and extreme-input scenarios and
their synthetic-frame helper to address the review's documentation warning.
Test logic and the crop/resize implementation are unchanged.

AI assistance: OpenAI Codex (GPT-6).
2026-10-30 02:47:31 +01:00
bflatasticandClaude Opus 5.5 eedd1dfaae Merge main into #1736; clean merge, no conflicts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 07:42:03 +07:00
bflatasticandClaude Opus 5.5 0bb52bb8ff Merge main into #2623; clean
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 07:38:57 +07:00
erythrofr 63ec5f2aad Export: apply crop once when calculating resize dimensions
Calculate frame_size from the original rendered dimensions and effective
render scale before cropping, so locked-aspect resize does not apply the
crop margins a second time in its dimension calculation.

Add dimension and decoded-PNG regressions for crop, resize, padding, scaled
ROI, both interpolation qualities, and zero or extreme requested sizes.

AI assistance: OpenAI Codex (GPT-6).
2026-10-30 00:39:56 +01:00
bflatastic 0039081952 Merge main into #2567; keep both test modules, and convert four layer stacks main's new render tests assign as Vec<Layer> with .into() 2026-10-30 06:01:06 +07:00
tylerjenningsw c9a91d9ddf Merge remote-tracking branch 'origin/main' into pr1736-avi-backend 2026-10-29 18:49:01 -04:00
tylerjenningsw 4daff9a74a Export tests: say why the H.264 pin moved with FilmCraft 09aaf9b (#1701) 2026-10-29 18:20:09 -04:00
BFlat 07d1de1764 Merge pull request #2534 from klosixgaming-arch/fix/2022-render-banding
export: dither 16/32 bpc renders on the way to 8 bits, and let Render Settings Color Depth set the render's depth (#2022)
2026-10-30 05:09:48 +07:00
tylerjenningsw 393a7aa565 Export tests: pin the H.264 bytes FilmCraft 09aaf9b writes (#1701)
The encoder's first-frame user_data_unregistered SEI now lists its settings
("... - options: rc=vbr bitrate=10000 ... scenecut=1", 211 bytes where
"filmcraft-h264enc 0.1.1 - clean-room H.264 encoder" took 50): +161 bytes.
The same build gives (104322, 11051847956767423392), the pin Linux CI took on
a base before the 19-byte nclx colr box, when that box is left out, so the
bytes match across platforms.
2026-10-29 17:57:08 -04:00
tylerjenningsw 3390e2fff7 Merge remote-tracking branch 'origin/main' into pr1736-avi-backend
# Conflicts:
#	crates/media/src/pool.rs
2026-10-29 17:11:16 -04:00
BFlat b669e4a951 Merge pull request #2476 from ashokram-si/feat/targa-sequence-output
Export: Targa (.tga) sequence output, 24-bit RGB or 32-bit RGB + Alpha
2026-10-30 01:19:27 +07:00
bflatasticandClaude Opus 5.5 3f00560f00 Export tests: re-pin the H.264 MP4 bytes for its BT.709 nclx colr box (+19 bytes)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 01:10:42 +07:00
Kaedo17 123095b6df export: tag BT.709 limited-range nclx; the ffmpeg oracles pick decoders by name and skip unbuildable fixtures
- Exported HEVC/AV1 nclx says BT.709 and limited range where the pipeline
  means it, matching what the players we tested assume; the round-trip
  tests pin the box values.
- The ffmpeg oracle helpers no longer read the flags column of
  `ffmpeg -decoders` for "is a decoder" — every row of that listing is a
  decoder, and the trailing D there is "supports direct rendering method
  1", which a build's hevc decoder may legitimately lack. Decoders are
  matched by the codec-name column alone.
- Fixtures a given ffmpeg build cannot actually encode (a listed encoder
  that fails at run time: hardware backends without their device, the
  noopenh264 stub) skip with a note instead of failing the run.
2026-10-30 01:30:53 +08:00
Claude 85e061fe0c Merge main into fix/2022-render-banding (#1631)
Resolve the export tests' module list (banding and h264_gpu_yuv both stay). #1631's
yuv420_frame checked Render Settings Color Depth itself; that depth is now the project's
depth for the whole render, so the GPU YUV path is taken only for 8 bpc renders. Above
8 bpc frames take the RGBA path, which dithers, so H.264 exports don't band either.
Test: renders_above_8_bpc_skip_the_planes.
2026-10-29 03:06:31 -05:00
Eduardo EspinosaandClaude Opus 5.5 e1d66a3c5c perf: share unchanged layers between undo states
Every undoable edit keeps the previous project for undo, so the comp it touches
is shared and Arc::make_mut deep-copies it: every layer and every keyframe. An
edit therefore costs time in proportion to the comp's size, and a script that
sets many keyframes in a big comp goes quadratic (a 1,600-layer build with
~100k sampled keys took ~45 minutes).

Comp::layers is now a Layers collection backed by Vec<Arc<Layer>>: copying the
stack copies pointers, and only the layer an edit changes is copied. The API
mirrors Vec<Layer>; serialized form is unchanged (a list of layers).
Comp::layer_mut and the iter_mut().filter/find call sites use find_mut /
iter_mut_where so they copy only the layers they actually change.

- prop.addKey in a 400-layer comp: 1.36 ms -> 0.16 ms per key (flat in comp size)
- the 1,600-layer script build: ~45 min -> 47 s, frames pixel-identical
- regression tests: an edit leaves the other layers shared with undo; layers
  round-trip as a plain list

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VkpGcKfWyCudfSsQNiWAaG
2026-10-28 22:20:23 -04:00
Matej Kozlovský 6e69b91a80 Export: H.264 frames convert to YUV 4:2:0 on the GPU
Accelerator::comp_frame_yuv420 (default None) renders a top-level comp frame and
converts it over the background to the H.264 export's 8-bit BT.709 limited-range
4:2:0, every byte within one level of the CPU conversion (the GPU kernel follows
it operation for operation, including NaN and half-away-from-zero ties, but a
driver may contract its arithmetic). A 4K frame then reads back 12 MB of planes
instead of 133 MB of RGBA f32.

The H.264 export asks the accelerator for planes when a frame needs nothing after
the render (progressive, project depth, no crop/resize, rendered at the output
size) and otherwise renders and converts on the CPU as before. Deferred
readbacks (a browser worker) keep the pass-based path. Sizes the kernel can't
take (width not a multiple of 8, odd height) are declined before any GPU work.

Like Cx::frames, h264_frames caps GPU frames in flight only while the
accelerator is up (map_frames_while with the same liveness check): once the GPU
stops for good, the remaining frames render on the CPU side by side instead of
one at a time.

rgba_to_yuv420 moves to effectcraft_raster::yuv so the export and the GPU tests
share one reference. The GPU tests skip without an adapter (tests::gpu()), as
the crate's others do.
2026-10-28 13:19:24 +01:00
Dylan M. Taylor 072f2619bd Refactor export for strict Clippy checks 2026-10-28 06:09:21 +00:00
Claude fa14090e72 G1: dither the final 8-bit conversion so gradients don't band (#2022)
Exports converted the float frame to 8 bits by plain rounding, so a smooth
gradient rendered at 16 or 32 bpc came out as flat bands, the same as at
8 bpc: raising the depth changed nothing visible. After Effects dithers
colours converted to 8 bpc for render and export; do the same.

- raster: dither_u8 and Image::to_rgba8_dithered / to_rgba8_over_dithered
  round each channel up or down against a hash of the pixel position with
  a fixed seed (deterministic, no clock or global RNG). A value already on
  an 8-bit code, as everything rendered at 8 bpc is, is unchanged.
- export: Cx::pixels dithers the colour for every 8-bit output (stills,
  H.264, ProRes, HEVC, AV1, VP9); GIF keeps plain rounding (palette).
- export: the Render Settings' Color Depth now overrides the project's
  depth for the whole render instead of only quantising the finished
  frame, so a 16 bpc render of an 8 bpc project keeps its precision.

Tests: crates/export/tests/it/banding.rs (ramp export at 8/16 bpc and with
Color Depth overrides), raster unit tests for dither_u8.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYXhNN7W7nB6sKjwwU7CDM
2026-10-27 15:38:08 -05:00
NetterSilverandClaude Opus 5.5 94399e62ff Pin movie export bytes
H.264 and ProRes exports of a 60-frame comp (several render batches, a
rotating stroked ring, a fading solid at a fractional position, a
Screen-mode shape, 8 bpc) must keep the exact bytes main wrote before the
two previous commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:40:41 +01:00
ashokram-si c51a08ceb4 Export: Targa (.tga) sequence output, 24-bit RGB or 32-bit RGB + Alpha
After Effects lists Targa among its still-image output formats; EffectCraft
imported Targa (#745) but could not render to it.

- OutputFormat::TargaSequence ("Targa Sequence", `.tga`, numbered like the
  other sequences; `tga` / `targa` as a format name or output extension).
- Written by the `image` crate's Targa encoder (its `tga` feature, already
  enabled in effectcraft-media; no new crates, Cargo.lock unchanged), with
  run-length compression off: an 18-byte header, top-left origin, 24-bit BGR
  for RGB, 32-bit BGRA with 8 alpha bits in the image descriptor for
  RGB + Alpha (straight or premultiplied), 8-bit grey for Alpha.
- The render queue's size estimate counts the uncompressed bytes.
- CLI usage, the renderQueue command specs, README, architecture.md and
  file-format-parity.md name the new format.

Tests: each Targa frame holds exactly the pixels of the PNG sequence of the
same job, with the expected header, numbering and size; the frames read back
through the Targa importer as the same picture (straight, and premultiplied
when interpreted so); the image-sequence round trip, the format parser and
the renderQueue commands cover it too.
2026-10-26 15:34:12 +05:30
tylerjenningsw 42b44c460a Merge main into enhance/filmcraft-avi-backend 2026-10-25 14:13:46 -04:00
aiongg 0173abde8c CI: dev-profile gate, one test binary per crate, nextest, line tables only (#2235)
* Dev profile: line tables only for workspace crates, no debug info for dependencies

* xtask ci: dev-profile gate, nextest, tests without examples, wasm --keep-going

* One integration-test binary per crate

* xtask ci: run effectcraft-gpu's shared-device tests in one cargo test process

* xtask ci: run every stage and report all failures

* xtask ci: name the stage type (clippy type_complexity)

* xtask ci: run every test pass and report all failures

* cargo fmt
2026-10-23 12:59:51 -04:00