7055 Commits
Author SHA1 Message Date
Mike-Solar cb7e911c35 Fix CI crash 2026-07-16 16:21:18 +08:00
Mike-Solar 9957577cb9 ffmpeg_bridge: fix cross-platform CI failures (Ubuntu/macOS/Windows)
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.
2026-07-16 08:35:19 +08:00
Mike-Solar c203ce1dbf fix: black preview when footage connects directly to a clip
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.
2026-07-16 01:06:24 +08:00
Mike-Solar e1d3019659 tests: migrate gtest suite to the ffmpeg_bridge API and add bridge coverage
- 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)
2026-07-15 23:00:13 +08:00
Mike-Solar 3a3ead6fc0 app: route all FFmpeg access through the ffmpeg_bridge C API
Replace every direct FFmpeg call in the editor and the render worker
with the pure C ffmpeg_bridge API, wrapped in thin C++ adapters that
preserve the original interfaces:

- avframeptr.h: olive::AVFrame adapter around FBFrame handles
- ffmpegutils: format conversion helpers on FB_* constants; the int
  overload is renamed GetCompatibleBridgePixelFormat to avoid a silent
  overload-resolution trap with the PixelFormat enum
- ffmpegdecoder/ffmpegencoder: rewritten as handle-based adapters over
  FBDecoder/FBProbe/FBEncoder/FBScaler/FBResampler
- audioprocessor: FBAudioGraph push/pull adapter
- pluginrenderer/OliveClip: sws/pixdesc usage converted to FBScaler and
  fb_pix_fmt_* queries
- AudioParams/channel layouts are plain uint64_t masks everywhere

Build integration: the root project no longer links FFMPEG directly;
only ffmpeg_bridge does. Binaries resolve the bridge library at runtime
via @loader_path inside the macOS app bundle (copied there post-build)
and via $ORIGIN/../ffmpeg_bridge/bin on Linux; on Windows the DLL is
installed next to the executables, so packages on all three platforms
ship the bridge library.

ffmpeg_bridge gains the extra API the adapters need:
fb_frame_make_writable, fb_decoder_get_format_duration,
fb_resampler_convert_frame, FB_PIX_FMT_YUV440P, SRT validation in
fb_probe_read_subtitle_stream, packed/planar fixes in
fb_encoder_write_audio, and a component-size fix in
fb_pix_fmt_component_size.
2026-07-15 23:00:06 +08:00
Mike-Solar ddb2b30cf4 ffmpeg_bridge: new shared library isolating all FFmpeg access behind a pure C API
The library lives outside of app/ and is the only component that includes
FFmpeg headers or links FFmpeg libraries. All objects (frames, packets,
decoder/encoder instances, scalers, resamplers, audio filter graphs) are
identified by opaque handles and never leave the library.

Public surface (include/ffmpeg_bridge/ffmpeg_bridge.h):
- FBFrame/FBPacket: AVFrame/AVPacket wrappers with field accessors
- FBDecoder: demux+decode instance with hwaccel fallback logic
- FBProbe: file probing, per-stream details, subtitle reading
- FBScaler/FBResampler/FBAudioGraph: swscale/swresample/avfilter wrappers
- FBEncoder: full export encoder (video filter graph, audio resampling,
  subtitles) ported from FFmpegEncoder
- FB_* constants mirror AV_* values, verified by static_asserts against
  the real FFmpeg headers inside the library

Two small bugs in the ported encoder were fixed: the resampler is now
properly freed with swr_free() (was re-initialized with swr_init() and
leaked), and codec option dictionaries are freed after avcodec_open2().
2026-07-15 22:07:57 +08:00
Mike-Solar 0f41620a0b core: remove direct FFmpeg dependency from libolivecore
- rational: store num/den natively instead of AVRational; math operators
  re-implemented natively (ported av_reduce/av_d2q/av_cmp_q semantics,
  verified bit-exact against FFmpeg)
- AudioParams: replace AVChannelLayout member with a plain uint64_t mask
  (new render/channellayout.h constants mirror AV_CH_LAYOUT_* values)
- Timecode: native rescale (av_rescale_q/av_rescale_q_rnd equivalents)
  with 128-bit intermediate precision
- core no longer finds or links FFMPEG::avutil

