Commit Graph
1198 Commits
Author SHA1 Message Date
Mike-Solar 43599dba9e Add batch proxy menu to Project Explorer and persist Use Proxy state
The Project Explorer previously only had an old Pre-Cache submenu that
required choosing a sequence. Replace it with the same Proxy menu that
the timeline uses:

- Generate Proxy: batch-generates proxies for all selected footage items
  that have an enabled video stream, using ProxyManager and the current
  proxy settings.
- Use Proxy: checkable toggle that enables/disables proxy playback for the
  selected footage.
- Reveal Proxy / Delete Proxy: consistent with the timeline context menu.

Also make Footage::SaveCustom() write the <proxy> element whenever
proxy_enabled_ is true, even if proxy_path_ is empty, and load it back
in LoadCustom(). This preserves the user's Use Proxy preference across
project saves so it is restored on the next open.

Translation files updated with lupdate; zh_CN and zh_TW translations for
the new Project Explorer strings (and the matching timeline strings) are
filled in.
2026-07-13 10:19:30 +08:00
Mike-Solar f0119a910c Enable video auto-cache by default
- Default ViewerOutput::autocache_input_video_ to true so new sequences
  and viewer outputs use the frame cache without requiring the user to
  manually enable Auto-Cache.
- Update the DefaultSequenceAutoCache2 config default to true for
  consistency.
2026-07-13 10:19:30 +08:00
Mike-Solar 282a06b777 Default to full-resolution preview and fix audio-waveform freeze
- Use a divider of 1 (full resolution) for new sequences and for
  footage-derived viewer parameters instead of the auto-downscaling
  heuristic, so the viewer defaults to full-res preview.
- In AudioWaveformView, base the view timebase on the video frame rate
  when video is present; fall back to the audio sample rate only for
  audio-only sources. Using the audio sample rate as the view timebase
  created an enormous scene rect (time * sample_rate * scale), which
  froze the waveform view and stalled playback updates when showing
  the audio waveform.
2026-07-13 10:19:30 +08:00
Mike-Solar 51ea3ca24e Use 10-bit packed preview format and add OCIO LUT regression tests
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.
2026-07-13 10:19:30 +08:00
Mike-Solar e8443f8f8f Fix crash when toggling Use Proxy during playback and proxy generation output format 2026-07-13 10:19:30 +08:00
Mike-Solar 0969e2adc5 Add diagnostics for proxy toggle synchronization
Add temporary qDebug logging to Footage, ProjectCopier,
RenderWorkerPool, and TimelineWidget to trace why Use Proxy cannot be
 toggled and why proxy footage may still be used after disabling.
2026-07-13 10:19:30 +08:00
Mike-Solar 818b76b64e Sync Footage proxy state to render worker copy project
Proxy state (enabled/path/state/etc.) is stored as Footage member data,
not as a Node input, so ProjectCopier did not synchronize it to the
internal copy project used by worker processes. This caused toggling
Use Proxy in the UI to have no effect on rendered output.

Add a Footage::ProxySettingsChanged signal and have ProjectCopier sync
the proxy state to the copied Footage node, marking the copy project
modified so RenderWorkerPool writes a fresh graph snapshot.
2026-07-13 10:19:30 +08:00
Mike-Solar e52570c89f Add diagnostics and robust direction reading for OCIO LUT node
- Introduce ReadDirectionInput() helper that accepts both integer and
  string ('Forward'/'Inverse') representations of the direction combo.
- Log every processor creation with the raw direction value and the OCIO
  transform direction being used, along with whether it is main or worker.
- This helps determine why Forward/Inverse switching reportedly has no
  effect in the viewer/worker.

Tests still pass.
2026-07-13 10:19:30 +08:00
Mike-Solar f131abc5f7 Fix OCIOLutNode direction changes being ignored
EnsureProcessor() was returning early whenever a processor existed and
processor_dirty_ was false, without checking whether the file or direction
input had changed. As a result, switching Forward/Inverse in the main GUI
re-used the old processor and produced no visible difference.

Now EnsureProcessor() also compares the current inputs against the values
used to create last_processor_, so direction/file changes always trigger a
regeneration before the color transform job is emitted.
2026-07-13 10:19:30 +08:00
Mike-Solar ca22028a52 Defer OCIO LUT processor generation in render worker and fix stale graph snapshots
- Override OCIOLutNode::Value() to ensure the processor is created/updated
  before the color transform job is emitted.
- In the worker process, mark the processor dirty on input/config changes
  instead of creating it synchronously during LoadGraph, which blocked the
  main process waiting for the graph load acknowledgement.
- Keep eager processor generation in the main GUI process so the viewer
  cache is invalidated immediately when the LUT file or direction changes.
