refactor(node,render): route oaknode->oakrender calls through the C ABI

- oakrender cache C API: add create_for_node (four cache kinds),
  get_uuid, request, load/save_state, set_saving_enabled,
  set_passthrough, get_passthroughs, get_valid_cache_filename,
  get_timebase, lock/unlock, invalidate_range (rational variant),
  get_native (C++ only, for the in-module PreviewAutoCacher)
- Node's four caches become owned OakRenderCache value handles; all
  cache access in node.cpp/clip/viewer/traverser/serializers goes
  through the C ABI
- oaknode_node_get_video_frame_cache returns an addref'd
  OakRenderCache; drop OakNodeFrameCache; oaktask precache/export and
  oakrender_video_ticket_params take the value handle
- color: OCIOBaseNode/OCIOLutNode hold OakColorProcessor handles
  (dtors added); oakrender gains color_processor_create_transform/
  create_lut/create_grading_primary/get_native and LUT library
  queries, keeping all OCIO transform construction inside oakrender;
  oaknode gains colormanager_wrap_borrowed/get_native
- RenderManager::instance() check -> oakrender_manager_available();
  cancel_video_tasks and disk cache path go through manager C API
- remaining node->render C++ symbol: only olive::Texture::~Texture
  via Variant's shared_ptr payload (recorded exception, same class as
  the UndoCommand inheritance)