Part of the FFmpeg isolation effort: all FFmpeg access is being moved
behind a dedicated shared library (ffmpeg_bridge).
2026-07-15 21:55:11 +08:00
Mike-Solar 3be4294e15 Fix Linux audio backend preference and worker footage render crash
- On Linux, automatically prefer PipeWire/JACK/PulseAudio over ALSA
  even when a saved ALSA device name exists in config.
- Restore Footage length after deserialization so worker snapshots
  have valid stream lengths and video playback can advance.
- Guard ResolveDecoderFromInput and ProcessAudioFootage against a
  null decoder cache to prevent worker crashes on direct Footage ->
  ViewerOutput connections.
- Keep Linux signal backtrace handler in the render worker.
- Add Oak project SVG logos.
2026-07-14 22:33:30 +08:00
Mike-Solar 5c8ce17c7e submodule: change core into nomarl folder, and move KDockWidgets into third_party. 2026-07-14 15:14:29 +08:00
Mike-Solar e37a87be67 docs: Update test plan. 2026-07-13 22:01:13 +08:00
Mike-Solar 93d92c93db Merge remote-tracking branch 'origin/main' 2026-07-13 18:47:33 +08:00
Mike-Solar 8b431c941e docs: Update README.md download link 2026-07-13 18:46:54 +08:00
Mike-Solar b4b52abbd4 Remove noisy graph-snapshot logs and add waveform-sync diagnostics
- Strip the dense RenderWorkerPool debug messages about cached/stale graph
  snapshots and cleanup to reduce log spam.
- Add qDebug logging and status-bar feedback to
  TimelineWidget::SynchronizeSelectedClipsByWaveform() so we can see why the
  sync action does nothing (e.g. not enough cached clips or no usable offset).
2026-07-13 18:05:02 +08:00
Mike-Solar 7cde0b0f1a Fix invalid channel layout (0x0) in audio processor and add playback diagnostics
- Add FixChannelLayout() helper to AudioProcessor::Open() to fall back to a
  default native channel layout when the input/output layout is unspecified,
  custom, or has a zero mask. This prevents FFmpeg's abuffer/aformat filters
  from rejecting 'channel_layouts=0x0' on Linux.
- Log audio processor open parameters, viewer audio queue state, and
  AudioManager::PushToOutput device/stream status to help diagnose silent
  playback on Linux.
2026-07-13 17:46:15 +08:00
Mike-Solar c6310d104d Prefer PipeWire/PulseAudio over raw ALSA/JACK default on Linux audio devices 2026-07-13 17:24:26 +08:00
Mike-Solar e484af9a1b Merge remote-tracking branch 'origin/main' 2026-07-13 17:05:22 +08:00
Mike-Solar 536d664cbb ui+ci: style KDDockWidgets tabs and add Applications symlink to DMG
- Add explicit QTabBar::tab styles to olive-dark/style.css so inactive
  KDDockWidgets tabs render with a dark background and white text instead
  of falling back to the native macOS light tab appearance.
- Update macOS CD to stage Oak.app alongside an Applications symlink
  before creating the DMG, matching standard macOS installer disk images.
2026-07-13 16:39:49 +08:00
Mike-Solar 36f48a6a4b ci(macos): skip Qt libs in custom bundler and process all binaries
The custom Python bundling script was copying Qt framework binaries as
flat dylibs (e.g. Contents/Frameworks/QtCore) on top of the frameworks
already deployed by macdeployqt (Contents/Frameworks/QtCore.framework).
This caused duplicate Objective-C class definitions and crashes in
QAction construction.

- Skip any dependency whose basename starts with 'Qt' or 'libQt'.
- Process every binary in Contents/MacOS (main app, worker, backends).
- Fix YAML duplicate 'run:' key from the previous commit.
2026-07-13 16:17:02 +08:00
Mike-Solar 035b460c2d ci(macos): make macdeployqt verbose and verify platform plugins
- Add -verbose=2 to macdeployqt so deployment issues are visible in CI logs.
- Pass -executable for oak-render-worker so its rpaths are also fixed.
- Add a verification step that fails the build if platform plugins are missing.
- Print otool -L for both main binary and worker to aid debugging.
2026-07-13 16:12:54 +08:00
Mike-Solar a4a932238c fix(macOS): disable KDDockWidgets QtQuick frontend to resolve launch crash
Oak only uses KDDockWidgets' QtWidgets frontend. Building the QtQuick
frontend caused duplicate QML module registration when QtQuick.framework
initialized, resulting in a SIGABRT in QQmlMetaType::qmlInsertModuleRegistration.