- Mark the ProjectCopier's internal render-proxy project as modified when
  its update queue is processed, and reset the flag after RenderWorkerPool
  writes a new graph snapshot. This fixes the worker loading a stale graph
  snapshot after switching cube files or direction, which caused the old
  LUT effect to persist.

All existing tests pass.
2026-07-13 10:19:30 +08:00
Mike-Solar a753d2f787 Always recreate LUT processor when input changes (debug)
Temporarily disable the last_path_/last_direction_ reuse check to rule
out stale processor reuse as the cause of LUT changes not appearing in
the viewer.
2026-07-13 10:19:30 +08:00
Mike-Solar 632ef5b495 Invalidate cache before cancelling tasks on LUT change
Reversing the order ensures that any render tasks that finish after the
cancel request will find the cache already invalidated, preventing stale
LUT-processed frames from being written back and shown in the viewer.
2026-07-13 10:19:30 +08:00
Mike-Solar fb50b5202e Do not block while cancelling video cache tasks on LUT change 2026-07-13 10:19:30 +08:00
Mike-Solar a4aaf10357 Use QApplication presence to detect main GUI process for LUT refresh
Checking applicationName was not reliable. The worker process uses
QGuiApplication while the main process uses QApplication, so use
qobject_cast<QApplication*> to determine whether it is safe to access
RenderManager/PreviewAutoCacher. This prevents the worker from crashing
when loading or switching LUT files.
2026-07-13 10:19:30 +08:00
Mike-Solar d83569c08e Fix worker crash when loading LUT node
The LUT processor generation was calling RenderManager::GetCacher()
during project load in the render worker, but the worker has no
RenderManager/PreviewAutoCacher. This caused a SEGV and made the main
process hang waiting for the worker. Only cancel/invalidate caches in
the main GUI process.
2026-07-13 10:19:30 +08:00
Mike-Solar 9185b6fd60 Auto-refresh viewer after LUT change without freezing
After synchronously generating the new LUT processor, cancel any
running background video cache jobs before invalidating the cache.
This prevents the preview autocacher from re-rendering the entire
timeline, which was causing the UI to freeze, while still updating
the current visible frame with the new LUT.
2026-07-13 10:19:30 +08:00
Mike-Solar d88341f9db Revert OCIO LUT processor generation to synchronous
Background generation caused the UI to freeze indefinitely when
switching LUT files, likely due to a deadlock between the worker
process, the preview autocacher, and the asynchronous set_processor
path. Synchronous generation is fast enough for typical 33^3 .cube
files and keeps the cache invalidation logic simple and safe.