Tests: new cache/color/manager/colormanager cases; all standalone
trees green (common 196, codec 22, audio 40, task 112, render 63,
timeline 125, node 98, plugin 102).
This commit is contained in:
2026-08-08 03:56:17 +08:00
parent 81431d180d
commit 5a564f30ca
40 changed files with 1553 additions and 237 deletions
+131
View File
@@ -28,6 +28,7 @@
// public headers reference each other relative to their own directory.
#include "error.h"
#include "renderer.h" /* OakCodecFrame */
#include "node/node.h" /* OakNodeNode */
#ifdef __cplusplus
extern "C" {
@@ -88,6 +89,128 @@ void oakrender_cache_free(OakRenderCache *cache);
*/
OakRenderCache oakrender_cache_wrap_borrowed(void *native_cache);
/**
* @brief Cache flavours owned by a node
* (olive::Node's video/thumbnail/audio/waveform caches).
*/
enum OakRenderCacheKind {
OAKRENDER_CACHE_VIDEO_FRAME = 0, /**< olive::FrameHashCache */
OAKRENDER_CACHE_THUMBNAIL = 1, /**< olive::ThumbnailCache */
OAKRENDER_CACHE_AUDIO_PLAYBACK = 2, /**< olive::AudioPlaybackCache */
OAKRENDER_CACHE_AUDIO_WAVEFORM = 3 /**< olive::AudioWaveformCache */
};
/**
* @brief Create a cache of the given kind with a parent node (the
* native back-pointer stays inside oakrender; it is used for
* project cache-path resolution and job bookkeeping only).
*
* Owned by the caller (reference count 1); release with
* oakrender_cache_free(). Empty handle for an empty parent handle, an
* unknown kind, or on allocation failure.
*/
OakRenderCache oakrender_cache_create_for_node(OakNodeNode parent,
int kind);
/**
* @brief Cache UUID as canonical text, two-stage
* (PlaybackCache::get_uuid()).
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKRENDER_E_* code for an empty cache.
*/
int oakrender_cache_get_uuid(OakRenderCache cache, char *buf,
int buf_size);
/**
* @brief Request caching of a time range on behalf of a viewer
* (PlaybackCache::request()).
*
* @return OAKRENDER_OK, or OAKRENDER_E_INVALID for an empty cache /
* context handle or a context that is not a viewer.
*/
int oakrender_cache_request(OakRenderCache cache, OakNodeNode context,
int64_t in_num, int64_t in_den,
int64_t out_num, int64_t out_den);
/**
* @brief Load/save the cache's on-disk state (PlaybackCache::load_state()
* / save_state()). OAKRENDER_E_INVALID for an empty cache.
*/
int oakrender_cache_load_state(OakRenderCache cache);
int oakrender_cache_save_state(OakRenderCache cache);
/**
* @brief Enable/disable persisting this cache
* (PlaybackCache::set_saving_enabled()).
*/
int oakrender_cache_set_saving_enabled(OakRenderCache cache, int enabled);
/**
* @brief Pass this cache's ranges through to another cache
* (PlaybackCache::set_passthrough()). OAKRENDER_E_INVALID for an
* empty cache or an empty `other`.
*/
int oakrender_cache_set_passthrough(OakRenderCache cache,
OakRenderCache other);
/**
* @brief The on-disk filename for the frame at a time
* (FrameHashCache::get_valid_cache_filename()), two-stage.
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKRENDER_E_* code (OAKRENDER_E_INVALID when the cache is not
* a frame hash cache).
*/
int oakrender_cache_get_valid_cache_filename(OakRenderCache cache,
int64_t time_num,
int64_t time_den, char *buf,
int buf_size);
/**
* @brief The passthrough ranges as flat {in_n, in_d, out_n, out_d}
* quadruples (PlaybackCache::get_passthroughs(); only the ranges
* cross the boundary, the per-range cache UUID text stays
* internal).
*
* Two-stage: call with ranges == NULL (or max_ranges == 0) to get the
* count; then call with a buffer of max_ranges * 4 int64_t values.
*
* @return Range count (>= 0), or a negative OAKRENDER_E_* code.
*/
int oakrender_cache_get_passthroughs(OakRenderCache cache, int64_t *ranges,
int max_ranges);
/**
* @brief The cache's frame timebase (FrameHashCache::get_timebase()).
* Out params may individually be NULL. OAKRENDER_E_INVALID for
* an empty cache or a non-frame-hash cache.
*/
int oakrender_cache_get_timebase(OakRenderCache cache, int *num,
int *den);
/**
* @brief Lock/unlock the cache's internal mutex (PlaybackCache::mutex()).
* Empty cache is a no-op. Always pair the calls.
*/
void oakrender_cache_lock(OakRenderCache cache);
void oakrender_cache_unlock(OakRenderCache cache);
#ifdef __cplusplus
} /* extern "C" */
namespace olive { class PlaybackCache; }
extern "C" {
#endif
/**
* @brief Borrowed access to the underlying C++ cache (C++ only, for
* oakrender-internal adapters such as PreviewAutoCacher). Valid
* while the handle is held. NULL-safe.
*/
olive::PlaybackCache *oakrender_cache_get_native(OakRenderCache cache);
/**
* @brief Set the frame timebase used to interpret all timestamps of this
* cache (FrameHashCache::set_timebase()).
@@ -112,6 +235,14 @@ int oakrender_cache_set_uuid(OakRenderCache cache, const char *uuid);
void oakrender_cache_invalidate(OakRenderCache cache, int64_t in_ts,
int64_t out_ts);
/**
* @brief Mark a rational time range invalidated
* (PlaybackCache::invalidate(TimeRange)). Empty cache is a no-op.
*/
void oakrender_cache_invalidate_range(OakRenderCache cache,
int64_t in_num, int64_t in_den,
int64_t out_num, int64_t out_den);
/**
* @brief Mark the timestamp range [in_ts, out_ts) validated
* (PlaybackCache::validate()). Empty cache is a no-op.
+88
View File
@@ -23,6 +23,8 @@
#include "error.h"
#include "renderer.h"
#include "common/colortransform.h" /* OakColorTransform */
#include "node/colormanager.h" /* OakNodeColorManager */
#ifdef __cplusplus
extern "C" {
@@ -94,6 +96,75 @@ void oakrender_color_processor_free(OakColorProcessor *processor);
*/
int oakrender_color_processor_is_valid(OakColorProcessor processor);
/**
* @brief Create a processor from an input colorspace and a destination
* transform on a node's color manager
* (ColorProcessor::create(ColorManager*, input, dest, dir)).
*
* @param manager Borrowed manager handle (e.g.
* oaknode_colormanager_wrap_borrowed()).
* @param direction OAKRENDER_COLOR_DIRECTION_NORMAL / _INVERSE.
* @return Processor handle with reference count 1; ctx is NULL for
* empty/invalid arguments or allocation failure.
*/
OakColorProcessor oakrender_color_processor_create_transform(
OakNodeColorManager manager, const char *input,
OakColorTransform dest, int direction);
/**
* @brief Create a processor from a LUT file on a node's color manager
* (OCIO FileTransform with linear interpolation; direction
* selects forward/inverse).
*
* @return Processor handle with reference count 1; ctx is NULL for
* empty/invalid arguments, an unreadable LUT, or allocation
* failure.
*/
OakColorProcessor oakrender_color_processor_create_lut(
OakNodeColorManager manager, const char *path, int direction);
/**
* @brief Grading-primary transform styles for
* oakrender_color_processor_create_grading_primary().
*/
enum OakRenderGradingPrimaryStyle {
OAKRENDER_GRADING_PRIMARY_LIN = 0, /**< OCIO GRADING_LIN */
OAKRENDER_GRADING_PRIMARY_LOG = 1 /**< OCIO GRADING_LOG */
};
/**
* @brief Create a dynamic grading-primary processor on a node's color
* manager (OCIO GradingPrimaryTransform, forward direction).
*
* @return Processor handle with reference count 1; ctx is NULL for
* invalid arguments or allocation failure.
*/
OakColorProcessor oakrender_color_processor_create_grading_primary(
OakNodeColorManager manager, int style);
/* ---- LUT library ---------------------------------------------------- */
/**
* @brief 1 when `extension` (without dot, case-insensitive) is a
* supported LUT extension (LUTLibrary::is_supported_extension()).
*/
int oakrender_lut_is_supported_extension(const char *extension);
/**
* @brief Number of supported LUT extensions
* (LUTLibrary::supported_extensions()).
*/
int oakrender_lut_supported_extensions_count(void);
/**
* @brief Supported LUT extension at `index`, two-stage string.
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKRENDER_E_* code for an out-of-range index.
*/
int oakrender_lut_supported_extension_at(int index, char *buf,
int buf_size);
/**
* @brief Convert a single RGBA color (ColorProcessor::convert_color()).
* On an invalid processor the input is copied through.
@@ -160,6 +231,23 @@ int oakrender_color_manager_display_transform(const char *display,
const char *view, char *buf,
int n);
#ifdef __cplusplus
} /* extern "C" */
#include <memory>
namespace olive { class ColorProcessor; }
extern "C" {
#endif
/**
* @brief Borrowed access to the underlying C++ processor (C++ only, for
* adapter layers; a shared_ptr copy keeps the object alive).
* Empty shared_ptr for an empty handle.
*/
std::shared_ptr<olive::ColorProcessor> oakrender_color_processor_get_native(
OakColorProcessor processor);
#ifdef __cplusplus
}
#endif
+14
View File
@@ -120,6 +120,20 @@ int oakrender_set_cacher_multicam(OakNodeNode multicam_or_NULL);
*/
int oakrender_set_display_color_processor(OakColorProcessor p_or_NULL);
/**
* @brief 1 when the process-wide RenderManager singleton exists
* (RenderManager::instance() != nullptr; only the main GUI
* process creates one), 0 otherwise.
*/
int oakrender_manager_available(void);
/**
* @brief Cancel in-flight video cache tasks on the manager's
* auto-cacher (PreviewAutoCacher::cancel_video_tasks()). No-op
* when no manager/auto-cacher exists (e.g. a worker process).
*/
void oakrender_cancel_video_tasks(int wait_for_done);
/* ---- Disk cache (olive::DiskManager) -------------------------------------- */
/**
+2 -1
View File
@@ -30,6 +30,7 @@
#include "olive/core/oakcore/audioparams.h"
#include "olive/core/oakcore/samplebuffer.h"
#include "render/error.h"
#include "render/cache.h"
#include "render/color.h"
#include "render/renderer.h"
@@ -89,7 +90,7 @@ typedef struct oakrender_video_ticket_params {
int force_channel_count; /**< 0 = off. */
OakColorProcessor force_color_output; /**< Borrowed; empty ctx = none. */
OakColorTransform force_color_transform; /**< By value; empty ctx = default. */
OakNodeFrameCache *cache; /**< Borrowed frame cache, may be NULL. */
OakRenderCache cache; /**< Borrowed frame cache; empty ctx = none. */
} oakrender_video_ticket_params;
/**