- Set KDDockWidgets_FRONTENDS to qtwidgets in ext/CMakeLists.txt.
- Remove the -qmldir flags from macOS CD deploy since QML plugins are no
  longer needed.
2026-07-13 15:54:55 +08:00
Mike-Solar e16facf123 fix: restore Qt translation files to valid XML
The .ts files had been corrupted by an earlier formatting run that
inserted spaces into XML tags (e.g. '<?xml version = "1.0" ... ?>'),
breaking lrelease parsing. Restore all files under app/ts/ from the last
good revision before the corruption.
2026-07-13 15:35:36 +08:00
Mike-Solar f03b6b58ff style: reformat C/C++ sources and headers with clang-format
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.
2026-07-13 15:34:11 +08:00
Mike-Solar 6a696bc234 Revert "docs: update README binary link to v0.4.0-alpha"
This reverts commit 7522543c48.
2026-07-13 15:31:35 +08:00
Mike-Solar e5eeaddf2f format: reformatting files 2026-07-13 15:30:43 +08:00
Mike-Solar 7522543c48 docs: update README binary link to v0.4.0-alpha 2026-07-13 15:29:13 +08:00
Mike-Solar 64abc9cc76 docs: update CONTRIBUTING.md to Linux Kernel Coding Style
- Reference Linux Kernel Coding Style instead of Google C++ Style Guide.
- Require tabs for indentation.
- Keep Javadoc-style documentation comments.
- Preserve the original naming rules section.
- Update project name to Oak Video Editor.
2026-07-13 15:27:57 +08:00
Mike-Solar f0d41eae52 build: rebrand output artifacts to Oak and fix macOS QML deployment
- 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.
2026-07-13 15:26:15 +08:00
Mike-Solar a4a2903e49 ci: Update CI/CD to use 32x runner for Windows. 2026-07-13 15:10:48 +08:00
Mike-Solar c31415e847 build: drop lib prefix from oakgl/oakvulkan DLLs on Windows
MinGW CMake defaults to prefixing shared libraries with 'lib', producing liboakgl.dll which the dynamic backend loader cannot find. Set PREFIX empty on Windows so the output names match the runtime names oakgl.dll / oakvulkan.dll.
2026-07-13 14:56:40 +08:00
Mike-Solar 8fa32f5df4 cd: switch RPM build back to job container with pre-checkout git install
Install git in the Fedora container before actions/checkout so the checkout step can clone the repository normally instead of falling back to the REST API.
2026-07-13 14:54:35 +08:00
Mike-Solar c786469a58 cd: fix Arch tarball creation and Fedora container checkout
- Arch: create the source tarball in /tmp to avoid file changed as we read it and exclude existing tarballs from the archive.

- RPM: run the Fedora build inside docker instead of a job container so actions/checkout is not hampered by a missing Git in the base image.
2026-07-13 14:52:19 +08:00
Mike-Solar 2f0beeb7da cd: add DEB, RPM and Arch Linux packages
- Add CPack configuration in CMakeLists.txt for .deb and .rpm generation
  with declared runtime dependencies.
- Add Arch Linux PKGBUILD template under app/packaging/arch/ and build it
  inside the official archlinux:base-devel Docker container.
- Extend CD workflow with deb, rpm and archlinux jobs and attach the
  resulting packages to the draft release.
2026-07-13 14:47:46 +08:00
Mike-Solar 847abbfd5c ci: Update CI/CD to use 32x runner for Windows. 2026-07-13 14:39:30 +08:00
Mike-Solar 2e1c40af63 test: use olive-render-worker.exe on Windows in render worker footage test
QFileInfo::exists() does not auto-append .exe on Windows, so the test
failed to locate the worker binary even though it was built.
2026-07-13 14:34:05 +08:00
Mike-Solar 2a11988b77 dpcs: Update build instructions 2026-07-13 14:32:17 +08:00
Mike-Solar 43773c430a docs: update build guides for official macOS support and sync Fedora deps
- English and Chinese build.md now list macOS as a fully supported
  platform and point to the dedicated macOS build guide.