The passthrough fix in OCIOBaseNode::Value() is retained so the
viewer shows the input frame while a processor is being created.
2026-07-13 10:19:30 +08:00
Mike-Solar 8636ee0dc6 Remove automatic full-cache invalidation on LUT processor change
InvalidateAll() on the OCIO LUT node caused the preview autocacher to
re-render the entire timeline, freezing the UI when switching LUT files.
Instead, let the new processor be used naturally on the next render
request (scrubbing/playback).
2026-07-13 10:19:30 +08:00
Mike-Solar 63a4008ce4 Avoid full cache invalidation in render worker after LUT processor is ready
InvalidateAll() on the OCIO LUT node triggered the worker's
PreviewAutoCacher to re-cache the entire timeline, causing the main
process to freeze while waiting for frames. Only invalidate in the
main GUI process so the viewer refreshes; the worker will naturally
use the new processor on its next render request.
2026-07-13 10:19:30 +08:00
Mike-Solar 800859b0ef Fix OCIO LUT async processor black screen and freeze
- 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.
2026-07-13 10:19:30 +08:00
Mike-Solar 68c0477715 Add hardware decoding support 2026-07-13 10:19:30 +08:00
Mike-Solar f6211f97a5 Fix render worker reuse and stabilize out-of-process video rendering 2026-07-13 10:19:30 +08:00
Mike-Solar 5b069b47fd Fix CI compatibility for LUT and decoder tests 2026-07-13 10:19:29 +08:00
Mike-Solar 8ae8e3a159 Implement proxy media workflow 2026-07-13 10:19:29 +08:00
Mike-Solar 9c1fba4932 Add timeline audio sync actions 2026-07-13 10:19:29 +08:00
Mike-Solar 08b1c6d562 Implement audio sync foundations 2026-07-13 10:19:29 +08:00
Mike-Solar cac5a40b58 Implement color LUT v0.4 features 2026-06-07 00:24:08 +08:00
Mike-Solar b23e01b916 Add render worker IPC loop 2026-06-04 13:57:36 +08:00
Mike-Solar 7ebfebb29a Fix OFX plugin render failures and stabilize integration tests
This commit resolves several categories of OFX plugin failures that
  manifested as magenta (pink) render output or crashes:

  1. Param default-value initialization
     - IntegerInstance, DoubleInstance, BooleanInstance, ChoiceInstance,
       and StringInstance now read kOfxParamPropDefault from the descriptor
       at construction time. Previously, when no PluginNode was attached
       (integration-test mode), get() returned 0/0.0/false, causing
       generator plugins to receive invalid extent/format/PAR values and
       crash in coordinate assertions.
     - IntegerInstance also fixed uninitialized `id` that caused
       kOfxStatErrBadHandle in CImg plugins.

  2. Clip property initialization
     - newClipInstance() now seeds pixelDepth and components from the
       host VideoParams instead of leaving them as None. This prevents
       Transform3x3Plugin and similar plugins from asserting on
       getPixelComponentCount() during fetchClip inside createInstance.
     - getAspectRatio() and getProjectPixelAspectRatio() now fall back
       to 1.0 when the project's PAR is not yet set, avoiding division-
       by-zero in coordinate conversion.

  3. Frame-rate and time-base preservation
     - setInputTexture() no longer overwrites the clip's frame_rate or
       time_base with the input texture's values. Multi-input plugins
       were crashing because setupClipPreferencesArgs throws when inputs
     have mismatched rates.

  4. Render loop hardening
     - getClipPreferences() is now wrapped in try/catch so that frame-
       rate mismatch exceptions mark render failure instead of aborting
       the render thread.
     - getRegionOfInterestAction() treats kOfxStatErrBadHandle as non-
       fatal and falls back to default RoI.
     - RenderPlugin syncs all clip instances after setVideoParam so that
       getAspectRatio/getFrameRate return valid values before
       createInstanceAction queries them.

  5. Test suite updates
     - All PluginMisc tests now use F32 input to match the host pipeline
       default.
     - CreateGradientTexture fixed to support F32 pixel format.
     - Added CImgBilateral and CImgGuided_MultiInput tests.
     - Secret parameters are now registered as hidden Node inputs so that
       getClipPreferences can read them (fixes generator pink screen).

  6. Debug logging in HostSupport
     - clipGetImage and clipGetRegionOfDefinition now catch exceptions
       and log the failing clip name for easier debugging.
2026-05-15 21:32:28 +08:00
Mike-Solar 4aa4d59770 feat: hide non-texture OFX params from node graph + host coordinate standardization
Hide non-texture OFX params from node graph
  --------------------------------------------
  OFX plugins like ColorCorrect expose dozens of scalar parameters as
  node inputs, making nodes extremely tall and pushing Source/Mask far
  down. Previously attempted via kInputFlagHidden, but that also hid
  them from the parameter panel.

  Fix: move the filter to NodeViewItem::IsInputValid() instead.
  For OFX plugin nodes (getPluginInstance() != nullptr), only
  kTexture inputs are rendered as ports. Scalar parameters remain
  fully visible in the parameter panel.

  Files: app/widget/nodeview/nodeviewitem.cpp
         app/node/plugins/Plugin.cpp

  Standardize OFX host coordinate system
  --------------------------------------
  Olive's OFX host had partial and inconsistent coordinate handling.

  1. Fix Project coordinate methods
     - getProjectSize() / getProjectExtent() / getProjectOffset()
       now multiply X by pixel_aspect_ratio(), returning canonical
       coordinates per the OFX spec.

  2. Fix Clip default RoD
     - OliveClipInstance::getRegionOfDefinition() default now returns
       {0, 0, width*PAR, height} instead of raw pixel coords.

  3. Add parameter coordinate system conversion
     - DoubleInstance / Double2DInstance / Double3DInstance now check
       _descriptor.getDefaultCoordinateSystem().
     - For kOfxParamCoordinatesNormalised:
         get: internal pixel value -> normalised (divide by extent)
         set: normalised plugin value -> pixel (multiply by extent)
     - DefaultValueForParam() also converts normalised defaults to
       canonical before storing in Node, keeping Olive internal/UI
       values consistently in pixel space.

  Files: app/pluginSupport/OlivePluginInstance.cpp
         app/pluginSupport/OliveClip.cpp
         app/pluginSupport/paraminstance.h
         app/node/plugins/Plugin.cpp
