- RenderManager: GPU-side members (context_, decoder_cache_,
shader_cache_, auto_cacher_, worker_pool_, decoder_clear_timer_) were
left uninitialized when the configured graphics backend is unknown
(e.g. dummy); ViewerWidget then dereferenced garbage and crashed.
Initialize them at declaration
- CurveView::SelectKeyframesOfInput ignored its reference parameter and
selected keyframes of every connected track; select only the
requested track's keyframes
- SeekableWidget::SeekToScenePoint dereferenced GetViewerNode()
unconditionally; skip the playhead update when no viewer is connected
- LoadOTIOTask: unknown root schema leaked the freshly allocated
project_ (delete + reset; OTIO is not enabled in local builds so this
file is compile-verified by inspection only)
Locked by new tests: RenderManagerDummyBackend,
TimeRuler.SeekToScenePointWithoutViewerIsNoOp,
CurveViewTest.SelectKeyframesOfInputSelectsOnlyRequestedTrack
- all 19 panel classes: construction, titles, context/signal wiring,
save/load data round-trips
- MainWindowLayoutInfo XML round-trip, MainStatusBar, offscreen
MainWindow construction with standard panels and menus
- RatioDialog parsing (decimal and : / ; separators), validation
- ChromaKey tolerance inputs are now spelled "upper/lower_tolerance_in";
old projects with the misspelled "tolerence" IDs keep loading (values
and connections) via a new Node::GetInputIDForLegacyID() hook applied
in LoadInput and connection deserialization
- flip/ripple/swirl/tile/wave node IDs moved to the consistent
org.olivevideoeditor.Olive.* domain; NodeFactory::CreateFromID maps
the old org.oliveeditor.* IDs so old projects still resolve
- Regression tests: legacy ChromaKey IDs (values + connections) and
legacy factory IDs
Node core:
- MathNode/TrigonometryNode combo strings realigned with Operation enums
- mathbase scalar/vector operand pick no longer uses bitwise type checks
- NodeSetPositionAndDependenciesRecursively moves dependencies again
- RemoveAllKeyframes undo actually restores keyframes
- NodeGroup GetInputName null-deref guard, passthrough ids use input id
- NodeValueTable::Has is an exact type match; tag fallback only for
empty tags; kStrCombo/kPushButton get data type names
- delete_all_keyframes no longer loops forever on unparented keyframes;
keyframe-load failures propagate; rational interpolation falls back to
double; OpacityEffect no longer leaks its internal MathNode
Audio/footage:
- AudioVisualWaveform: GetSummaryFromTime underflow OOB read, TrimIn
prepend length bookkeeping, OverwriteSums source channel indexing
- PanNode inserts the pan value into the sample job (keyframed pan
works); OutputParamsChanged is emitted on device change; PortAudio
device indices are validated before Pa_GetDeviceInfo
- Footage: AdjustTimeByLoopMode no longer hangs/UBs on degenerate
lengths, GetStreamIndex bounds-checked, CheckFootage clears stale
state on missing files, failed probes are not cached,
FootageDescription::Load requires its own root element
Render/track:
- ViewerOutput pushes the tagged samples value; TrackList disconnects
the track-height lambda; GetTrackFromReference validity check
- RenderManager dummy backend: null-initialized threads, guarded
decoder-cache/timer paths; Renderer::Destroy releases color cache
shaders/textures; unknown dynamic backends no longer alias to oakgl
- SharedMemoryRegion POSIX attach validates segment size; ReadMessage
skips blank lines instead of failing; GC counter clamped;
IsRenderingCustomRange implemented; TimeOffsetNode gets a true
inverse OutputTimeAdjustment; zero-speed clips return the held frame
Plugin/nodes:
- OliveClip: stored default region of definition is honored, on-demand
images are cached; OliveHost sets host identity properties and logs
instead of showing modal dialogs offscreen; Plugin.h dead decls gone
- DespillNode guards graph-less use with Rec.709 fallback; description
typos fixed (despill, swirl); mosaic applies when only one axis
matches; Windows-only Project filename separator test fixed
- node_save_load_test: Node Save/Load round trips for values, keyframes,
hints, caches, connections, positions
- node_polygon_folder_test: Folder child management, PolygonGenerator
rasterization/gizmos, TextGeneratorV1/V2
- footage_probe_test: real FFmpeg/OIIO probing of demo.mp4/img.png,
metadata cache, footage state transitions
- render_tail_test: DynamicRenderer, color-context shader plumbing,
PreviewAutoCacher pause/clear paths, DiskManager edges,
AudioPlaybackCache segment I/O
Also fixes AudioPlaybackCache::WritePartOfSampleBuffer, found by the new
tests: zero padding was written via QFile::write(const char*) which
treats the buffer as a NUL-terminated string, so no padding bytes were
ever written; the write length was also computed from the segment end
instead of the range end, making WriteSilence() spin forever on an
empty buffer
- File inputs marked with the 'lut_library' property (currently the
OCIO LUT node) now show a combo box populated from the global LUT
library above the path field: pick a library LUT directly, or use
'Other (Custom File)...' with the regular path field; selections go
through the standard undoable input-change path
- Refresh zh_CN translations with lupdate and translate all strings
introduced by the proxy dialog, LUT library, LUT picker, waveform
sync and footage start time work
- Document the new per-footage custom <proxy> attributes and the
'manual' source-start-time origin in the project file reference
- Add LutFileField UI tests
- Waveform sync no longer treats uncached waveform regions as silence:
the envelope extraction now reports a per-window validity mask and the
correlation skips invalid windows on either side, improving accuracy
for partially cached clips
- Add stretch/speed sync: AudioWaveformSync::EstimateStretchAndOffset
searches a playback-rate range plus offset, and a new timeline
context action 'Synchronize by Waveform (Adjust Speed)' applies the
estimated rate as a clip speed change (with undo) when plain offset
alignment is inconclusive
- Footage properties dialog gains a Source Start Time field so the
value used by source-time sync can be viewed and edited manually
instead of relying solely on auto-detected metadata; applied via an
undo command, with Footage::ClearSourceStartTime() for removal
- Regression tests for masked correlation, stretch estimation, the
envelope validity mask, and source-start-time set/clear
- Add a global LUT library: user-configurable directories (new
Preferences > LUT tab) scanned recursively for .cube/.3dl files; LUT
node file pickers offer the library dirs as sidebar shortcuts via a
'lut_library' input property handled by the param view bridge
- OCIOLutNode no longer fails silently: missing files, unsupported
extensions and OCIO load errors are recorded in last_error() and
surfaced in the status bar (input still passes through for rendering
safety)
- ColorDialog: re-enable the display -> reference conversion using
ColorProcessor::kInverse with a validity guard, and re-enable the
Display tab in ColorValuesWidget; covered by a round-trip regression
test proving the old OCIO inverse crash no longer occurs
- OCIOGradingTransformLinearNode: enforce the OCIO clampWhite >
clampBlack invariant per frame in Value() so keyframed/connected
values cannot produce invalid grading transforms, and constrain the
white clamp UI minimum whenever the black clamp is static
- Regression tests for LUT extension checks, direction switching, node
error reporting, LUT library scanning, display inverse round-trip and
clamp enforcement
- New ProxyDialog (Tools > Proxy Settings..., plus 'Proxy Settings...'
in the project panel and timeline Proxy submenus) unifying global
proxy settings, per-footage custom presets, generation and deletion
in one place instead of three scattered entry points; this also fixes
the Tools menu action opening the wrong preferences tab
- Preferences Disk tab gains an 'include audio in proxies' checkbox and
an ffmpeg executable path field (blank = auto-detect)
- Add ProxyDialog smoke tests
- Footage can store custom proxy parameters (width/height/crf/preset/
extension/audio) that override the global settings; they are
serialized with the project and used by every generation entry point
via Footage::GetEffectiveProxyParams()
- Proxies now include the source audio streams (AAC) unless disabled;
the proxy filename records the audio flag and offline audio rendering
decodes from the proxy when present
- ProxyTask resolves ffmpeg from the new FFmpegPath config key first,
then PATH, then common install locations (e.g. Homebrew on macOS),
instead of relying on PATH only; the error message points at the
preferences when no executable is found
- ProxyTask::BuildArguments() is extracted for testability
- Add ProxyIncludeAudio and FFmpegPath config defaults
- Add regression tests for the filename audio marker, config-backed
params, ffmpeg resolution, argument building, and custom-param
persistence
The CI runner has no Vulkan runtime (liboakvulkan.so fails to load) and
no display (offscreen QOpenGLWidget cannot create a context). The
viewer display tests only checked that the parameter was "vulkan", so
they ran on the OpenGL fallback and segfaulted with no usable GL
context. Probe the backend the same way the other render test fixtures
do (load, verify the backend kind actually matches the request, init)
and skip when it is unavailable. Also replace the stale "temporary
scratch test" file header now that this is a committed regression test.
Ubuntu (FFmpeg 7.0) build failure: the public FB_PIX_FMT_* values were
hardcoded to AVPixelFormat enum values, but those shift between FFmpeg
releases (new formats are inserted mid-enum: X2RGB10 in 7.0,
RGBF16/GRAYF16 later), so the static_asserts in internal.h failed and
RGBF16LE/GRAYF16LE did not exist at all.
The FB pixel format values are now fixed identifiers translated inside
the library by pixel format name (stable across releases):
- fb::PixFmtToAV/PixFmtFromAV resolve the static table by name;
formats a decoder produces that have no static identifier (hardware
downloads like nv12/p010le/p210le) receive process-local dynamic ids
>= 1000 so they keep round-tripping through the API (scaler etc.)
instead of collapsing to NONE and crashing sws.
- All crossing points translated: scaler, frame get/set format,
decoder/probe stream info, encoder config and write_video_frame,
fb_pix_fmt_* utilities, fb_find_best_pix_fmt_of_list (which also
reinterpret_cast the caller's list; now translated element-wise and
properly NONE-terminated).
- nv12 and p010le get static identifiers as the common hardware
download formats.
- Hardware frame detection no longer compares pixel formats (breaks
across format spaces); it uses the existing fb_frame_is_hw().
macOS test failures (FFmpegBridgeEncoder.WritePngVideoAndProbeBack,
WritePcmAudioAndProbeBack): config.filename held a dangling pointer to
a temporary QByteArray (UB; happened to work on Linux). Keep the
QByteArray alive for the encoder's lifetime.
Windows (MSYS2 UCRT64) build failure: timecodefunctions.h used int64_t
without including <cstdint> (previously pulled in transitively).
Full gtest suite: 584 passed.
ClipBlock::kBufferIn is declared as NodeValue::kNone with no value
hint, so when a footage node is connected straight to a clip's buffer
input (no effect node in between), the traverser has no type to look
up in the footage's value table and falls back to its last entry. A
footage pushes its video texture first and its audio samples last, so
a video clip ended up fed with audio samples, produced no texture and
the preview went silently black. With any node in between, the table
only carries the passthrough texture, which is why the bug only showed
on direct connections.
Make Node::GetValueHintForInput virtual and override it in ClipBlock
to prefer the value type matching the clip's track (kTexture on video
tracks, kSamples on audio tracks).
Regression tests cover the exact application render path
(PreviewAutoCacher -> RenderManager -> RenderWorkerPool ->
oak-render-worker) for both the direct and indirect cases, the hint
following the track type, and viewer display widgets. The direct-case
test reproduces the black frame without the fix and passes with it.
Full suite: 584 passed.
- Replace direct FFmpeg usage in the test suite (channel layout masks,
pixel/sample format constants, AVFrame field access, sws_scale) with
the bridge equivalents and the olive::AVFrame adapter
- Drop CoreRational.ToAVRational (API removed with core's FFmpeg
dependency) and the GetSwsColorspaceFromAVColorSpace tests (helper
moved inside the bridge)
- New ffmpeg_bridge_test.cpp exercises the C API directly: constants vs
core, error strings, pixel format utilities, frames/packets, scaler,
resampler, audio graph tempo processing, probe/decoder round-trip on
tests/demo.mp4 (including hw-frame transfer), SRT subtitle reading,
and encoder end-to-end tests (PNG video and PCM audio probed back)
Run clang-format over all project C/C++ source and header files
(.c, .cpp, .cc, .h, .hpp, .hh, .m, .mm) under app/ and tests/.
Non-source files (svg, qm, qrc, etc.) were not touched.
- Rename macOS bundle output from Olive.app to Oak.app.
- Rename editor binary to oak-editor and render worker to oak-render-worker.
- Rename crash handler output to oak-crashhandler.
- Update worker lookup, NSIS installer, Linux desktop/AppRun, crashhandler
symbol paths, and documentation for the new binary names.
- Update CD workflow paths and add -qmldir flags to macdeployqt so QtQuick
/ QML plugins required by KDDockWidgets are bundled, fixing the launch
crash on macOS.
- Update user-facing GitHub URLs to OakVideoEditorCommunity/oak.
- RenderWorkerFootageTest: skip when the dynamic render backend is not
built; we cannot verify backend availability without it, and the tests
fail on headless/GPU-less CI runners.
- NodeProject.FilenameAndNameUpdate: use a plain filename instead of
/tmp/... so the expected name does not depend on POSIX temp paths or
Windows backslash normalization.
- Make olive-editor depend on olive-render-worker on all platforms so the
worker is always built with the main app.
- Copy olive-render-worker and dynamic render backends (oakgl, oakvulkan)
into the macOS app bundle next to the executable.
- Include oakgl.dll and oakvulkan.dll in the Windows NSIS installer.
- Fix PluginSmokeThread.ConcurrentParamAccess CI failure by adding a mutex
around IntegerInstance's no-node fallback storage and serializing the
test's set/get pair.
- Hide the render worker's Dock icon on macOS via
NSApplicationActivationPolicyProhibited.
Renderer / preview:
- Switch the preview/display readback format from F16 to packed
10-bit RGBA (PixelFormat::U10) to halve GPU->CPU/IPC bandwidth
while keeping 10-bit panel precision.
- Add U10 support to VideoParams, FFmpeg/OIIO/OCIO utility mappings,
OpenGL (GL_RGB10_A2), Vulkan (VK_FORMAT_A2B10G10R10_UNORM_PACK32),
and plugin bit-depth lookups.
- Update preview autocacher comment to reflect the new behavior.
OCIO LUT tests:
- Add four E2E-style ColorLutNode gtests that drive a SolidGenerator
-> OCIOLutNode graph through NodeTraverser and compare resulting
pixels on the CPU. They cover forward/inverse transforms and verify
that switching LUT direction and LUT file updates both the processor
and the output pixels.
Cleanup:
- Remove a leftover SolidGenerator::Value debug fprintf.
- Capture render worker stderr in RenderWorkerFootageTest for better
diagnostics.
- Pass through input texture when the LUT processor is not ready yet,
preventing black frames while the processor is being generated.
- Serialize processor generation with a single in-flight task to avoid
concurrent OCIO lock contention that could freeze the UI.
- Invalidate cached frames after the async processor is set so the viewer
refreshes automatically without requiring the playhead to be moved.
- Add OAK_DISABLE_HWACCEL environment variable to force software decoding.
- Add FFmpegDecoderHW regression test for H.264 4:2:2 10-bit decoding.
- Add shared UBO layout across vertex + fragment stages so vertex
uniforms like ove_mvpmat compile and bind correctly.
- Rewrite uniform extraction/injection to avoid corrupting the UBO
block and to keep explicit sampler bindings stable.
- Make the UBO and sampler descriptor bindings visible to both vertex
and fragment stages.
- Add layout locations for vertex varyings (ove_texcoord) and fragment
inputs so SPIR-V generation succeeds.
- Extend TransitionImageLayout() to cover all layout pairs used by
upload/download/clear/blit.
- Add subpass dependencies to the cached render pass and leave
destinations in SHADER_READ_ONLY_OPTIMAL after Blit().
- Move descriptor allocation before command recording and abort cleanly
if allocation fails; switch Blit() to the persistent linear sampler.
- Add a gtest that creates a Vulkan backend, uploads a red U8 RGBA
texture, blits through the default pass-through shader, and verifies
the downloaded pixel is red. This test passes on the current system.
ctest passes 4/4; DynamicRenderBackend.* passes 3/1 (Vulkan fallback
skipped because Vulkan is available).
- Add PickRenderableFormat / IsColorAttachmentSupported so 3-channel
Vulkan formats fall back to 4-channel when unsupported.
- Make oakvulkan target and C ABI check conditional on Vulkan_FOUND;
skip liboakvulkan build/dependencies when Vulkan headers/libs are
absent.
- Update Preferences tooltip to reflect Vulkan is an experimental
prototype that may fall back to OpenGL.
- Revise dynamic backend plan doc: phase 3/4/5 described as prototype
frameworks with runtime validation pending, and list recent Vulkan
fixes (init idempotency, descriptor/sampler lifetime, dynamic
viewport/scissor, render pass clear, format probing).
Both OAK_ENABLE_DYNAMIC_RENDER_BACKEND=ON and OFF configurations
build and pass ctest (4/4).
- Extract libolive-rendercore static library to minimize backend link boundary.
- Add DynamicRenderer adapter with C ABI (oakgl/oakvulkan shared libs).
- Make OAK_ENABLE_DYNAMIC_RENDER_BACKEND default ON with OpenGL fallback.
- Implement VulkanRenderer prototype (textures, shaders, UBO blit, readback).
- Add backend-neutral viewer readback path (offscreen -> QImage -> QPainter).
- Refactor PluginRenderer to be renderer-agnostic; OFX plugins fall back to CPU
path on non-OpenGL backends while preserving OpenGL render path.
- Add Renderer::AttachOutputTexture/DetachOutputTexture and C ABI forwards.
- Update docs/zh/render-backend-dynamic-plan.md for Phase 3/4/5.