- Chinese build.md Fedora dependency list synced with English: use
  ffmpeg-free-devel and add bzip2-devel.
2026-07-13 14:29:14 +08:00
Mike-Solar e797914c62 Edit README 2026-07-13 14:25:23 +08:00
Mike-Solar 8f3c06555f test: skip worker/backend tests when GPU backend unavailable and fix cross-platform path test
- 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.
2026-07-13 14:25:02 +08:00
Mike-Solar a5c98e1297 Edit README 2026-07-13 14:23:05 +08:00
Mike-Solar 288e9050e1 fix: guard SIGPIPE ignore with #ifndef _WIN32
SIGPIPE is not available on Windows (MSYS2 UCRT64), causing a build
failure. The signal handling is only needed on POSIX systems.
2026-07-13 14:03:26 +08:00
Mike-Solar ea78558a31 render: reference-count graph snapshots to prevent premature deletion
Proxy generation modifies the project, causing graph snapshots to be
rewritten. The old implementation deleted the previous snapshot
immediately, even though queued render jobs still held its path. The
worker then failed to load the deleted file.

Add per-path reference counting:
- Increment when a job is created with a snapshot path.
- Decrement when the job is processed, cancelled or removed.
- Only delete a snapshot when its reference count reaches zero and it
  is no longer the cached snapshot for the project.

Also keep snapshots in the system temp directory as before, since the
location itself was not the bug.
2026-07-13 13:43:20 +08:00
Mike-Solar 8580542ac7 render: write graph snapshots to AppLocalData instead of system temp
The worker process on macOS could not see the graph snapshot when it
was placed in /var/folders/.../T (likely sandbox/working-directory
visibility). Write snapshots to a 'render-graphs' subdirectory of the
application's persistent data location instead, which both the editor
and the worker can access on all platforms.
2026-07-13 13:29:55 +08:00
Mike-Solar 5a5ad3bc14 render: add diagnostics for worker graph load failures
- Report QFile::errorString() when ProjectSerializer::Load() fails to open
  the graph file, so the worker log shows why instead of an empty detail.
- In olive-render-worker LoadGraph(), check file existence, size and
  readability before delegating to the serializer and log the attempt.
2026-07-13 13:25:25 +08:00
Mike-Solar 3abb4ff75b docs: update README and remove obsolete documentation/files
- Update CI badge URL to OakVideoEditorCommunity in README.
- Remove outdated TODO files, vcpkg.json, patch file and stale log.
- Clean up obsolete docs and move ofx-pluginrenderer-functions-zh.md
  into docs/zh/.
2026-07-13 13:14:37 +08:00
Mike-Solar 182bfd0aad build: bundle render worker/backends and fix concurrent param test
- 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.
2026-07-13 13:12:28 +08:00
Mike-Solar 4f23051b2b Fix waveform sync using stale selection and add Ctrl+Shift+W shortcut 2026-07-13 11:09:32 +08:00
Mike-Solar f3389fe6ba Allow waveform sync with partially cached audio and add regression tests 2026-07-13 10:54:12 +08:00
Mike-Solar 0410ff2fe7 Skip GPU-dependent tests when Vulkan/OpenGL backend is unavailable in CI 2026-07-13 10:44:27 +08:00
Mike-Solar e881bb049f Remove some logs 2026-07-13 10:29:02 +08:00
Mike-Solar 942ffd1635 test: extend coverage for file/qt/xml utilities and core audio/math
Add/extend tests for:
- FileFunctions: config/temp paths, autorecovery, directory overwrite/copy
- QtUtils: word wrap, formatted date/time, qHash for rational/TimeRange
- XMLUtils: cancel atom integration
- Core rational: construction, arithmetic, comparisons, NaN handling
- Core SampleBuffer: allocation, channel ops, volume/silence/reverse/speed

Coverage improvements:
- filefunctions.cpp: 74% -> 90%
- qtutils.cpp: 41% -> 73%
- xmlutils.cpp: 88% -> 100%
- rational.cpp: 74% -> 92%
- samplebuffer.cpp: 55% -> 96%
2026-07-13 10:19:30 +08:00