2026-05-14 21:54:18 +08:00
Mike-Solar e012f16083 feat: group OpenFX plugins under dedicated "OpenFX" category with sub-groups
All OpenFX plugins were previously hardcoded to return kCategoryUnknown,
  causing them to pile up under "Uncategorized" in the node creation menu.

  This commit introduces a two-level grouping system for OFX plugins:

  1. Add new kCategoryOpenFX top-level category
     - Node::CategoryID enum extended with kCategoryOpenFX
     - PluginNode::Category() now returns {kCategoryOpenFX}
     - Node::GetCategoryName() returns "OpenFX"

  2. Add secondary sub-grouping support
     - Node base class gains virtual SubCategory() method
     - PluginNode implements SubCategory() backed by sub_category_ member
     - sub_category_ is set in the constructor from the plugin's OFX context:
         Filter     → "Filter"
         Generator  → "Generator"
         Transition → "Transition"
         others     → "General"

  3. Update NodeFactory::CreateMenu()
     - When a node belongs to kCategoryOpenFX and provides a non-empty
       SubCategory(), creates a second-level submenu under "OpenFX"
     - Nodes without a sub-category are placed directly in the top menu

  Expected menu layout:
    OpenFX
      ├── Filter
      │     ├── ColorCorrect
      │     └── ...
      ├── Generator
      ├── Transition
      └── General

  All 4 test suites pass.
2026-05-14 21:05:29 +08:00
Mike-Solar b2de04962d feat: heuristic semantic display for OFX RGBA parameters
ColorCorrectOFX and similar plugins declare per-channel controls
  (Gamma, Contrast, Saturation, Gain, Offset) as kOfxParamTypeRGBA.
  Olive previously mapped every RGBA param to NodeValue::kColor and
  rendered it as a ColorButton, which is semantically wrong for
  adjustment sliders.

  This commit adds heuristic semantic detection to distinguish
  "true color" inputs (color pickers) from "per-channel scalar"
  inputs (float sliders):

    - label/hint/name keywords ("gamma", "contrast", "gain", ...)
    - display range outside [0, 1]
    - uniform default values across all channels

  The detected semantic ("color" or "scalar") is stored as the
  node input property "color_semantic".  The display range and hint
  are also persisted as "min" / "max" / "tooltip".

  NodeParamViewWidgetBridge now branches on "color_semantic":
    - "scalar"  → 4× FloatSlider (reuses existing ProcessSlider /
      keyframe-track logic, since kColor already splits into 4 tracks)
    - otherwise → ColorButton (unchanged)

  All 4 test suites pass.
2026-05-14 20:50:45 +08:00
Mike-Solar 599c876d03 全链路强制F32 2026-05-14 01:51:14 +08:00
Mike-Solar c1b77ceec5 Merge branch 'plugin' 2026-01-17 17:03:39 +08:00
Mike-Solar a2698e7ef4 solve problem invalid roi and param 2026-01-17 16:41:03 +08:00
Mike-Solar bfb1b2fce4 update copyright back 2026-01-16 21:22:05 +08:00
Mike-Solar e851653fa3 尝试修复粉紫屏未果 2026-01-16 21:11:24 +08:00
Mike-Solar 4d393f3d23 尝试解决插件bug 2026-01-10 18:56:58 +08:00
Mike-Solar 8ed5660faf solve some bugs 2026-01-05 18:01:13 +08:00
Mike-Solar b8669f6a11 Change project name; 2026-01-05 16:22:26 +08:00
Mike-Solar 86e82b13e2 remove unused includes 2026-01-05 14:24:28 +08:00
Mike-Solar 8263ccf814 修正测试 2026-01-05 03:11:34 +08:00
Mike-Solar 003c3bb5be 修改部分语法错误 2026-01-05 02:25:13 +08:00
Mike-Solar cad331eb2c Fix compile errors 2026-01-05 01:50:05 +08:00
Mike-Solar c136cdf7f6 完成1 2026-01-05 00:03:51 +08:00
Mike-Solar 1b29bd147e Add missing param instance types (String, Double3D/Integer3D, Group/Page, Custom/Bytes) and mapping to node inputs. app/pluginSupport/OlivePluginInstance.cpp, app/node/plugins/Plugin.cpp 2026-01-04 22:53:26 +08:00
Mike-Solar 3b16824f34 Ensure render path sets per-frame output data and handles ROD/bounds correctly. 2026-01-04 22:40:05 +08:00
Mike-Solar f191486375 Implement multi-input OFX clip wiring and texture handling
Store PluginJob input values for lookup
Add per-clip texture inputs on plugin nodes
Map input clips to textures during render (with Source fallback)
2026-01-04 22:30:41 +08:00
Mike Solar 7c0f37b0a7 Implement default methods for plugin parameter editing and progress, and integrate plugin rendering into the build system. 2025-12-24 21:07:17 +08:00
Mike Solar 88ba0e4841 Update plugin parameter instances to use shared pointers and add new parameter creation logic 2025-12-24 17:51:56 +08:00