style: unify identifier naming per updated conventions
Automated with clang-tidy readability-identifier-naming (config added to .clang-tidy) plus scripted passes, per the updated rules now documented in CONTRIBUTING.md: - types (class/struct/enum/alias/template params): PascalCase - functions, variables, members: snake_case (incl. rational -> Rational) - private/protected members: trailing underscore; static member variables likewise (instance_, available_themes_) - constants and enum values: snake_case (kLinear -> k_linear, F32P -> f32p); ALL_CAPS reserved for macros - macros: OAK_ prefix (OLIVE_ADD_TEST/OLIVE_ASSERT/OLIVE_CONFIG -> OAK_ADD_TEST/OAK_ASSERT/OAK_CONFIG, GL_PREAMBLE -> OAK_GL_PREAMBLE, include guards -> OAK_*) - file names: all lowercase (Current/Plugin/OliveHost/OliveClip/ OlivePluginInstance -> current/plugin/olivehost/oliveclip/ oliveplugininstance) - getters share the member name sans underscore, setters set_foo() - Qt and third-party (OpenFX) virtual overrides and framework callbacks keep their original names (exempt in .clang-tidy) Manual follow-ups required where automation could not reach: - string-based QMetaObject/SIGNAL/SLOT references updated to renamed methods (AddTask, CreatedFile, DeleteSpecificFile, moveSelectionUp, ...) - macro bodies referencing renamed methods (OLIVE_CONFIG, NODE_DEFAULT_DESTRUCTOR, MANAGEDDISPLAYWIDGET_*) - self-shadowing locals renamed where signals/methods became same-named (size_changed, worker_count, selected_items, import param, filters) - third_party OFX member/namespace usages restored (OFX::Host::*, _created, _clipPrefsDirty, createInstance, clearPersistentMessage) - STL protocol aliases restored (const_iterator) with .clang-tidy ignore rules; qHash overloads restored Full build and test suite pass: ctest 4/4, ~1960 gtest cases green.
This commit is contained in:
@@ -19,14 +19,14 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef ALPHAASSOC_H
|
||||
#define ALPHAASSOC_H
|
||||
#ifndef OAK_ALPHAASSOC_H
|
||||
#define OAK_ALPHAASSOC_H
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
enum AlphaAssociated { kAlphaNone, kAlphaUnassociated, kAlphaAssociated };
|
||||
enum AlphaAssociated { k_alpha_none, k_alpha_unassociated, k_alpha_associated };
|
||||
|
||||
}
|
||||
|
||||
#endif // ALPHAASSOC_H
|
||||
#endif // OAK_ALPHAASSOC_H
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
const qint64 AudioPlaybackCache::kDefaultSegmentSizePerChannel =
|
||||
const qint64 AudioPlaybackCache::k_default_segment_size_per_channel =
|
||||
10 * 1024 * 1024;
|
||||
|
||||
AudioPlaybackCache::AudioPlaybackCache(QObject *parent)
|
||||
@@ -44,7 +44,7 @@ AudioPlaybackCache::~AudioPlaybackCache()
|
||||
{
|
||||
}
|
||||
|
||||
void AudioPlaybackCache::SetParameters(const AudioParams ¶ms)
|
||||
void AudioPlaybackCache::set_parameters(const AudioParams ¶ms)
|
||||
{
|
||||
if (params_ == params) {
|
||||
return;
|
||||
@@ -53,29 +53,29 @@ void AudioPlaybackCache::SetParameters(const AudioParams ¶ms)
|
||||
params_ = params;
|
||||
}
|
||||
|
||||
void AudioPlaybackCache::WritePCM(const TimeRange &range,
|
||||
void AudioPlaybackCache::write_pcm(const TimeRange &range,
|
||||
const TimeRangeList &valid_ranges,
|
||||
const SampleBuffer &samples)
|
||||
{
|
||||
for (const TimeRange &r : valid_ranges) {
|
||||
if (WritePartOfSampleBuffer(samples, r.in(), r.in() - range.in(),
|
||||
if (write_part_of_sample_buffer(samples, r.in(), r.in() - range.in(),
|
||||
r.length())) {
|
||||
Validate(r);
|
||||
validate(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioPlaybackCache::WriteSilence(const TimeRange &range)
|
||||
void AudioPlaybackCache::write_silence(const TimeRange &range)
|
||||
{
|
||||
// WritePCM will automatically fill non-existent bytes with silence, so we just have to send
|
||||
// it an empty sample buffer
|
||||
WritePCM(range, { range }, SampleBuffer());
|
||||
write_pcm(range, { range }, SampleBuffer());
|
||||
}
|
||||
|
||||
bool AudioPlaybackCache::WritePartOfSampleBuffer(const SampleBuffer &samples,
|
||||
const rational &write_start,
|
||||
const rational &buffer_start,
|
||||
const rational &length)
|
||||
bool AudioPlaybackCache::write_part_of_sample_buffer(const SampleBuffer &samples,
|
||||
const Rational &write_start,
|
||||
const Rational &buffer_start,
|
||||
const Rational &length)
|
||||
{
|
||||
int64_t length_in_bytes = params_.time_to_bytes_per_channel(length);
|
||||
|
||||
@@ -94,9 +94,9 @@ bool AudioPlaybackCache::WritePartOfSampleBuffer(const SampleBuffer &samples,
|
||||
bool success = true;
|
||||
|
||||
while (current_cache_offset != end_cache_offset) {
|
||||
int64_t segment = current_cache_offset / kDefaultSegmentSizePerChannel;
|
||||
int64_t segment_start = segment * kDefaultSegmentSizePerChannel;
|
||||
int64_t segment_end = segment_start + kDefaultSegmentSizePerChannel;
|
||||
int64_t segment = current_cache_offset / k_default_segment_size_per_channel;
|
||||
int64_t segment_start = segment * k_default_segment_size_per_channel;
|
||||
int64_t segment_end = segment_start + k_default_segment_size_per_channel;
|
||||
|
||||
int64_t offset_in_segment = current_cache_offset - segment_start;
|
||||
// Never write past the end of the requested range
|
||||
@@ -111,9 +111,9 @@ bool AudioPlaybackCache::WritePartOfSampleBuffer(const SampleBuffer &samples,
|
||||
}
|
||||
|
||||
for (int channel = 0; channel < params_.channel_count(); channel++) {
|
||||
QString filename = GetSegmentFilename(segment, channel);
|
||||
QString filename = get_segment_filename(segment, channel);
|
||||
|
||||
if (!FileFunctions::DirectoryIsValid(QFileInfo(filename).dir())) {
|
||||
if (!FileFunctions::directory_is_valid(QFileInfo(filename).dir())) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
@@ -147,10 +147,10 @@ bool AudioPlaybackCache::WritePartOfSampleBuffer(const SampleBuffer &samples,
|
||||
return success;
|
||||
}
|
||||
|
||||
QString AudioPlaybackCache::GetSegmentFilename(qint64 segment_index,
|
||||
QString AudioPlaybackCache::get_segment_filename(qint64 segment_index,
|
||||
int channel)
|
||||
{
|
||||
return GetThisCacheDirectory().filePath(QStringLiteral("%1.%2").arg(
|
||||
return get_this_cache_directory().filePath(QStringLiteral("%1.%2").arg(
|
||||
QString::number(segment_index), QString::number(channel)));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef AUDIOPLAYBACKCACHE_H
|
||||
#define AUDIOPLAYBACKCACHE_H
|
||||
#ifndef OAK_AUDIOPLAYBACKCACHE_H
|
||||
#define OAK_AUDIOPLAYBACKCACHE_H
|
||||
|
||||
#include "audio/audiovisualwaveform.h"
|
||||
#include "render/playbackcache.h"
|
||||
@@ -58,31 +58,31 @@ public:
|
||||
|
||||
virtual ~AudioPlaybackCache() override;
|
||||
|
||||
AudioParams GetParameters()
|
||||
AudioParams get_parameters()
|
||||
{
|
||||
return params_;
|
||||
}
|
||||
|
||||
void SetParameters(const AudioParams ¶ms);
|
||||
void set_parameters(const AudioParams ¶ms);
|
||||
|
||||
void WritePCM(const TimeRange &range, const TimeRangeList &valid_ranges,
|
||||
void write_pcm(const TimeRange &range, const TimeRangeList &valid_ranges,
|
||||
const SampleBuffer &samples);
|
||||
|
||||
void WriteSilence(const TimeRange &range);
|
||||
void write_silence(const TimeRange &range);
|
||||
|
||||
private:
|
||||
bool WritePartOfSampleBuffer(const SampleBuffer &samples,
|
||||
const rational &write_start,
|
||||
const rational &buffer_start,
|
||||
const rational &length);
|
||||
bool write_part_of_sample_buffer(const SampleBuffer &samples,
|
||||
const Rational &write_start,
|
||||
const Rational &buffer_start,
|
||||
const Rational &length);
|
||||
|
||||
QString GetSegmentFilename(qint64 segment_index, int channel);
|
||||
QString get_segment_filename(qint64 segment_index, int channel);
|
||||
|
||||
static const qint64 kDefaultSegmentSizePerChannel;
|
||||
static const qint64 k_default_segment_size_per_channel;
|
||||
|
||||
AudioParams params_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // AUDIOPLAYBACKCACHE_H
|
||||
#endif // OAK_AUDIOPLAYBACKCACHE_H
|
||||
|
||||
@@ -32,51 +32,51 @@ AudioWaveformCache::AudioWaveformCache(QObject *parent)
|
||||
waveforms_ = std::make_shared<AudioVisualWaveform>();
|
||||
}
|
||||
|
||||
void AudioWaveformCache::WriteWaveform(const TimeRange &range,
|
||||
void AudioWaveformCache::write_waveform(const TimeRange &range,
|
||||
const TimeRangeList &valid_ranges,
|
||||
const AudioVisualWaveform *waveform)
|
||||
{
|
||||
// Write each valid range to the segments
|
||||
foreach (const TimeRange &r, valid_ranges) {
|
||||
if (waveform) {
|
||||
waveforms_->OverwriteSums(*waveform, r.in(), r.in() - range.in(),
|
||||
waveforms_->overwrite_sums(*waveform, r.in(), r.in() - range.in(),
|
||||
r.length());
|
||||
}
|
||||
|
||||
Validate(r);
|
||||
validate(r);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSubRect(QPainter *painter, const QRect &rect, const double &scale,
|
||||
void draw_sub_rect(QPainter *painter, const QRect &rect, const double &scale,
|
||||
const TimeRange &wave_range,
|
||||
const AudioVisualWaveform &waveform, const TimeRange &subrange)
|
||||
{
|
||||
// Find start time of passthrough
|
||||
TimeRange intersect = wave_range.Intersected(subrange);
|
||||
TimeRange intersect = wave_range.intersected(subrange);
|
||||
|
||||
// Create new rect that starts at the offset of pass_start from start_time
|
||||
// Set rect width to either length of passthrough or until the end
|
||||
QRect pass_rect(
|
||||
rect.x() + (intersect.in() - wave_range.in()).toDouble() * scale,
|
||||
rect.y(), intersect.length().toDouble() * scale, rect.height());
|
||||
rect.x() + (intersect.in() - wave_range.in()).to_double() * scale,
|
||||
rect.y(), intersect.length().to_double() * scale, rect.height());
|
||||
|
||||
// Draw waveform with this info
|
||||
AudioVisualWaveform::DrawWaveform(painter, pass_rect, scale, waveform,
|
||||
AudioVisualWaveform::draw_waveform(painter, pass_rect, scale, waveform,
|
||||
intersect.in());
|
||||
}
|
||||
|
||||
void AudioWaveformCache::Draw(QPainter *painter, const QRect &rect,
|
||||
const double &scale,
|
||||
const rational &start_time) const
|
||||
const Rational &start_time) const
|
||||
{
|
||||
if (!passthroughs_.empty()) {
|
||||
TimeRange wave_range(start_time,
|
||||
start_time +
|
||||
rational::fromDouble(rect.width() / scale));
|
||||
Rational::from_double(rect.width() / scale));
|
||||
TimeRangeList draw_range = { wave_range };
|
||||
for (const WaveformPassthrough &p : passthroughs_) {
|
||||
if (draw_range.OverlapsWith(p, true, false)) {
|
||||
DrawSubRect(painter, rect, scale, wave_range, *p.waveform, p);
|
||||
if (draw_range.overlaps_with(p, true, false)) {
|
||||
draw_sub_rect(painter, rect, scale, wave_range, *p.waveform, p);
|
||||
|
||||
// Remove this range
|
||||
draw_range.remove(p);
|
||||
@@ -84,31 +84,31 @@ void AudioWaveformCache::Draw(QPainter *painter, const QRect &rect,
|
||||
}
|
||||
|
||||
for (const TimeRange &r : draw_range) {
|
||||
DrawSubRect(painter, rect, scale, wave_range, *waveforms_, r);
|
||||
draw_sub_rect(painter, rect, scale, wave_range, *waveforms_, r);
|
||||
}
|
||||
} else {
|
||||
AudioVisualWaveform::DrawWaveform(painter, rect, scale, *waveforms_,
|
||||
AudioVisualWaveform::draw_waveform(painter, rect, scale, *waveforms_,
|
||||
start_time);
|
||||
}
|
||||
}
|
||||
|
||||
AudioVisualWaveform::Sample
|
||||
AudioWaveformCache::GetSummaryFromTime(const rational &start,
|
||||
const rational &length) const
|
||||
AudioWaveformCache::get_summary_from_time(const Rational &start,
|
||||
const Rational &length) const
|
||||
{
|
||||
return waveforms_->GetSummaryFromTime(start, length);
|
||||
return waveforms_->get_summary_from_time(start, length);
|
||||
}
|
||||
|
||||
rational AudioWaveformCache::length() const
|
||||
Rational AudioWaveformCache::length() const
|
||||
{
|
||||
return waveforms_->length();
|
||||
}
|
||||
|
||||
void AudioWaveformCache::SetPassthrough(PlaybackCache *cache)
|
||||
void AudioWaveformCache::set_passthrough(PlaybackCache *cache)
|
||||
{
|
||||
AudioWaveformCache *c = static_cast<AudioWaveformCache *>(cache);
|
||||
|
||||
for (const TimeRange &r : c->GetValidatedRanges()) {
|
||||
for (const TimeRange &r : c->get_validated_ranges()) {
|
||||
WaveformPassthrough t = r;
|
||||
t.waveform = c->waveforms_;
|
||||
passthroughs_.push_back(t);
|
||||
@@ -116,8 +116,8 @@ void AudioWaveformCache::SetPassthrough(PlaybackCache *cache)
|
||||
passthroughs_.insert(passthroughs_.end(), c->passthroughs_.begin(),
|
||||
c->passthroughs_.end());
|
||||
|
||||
SetParameters(c->GetParameters());
|
||||
SetSavingEnabled(c->IsSavingEnabled());
|
||||
set_parameters(c->get_parameters());
|
||||
set_saving_enabled(c->is_saving_enabled());
|
||||
}
|
||||
|
||||
void AudioWaveformCache::InvalidateEvent(const TimeRange &range)
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef AUDIOWAVEFORMCACHE_H
|
||||
#define AUDIOWAVEFORMCACHE_H
|
||||
#ifndef OAK_AUDIOWAVEFORMCACHE_H
|
||||
#define OAK_AUDIOWAVEFORMCACHE_H
|
||||
|
||||
#include "audio/audiovisualwaveform.h"
|
||||
#include "playbackcache.h"
|
||||
@@ -33,29 +33,29 @@ class AudioWaveformCache : public PlaybackCache {
|
||||
public:
|
||||
AudioWaveformCache(QObject *parent = nullptr);
|
||||
|
||||
void WriteWaveform(const TimeRange &range,
|
||||
void write_waveform(const TimeRange &range,
|
||||
const TimeRangeList &valid_ranges,
|
||||
const AudioVisualWaveform *waveform);
|
||||
|
||||
const AudioParams &GetParameters() const
|
||||
const AudioParams &get_parameters() const
|
||||
{
|
||||
return params_;
|
||||
}
|
||||
void SetParameters(const AudioParams &p)
|
||||
void set_parameters(const AudioParams &p)
|
||||
{
|
||||
params_ = p;
|
||||
waveforms_->set_channel_count(p.channel_count());
|
||||
}
|
||||
|
||||
void Draw(QPainter *painter, const QRect &rect, const double &scale,
|
||||
const rational &start_time) const;
|
||||
const Rational &start_time) const;
|
||||
|
||||
AudioVisualWaveform::Sample
|
||||
GetSummaryFromTime(const rational &start, const rational &length) const;
|
||||
get_summary_from_time(const Rational &start, const Rational &length) const;
|
||||
|
||||
rational length() const;
|
||||
Rational length() const;
|
||||
|
||||
virtual void SetPassthrough(PlaybackCache *cache) override;
|
||||
virtual void set_passthrough(PlaybackCache *cache) override;
|
||||
|
||||
protected:
|
||||
virtual void InvalidateEvent(const TimeRange &range) override;
|
||||
@@ -82,4 +82,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // AUDIOWAVEFORMCACHE_H
|
||||
#endif // OAK_AUDIOWAVEFORMCACHE_H
|
||||
|
||||
@@ -21,8 +21,8 @@ DynamicRenderer::DynamicRenderer(const QString &backend, QObject *parent)
|
||||
// resources, destroy the opaque backend object, then unload the shared library.
|
||||
DynamicRenderer::~DynamicRenderer()
|
||||
{
|
||||
Destroy();
|
||||
PostDestroy();
|
||||
destroy();
|
||||
post_destroy();
|
||||
if (handle_ && destroy_) {
|
||||
destroy_(handle_);
|
||||
handle_ = nullptr;
|
||||
@@ -35,7 +35,7 @@ DynamicRenderer::~DynamicRenderer()
|
||||
// Builds the private backend library path for the current platform.
|
||||
// The search is intentionally restricted to Oak-controlled directories so a
|
||||
// system libGL/libvulkan loader is never mistaken for an Oak render backend.
|
||||
QString DynamicRenderer::LibraryFilename() const
|
||||
QString DynamicRenderer::library_filename() const
|
||||
{
|
||||
QString base;
|
||||
if (backend_ == QStringLiteral("opengl")) {
|
||||
@@ -78,20 +78,20 @@ QString DynamicRenderer::LibraryFilename() const
|
||||
// Loads the selected backend, resolves its C ABI table, creates the opaque
|
||||
// backend object, and optionally falls back from Vulkan to OpenGL when runtime
|
||||
// availability checks fail.
|
||||
bool DynamicRenderer::Load()
|
||||
bool DynamicRenderer::load()
|
||||
{
|
||||
if (handle_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
library_.setFileName(LibraryFilename());
|
||||
library_.setFileName(library_filename());
|
||||
if (!library_.load()) {
|
||||
if (backend_ == QStringLiteral("vulkan")) {
|
||||
qWarning()
|
||||
<< "Failed to load Vulkan render backend" << library_.fileName()
|
||||
<< library_.errorString() << "falling back to OpenGL backend";
|
||||
backend_ = QStringLiteral("opengl");
|
||||
library_.setFileName(LibraryFilename());
|
||||
library_.setFileName(library_filename());
|
||||
}
|
||||
|
||||
if (!library_.load()) {
|
||||
@@ -101,7 +101,7 @@ bool DynamicRenderer::Load()
|
||||
}
|
||||
}
|
||||
|
||||
if (!ResolveFunctions()) {
|
||||
if (!resolve_functions()) {
|
||||
qWarning() << "Render backend is missing required symbols" << backend_;
|
||||
library_.unload();
|
||||
return false;
|
||||
@@ -121,7 +121,7 @@ bool DynamicRenderer::Load()
|
||||
qWarning() << "Render backend is not available" << backend_
|
||||
<< library_.fileName();
|
||||
if (backend_ == QStringLiteral("vulkan")) {
|
||||
return FallbackToOpenGL();
|
||||
return fallback_to_open_gl();
|
||||
}
|
||||
destroy_(handle_);
|
||||
handle_ = nullptr;
|
||||
@@ -133,9 +133,9 @@ bool DynamicRenderer::Load()
|
||||
|
||||
// Resolves the mandatory C ABI entry points from the loaded shared library.
|
||||
// Optional information probes are resolved after the required render interface.
|
||||
bool DynamicRenderer::ResolveFunctions()
|
||||
bool DynamicRenderer::resolve_functions()
|
||||
{
|
||||
ResetFunctions();
|
||||
reset_functions();
|
||||
#define RESOLVE(member, type, symbol) \
|
||||
member = reinterpret_cast<type>(library_.resolve(symbol)); \
|
||||
if (!member) \
|
||||
@@ -185,7 +185,7 @@ bool DynamicRenderer::ResolveFunctions()
|
||||
|
||||
// Discards a partially-created backend and restarts loading with the OpenGL
|
||||
// backend. This keeps RenderManager's fallback path inside the adapter.
|
||||
bool DynamicRenderer::FallbackToOpenGL()
|
||||
bool DynamicRenderer::fallback_to_open_gl()
|
||||
{
|
||||
if (handle_ && destroy_) {
|
||||
destroy_(handle_);
|
||||
@@ -194,14 +194,14 @@ bool DynamicRenderer::FallbackToOpenGL()
|
||||
if (library_.isLoaded()) {
|
||||
library_.unload();
|
||||
}
|
||||
ResetFunctions();
|
||||
reset_functions();
|
||||
backend_ = QStringLiteral("opengl");
|
||||
return Load();
|
||||
return load();
|
||||
}
|
||||
|
||||
// Clears all cached C function pointers so a failed backend cannot leave stale
|
||||
// call targets behind for a later fallback load.
|
||||
void DynamicRenderer::ResetFunctions()
|
||||
void DynamicRenderer::reset_functions()
|
||||
{
|
||||
create_ = nullptr;
|
||||
destroy_ = nullptr;
|
||||
@@ -228,22 +228,22 @@ void DynamicRenderer::ResetFunctions()
|
||||
}
|
||||
|
||||
// Returns backend metadata exposed by the dynamic library when available.
|
||||
bool DynamicRenderer::GetBackendInfo(OakRenderBackendInfo *out_info) const
|
||||
bool DynamicRenderer::get_backend_info(OakRenderBackendInfo *out_info) const
|
||||
{
|
||||
return handle_ && get_info_ && out_info && get_info_(handle_, out_info);
|
||||
}
|
||||
|
||||
// Initializes the loaded backend using its own context/device creation path.
|
||||
bool DynamicRenderer::Init()
|
||||
bool DynamicRenderer::init()
|
||||
{
|
||||
return Load() && init_(handle_);
|
||||
return load() && init_(handle_);
|
||||
}
|
||||
|
||||
// Initializes an OpenGL backend against an existing widget context; non-OpenGL
|
||||
// backends may ignore the context on the library side.
|
||||
bool DynamicRenderer::InitWithOpenGLContext(QOpenGLContext *context)
|
||||
bool DynamicRenderer::init_with_open_gl_context(QOpenGLContext *context)
|
||||
{
|
||||
if (!Load()) {
|
||||
if (!load()) {
|
||||
return false;
|
||||
}
|
||||
init_with_context_(handle_, context);
|
||||
@@ -252,7 +252,7 @@ bool DynamicRenderer::InitWithOpenGLContext(QOpenGLContext *context)
|
||||
|
||||
// Forwards post-destroy cleanup to the backend while the library is still
|
||||
// loaded and its symbols are still valid.
|
||||
void DynamicRenderer::PostDestroy()
|
||||
void DynamicRenderer::post_destroy()
|
||||
{
|
||||
if (handle_ && post_destroy_) {
|
||||
post_destroy_(handle_);
|
||||
@@ -261,7 +261,7 @@ void DynamicRenderer::PostDestroy()
|
||||
|
||||
// Runs backend post-initialization after Init/InitWithOpenGLContext has
|
||||
// established the device or GL context.
|
||||
void DynamicRenderer::PostInit()
|
||||
void DynamicRenderer::post_init()
|
||||
{
|
||||
if (handle_) {
|
||||
post_init_(handle_);
|
||||
@@ -269,7 +269,7 @@ void DynamicRenderer::PostInit()
|
||||
}
|
||||
|
||||
// Forwards render target clearing through the C ABI.
|
||||
void DynamicRenderer::ClearDestination(Texture *texture, double r, double g,
|
||||
void DynamicRenderer::clear_destination(Texture *texture, double r, double g,
|
||||
double b, double a)
|
||||
{
|
||||
clear_destination_(handle_, texture, r, g, b, a);
|
||||
@@ -277,7 +277,7 @@ void DynamicRenderer::ClearDestination(Texture *texture, double r, double g,
|
||||
|
||||
// Creates a backend-native shader and receives the result as an opaque QVariant
|
||||
// because this first-generation ABI still shares C++/Qt types between modules.
|
||||
QVariant DynamicRenderer::CreateNativeShader(ShaderCode code)
|
||||
QVariant DynamicRenderer::create_native_shader(ShaderCode code)
|
||||
{
|
||||
QVariant out;
|
||||
create_native_shader_(handle_, &code, &out);
|
||||
@@ -285,13 +285,13 @@ QVariant DynamicRenderer::CreateNativeShader(ShaderCode code)
|
||||
}
|
||||
|
||||
// Releases a backend-native shader handle.
|
||||
void DynamicRenderer::DestroyNativeShader(QVariant shader)
|
||||
void DynamicRenderer::destroy_native_shader(QVariant shader)
|
||||
{
|
||||
destroy_native_shader_(handle_, &shader);
|
||||
}
|
||||
|
||||
// Uploads CPU pixel data into a backend texture through the dynamic ABI.
|
||||
void DynamicRenderer::UploadToTexture(const QVariant &handle,
|
||||
void DynamicRenderer::upload_to_texture(const QVariant &handle,
|
||||
const VideoParams ¶ms,
|
||||
const void *data, int linesize)
|
||||
{
|
||||
@@ -299,7 +299,7 @@ void DynamicRenderer::UploadToTexture(const QVariant &handle,
|
||||
}
|
||||
|
||||
// Downloads backend texture data into a caller-provided CPU buffer.
|
||||
void DynamicRenderer::DownloadFromTexture(const QVariant &handle,
|
||||
void DynamicRenderer::download_from_texture(const QVariant &handle,
|
||||
const VideoParams ¶ms, void *data,
|
||||
int linesize)
|
||||
{
|
||||
@@ -307,13 +307,13 @@ void DynamicRenderer::DownloadFromTexture(const QVariant &handle,
|
||||
}
|
||||
|
||||
// Waits for backend work to become visible to subsequent CPU or GPU consumers.
|
||||
void DynamicRenderer::Flush()
|
||||
void DynamicRenderer::flush()
|
||||
{
|
||||
flush_(handle_);
|
||||
}
|
||||
|
||||
// Reads a single pixel through the backend-provided readback hook.
|
||||
Color DynamicRenderer::GetPixelFromTexture(Texture *texture, const QPointF &pt)
|
||||
Color DynamicRenderer::get_pixel_from_texture(Texture *texture, const QPointF &pt)
|
||||
{
|
||||
Color out;
|
||||
get_pixel_from_texture_(handle_, texture, &pt, &out);
|
||||
@@ -322,7 +322,7 @@ Color DynamicRenderer::GetPixelFromTexture(Texture *texture, const QPointF &pt)
|
||||
|
||||
// Exposes the wrapped OpenGL context when the backend is OpenGL; Vulkan returns
|
||||
// null so callers can avoid GL-only paths.
|
||||
QOpenGLContext *DynamicRenderer::OpenGLContext() const
|
||||
QOpenGLContext *DynamicRenderer::open_gl_context() const
|
||||
{
|
||||
return opengl_context_ && handle_ ?
|
||||
static_cast<QOpenGLContext *>(opengl_context_(handle_)) :
|
||||
@@ -330,18 +330,18 @@ QOpenGLContext *DynamicRenderer::OpenGLContext() const
|
||||
}
|
||||
|
||||
// Reports the effective backend after any load-time fallback has completed.
|
||||
bool DynamicRenderer::IsOpenGL() const
|
||||
bool DynamicRenderer::is_open_gl() const
|
||||
{
|
||||
return backend_ == QStringLiteral("opengl");
|
||||
}
|
||||
|
||||
bool DynamicRenderer::IsVulkan() const
|
||||
bool DynamicRenderer::is_vulkan() const
|
||||
{
|
||||
return backend_ == QStringLiteral("vulkan");
|
||||
}
|
||||
|
||||
// Dispatches a shader blit to the loaded backend.
|
||||
void DynamicRenderer::Blit(QVariant shader, AcceleratedJob &job,
|
||||
void DynamicRenderer::blit(QVariant shader, AcceleratedJob &job,
|
||||
Texture *destination, VideoParams destination_params,
|
||||
bool clear_destination)
|
||||
{
|
||||
@@ -350,7 +350,7 @@ void DynamicRenderer::Blit(QVariant shader, AcceleratedJob &job,
|
||||
}
|
||||
|
||||
// Allocates a backend-native texture and wraps its opaque handle in QVariant.
|
||||
QVariant DynamicRenderer::CreateNativeTexture(int width, int height, int depth,
|
||||
QVariant DynamicRenderer::create_native_texture(int width, int height, int depth,
|
||||
PixelFormat format,
|
||||
int channel_count,
|
||||
const void *data, int linesize)
|
||||
@@ -362,14 +362,14 @@ QVariant DynamicRenderer::CreateNativeTexture(int width, int height, int depth,
|
||||
}
|
||||
|
||||
// Releases a backend-native texture handle.
|
||||
void DynamicRenderer::DestroyNativeTexture(QVariant texture)
|
||||
void DynamicRenderer::destroy_native_texture(QVariant texture)
|
||||
{
|
||||
destroy_native_texture_(handle_, &texture);
|
||||
}
|
||||
|
||||
// Releases renderer-owned backend resources before the backend object itself is
|
||||
// destroyed.
|
||||
void DynamicRenderer::DestroyInternal()
|
||||
void DynamicRenderer::destroy_internal()
|
||||
{
|
||||
if (handle_) {
|
||||
destroy_internal_(handle_);
|
||||
@@ -377,7 +377,7 @@ void DynamicRenderer::DestroyInternal()
|
||||
}
|
||||
|
||||
// Exposes OFX OpenGL output binding through the dynamic backend when supported.
|
||||
void DynamicRenderer::AttachOutputTexture(Texture *texture)
|
||||
void DynamicRenderer::attach_output_texture(Texture *texture)
|
||||
{
|
||||
if (attach_output_texture_ && texture) {
|
||||
QVariant id = texture->id();
|
||||
@@ -386,7 +386,7 @@ void DynamicRenderer::AttachOutputTexture(Texture *texture)
|
||||
}
|
||||
|
||||
// Clears any OFX output texture binding owned by the backend.
|
||||
void DynamicRenderer::DetachOutputTexture()
|
||||
void DynamicRenderer::detach_output_texture()
|
||||
{
|
||||
if (detach_output_texture_) {
|
||||
detach_output_texture_(handle_);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef DYNAMICRENDERER_H
|
||||
#define DYNAMICRENDERER_H
|
||||
#ifndef OAK_DYNAMICRENDERER_H
|
||||
#define OAK_DYNAMICRENDERER_H
|
||||
|
||||
#include <QLibrary>
|
||||
#include <QString>
|
||||
@@ -21,14 +21,14 @@ public:
|
||||
// Destroys backend resources and unloads the dynamic library.
|
||||
virtual ~DynamicRenderer() override;
|
||||
|
||||
using Renderer::Blit;
|
||||
using Renderer::blit;
|
||||
|
||||
// Loads the backend library, resolves C ABI symbols, and creates the handle.
|
||||
bool Load();
|
||||
bool load();
|
||||
// Initializes an OpenGL backend with a caller-owned viewer context.
|
||||
bool InitWithOpenGLContext(QOpenGLContext *context);
|
||||
bool init_with_open_gl_context(QOpenGLContext *context);
|
||||
// Retrieves backend metadata through the optional info entry point.
|
||||
bool GetBackendInfo(OakRenderBackendInfo *out_info) const;
|
||||
bool get_backend_info(OakRenderBackendInfo *out_info) const;
|
||||
// Returns the effective backend after any load-time fallback.
|
||||
QString backend_name() const
|
||||
{
|
||||
@@ -36,70 +36,70 @@ public:
|
||||
}
|
||||
|
||||
// Initializes the backend using its default device/context path.
|
||||
virtual bool Init() override;
|
||||
virtual bool init() override;
|
||||
// Runs backend post-destroy cleanup.
|
||||
virtual void PostDestroy() override;
|
||||
virtual void post_destroy() override;
|
||||
// Runs backend post-init setup.
|
||||
virtual void PostInit() override;
|
||||
virtual void post_init() override;
|
||||
// Clears either a native texture destination or the backend output target.
|
||||
virtual void ClearDestination(Texture *texture = nullptr, double r = 0.0,
|
||||
virtual void clear_destination(Texture *texture = nullptr, double r = 0.0,
|
||||
double g = 0.0, double b = 0.0,
|
||||
double a = 0.0) override;
|
||||
// Creates a native shader through the dynamic backend.
|
||||
virtual QVariant CreateNativeShader(ShaderCode code) override;
|
||||
virtual QVariant create_native_shader(ShaderCode code) override;
|
||||
// Destroys a native shader through the dynamic backend.
|
||||
virtual void DestroyNativeShader(QVariant shader) override;
|
||||
virtual void destroy_native_shader(QVariant shader) override;
|
||||
// Uploads CPU pixels to a backend texture.
|
||||
virtual void UploadToTexture(const QVariant &handle,
|
||||
virtual void upload_to_texture(const QVariant &handle,
|
||||
const VideoParams ¶ms, const void *data,
|
||||
int linesize) override;
|
||||
// Downloads backend texture pixels to CPU memory.
|
||||
virtual void DownloadFromTexture(const QVariant &handle,
|
||||
virtual void download_from_texture(const QVariant &handle,
|
||||
const VideoParams ¶ms, void *data,
|
||||
int linesize) override;
|
||||
// Waits for backend work to complete.
|
||||
virtual void Flush() override;
|
||||
virtual void flush() override;
|
||||
// Reads one pixel from a backend texture.
|
||||
virtual Color GetPixelFromTexture(Texture *texture,
|
||||
virtual Color get_pixel_from_texture(Texture *texture,
|
||||
const QPointF &pt) override;
|
||||
// Returns the wrapped OpenGL context for OpenGL backends.
|
||||
virtual QOpenGLContext *OpenGLContext() const override;
|
||||
virtual QOpenGLContext *open_gl_context() const override;
|
||||
|
||||
// Reports whether the effective backend is OpenGL.
|
||||
virtual bool IsOpenGL() const override;
|
||||
virtual bool is_open_gl() const override;
|
||||
// Reports whether the effective backend is Vulkan.
|
||||
virtual bool IsVulkan() const override;
|
||||
virtual bool is_vulkan() const override;
|
||||
|
||||
// Attaches a texture for OFX OpenGL output when supported.
|
||||
virtual void AttachOutputTexture(Texture *texture) override;
|
||||
virtual void attach_output_texture(Texture *texture) override;
|
||||
|
||||
// Detaches any OFX output texture binding when supported.
|
||||
virtual void DetachOutputTexture() override;
|
||||
virtual void detach_output_texture() override;
|
||||
|
||||
protected:
|
||||
// Dispatches a shader blit through the dynamic backend.
|
||||
virtual void Blit(QVariant shader, AcceleratedJob &job,
|
||||
virtual void blit(QVariant shader, AcceleratedJob &job,
|
||||
Texture *destination, VideoParams destination_params,
|
||||
bool clear_destination) override;
|
||||
// Allocates a native texture through the dynamic backend.
|
||||
virtual QVariant CreateNativeTexture(int width, int height, int depth,
|
||||
virtual QVariant create_native_texture(int width, int height, int depth,
|
||||
PixelFormat format, int channel_count,
|
||||
const void *data = nullptr,
|
||||
int linesize = 0) override;
|
||||
// Releases a native texture through the dynamic backend.
|
||||
virtual void DestroyNativeTexture(QVariant texture) override;
|
||||
virtual void destroy_native_texture(QVariant texture) override;
|
||||
// Releases backend-owned renderer resources.
|
||||
virtual void DestroyInternal() override;
|
||||
virtual void destroy_internal() override;
|
||||
|
||||
private:
|
||||
// Resolves required backend C ABI symbols.
|
||||
bool ResolveFunctions();
|
||||
bool resolve_functions();
|
||||
// Replaces a failed Vulkan backend with OpenGL.
|
||||
bool FallbackToOpenGL();
|
||||
bool fallback_to_open_gl();
|
||||
// Clears all cached function pointers.
|
||||
void ResetFunctions();
|
||||
void reset_functions();
|
||||
// Resolves the private backend library path.
|
||||
QString LibraryFilename() const;
|
||||
QString library_filename() const;
|
||||
|
||||
QString backend_;
|
||||
QLibrary library_;
|
||||
@@ -131,4 +131,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // DYNAMICRENDERER_H
|
||||
#endif // OAK_DYNAMICRENDERER_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef RENDERBACKEND_C_H
|
||||
#define RENDERBACKEND_C_H
|
||||
#ifndef OAK_RENDERBACKEND_C_H
|
||||
#define OAK_RENDERBACKEND_C_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@@ -20,20 +20,20 @@ typedef void *OakRenderBackendHandle;
|
||||
|
||||
/* Identifies the concrete backend behind a dynamically loaded library. */
|
||||
enum OakRenderBackendKind {
|
||||
OAK_RENDER_BACKEND_UNKNOWN = 0,
|
||||
OAK_RENDER_BACKEND_OPENGL = 1,
|
||||
OAK_RENDER_BACKEND_VULKAN = 2
|
||||
oak_render_backend_unknown = 0,
|
||||
oak_render_backend_opengl = 1,
|
||||
oak_render_backend_vulkan = 2
|
||||
};
|
||||
|
||||
/* Capability bits advertised by a backend through oak_renderer_get_info(). */
|
||||
enum OakRenderBackendCapability {
|
||||
OAK_RENDER_BACKEND_CAP_TEXTURES = 1ULL << 0,
|
||||
OAK_RENDER_BACKEND_CAP_SHADERS = 1ULL << 1,
|
||||
OAK_RENDER_BACKEND_CAP_BLIT = 1ULL << 2,
|
||||
OAK_RENDER_BACKEND_CAP_READBACK = 1ULL << 3,
|
||||
OAK_RENDER_BACKEND_CAP_VIEWER_CONTEXT = 1ULL << 4,
|
||||
OAK_RENDER_BACKEND_CAP_INSTANCE = 1ULL << 5,
|
||||
OAK_RENDER_BACKEND_CAP_DEVICE = 1ULL << 6
|
||||
oak_render_backend_cap_textures = 1ULL << 0,
|
||||
oak_render_backend_cap_shaders = 1ULL << 1,
|
||||
oak_render_backend_cap_blit = 1ULL << 2,
|
||||
oak_render_backend_cap_readback = 1ULL << 3,
|
||||
oak_render_backend_cap_viewer_context = 1ULL << 4,
|
||||
oak_render_backend_cap_instance = 1ULL << 5,
|
||||
oak_render_backend_cap_device = 1ULL << 6
|
||||
};
|
||||
|
||||
/* Static and runtime metadata returned by the backend. */
|
||||
@@ -118,4 +118,4 @@ typedef void *(*OakBackendOpenGLContextFn)(OakRenderBackendHandle handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // RENDERBACKEND_C_H
|
||||
#endif // OAK_RENDERBACKEND_C_H
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CANCELATOM_H
|
||||
#define CANCELATOM_H
|
||||
#ifndef OAK_CANCELATOM_H
|
||||
#define OAK_CANCELATOM_H
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
bool IsCancelled()
|
||||
bool is_cancelled()
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
if (cancelled_) {
|
||||
@@ -41,13 +41,13 @@ public:
|
||||
return cancelled_;
|
||||
}
|
||||
|
||||
void Cancel()
|
||||
void cancel()
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
cancelled_ = true;
|
||||
}
|
||||
|
||||
bool HeardCancel()
|
||||
bool heard_cancel()
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
return heard_;
|
||||
@@ -63,4 +63,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // CANCELATOM_H
|
||||
#endif // OAK_CANCELATOM_H
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
bool Renderer::GetColorContext(const ColorTransformJob &color_job,
|
||||
bool Renderer::get_color_context(const ColorTransformJob &color_job,
|
||||
Renderer::ColorContext *ctx)
|
||||
{
|
||||
QMutexLocker locker(&color_cache_mutex_);
|
||||
@@ -47,37 +47,37 @@ bool Renderer::GetColorContext(const ColorTransformJob &color_job,
|
||||
|
||||
// Create shader description
|
||||
QString ocio_func_name;
|
||||
if (color_job.GetFunctionName().isEmpty()) {
|
||||
if (color_job.get_function_name().isEmpty()) {
|
||||
ocio_func_name = "OCIODisplay";
|
||||
} else {
|
||||
ocio_func_name = color_job.GetFunctionName();
|
||||
ocio_func_name = color_job.get_function_name();
|
||||
}
|
||||
auto shader_desc = OCIO::GpuShaderDesc::CreateShaderDesc();
|
||||
shader_desc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_ES_3_0);
|
||||
auto shader_desc = ocio::GpuShaderDesc::CreateShaderDesc();
|
||||
shader_desc->setLanguage(ocio::GPU_LANGUAGE_GLSL_ES_3_0);
|
||||
shader_desc->setFunctionName(ocio_func_name.toUtf8());
|
||||
shader_desc->setResourcePrefix("ocio_");
|
||||
|
||||
// Generate shader
|
||||
color_job.GetColorProcessor()
|
||||
->GetProcessor()
|
||||
color_job.get_color_processor()
|
||||
->get_processor()
|
||||
->getDefaultGPUProcessor()
|
||||
->extractGpuShaderInfo(shader_desc);
|
||||
|
||||
ShaderCode code;
|
||||
if (const Node *shader_src = color_job.CustomShaderSource()) {
|
||||
if (const Node *shader_src = color_job.custom_shader_source()) {
|
||||
// Use shader code from associated node
|
||||
code = shader_src->GetShaderCode(
|
||||
{ color_job.CustomShaderID(), shader_desc->getShaderText() });
|
||||
code = shader_src->get_shader_code(
|
||||
{ color_job.custom_shader_id(), shader_desc->getShaderText() });
|
||||
} else {
|
||||
// Generate shader code using OCIO stub and our auto-generated name
|
||||
code = FileFunctions::ReadFileAsString(
|
||||
code = FileFunctions::read_file_as_string(
|
||||
QStringLiteral(":/shaders/colormanage.frag"));
|
||||
code.set_frag_code(
|
||||
code.frag_code().arg(shader_desc->getShaderText()));
|
||||
}
|
||||
|
||||
// Try to compile shader
|
||||
color_ctx.compiled_shader = CreateNativeShader(code);
|
||||
color_ctx.compiled_shader = create_native_shader(code);
|
||||
|
||||
if (color_ctx.compiled_shader.isNull()) {
|
||||
return false;
|
||||
@@ -88,7 +88,7 @@ bool Renderer::GetColorContext(const ColorTransformJob &color_job,
|
||||
const char *tex_name = nullptr;
|
||||
const char *sampler_name = nullptr;
|
||||
unsigned int edge_len = 0;
|
||||
OCIO::Interpolation interpolation = OCIO::INTERP_LINEAR;
|
||||
ocio::Interpolation interpolation = ocio::INTERP_LINEAR;
|
||||
|
||||
shader_desc->get3DTexture(i, tex_name, sampler_name, edge_len,
|
||||
interpolation);
|
||||
@@ -107,14 +107,14 @@ bool Renderer::GetColorContext(const ColorTransformJob &color_job,
|
||||
}
|
||||
|
||||
// Allocate 3D LUT
|
||||
color_ctx.lut3d_textures[i].texture = CreateTexture(
|
||||
VideoParams(edge_len, edge_len, edge_len, PixelFormat::F32,
|
||||
VideoParams::kRGBChannelCount),
|
||||
color_ctx.lut3d_textures[i].texture = create_texture(
|
||||
VideoParams(edge_len, edge_len, edge_len, PixelFormat::f32,
|
||||
VideoParams::k_rgb_channel_count),
|
||||
values);
|
||||
color_ctx.lut3d_textures[i].name = sampler_name;
|
||||
color_ctx.lut3d_textures[i].interpolation =
|
||||
(interpolation == OCIO::INTERP_NEAREST) ? Texture::kNearest :
|
||||
Texture::kLinear;
|
||||
(interpolation == ocio::INTERP_NEAREST) ? Texture::k_nearest :
|
||||
Texture::k_linear;
|
||||
}
|
||||
|
||||
color_ctx.lut1d_textures.resize(shader_desc->getNumTextures());
|
||||
@@ -122,13 +122,13 @@ bool Renderer::GetColorContext(const ColorTransformJob &color_job,
|
||||
const char *tex_name = nullptr;
|
||||
const char *sampler_name = nullptr;
|
||||
unsigned int width = 0, height = 0;
|
||||
OCIO::GpuShaderDesc::TextureType channel =
|
||||
OCIO::GpuShaderDesc::TEXTURE_RGB_CHANNEL;
|
||||
OCIO::Interpolation interpolation = OCIO::INTERP_LINEAR;
|
||||
ocio::GpuShaderDesc::TextureType channel =
|
||||
ocio::GpuShaderDesc::TEXTURE_RGB_CHANNEL;
|
||||
ocio::Interpolation interpolation = ocio::INTERP_LINEAR;
|
||||
#if OCIO_VERSION_MAJOR > 2 || \
|
||||
(OCIO_VERSION_MAJOR == 2 && OCIO_VERSION_MINOR >= 3)
|
||||
OCIO::GpuShaderDesc::TextureDimensions dimensions =
|
||||
OCIO::GpuShaderDesc::TEXTURE_2D;
|
||||
ocio::GpuShaderDesc::TextureDimensions dimensions =
|
||||
ocio::GpuShaderDesc::TEXTURE_2D;
|
||||
shader_desc->getTexture(i, tex_name, sampler_name, width, height,
|
||||
channel, dimensions, interpolation);
|
||||
#else
|
||||
@@ -151,17 +151,17 @@ bool Renderer::GetColorContext(const ColorTransformJob &color_job,
|
||||
|
||||
// Allocate 1D LUT
|
||||
int lut_channels =
|
||||
(channel == OCIO::GpuShaderDesc::TEXTURE_RED_CHANNEL) ?
|
||||
(channel == ocio::GpuShaderDesc::TEXTURE_RED_CHANNEL) ?
|
||||
1 :
|
||||
VideoParams::kRGBChannelCount;
|
||||
VideoParams lut_params(width, height, PixelFormat::F32,
|
||||
VideoParams::k_rgb_channel_count;
|
||||
VideoParams lut_params(width, height, PixelFormat::f32,
|
||||
lut_channels);
|
||||
color_ctx.lut1d_textures[i].texture =
|
||||
CreateTexture(lut_params, values);
|
||||
create_texture(lut_params, values);
|
||||
color_ctx.lut1d_textures[i].name = sampler_name;
|
||||
color_ctx.lut1d_textures[i].interpolation =
|
||||
(interpolation == OCIO::INTERP_NEAREST) ? Texture::kNearest :
|
||||
Texture::kLinear;
|
||||
(interpolation == ocio::INTERP_NEAREST) ? Texture::k_nearest :
|
||||
Texture::k_linear;
|
||||
}
|
||||
|
||||
locker.relock();
|
||||
@@ -171,59 +171,59 @@ bool Renderer::GetColorContext(const ColorTransformJob &color_job,
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::BlitColorManaged(const ColorTransformJob &color_job,
|
||||
void Renderer::blit_color_managed(const ColorTransformJob &color_job,
|
||||
Texture *destination, const VideoParams ¶ms)
|
||||
{
|
||||
ColorContext color_ctx;
|
||||
if (!GetColorContext(color_job, &color_ctx)) {
|
||||
if (!get_color_context(color_job, &color_ctx)) {
|
||||
ShaderJob fallback_job;
|
||||
fallback_job.Insert(QStringLiteral("ove_maintex"),
|
||||
color_job.GetInputTexture());
|
||||
fallback_job.Insert(QStringLiteral("ove_mvpmat"),
|
||||
NodeValue(NodeValue::kMatrix,
|
||||
color_job.GetTransformMatrix()));
|
||||
fallback_job.insert(QStringLiteral("ove_maintex"),
|
||||
color_job.get_input_texture());
|
||||
fallback_job.insert(QStringLiteral("ove_mvpmat"),
|
||||
NodeValue(NodeValue::k_matrix,
|
||||
color_job.get_transform_matrix()));
|
||||
|
||||
if (destination) {
|
||||
BlitToTexture(GetDefaultShader(), fallback_job, destination,
|
||||
color_job.IsClearDestinationEnabled());
|
||||
blit_to_texture(get_default_shader(), fallback_job, destination,
|
||||
color_job.is_clear_destination_enabled());
|
||||
} else {
|
||||
Blit(GetDefaultShader(), fallback_job, params,
|
||||
color_job.IsClearDestinationEnabled());
|
||||
blit(get_default_shader(), fallback_job, params,
|
||||
color_job.is_clear_destination_enabled());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ShaderJob job;
|
||||
job.Insert(QStringLiteral("ove_maintex"), color_job.GetInputTexture());
|
||||
job.Insert(QStringLiteral("ove_mvpmat"),
|
||||
NodeValue(NodeValue::kMatrix, color_job.GetTransformMatrix()));
|
||||
job.Insert(QStringLiteral("ove_cropmatrix"),
|
||||
NodeValue(NodeValue::kMatrix,
|
||||
color_job.GetCropMatrix().inverted()));
|
||||
job.Insert(QStringLiteral("ove_maintex_alpha"),
|
||||
NodeValue(NodeValue::kInt,
|
||||
int(color_job.GetInputAlphaAssociation())));
|
||||
job.Insert(QStringLiteral("ove_force_opaque"),
|
||||
NodeValue(NodeValue::kBoolean, color_job.GetForceOpaque()));
|
||||
job.Insert(color_job.GetValues());
|
||||
job.insert(QStringLiteral("ove_maintex"), color_job.get_input_texture());
|
||||
job.insert(QStringLiteral("ove_mvpmat"),
|
||||
NodeValue(NodeValue::k_matrix, color_job.get_transform_matrix()));
|
||||
job.insert(QStringLiteral("ove_cropmatrix"),
|
||||
NodeValue(NodeValue::k_matrix,
|
||||
color_job.get_crop_matrix().inverted()));
|
||||
job.insert(QStringLiteral("ove_maintex_alpha"),
|
||||
NodeValue(NodeValue::k_int,
|
||||
int(color_job.get_input_alpha_association())));
|
||||
job.insert(QStringLiteral("ove_force_opaque"),
|
||||
NodeValue(NodeValue::k_boolean, color_job.get_force_opaque()));
|
||||
job.insert(color_job.get_values());
|
||||
|
||||
foreach (const ColorContext::LUT &l, color_ctx.lut3d_textures) {
|
||||
job.Insert(l.name, NodeValue(NodeValue::kTexture,
|
||||
job.insert(l.name, NodeValue(NodeValue::k_texture,
|
||||
QVariant::fromValue(l.texture)));
|
||||
job.SetInterpolation(l.name, l.interpolation);
|
||||
job.set_interpolation(l.name, l.interpolation);
|
||||
}
|
||||
foreach (const ColorContext::LUT &l, color_ctx.lut1d_textures) {
|
||||
job.Insert(l.name, NodeValue(NodeValue::kTexture,
|
||||
job.insert(l.name, NodeValue(NodeValue::k_texture,
|
||||
QVariant::fromValue(l.texture)));
|
||||
job.SetInterpolation(l.name, l.interpolation);
|
||||
job.set_interpolation(l.name, l.interpolation);
|
||||
}
|
||||
|
||||
if (destination) {
|
||||
BlitToTexture(color_ctx.compiled_shader, job, destination,
|
||||
color_job.IsClearDestinationEnabled());
|
||||
blit_to_texture(color_ctx.compiled_shader, job, destination,
|
||||
color_job.is_clear_destination_enabled());
|
||||
} else {
|
||||
Blit(color_ctx.compiled_shader, job, params,
|
||||
color_job.IsClearDestinationEnabled());
|
||||
blit(color_ctx.compiled_shader, job, params,
|
||||
color_job.is_clear_destination_enabled());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,40 +39,40 @@ ColorProcessor::ColorProcessor(ColorManager *config, const QString &input,
|
||||
// Resolve role names (e.g. "scene_linear") to canonical colorspace names
|
||||
// so they can be passed to getProcessor()/DisplayViewTransform.
|
||||
QString resolved_input = input;
|
||||
OCIO::ConstConfigRcPtr ocio_config = config->GetConfig();
|
||||
ocio::ConstConfigRcPtr ocio_config = config->get_config();
|
||||
if (ocio_config && ocio_config->hasRole(input.toUtf8())) {
|
||||
resolved_input = ocio_config->getCanonicalName(input.toUtf8());
|
||||
}
|
||||
|
||||
const QString &output = (transform.output().isEmpty()) ?
|
||||
config->GetDefaultDisplay() :
|
||||
config->get_default_display() :
|
||||
transform.output();
|
||||
|
||||
if (transform.is_display()) {
|
||||
const QString &view = (transform.view().isEmpty()) ?
|
||||
config->GetDefaultView(output) :
|
||||
config->get_default_view(output) :
|
||||
transform.view();
|
||||
|
||||
auto display_transform = OCIO::DisplayViewTransform::Create();
|
||||
auto display_transform = ocio::DisplayViewTransform::Create();
|
||||
|
||||
display_transform->setSrc(resolved_input.toUtf8());
|
||||
display_transform->setDisplay(output.toUtf8());
|
||||
display_transform->setView(view.toUtf8());
|
||||
display_transform->setDirection(direction == kNormal ?
|
||||
OCIO::TRANSFORM_DIR_FORWARD :
|
||||
OCIO::TRANSFORM_DIR_INVERSE);
|
||||
display_transform->setDirection(direction == k_normal ?
|
||||
ocio::TRANSFORM_DIR_FORWARD :
|
||||
ocio::TRANSFORM_DIR_INVERSE);
|
||||
|
||||
if (transform.look().isEmpty()) {
|
||||
processor_ = ocio_config->getProcessor(display_transform);
|
||||
} else {
|
||||
auto group = OCIO::GroupTransform::Create();
|
||||
auto group = ocio::GroupTransform::Create();
|
||||
|
||||
const char *out_cs =
|
||||
OCIO::LookTransform::GetLooksResultColorSpace(
|
||||
ocio::LookTransform::GetLooksResultColorSpace(
|
||||
ocio_config, ocio_config->getCurrentContext(),
|
||||
transform.look().toUtf8());
|
||||
|
||||
auto lt = OCIO::LookTransform::Create();
|
||||
auto lt = ocio::LookTransform::Create();
|
||||
lt->setSrc(resolved_input.toUtf8());
|
||||
lt->setDst(out_cs);
|
||||
lt->setLooks(transform.look().toUtf8());
|
||||
@@ -86,7 +86,7 @@ ColorProcessor::ColorProcessor(ColorManager *config, const QString &input,
|
||||
}
|
||||
|
||||
} else {
|
||||
if (direction == kNormal) {
|
||||
if (direction == k_normal) {
|
||||
processor_ = ocio_config->getProcessor(resolved_input.toUtf8(),
|
||||
output.toUtf8());
|
||||
} else {
|
||||
@@ -98,41 +98,41 @@ ColorProcessor::ColorProcessor(ColorManager *config, const QString &input,
|
||||
if (processor_) {
|
||||
cpu_processor_ = processor_->getDefaultCPUProcessor();
|
||||
}
|
||||
} catch (OCIO::Exception &e) {
|
||||
} catch (ocio::Exception &e) {
|
||||
qWarning() << "ColorProcessor exception:" << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
ColorProcessor::ColorProcessor(OCIO::ConstProcessorRcPtr processor)
|
||||
ColorProcessor::ColorProcessor(ocio::ConstProcessorRcPtr processor)
|
||||
{
|
||||
processor_ = processor;
|
||||
cpu_processor_ = processor_ ? processor_->getDefaultCPUProcessor() :
|
||||
nullptr;
|
||||
}
|
||||
|
||||
void ColorProcessor::ConvertFrame(Frame *f)
|
||||
void ColorProcessor::convert_frame(Frame *f)
|
||||
{
|
||||
if (!cpu_processor_) {
|
||||
return;
|
||||
}
|
||||
|
||||
OCIO::BitDepth ocio_bit_depth =
|
||||
OCIOUtils::GetOCIOBitDepthFromPixelFormat(f->format());
|
||||
ocio::BitDepth ocio_bit_depth =
|
||||
OCIOUtils::get_ocio_bit_depth_from_pixel_format(f->format());
|
||||
|
||||
if (ocio_bit_depth == OCIO::BIT_DEPTH_UNKNOWN) {
|
||||
if (ocio_bit_depth == ocio::BIT_DEPTH_UNKNOWN) {
|
||||
qCritical() << "Tried to color convert frame with no format";
|
||||
return;
|
||||
}
|
||||
|
||||
OCIO::PackedImageDesc img(f->data(), f->width(), f->height(),
|
||||
ocio::PackedImageDesc img(f->data(), f->width(), f->height(),
|
||||
f->channel_count(), ocio_bit_depth,
|
||||
OCIO::AutoStride, OCIO::AutoStride,
|
||||
ocio::AutoStride, ocio::AutoStride,
|
||||
f->linesize_bytes());
|
||||
|
||||
cpu_processor_->apply(img);
|
||||
}
|
||||
|
||||
Color ColorProcessor::ConvertColor(const Color &in)
|
||||
Color ColorProcessor::convert_color(const Color &in)
|
||||
{
|
||||
if (!cpu_processor_) {
|
||||
return in;
|
||||
@@ -147,7 +147,7 @@ Color ColorProcessor::ConvertColor(const Color &in)
|
||||
return Color(c[0], c[1], c[2], c[3]);
|
||||
}
|
||||
|
||||
ColorProcessorPtr ColorProcessor::Create(ColorManager *config,
|
||||
ColorProcessorPtr ColorProcessor::create(ColorManager *config,
|
||||
const QString &input,
|
||||
const ColorTransform &transform,
|
||||
Direction direction)
|
||||
@@ -156,19 +156,19 @@ ColorProcessorPtr ColorProcessor::Create(ColorManager *config,
|
||||
direction);
|
||||
}
|
||||
|
||||
ColorProcessorPtr ColorProcessor::Create(OCIO::ConstProcessorRcPtr processor)
|
||||
ColorProcessorPtr ColorProcessor::create(ocio::ConstProcessorRcPtr processor)
|
||||
{
|
||||
return std::make_shared<ColorProcessor>(processor);
|
||||
}
|
||||
|
||||
OCIO::ConstProcessorRcPtr ColorProcessor::GetProcessor()
|
||||
ocio::ConstProcessorRcPtr ColorProcessor::get_processor()
|
||||
{
|
||||
return processor_;
|
||||
}
|
||||
|
||||
void ColorProcessor::ConvertFrame(FramePtr f)
|
||||
void ColorProcessor::convert_frame(FramePtr f)
|
||||
{
|
||||
ConvertFrame(f.get());
|
||||
convert_frame(f.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-15
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef COLORPROCESSOR_H
|
||||
#define COLORPROCESSOR_H
|
||||
#ifndef OAK_COLORPROCESSOR_H
|
||||
#define OAK_COLORPROCESSOR_H
|
||||
|
||||
#include "codec/frame.h"
|
||||
#include "common/ocioutils.h"
|
||||
@@ -36,26 +36,26 @@ using ColorProcessorPtr = std::shared_ptr<ColorProcessor>;
|
||||
|
||||
class ColorProcessor {
|
||||
public:
|
||||
enum Direction { kNormal, kInverse };
|
||||
enum Direction { k_normal, k_inverse };
|
||||
|
||||
ColorProcessor(ColorManager *config, const QString &input,
|
||||
const ColorTransform &dest_space,
|
||||
Direction direction = kNormal);
|
||||
ColorProcessor(OCIO::ConstProcessorRcPtr processor);
|
||||
Direction direction = k_normal);
|
||||
ColorProcessor(ocio::ConstProcessorRcPtr processor);
|
||||
|
||||
DISABLE_COPY_MOVE(ColorProcessor)
|
||||
|
||||
static ColorProcessorPtr Create(ColorManager *config, const QString &input,
|
||||
static ColorProcessorPtr create(ColorManager *config, const QString &input,
|
||||
const ColorTransform &dest_space,
|
||||
Direction direction = kNormal);
|
||||
static ColorProcessorPtr Create(OCIO::ConstProcessorRcPtr processor);
|
||||
Direction direction = k_normal);
|
||||
static ColorProcessorPtr create(ocio::ConstProcessorRcPtr processor);
|
||||
|
||||
OCIO::ConstProcessorRcPtr GetProcessor();
|
||||
ocio::ConstProcessorRcPtr get_processor();
|
||||
|
||||
void ConvertFrame(FramePtr f);
|
||||
void ConvertFrame(Frame *f);
|
||||
void convert_frame(FramePtr f);
|
||||
void convert_frame(Frame *f);
|
||||
|
||||
Color ConvertColor(const Color &in);
|
||||
Color convert_color(const Color &in);
|
||||
|
||||
const char *id() const
|
||||
{
|
||||
@@ -63,9 +63,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
OCIO::ConstProcessorRcPtr processor_;
|
||||
ocio::ConstProcessorRcPtr processor_;
|
||||
|
||||
OCIO::ConstCPUProcessorRcPtr cpu_processor_;
|
||||
ocio::ConstCPUProcessorRcPtr cpu_processor_;
|
||||
};
|
||||
|
||||
using ColorProcessorChain = QVector<ColorProcessorPtr>;
|
||||
@@ -74,4 +74,4 @@ using ColorProcessorChain = QVector<ColorProcessorPtr>;
|
||||
|
||||
Q_DECLARE_METATYPE(olive::ColorProcessorPtr)
|
||||
|
||||
#endif // COLORPROCESSOR_H
|
||||
#endif // OAK_COLORPROCESSOR_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef COLORPROCESSORCACHE_H
|
||||
#define COLORPROCESSORCACHE_H
|
||||
#ifndef OAK_COLORPROCESSORCACHE_H
|
||||
#define OAK_COLORPROCESSORCACHE_H
|
||||
|
||||
#include "render/colorprocessor.h"
|
||||
|
||||
@@ -31,4 +31,4 @@ using ColorProcessorCache = QHash<QString, ColorProcessorPtr>;
|
||||
|
||||
}
|
||||
|
||||
#endif // COLORPROCESSORCACHE_H
|
||||
#endif // OAK_COLORPROCESSORCACHE_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef COLORTRANSFORM_H
|
||||
#define COLORTRANSFORM_H
|
||||
#ifndef OAK_COLORTRANSFORM_H
|
||||
#define OAK_COLORTRANSFORM_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
@@ -89,4 +89,4 @@ private:
|
||||
|
||||
Q_DECLARE_METATYPE(olive::ColorTransform)
|
||||
|
||||
#endif // COLORTRANSFORM_H
|
||||
#endif // OAK_COLORTRANSFORM_H
|
||||
|
||||
+61
-61
@@ -41,13 +41,13 @@ DiskManager *DiskManager::instance_ = nullptr;
|
||||
DiskManager::DiskManager()
|
||||
{
|
||||
// Add default cache location
|
||||
QFile default_disk_cache_file(GetDefaultDiskCacheConfigFile());
|
||||
QFile default_disk_cache_file(get_default_disk_cache_config_file());
|
||||
if (default_disk_cache_file.open(QFile::ReadOnly)) {
|
||||
QString default_dir = default_disk_cache_file.readAll();
|
||||
|
||||
if (!default_dir.isEmpty()) {
|
||||
if (FileFunctions::DirectoryIsValid(default_dir)) {
|
||||
GetOpenFolder(default_dir);
|
||||
if (FileFunctions::directory_is_valid(default_dir)) {
|
||||
get_open_folder(default_dir);
|
||||
} else {
|
||||
QMessageBox::warning(
|
||||
nullptr, tr("Disk Cache Error"),
|
||||
@@ -60,10 +60,10 @@ DiskManager::DiskManager()
|
||||
|
||||
// If no custom default was loaded, load default
|
||||
if (open_folders_.isEmpty()) {
|
||||
GetOpenFolder(GetDefaultDiskCachePath());
|
||||
get_open_folder(get_default_disk_cache_path());
|
||||
}
|
||||
|
||||
QFile disk_cache_index(QDir(FileFunctions::GetConfigurationLocation())
|
||||
QFile disk_cache_index(QDir(FileFunctions::get_configuration_location())
|
||||
.filePath(QStringLiteral("diskcache2")));
|
||||
|
||||
if (disk_cache_index.open(QFile::ReadOnly)) {
|
||||
@@ -71,7 +71,7 @@ DiskManager::DiskManager()
|
||||
|
||||
QString line;
|
||||
while (stream.readLineInto(&line)) {
|
||||
GetOpenFolder(line);
|
||||
get_open_folder(line);
|
||||
}
|
||||
|
||||
disk_cache_index.close();
|
||||
@@ -80,22 +80,22 @@ DiskManager::DiskManager()
|
||||
|
||||
DiskManager::~DiskManager()
|
||||
{
|
||||
QFile default_disk_cache_file(GetDefaultDiskCacheConfigFile());
|
||||
QFile default_disk_cache_file(get_default_disk_cache_config_file());
|
||||
if (default_disk_cache_file.open(QFile::WriteOnly)) {
|
||||
if (GetDefaultDiskCachePath() != GetDefaultCachePath()) {
|
||||
default_disk_cache_file.write(GetDefaultCachePath().toUtf8());
|
||||
if (get_default_disk_cache_path() != get_default_cache_path()) {
|
||||
default_disk_cache_file.write(get_default_cache_path().toUtf8());
|
||||
}
|
||||
|
||||
default_disk_cache_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
void DiskManager::CreateInstance()
|
||||
void DiskManager::create_instance()
|
||||
{
|
||||
instance_ = new DiskManager();
|
||||
}
|
||||
|
||||
void DiskManager::DestroyInstance()
|
||||
void DiskManager::destroy_instance()
|
||||
{
|
||||
delete instance_;
|
||||
instance_ = nullptr;
|
||||
@@ -106,59 +106,59 @@ DiskManager *DiskManager::instance()
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void DiskManager::Accessed(const QString &cache_folder, const QString &filename)
|
||||
void DiskManager::accessed(const QString &cache_folder, const QString &filename)
|
||||
{
|
||||
DiskCacheFolder *f = GetOpenFolder(cache_folder);
|
||||
DiskCacheFolder *f = get_open_folder(cache_folder);
|
||||
|
||||
f->Accessed(filename);
|
||||
f->accessed(filename);
|
||||
}
|
||||
|
||||
void DiskManager::CreatedFile(const QString &cache_folder,
|
||||
void DiskManager::created_file(const QString &cache_folder,
|
||||
const QString &filename)
|
||||
{
|
||||
DiskCacheFolder *f = GetOpenFolder(cache_folder);
|
||||
DiskCacheFolder *f = get_open_folder(cache_folder);
|
||||
|
||||
f->CreatedFile(filename);
|
||||
f->created_file(filename);
|
||||
}
|
||||
|
||||
void DiskManager::DeleteSpecificFile(const QString &filename)
|
||||
void DiskManager::delete_specific_file(const QString &filename)
|
||||
{
|
||||
foreach (DiskCacheFolder *f, open_folders_) {
|
||||
f->DeleteSpecificFile(filename);
|
||||
f->delete_specific_file(filename);
|
||||
}
|
||||
}
|
||||
|
||||
bool DiskManager::ClearDiskCache(const QString &cache_folder)
|
||||
bool DiskManager::clear_disk_cache(const QString &cache_folder)
|
||||
{
|
||||
DiskCacheFolder *f = GetOpenFolder(cache_folder);
|
||||
DiskCacheFolder *f = get_open_folder(cache_folder);
|
||||
|
||||
return f->ClearCache();
|
||||
return f->clear_cache();
|
||||
}
|
||||
|
||||
DiskCacheFolder *DiskManager::GetOpenFolder(const QString &path)
|
||||
DiskCacheFolder *DiskManager::get_open_folder(const QString &path)
|
||||
{
|
||||
// If path is empty, this must mean default
|
||||
if (path.isEmpty()) {
|
||||
return GetDefaultCacheFolder();
|
||||
return get_default_cache_folder();
|
||||
}
|
||||
|
||||
// See if we have an existing path with this name
|
||||
foreach (DiskCacheFolder *f, open_folders_) {
|
||||
if (f->GetPath() == path) {
|
||||
if (f->get_path() == path) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
// We must have to open this folder
|
||||
DiskCacheFolder *f = new DiskCacheFolder(path, this);
|
||||
connect(f, &DiskCacheFolder::DeletedFrame, this,
|
||||
&DiskManager::DeletedFrame);
|
||||
connect(f, &DiskCacheFolder::deleted_frame, this,
|
||||
&DiskManager::deleted_frame);
|
||||
open_folders_.append(f);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
bool DiskManager::ShowDiskCacheChangeConfirmationDialog(QWidget *parent)
|
||||
bool DiskManager::show_disk_cache_change_confirmation_dialog(QWidget *parent)
|
||||
{
|
||||
return (
|
||||
QMessageBox::question(
|
||||
@@ -168,30 +168,30 @@ bool DiskManager::ShowDiskCacheChangeConfirmationDialog(QWidget *parent)
|
||||
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok);
|
||||
}
|
||||
|
||||
QString DiskManager::GetDefaultDiskCacheConfigFile()
|
||||
QString DiskManager::get_default_disk_cache_config_file()
|
||||
{
|
||||
return QDir(FileFunctions::GetConfigurationLocation())
|
||||
return QDir(FileFunctions::get_configuration_location())
|
||||
.filePath(QStringLiteral("defaultdiskcache"));
|
||||
}
|
||||
|
||||
QString DiskManager::GetDefaultDiskCachePath()
|
||||
QString DiskManager::get_default_disk_cache_path()
|
||||
{
|
||||
return QDir(QStandardPaths::writableLocation(
|
||||
QStandardPaths::AppLocalDataLocation))
|
||||
.filePath("mediacache");
|
||||
}
|
||||
|
||||
void DiskManager::ShowDiskCacheSettingsDialog(DiskCacheFolder *folder,
|
||||
void DiskManager::show_disk_cache_settings_dialog(DiskCacheFolder *folder,
|
||||
QWidget *parent)
|
||||
{
|
||||
DiskCacheDialog d(folder, parent);
|
||||
d.exec();
|
||||
}
|
||||
|
||||
void DiskManager::ShowDiskCacheSettingsDialog(const QString &path,
|
||||
void DiskManager::show_disk_cache_settings_dialog(const QString &path,
|
||||
QWidget *parent)
|
||||
{
|
||||
if (!FileFunctions::DirectoryIsValid(path)) {
|
||||
if (!FileFunctions::directory_is_valid(path)) {
|
||||
QMessageBox::critical(
|
||||
parent, tr("Disk Cache Error"),
|
||||
tr("Failed to open disk cache at \"%1\". Try a different folder.")
|
||||
@@ -199,28 +199,28 @@ void DiskManager::ShowDiskCacheSettingsDialog(const QString &path,
|
||||
return;
|
||||
}
|
||||
|
||||
DiskCacheFolder *folder = GetOpenFolder(path);
|
||||
DiskCacheFolder *folder = get_open_folder(path);
|
||||
|
||||
ShowDiskCacheSettingsDialog(folder, parent);
|
||||
show_disk_cache_settings_dialog(folder, parent);
|
||||
}
|
||||
|
||||
DiskCacheFolder::DiskCacheFolder(const QString &path, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
SetPath(path);
|
||||
set_path(path);
|
||||
|
||||
save_timer_.setInterval(OLIVE_CONFIG("DiskCacheSaveInterval").toInt());
|
||||
save_timer_.setInterval(OAK_CONFIG("DiskCacheSaveInterval").toInt());
|
||||
connect(&save_timer_, &QTimer::timeout, this,
|
||||
&DiskCacheFolder::SaveDiskCacheIndex);
|
||||
&DiskCacheFolder::save_disk_cache_index);
|
||||
save_timer_.start();
|
||||
}
|
||||
|
||||
DiskCacheFolder::~DiskCacheFolder()
|
||||
{
|
||||
CloseCacheFolder();
|
||||
close_cache_folder();
|
||||
}
|
||||
|
||||
bool DiskCacheFolder::ClearCache()
|
||||
bool DiskCacheFolder::clear_cache()
|
||||
{
|
||||
bool deleted_files = true;
|
||||
|
||||
@@ -231,7 +231,7 @@ bool DiskCacheFolder::ClearCache()
|
||||
QString filename = i.key();
|
||||
|
||||
if (QFile::remove(filename) || !QFileInfo::exists(filename)) {
|
||||
emit DeletedFrame(path_, filename);
|
||||
emit deleted_frame(path_, filename);
|
||||
i = disk_data_.erase(i);
|
||||
} else {
|
||||
qWarning() << "Failed to delete" << filename;
|
||||
@@ -243,7 +243,7 @@ bool DiskCacheFolder::ClearCache()
|
||||
return deleted_files;
|
||||
}
|
||||
|
||||
void DiskCacheFolder::Accessed(const QString &filename)
|
||||
void DiskCacheFolder::accessed(const QString &filename)
|
||||
{
|
||||
if (!disk_data_.contains(filename)) {
|
||||
return;
|
||||
@@ -252,7 +252,7 @@ void DiskCacheFolder::Accessed(const QString &filename)
|
||||
disk_data_[filename].access_time = QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
void DiskCacheFolder::CreatedFile(const QString &filename)
|
||||
void DiskCacheFolder::created_file(const QString &filename)
|
||||
{
|
||||
qint64 file_size = QFile(filename).size();
|
||||
|
||||
@@ -262,19 +262,19 @@ void DiskCacheFolder::CreatedFile(const QString &filename)
|
||||
consumption_ += file_size;
|
||||
|
||||
while (consumption_ > limit_) {
|
||||
DeleteLeastRecent();
|
||||
delete_least_recent();
|
||||
}
|
||||
}
|
||||
|
||||
void DiskCacheFolder::SetPath(const QString &path)
|
||||
void DiskCacheFolder::set_path(const QString &path)
|
||||
{
|
||||
// If this is currently set to a folder, close it out now
|
||||
CloseCacheFolder();
|
||||
close_cache_folder();
|
||||
|
||||
// Signal that disk cache is gone
|
||||
if (!disk_data_.empty()) {
|
||||
for (auto it = disk_data_.cbegin(); it != disk_data_.cend(); it++) {
|
||||
emit DeletedFrame(path_, it.key());
|
||||
emit deleted_frame(path_, it.key());
|
||||
}
|
||||
disk_data_.clear();
|
||||
}
|
||||
@@ -289,7 +289,7 @@ void DiskCacheFolder::SetPath(const QString &path)
|
||||
|
||||
// Attempt to load existing index file from path
|
||||
QDir path_dir(path_);
|
||||
FileFunctions::DirectoryIsValid(path_dir);
|
||||
FileFunctions::directory_is_valid(path_dir);
|
||||
|
||||
index_path_ = path_dir.filePath(QStringLiteral("index"));
|
||||
|
||||
@@ -320,7 +320,7 @@ void DiskCacheFolder::SetPath(const QString &path)
|
||||
}
|
||||
}
|
||||
|
||||
bool DiskCacheFolder::DeleteFileInternal(
|
||||
bool DiskCacheFolder::delete_file_internal(
|
||||
QMap<QString, HashTime>::iterator hash_to_delete)
|
||||
{
|
||||
// Cache HashTime object
|
||||
@@ -337,26 +337,26 @@ bool DiskCacheFolder::DeleteFileInternal(
|
||||
// Reduce consumption
|
||||
consumption_ -= ht.file_size;
|
||||
|
||||
emit DeletedFrame(path_, filename);
|
||||
emit deleted_frame(path_, filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DiskCacheFolder::DeleteSpecificFile(const QString &f)
|
||||
bool DiskCacheFolder::delete_specific_file(const QString &f)
|
||||
{
|
||||
for (auto it = disk_data_.begin(); it != disk_data_.end(); it++) {
|
||||
if (it.key() == f) {
|
||||
// Break out of this loop, assuming we'll only have one instance of each filename
|
||||
return DeleteFileInternal(it);
|
||||
// Break out of this loop, assuming we'll only have one instance_ of each filename
|
||||
return delete_file_internal(it);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DiskCacheFolder::DeleteLeastRecent()
|
||||
bool DiskCacheFolder::delete_least_recent()
|
||||
{
|
||||
auto hash_to_delete = disk_data_.begin();
|
||||
|
||||
@@ -367,10 +367,10 @@ bool DiskCacheFolder::DeleteLeastRecent()
|
||||
}
|
||||
}
|
||||
|
||||
bool e = DeleteFileInternal(hash_to_delete);
|
||||
bool e = delete_file_internal(hash_to_delete);
|
||||
|
||||
if (e) {
|
||||
Core::instance()->WarnCacheFull();
|
||||
Core::instance()->warn_cache_full();
|
||||
}
|
||||
|
||||
return e;
|
||||
@@ -379,7 +379,7 @@ bool DiskCacheFolder::DeleteLeastRecent()
|
||||
}
|
||||
}
|
||||
|
||||
void DiskCacheFolder::CloseCacheFolder()
|
||||
void DiskCacheFolder::close_cache_folder()
|
||||
{
|
||||
if (path_.isEmpty()) {
|
||||
return;
|
||||
@@ -388,14 +388,14 @@ void DiskCacheFolder::CloseCacheFolder()
|
||||
if (clear_on_close_) {
|
||||
// If we're not moving to new and we're set to clear on close, clear now or else it'll never
|
||||
// get cleared later
|
||||
ClearCache();
|
||||
clear_cache();
|
||||
}
|
||||
|
||||
// Save current cache index
|
||||
SaveDiskCacheIndex();
|
||||
save_disk_cache_index();
|
||||
}
|
||||
|
||||
void DiskCacheFolder::SaveDiskCacheIndex()
|
||||
void DiskCacheFolder::save_disk_cache_index()
|
||||
{
|
||||
QFile cache_index_file(index_path_);
|
||||
|
||||
|
||||
+36
-36
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef DISKMANAGER_H
|
||||
#define DISKMANAGER_H
|
||||
#ifndef OAK_DISKMANAGER_H
|
||||
#define OAK_DISKMANAGER_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
@@ -40,43 +40,43 @@ public:
|
||||
|
||||
virtual ~DiskCacheFolder() override;
|
||||
|
||||
bool ClearCache();
|
||||
bool clear_cache();
|
||||
|
||||
void Accessed(const QString &filename);
|
||||
void accessed(const QString &filename);
|
||||
|
||||
void CreatedFile(const QString &filename);
|
||||
void created_file(const QString &filename);
|
||||
|
||||
const QString &GetPath() const
|
||||
const QString &get_path() const
|
||||
{
|
||||
return path_;
|
||||
}
|
||||
|
||||
void SetPath(const QString &path);
|
||||
void set_path(const QString &path);
|
||||
|
||||
qint64 GetLimit() const
|
||||
qint64 get_limit() const
|
||||
{
|
||||
return limit_;
|
||||
}
|
||||
|
||||
bool GetClearOnClose() const
|
||||
bool get_clear_on_close() const
|
||||
{
|
||||
return clear_on_close_;
|
||||
}
|
||||
|
||||
void SetLimit(qint64 l)
|
||||
void set_limit(qint64 l)
|
||||
{
|
||||
limit_ = l;
|
||||
}
|
||||
|
||||
void SetClearOnClose(bool e)
|
||||
void set_clear_on_close(bool e)
|
||||
{
|
||||
clear_on_close_ = e;
|
||||
}
|
||||
|
||||
bool DeleteSpecificFile(const QString &f);
|
||||
bool delete_specific_file(const QString &f);
|
||||
|
||||
signals:
|
||||
void DeletedFrame(const QString &path, const QString &filename);
|
||||
void deleted_frame(const QString &path, const QString &filename);
|
||||
|
||||
private:
|
||||
struct HashTime {
|
||||
@@ -84,11 +84,11 @@ private:
|
||||
qint64 access_time;
|
||||
};
|
||||
|
||||
bool DeleteFileInternal(QMap<QString, HashTime>::iterator hash_to_delete);
|
||||
bool delete_file_internal(QMap<QString, HashTime>::iterator hash_to_delete);
|
||||
|
||||
bool DeleteLeastRecent();
|
||||
bool delete_least_recent();
|
||||
|
||||
void CloseCacheFolder();
|
||||
void close_cache_folder();
|
||||
|
||||
QString path_;
|
||||
|
||||
@@ -105,58 +105,58 @@ private:
|
||||
QTimer save_timer_;
|
||||
|
||||
private slots:
|
||||
void SaveDiskCacheIndex();
|
||||
void save_disk_cache_index();
|
||||
};
|
||||
|
||||
class DiskManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static void CreateInstance();
|
||||
static void create_instance();
|
||||
|
||||
static void DestroyInstance();
|
||||
static void destroy_instance();
|
||||
|
||||
static DiskManager *instance();
|
||||
|
||||
bool ClearDiskCache(const QString &cache_folder);
|
||||
bool clear_disk_cache(const QString &cache_folder);
|
||||
|
||||
DiskCacheFolder *GetDefaultCacheFolder() const
|
||||
DiskCacheFolder *get_default_cache_folder() const
|
||||
{
|
||||
// The first folder will always be the default
|
||||
return open_folders_.first();
|
||||
}
|
||||
|
||||
const QString &GetDefaultCachePath() const
|
||||
const QString &get_default_cache_path() const
|
||||
{
|
||||
return GetDefaultCacheFolder()->GetPath();
|
||||
return get_default_cache_folder()->get_path();
|
||||
}
|
||||
|
||||
DiskCacheFolder *GetOpenFolder(const QString &path);
|
||||
DiskCacheFolder *get_open_folder(const QString &path);
|
||||
|
||||
const QVector<DiskCacheFolder *> &GetOpenFolders() const
|
||||
const QVector<DiskCacheFolder *> &get_open_folders() const
|
||||
{
|
||||
return open_folders_;
|
||||
}
|
||||
|
||||
static bool ShowDiskCacheChangeConfirmationDialog(QWidget *parent);
|
||||
static bool show_disk_cache_change_confirmation_dialog(QWidget *parent);
|
||||
|
||||
static QString GetDefaultDiskCacheConfigFile();
|
||||
static QString get_default_disk_cache_config_file();
|
||||
|
||||
static QString GetDefaultDiskCachePath();
|
||||
static QString get_default_disk_cache_path();
|
||||
|
||||
void ShowDiskCacheSettingsDialog(DiskCacheFolder *folder, QWidget *parent);
|
||||
void ShowDiskCacheSettingsDialog(const QString &path, QWidget *parent);
|
||||
void show_disk_cache_settings_dialog(DiskCacheFolder *folder, QWidget *parent);
|
||||
void show_disk_cache_settings_dialog(const QString &path, QWidget *parent);
|
||||
|
||||
public slots:
|
||||
void Accessed(const QString &cache_folder, const QString &filename);
|
||||
void accessed(const QString &cache_folder, const QString &filename);
|
||||
|
||||
void CreatedFile(const QString &cache_folder, const QString &filename);
|
||||
void created_file(const QString &cache_folder, const QString &filename);
|
||||
|
||||
void DeleteSpecificFile(const QString &filename);
|
||||
void delete_specific_file(const QString &filename);
|
||||
|
||||
signals:
|
||||
void DeletedFrame(const QString &path, const QString &filename);
|
||||
void deleted_frame(const QString &path, const QString &filename);
|
||||
|
||||
void InvalidateProject(Project *p);
|
||||
void invalidate_project(Project *p);
|
||||
|
||||
private:
|
||||
DiskManager();
|
||||
@@ -170,4 +170,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // DISKMANAGER_H
|
||||
#endif // OAK_DISKMANAGER_H
|
||||
|
||||
@@ -42,37 +42,37 @@ FrameHashCache::FrameHashCache(QObject *parent)
|
||||
: super(parent)
|
||||
{
|
||||
if (DiskManager::instance()) {
|
||||
connect(DiskManager::instance(), &DiskManager::DeletedFrame, this,
|
||||
&FrameHashCache::HashDeleted);
|
||||
connect(DiskManager::instance(), &DiskManager::InvalidateProject, this,
|
||||
&FrameHashCache::ProjectInvalidated);
|
||||
connect(DiskManager::instance(), &DiskManager::deleted_frame, this,
|
||||
&FrameHashCache::hash_deleted);
|
||||
connect(DiskManager::instance(), &DiskManager::invalidate_project, this,
|
||||
&FrameHashCache::project_invalidated);
|
||||
}
|
||||
}
|
||||
|
||||
void FrameHashCache::SetTimebase(const rational &tb)
|
||||
void FrameHashCache::set_timebase(const Rational &tb)
|
||||
{
|
||||
timebase_ = tb;
|
||||
}
|
||||
|
||||
void FrameHashCache::ValidateTimestamp(const int64_t &ts)
|
||||
void FrameHashCache::validate_timestamp(const int64_t &ts)
|
||||
{
|
||||
TimeRange frame_range(ToTime(ts), ToTime(ts + 1));
|
||||
Validate(frame_range);
|
||||
TimeRange frame_range(to_time(ts), to_time(ts + 1));
|
||||
validate(frame_range);
|
||||
}
|
||||
|
||||
void FrameHashCache::ValidateTime(const rational &time)
|
||||
void FrameHashCache::validate_time(const Rational &time)
|
||||
{
|
||||
Validate(TimeRange(time, time + timebase_));
|
||||
validate(TimeRange(time, time + timebase_));
|
||||
}
|
||||
|
||||
QString FrameHashCache::GetValidCacheFilename(const rational &time) const
|
||||
QString FrameHashCache::get_valid_cache_filename(const Rational &time) const
|
||||
{
|
||||
if (IsFrameCached(time)) {
|
||||
return CachePathName(time);
|
||||
} else if (!GetPassthroughs().empty()) {
|
||||
for (const Passthrough &p : GetPassthroughs()) {
|
||||
if (p.Contains(time)) {
|
||||
return CachePathName(GetCacheDirectory(), p.cache, time,
|
||||
if (is_frame_cached(time)) {
|
||||
return cache_path_name(time);
|
||||
} else if (!get_passthroughs().empty()) {
|
||||
for (const Passthrough &p : get_passthroughs()) {
|
||||
if (p.contains(time)) {
|
||||
return cache_path_name(get_cache_directory(), p.cache, time,
|
||||
timebase_);
|
||||
}
|
||||
}
|
||||
@@ -81,12 +81,12 @@ QString FrameHashCache::GetValidCacheFilename(const rational &time) const
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool FrameHashCache::SaveCacheFrame(const int64_t &time, FramePtr frame) const
|
||||
bool FrameHashCache::save_cache_frame(const int64_t &time, FramePtr frame) const
|
||||
{
|
||||
return SaveCacheFrame(GetCacheDirectory(), GetUuid(), time, frame);
|
||||
return save_cache_frame(get_cache_directory(), get_uuid(), time, frame);
|
||||
}
|
||||
|
||||
bool FrameHashCache::SaveCacheFrame(const QString &cache_path,
|
||||
bool FrameHashCache::save_cache_frame(const QString &cache_path,
|
||||
const QUuid &uuid, const int64_t &time,
|
||||
FramePtr frame)
|
||||
{
|
||||
@@ -95,13 +95,13 @@ bool FrameHashCache::SaveCacheFrame(const QString &cache_path,
|
||||
return false;
|
||||
}
|
||||
|
||||
QString fn = CachePathName(cache_path, uuid, time);
|
||||
QString fn = cache_path_name(cache_path, uuid, time);
|
||||
|
||||
bool ret = SaveCacheFrame(fn, frame);
|
||||
bool ret = save_cache_frame(fn, frame);
|
||||
|
||||
// Register frame with the disk manager
|
||||
if (ret) {
|
||||
QMetaObject::invokeMethod(DiskManager::instance(), "CreatedFile",
|
||||
QMetaObject::invokeMethod(DiskManager::instance(), "created_file",
|
||||
Q_ARG(QString, cache_path),
|
||||
Q_ARG(QString, fn));
|
||||
}
|
||||
@@ -109,22 +109,22 @@ bool FrameHashCache::SaveCacheFrame(const QString &cache_path,
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FrameHashCache::SaveCacheFrame(const QString &cache_path,
|
||||
const QUuid &uuid, const rational &time,
|
||||
const rational &tb, FramePtr frame)
|
||||
bool FrameHashCache::save_cache_frame(const QString &cache_path,
|
||||
const QUuid &uuid, const Rational &time,
|
||||
const Rational &tb, FramePtr frame)
|
||||
{
|
||||
if (cache_path.isEmpty()) {
|
||||
qWarning() << "Failed to save cache frame with empty path";
|
||||
return false;
|
||||
}
|
||||
|
||||
QString fn = CachePathName(cache_path, uuid, time, tb);
|
||||
QString fn = cache_path_name(cache_path, uuid, time, tb);
|
||||
|
||||
bool ret = SaveCacheFrame(fn, frame);
|
||||
bool ret = save_cache_frame(fn, frame);
|
||||
|
||||
// Register frame with the disk manager
|
||||
if (ret) {
|
||||
QMetaObject::invokeMethod(DiskManager::instance(), "CreatedFile",
|
||||
QMetaObject::invokeMethod(DiskManager::instance(), "created_file",
|
||||
Q_ARG(QString, cache_path),
|
||||
Q_ARG(QString, fn));
|
||||
}
|
||||
@@ -132,28 +132,28 @@ bool FrameHashCache::SaveCacheFrame(const QString &cache_path,
|
||||
return ret;
|
||||
}
|
||||
|
||||
FramePtr FrameHashCache::LoadCacheFrame(const QString &cache_path,
|
||||
FramePtr FrameHashCache::load_cache_frame(const QString &cache_path,
|
||||
const QUuid &uuid, const int64_t &time)
|
||||
{
|
||||
// Minor optimization, we store frames currently being saved just in case something tries to load
|
||||
// while we're saving. This should *occasionally* optimize and also prevent scenarios where
|
||||
// we try to load a frame that's half way through being saved.
|
||||
QString filename = CachePathName(cache_path, uuid, time);
|
||||
QString filename = cache_path_name(cache_path, uuid, time);
|
||||
|
||||
if (cache_path.isEmpty()) {
|
||||
qWarning() << "Failed to load cache frame with empty path";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return LoadCacheFrame(filename);
|
||||
return load_cache_frame(filename);
|
||||
}
|
||||
|
||||
FramePtr FrameHashCache::LoadCacheFrame(const int64_t &hash) const
|
||||
FramePtr FrameHashCache::load_cache_frame(const int64_t &hash) const
|
||||
{
|
||||
return LoadCacheFrame(GetCacheDirectory(), GetUuid(), hash);
|
||||
return load_cache_frame(get_cache_directory(), get_uuid(), hash);
|
||||
}
|
||||
|
||||
FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
|
||||
FramePtr FrameHashCache::load_cache_frame(const QString &fn)
|
||||
{
|
||||
FramePtr frame = nullptr;
|
||||
|
||||
@@ -174,23 +174,23 @@ FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
|
||||
|
||||
PixelFormat image_format;
|
||||
if (pix_type == Imf::HALF) {
|
||||
image_format = PixelFormat::F16;
|
||||
image_format = PixelFormat::f16;
|
||||
} else {
|
||||
image_format = PixelFormat::F32;
|
||||
image_format = PixelFormat::f32;
|
||||
}
|
||||
|
||||
int channel_count = has_alpha ? VideoParams::kRGBAChannelCount :
|
||||
VideoParams::kRGBChannelCount;
|
||||
int channel_count = has_alpha ? VideoParams::k_rgba_channel_count :
|
||||
VideoParams::k_rgb_channel_count;
|
||||
|
||||
frame = Frame::Create();
|
||||
frame = Frame::create();
|
||||
frame->set_video_params(VideoParams(
|
||||
width * div, height * div, image_format, channel_count,
|
||||
rational::fromDouble(file.header().pixelAspectRatio()),
|
||||
VideoParams::kInterlaceNone, div));
|
||||
Rational::from_double(file.header().pixelAspectRatio()),
|
||||
VideoParams::k_interlace_none, div));
|
||||
|
||||
frame->allocate();
|
||||
|
||||
int bpc = VideoParams::GetBytesPerChannel(image_format);
|
||||
int bpc = VideoParams::get_bytes_per_channel(image_format);
|
||||
|
||||
size_t xs = channel_count * bpc;
|
||||
size_t ys = frame->linesize_bytes();
|
||||
@@ -217,17 +217,17 @@ FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
|
||||
if (img.load(fn, "jpg")) {
|
||||
// FIXME: Hardcoded
|
||||
const int div = 1;
|
||||
const PixelFormat image_format = PixelFormat::U8;
|
||||
const PixelFormat image_format = PixelFormat::u8;
|
||||
const int channel_count = 4;
|
||||
const rational par(1, 1);
|
||||
const Rational par(1, 1);
|
||||
|
||||
// Convert to frame (FIXME: might be slow? may be a better way to do this on the GPU)
|
||||
img.convertTo(QImage::Format_RGBA8888_Premultiplied);
|
||||
|
||||
frame = Frame::Create();
|
||||
frame = Frame::create();
|
||||
frame->set_video_params(VideoParams(
|
||||
img.width() * div, img.height() * div, image_format,
|
||||
channel_count, par, VideoParams::kInterlaceNone, div));
|
||||
channel_count, par, VideoParams::k_interlace_none, div));
|
||||
|
||||
frame->allocate();
|
||||
|
||||
@@ -235,7 +235,7 @@ FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
|
||||
memcpy(frame->data() + frame->linesize_bytes() * i,
|
||||
img.bits() + img.bytesPerLine() * i,
|
||||
frame->width() *
|
||||
frame->video_params().GetBytesPerPixel());
|
||||
frame->video_params().get_bytes_per_pixel());
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -246,7 +246,7 @@ FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
|
||||
|
||||
// Assume this frame is corrupt in some way and delete it
|
||||
QMetaObject::invokeMethod(DiskManager::instance(),
|
||||
"DeleteSpecificFile",
|
||||
"delete_specific_file",
|
||||
Q_ARG(QString, fn));
|
||||
}
|
||||
}
|
||||
@@ -255,10 +255,10 @@ FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
|
||||
return frame;
|
||||
}
|
||||
|
||||
void FrameHashCache::SetPassthrough(PlaybackCache *cache)
|
||||
void FrameHashCache::set_passthrough(PlaybackCache *cache)
|
||||
{
|
||||
super::SetPassthrough(cache);
|
||||
SetTimebase(static_cast<FrameHashCache *>(cache)->GetTimebase());
|
||||
super::set_passthrough(cache);
|
||||
set_timebase(static_cast<FrameHashCache *>(cache)->get_timebase());
|
||||
}
|
||||
|
||||
void FrameHashCache::LoadStateEvent(QDataStream &stream)
|
||||
@@ -272,7 +272,7 @@ void FrameHashCache::LoadStateEvent(QDataStream &stream)
|
||||
case 1:
|
||||
stream >> num;
|
||||
stream >> den;
|
||||
timebase_ = rational(num, den);
|
||||
timebase_ = Rational(num, den);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -287,60 +287,60 @@ void FrameHashCache::SaveStateEvent(QDataStream &stream)
|
||||
stream << timebase_.denominator();
|
||||
}
|
||||
|
||||
rational FrameHashCache::ToTime(const int64_t &ts) const
|
||||
Rational FrameHashCache::to_time(const int64_t &ts) const
|
||||
{
|
||||
return Timecode::timestamp_to_time(ts, timebase_);
|
||||
}
|
||||
|
||||
int64_t FrameHashCache::ToTimestamp(const rational &ts,
|
||||
int64_t FrameHashCache::to_timestamp(const Rational &ts,
|
||||
Timecode::Rounding rounding) const
|
||||
{
|
||||
return Timecode::time_to_timestamp(ts, timebase_, rounding);
|
||||
}
|
||||
|
||||
void FrameHashCache::HashDeleted(const QString &path, const QString &filename)
|
||||
void FrameHashCache::hash_deleted(const QString &path, const QString &filename)
|
||||
{
|
||||
QString cache_dir = GetCacheDirectory();
|
||||
QString cache_dir = get_cache_directory();
|
||||
if (cache_dir.isEmpty() || path != cache_dir) {
|
||||
return;
|
||||
}
|
||||
|
||||
QFileInfo info(filename);
|
||||
if (GetUuid().toString() != info.dir().dirName()) {
|
||||
if (get_uuid().toString() != info.dir().dirName()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t timestamp = info.fileName().toLongLong();
|
||||
Invalidate(TimeRange(ToTime(timestamp), ToTime(timestamp + 1)));
|
||||
invalidate(TimeRange(to_time(timestamp), to_time(timestamp + 1)));
|
||||
}
|
||||
|
||||
void FrameHashCache::ProjectInvalidated(Project *p)
|
||||
void FrameHashCache::project_invalidated(Project *p)
|
||||
{
|
||||
if (GetProject() == p) {
|
||||
InvalidateAll();
|
||||
if (get_project() == p) {
|
||||
invalidate_all();
|
||||
}
|
||||
}
|
||||
|
||||
QString FrameHashCache::CachePathName(const int64_t &time) const
|
||||
QString FrameHashCache::cache_path_name(const int64_t &time) const
|
||||
{
|
||||
return CachePathName(GetCacheDirectory(), GetUuid(), time);
|
||||
return cache_path_name(get_cache_directory(), get_uuid(), time);
|
||||
}
|
||||
|
||||
QString FrameHashCache::CachePathName(const rational &time) const
|
||||
QString FrameHashCache::cache_path_name(const Rational &time) const
|
||||
{
|
||||
return CachePathName(GetCacheDirectory(), GetUuid(), time, timebase_);
|
||||
return cache_path_name(get_cache_directory(), get_uuid(), time, timebase_);
|
||||
}
|
||||
|
||||
QString FrameHashCache::CachePathName(const QString &cache_path,
|
||||
QString FrameHashCache::cache_path_name(const QString &cache_path,
|
||||
const QUuid &cache_id,
|
||||
const int64_t &time)
|
||||
{
|
||||
QString filename = GetThisCacheDirectory(cache_path, cache_id)
|
||||
QString filename = get_this_cache_directory(cache_path, cache_id)
|
||||
.filePath(QString::number(time));
|
||||
|
||||
// Register that in some way this hash has been accessed
|
||||
if (DiskManager::instance()) {
|
||||
QMetaObject::invokeMethod(DiskManager::instance(), "Accessed",
|
||||
QMetaObject::invokeMethod(DiskManager::instance(), "accessed",
|
||||
Q_ARG(QString, cache_path),
|
||||
Q_ARG(QString, filename));
|
||||
}
|
||||
@@ -348,29 +348,29 @@ QString FrameHashCache::CachePathName(const QString &cache_path,
|
||||
return filename;
|
||||
}
|
||||
|
||||
QString FrameHashCache::CachePathName(const QString &cache_path,
|
||||
QString FrameHashCache::cache_path_name(const QString &cache_path,
|
||||
const QUuid &cache_id,
|
||||
const rational &time, const rational &tb)
|
||||
const Rational &time, const Rational &tb)
|
||||
{
|
||||
return CachePathName(cache_path, cache_id,
|
||||
return cache_path_name(cache_path, cache_id,
|
||||
Timecode::time_to_timestamp(time, tb,
|
||||
Timecode::kRound));
|
||||
Timecode::k_round));
|
||||
}
|
||||
|
||||
bool FrameHashCache::SaveCacheFrame(const QString &filename,
|
||||
bool FrameHashCache::save_cache_frame(const QString &filename,
|
||||
const FramePtr frame)
|
||||
{
|
||||
// Ensure directory is created
|
||||
QDir cache_dir = QFileInfo(filename).dir();
|
||||
if (!FileFunctions::DirectoryIsValid(cache_dir)) {
|
||||
if (!FileFunctions::directory_is_valid(cache_dir)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (VideoParams::FormatIsFloat(frame->format())) {
|
||||
if (VideoParams::format_is_float(frame->format())) {
|
||||
// Floating point types are stored in EXR
|
||||
Imf::PixelType pix_type;
|
||||
|
||||
if (frame->format() == PixelFormat::F16) {
|
||||
if (frame->format() == PixelFormat::f16) {
|
||||
pix_type = Imf::HALF;
|
||||
} else {
|
||||
pix_type = Imf::FLOAT;
|
||||
@@ -380,14 +380,14 @@ bool FrameHashCache::SaveCacheFrame(const QString &filename,
|
||||
header.channels().insert("R", Imf::Channel(pix_type));
|
||||
header.channels().insert("G", Imf::Channel(pix_type));
|
||||
header.channels().insert("B", Imf::Channel(pix_type));
|
||||
if (frame->channel_count() == VideoParams::kRGBAChannelCount) {
|
||||
if (frame->channel_count() == VideoParams::k_rgba_channel_count) {
|
||||
header.channels().insert("A", Imf::Channel(pix_type));
|
||||
}
|
||||
|
||||
header.compression() = Imf::DWAA_COMPRESSION;
|
||||
header.insert("dwaCompressionLevel", Imf::FloatAttribute(200.0f));
|
||||
header.pixelAspectRatio() =
|
||||
frame->video_params().pixel_aspect_ratio().toDouble();
|
||||
frame->video_params().pixel_aspect_ratio().to_double();
|
||||
|
||||
header.insert("oliveDivider",
|
||||
Imf::IntAttribute(frame->video_params().divider()));
|
||||
@@ -395,7 +395,7 @@ bool FrameHashCache::SaveCacheFrame(const QString &filename,
|
||||
try {
|
||||
Imf::OutputFile out(filename.toUtf8(), header, 0);
|
||||
|
||||
int bpc = VideoParams::GetBytesPerChannel(frame->format());
|
||||
int bpc = VideoParams::get_bytes_per_channel(frame->format());
|
||||
|
||||
size_t xs = frame->channel_count() * bpc;
|
||||
size_t ys = frame->linesize_bytes();
|
||||
@@ -407,7 +407,7 @@ bool FrameHashCache::SaveCacheFrame(const QString &filename,
|
||||
xs, ys));
|
||||
framebuffer.insert(
|
||||
"B", Imf::Slice(pix_type, frame->data() + 2 * bpc, xs, ys));
|
||||
if (frame->channel_count() == VideoParams::kRGBAChannelCount) {
|
||||
if (frame->channel_count() == VideoParams::k_rgba_channel_count) {
|
||||
framebuffer.insert(
|
||||
"A", Imf::Slice(pix_type, frame->data() + 3 * bpc, xs, ys));
|
||||
}
|
||||
@@ -425,25 +425,25 @@ bool FrameHashCache::SaveCacheFrame(const QString &filename,
|
||||
QImage::Format fmt = QImage::Format_Invalid;
|
||||
|
||||
switch (frame->format()) {
|
||||
case PixelFormat::U8:
|
||||
if (frame->channel_count() == VideoParams::kRGBAChannelCount) {
|
||||
case PixelFormat::u8:
|
||||
if (frame->channel_count() == VideoParams::k_rgba_channel_count) {
|
||||
fmt = QImage::Format_RGBA8888_Premultiplied;
|
||||
} else if (frame->channel_count() ==
|
||||
VideoParams::kRGBChannelCount) {
|
||||
VideoParams::k_rgb_channel_count) {
|
||||
fmt = QImage::Format_RGB888;
|
||||
}
|
||||
break;
|
||||
case PixelFormat::U10:
|
||||
case PixelFormat::u10:
|
||||
break;
|
||||
case PixelFormat::U16:
|
||||
if (frame->channel_count() == VideoParams::kRGBAChannelCount) {
|
||||
case PixelFormat::u16:
|
||||
if (frame->channel_count() == VideoParams::k_rgba_channel_count) {
|
||||
fmt = QImage::Format_RGBA64_Premultiplied;
|
||||
}
|
||||
break;
|
||||
case PixelFormat::F16:
|
||||
case PixelFormat::F32:
|
||||
case PixelFormat::COUNT:
|
||||
case PixelFormat::INVALID:
|
||||
case PixelFormat::f16:
|
||||
case PixelFormat::f32:
|
||||
case PixelFormat::count:
|
||||
case PixelFormat::invalid:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+32
-32
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef VIDEORENDERFRAMECACHE_H
|
||||
#define VIDEORENDERFRAMECACHE_H
|
||||
#ifndef OAK_VIDEORENDERFRAMECACHE_H
|
||||
#define OAK_VIDEORENDERFRAMECACHE_H
|
||||
|
||||
#include "codec/frame.h"
|
||||
#include "render/playbackcache.h"
|
||||
@@ -34,64 +34,64 @@ class FrameHashCache : public PlaybackCache {
|
||||
public:
|
||||
FrameHashCache(QObject *parent = nullptr);
|
||||
|
||||
const rational &GetTimebase() const
|
||||
const Rational &get_timebase() const
|
||||
{
|
||||
return timebase_;
|
||||
}
|
||||
|
||||
void SetTimebase(const rational &tb);
|
||||
void set_timebase(const Rational &tb);
|
||||
|
||||
void ValidateTimestamp(const int64_t &ts);
|
||||
void ValidateTime(const rational &time);
|
||||
void validate_timestamp(const int64_t &ts);
|
||||
void validate_time(const Rational &time);
|
||||
|
||||
bool IsFrameCached(const rational &time) const
|
||||
bool is_frame_cached(const Rational &time) const
|
||||
{
|
||||
return GetValidatedRanges().contains(time);
|
||||
return get_validated_ranges().contains(time);
|
||||
}
|
||||
|
||||
QString GetValidCacheFilename(const rational &time) const;
|
||||
QString get_valid_cache_filename(const Rational &time) const;
|
||||
|
||||
static bool SaveCacheFrame(const QString &filename, FramePtr frame);
|
||||
bool SaveCacheFrame(const int64_t &time, FramePtr frame) const;
|
||||
static bool SaveCacheFrame(const QString &cache_path, const QUuid &uuid,
|
||||
static bool save_cache_frame(const QString &filename, FramePtr frame);
|
||||
bool save_cache_frame(const int64_t &time, FramePtr frame) const;
|
||||
static bool save_cache_frame(const QString &cache_path, const QUuid &uuid,
|
||||
const int64_t &time, FramePtr frame);
|
||||
static bool SaveCacheFrame(const QString &cache_path, const QUuid &uuid,
|
||||
const rational &time, const rational &tb,
|
||||
static bool save_cache_frame(const QString &cache_path, const QUuid &uuid,
|
||||
const Rational &time, const Rational &tb,
|
||||
FramePtr frame);
|
||||
static FramePtr LoadCacheFrame(const QString &cache_path, const QUuid &uuid,
|
||||
static FramePtr load_cache_frame(const QString &cache_path, const QUuid &uuid,
|
||||
const int64_t &time);
|
||||
FramePtr LoadCacheFrame(const int64_t &time) const;
|
||||
static FramePtr LoadCacheFrame(const QString &fn);
|
||||
FramePtr load_cache_frame(const int64_t &time) const;
|
||||
static FramePtr load_cache_frame(const QString &fn);
|
||||
|
||||
virtual void SetPassthrough(PlaybackCache *cache) override;
|
||||
virtual void set_passthrough(PlaybackCache *cache) override;
|
||||
|
||||
protected:
|
||||
virtual void LoadStateEvent(QDataStream &stream) override;
|
||||
virtual void SaveStateEvent(QDataStream &stream) override;
|
||||
|
||||
private:
|
||||
rational ToTime(const int64_t &ts) const;
|
||||
int64_t ToTimestamp(const rational &ts,
|
||||
Timecode::Rounding rounding = Timecode::kRound) const;
|
||||
Rational to_time(const int64_t &ts) const;
|
||||
int64_t to_timestamp(const Rational &ts,
|
||||
Timecode::Rounding rounding = Timecode::k_round) const;
|
||||
|
||||
/**
|
||||
* @brief Return the path of the cached image at this time
|
||||
*/
|
||||
QString CachePathName(const int64_t &time) const;
|
||||
QString CachePathName(const rational &time) const;
|
||||
QString cache_path_name(const int64_t &time) const;
|
||||
QString cache_path_name(const Rational &time) const;
|
||||
|
||||
static QString CachePathName(const QString &cache_path,
|
||||
static QString cache_path_name(const QString &cache_path,
|
||||
const QUuid &cache_id, const int64_t &time);
|
||||
static QString CachePathName(const QString &cache_path,
|
||||
const QUuid &cache_id, const rational &time,
|
||||
const rational &tb);
|
||||
static QString cache_path_name(const QString &cache_path,
|
||||
const QUuid &cache_id, const Rational &time,
|
||||
const Rational &tb);
|
||||
|
||||
rational timebase_;
|
||||
Rational timebase_;
|
||||
|
||||
private slots:
|
||||
void HashDeleted(const QString &path, const QString &filename);
|
||||
void hash_deleted(const QString &path, const QString &filename);
|
||||
|
||||
void ProjectInvalidated(Project *p);
|
||||
void project_invalidated(Project *p);
|
||||
};
|
||||
|
||||
class ThumbnailCache : public FrameHashCache {
|
||||
@@ -100,10 +100,10 @@ public:
|
||||
ThumbnailCache(QObject *parent = nullptr)
|
||||
: FrameHashCache(parent)
|
||||
{
|
||||
SetTimebase(rational(1, 10));
|
||||
set_timebase(Rational(1, 10));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // VIDEORENDERFRAMECACHE_H
|
||||
#endif // OAK_VIDEORENDERFRAMECACHE_H
|
||||
|
||||
+13
-13
@@ -28,14 +28,14 @@ namespace olive
|
||||
{
|
||||
|
||||
FrameManager *FrameManager::instance_ = nullptr;
|
||||
const int FrameManager::kFrameLifetime = 5000;
|
||||
const int FrameManager::k_frame_lifetime = 5000;
|
||||
|
||||
void FrameManager::CreateInstance()
|
||||
void FrameManager::create_instance()
|
||||
{
|
||||
instance_ = new FrameManager();
|
||||
}
|
||||
|
||||
void FrameManager::DestroyInstance()
|
||||
void FrameManager::destroy_instance()
|
||||
{
|
||||
delete instance_;
|
||||
instance_ = nullptr;
|
||||
@@ -46,19 +46,19 @@ FrameManager *FrameManager::instance()
|
||||
return instance_;
|
||||
}
|
||||
|
||||
char *FrameManager::Allocate(int size)
|
||||
char *FrameManager::allocate(int size)
|
||||
{
|
||||
if (instance()) {
|
||||
return instance()->AllocateFromPool(size);
|
||||
return instance()->allocate_from_pool(size);
|
||||
} else {
|
||||
return new char[size];
|
||||
}
|
||||
}
|
||||
|
||||
void FrameManager::Deallocate(int size, char *buffer)
|
||||
void FrameManager::deallocate(int size, char *buffer)
|
||||
{
|
||||
if (instance()) {
|
||||
instance()->DeallocateToPool(size, buffer);
|
||||
instance()->deallocate_to_pool(size, buffer);
|
||||
} else {
|
||||
delete[] buffer;
|
||||
}
|
||||
@@ -66,13 +66,13 @@ void FrameManager::Deallocate(int size, char *buffer)
|
||||
|
||||
FrameManager::FrameManager()
|
||||
{
|
||||
clear_timer_.setInterval(kFrameLifetime);
|
||||
clear_timer_.setInterval(k_frame_lifetime);
|
||||
connect(&clear_timer_, &QTimer::timeout, this,
|
||||
&FrameManager::GarbageCollection);
|
||||
&FrameManager::garbage_collection);
|
||||
clear_timer_.start();
|
||||
}
|
||||
|
||||
char *FrameManager::AllocateFromPool(int size)
|
||||
char *FrameManager::allocate_from_pool(int size)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
|
||||
@@ -90,7 +90,7 @@ char *FrameManager::AllocateFromPool(int size)
|
||||
return buf;
|
||||
}
|
||||
|
||||
void FrameManager::DeallocateToPool(int size, char *buffer)
|
||||
void FrameManager::deallocate_to_pool(int size, char *buffer)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
|
||||
@@ -99,11 +99,11 @@ void FrameManager::DeallocateToPool(int size, char *buffer)
|
||||
buffer_list.push_back({ QDateTime::currentMSecsSinceEpoch(), buffer });
|
||||
}
|
||||
|
||||
void FrameManager::GarbageCollection()
|
||||
void FrameManager::garbage_collection()
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
|
||||
qint64 min_life = QDateTime::currentMSecsSinceEpoch() - kFrameLifetime;
|
||||
qint64 min_life = QDateTime::currentMSecsSinceEpoch() - k_frame_lifetime;
|
||||
|
||||
for (auto it = pool_.begin(); it != pool_.end(); it++) {
|
||||
std::list<Buffer> &list = it->second;
|
||||
|
||||
+11
-11
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef FRAMEMANAGER_H
|
||||
#define FRAMEMANAGER_H
|
||||
#ifndef OAK_FRAMEMANAGER_H
|
||||
#define OAK_FRAMEMANAGER_H
|
||||
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
@@ -32,15 +32,15 @@ namespace olive
|
||||
class FrameManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static void CreateInstance();
|
||||
static void create_instance();
|
||||
|
||||
static void DestroyInstance();
|
||||
static void destroy_instance();
|
||||
|
||||
static FrameManager *instance();
|
||||
|
||||
static char *Allocate(int size);
|
||||
static char *allocate(int size);
|
||||
|
||||
static void Deallocate(int size, char *buffer);
|
||||
static void deallocate(int size, char *buffer);
|
||||
|
||||
private:
|
||||
FrameManager();
|
||||
@@ -55,7 +55,7 @@ private:
|
||||
*
|
||||
* Thread-safe.
|
||||
*/
|
||||
char *AllocateFromPool(int size);
|
||||
char *allocate_from_pool(int size);
|
||||
|
||||
/**
|
||||
* @brief Deallocate buffer
|
||||
@@ -65,11 +65,11 @@ private:
|
||||
*
|
||||
* Thread-safe.
|
||||
*/
|
||||
void DeallocateToPool(int size, char *buffer);
|
||||
void deallocate_to_pool(int size, char *buffer);
|
||||
|
||||
static FrameManager *instance_;
|
||||
|
||||
static const int kFrameLifetime;
|
||||
static const int k_frame_lifetime;
|
||||
|
||||
struct Buffer {
|
||||
qint64 time;
|
||||
@@ -83,9 +83,9 @@ private:
|
||||
QTimer clear_timer_;
|
||||
|
||||
private slots:
|
||||
void GarbageCollection();
|
||||
void garbage_collection();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FRAMEMANAGER_H
|
||||
#endif // OAK_FRAMEMANAGER_H
|
||||
|
||||
@@ -28,30 +28,30 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
TexturePtr Renderer::InterlaceTexture(TexturePtr top, TexturePtr bottom,
|
||||
TexturePtr Renderer::interlace_texture(TexturePtr top, TexturePtr bottom,
|
||||
const VideoParams ¶ms)
|
||||
{
|
||||
color_cache_mutex_.lock();
|
||||
if (interlace_texture_.isNull()) {
|
||||
interlace_texture_ =
|
||||
CreateNativeShader(ShaderCode(FileFunctions::ReadFileAsString(
|
||||
create_native_shader(ShaderCode(FileFunctions::read_file_as_string(
|
||||
QStringLiteral(":/shaders/interlace.frag"))));
|
||||
}
|
||||
color_cache_mutex_.unlock();
|
||||
|
||||
ShaderJob job;
|
||||
job.Insert(QStringLiteral("top_tex_in"),
|
||||
NodeValue(NodeValue::kTexture, QVariant::fromValue(top)));
|
||||
job.Insert(QStringLiteral("bottom_tex_in"),
|
||||
NodeValue(NodeValue::kTexture, QVariant::fromValue(bottom)));
|
||||
job.Insert(QStringLiteral("resolution_in"),
|
||||
NodeValue(NodeValue::kVec2,
|
||||
job.insert(QStringLiteral("top_tex_in"),
|
||||
NodeValue(NodeValue::k_texture, QVariant::fromValue(top)));
|
||||
job.insert(QStringLiteral("bottom_tex_in"),
|
||||
NodeValue(NodeValue::k_texture, QVariant::fromValue(bottom)));
|
||||
job.insert(QStringLiteral("resolution_in"),
|
||||
NodeValue(NodeValue::k_vec2,
|
||||
QVector2D(params.effective_width(),
|
||||
params.effective_height())));
|
||||
|
||||
TexturePtr output = CreateTexture(params);
|
||||
TexturePtr output = create_texture(params);
|
||||
|
||||
BlitToTexture(interlace_texture_, job, output.get());
|
||||
blit_to_texture(interlace_texture_, job, output.get());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -31,54 +31,54 @@ namespace
|
||||
{
|
||||
|
||||
// Round `value` up to the next multiple of `align` (align must be a power of two).
|
||||
size_t AlignUp(size_t value, size_t align)
|
||||
size_t align_up(size_t value, size_t align)
|
||||
{
|
||||
return (value + (align - 1)) & ~(align - 1);
|
||||
}
|
||||
|
||||
constexpr size_t kAlign = 64; // Cache-line alignment for each sub-region.
|
||||
constexpr size_t k_align = 64; // Cache-line alignment for each sub-region.
|
||||
|
||||
} // namespace
|
||||
|
||||
size_t FrameSlotPool::BytesNeeded(uint32_t slot_count, size_t slot_data_bytes)
|
||||
size_t FrameSlotPool::bytes_needed(uint32_t slot_count, size_t slot_data_bytes)
|
||||
{
|
||||
const uint32_t ring_cap = RingCapacity(slot_count);
|
||||
size_t total = AlignUp(sizeof(Header), kAlign);
|
||||
const uint32_t ring_cap = ring_capacity(slot_count);
|
||||
size_t total = align_up(sizeof(Header), k_align);
|
||||
total +=
|
||||
AlignUp(SpscRingBuffer::BytesNeeded(ring_cap), kAlign); // free ring
|
||||
align_up(SpscRingBuffer::bytes_needed(ring_cap), k_align); // free ring
|
||||
total +=
|
||||
AlignUp(SpscRingBuffer::BytesNeeded(ring_cap), kAlign); // ready ring
|
||||
align_up(SpscRingBuffer::bytes_needed(ring_cap), k_align); // ready ring
|
||||
total +=
|
||||
AlignUp(sizeof(FrameSlotMeta) * slot_count, kAlign); // metadata array
|
||||
total += AlignUp(slot_data_bytes, kAlign) * slot_count; // pixel data blocks
|
||||
align_up(sizeof(FrameSlotMeta) * slot_count, k_align); // metadata array
|
||||
total += align_up(slot_data_bytes, k_align) * slot_count; // pixel data blocks
|
||||
return total;
|
||||
}
|
||||
|
||||
FrameSlotPool FrameSlotPool::Create(void *mem, uint32_t slot_count,
|
||||
FrameSlotPool FrameSlotPool::create(void *mem, uint32_t slot_count,
|
||||
size_t slot_data_bytes)
|
||||
{
|
||||
FrameSlotPool pool;
|
||||
pool.base_ = reinterpret_cast<uint8_t *>(mem);
|
||||
|
||||
const uint32_t ring_cap = RingCapacity(slot_count);
|
||||
const uint32_t ring_cap = ring_capacity(slot_count);
|
||||
|
||||
size_t offset = 0;
|
||||
const size_t header_off = offset;
|
||||
offset += AlignUp(sizeof(Header), kAlign);
|
||||
offset += align_up(sizeof(Header), k_align);
|
||||
|
||||
const size_t free_off = offset;
|
||||
offset += AlignUp(SpscRingBuffer::BytesNeeded(ring_cap), kAlign);
|
||||
offset += align_up(SpscRingBuffer::bytes_needed(ring_cap), k_align);
|
||||
|
||||
const size_t ready_off = offset;
|
||||
offset += AlignUp(SpscRingBuffer::BytesNeeded(ring_cap), kAlign);
|
||||
offset += align_up(SpscRingBuffer::bytes_needed(ring_cap), k_align);
|
||||
|
||||
const size_t meta_off = offset;
|
||||
offset += AlignUp(sizeof(FrameSlotMeta) * slot_count, kAlign);
|
||||
offset += align_up(sizeof(FrameSlotMeta) * slot_count, k_align);
|
||||
|
||||
const size_t data_off = offset;
|
||||
|
||||
pool.header_ = reinterpret_cast<Header *>(pool.base_ + header_off);
|
||||
pool.header_->magic = kMagic;
|
||||
pool.header_->magic = k_magic;
|
||||
pool.header_->slot_count = slot_count;
|
||||
pool.header_->slot_data_bytes = slot_data_bytes;
|
||||
pool.header_->free_ring_offset = free_off;
|
||||
@@ -86,8 +86,8 @@ FrameSlotPool FrameSlotPool::Create(void *mem, uint32_t slot_count,
|
||||
pool.header_->meta_offset = meta_off;
|
||||
pool.header_->data_offset = data_off;
|
||||
|
||||
pool.free_ring_ = SpscRingBuffer::Create(pool.base_ + free_off, ring_cap);
|
||||
pool.ready_ring_ = SpscRingBuffer::Create(pool.base_ + ready_off, ring_cap);
|
||||
pool.free_ring_ = SpscRingBuffer::create(pool.base_ + free_off, ring_cap);
|
||||
pool.ready_ring_ = SpscRingBuffer::create(pool.base_ + ready_off, ring_cap);
|
||||
pool.meta_ = reinterpret_cast<FrameSlotMeta *>(pool.base_ + meta_off);
|
||||
pool.data_ = pool.base_ + data_off;
|
||||
|
||||
@@ -95,19 +95,19 @@ FrameSlotPool FrameSlotPool::Create(void *mem, uint32_t slot_count,
|
||||
|
||||
// Seed the free ring with every slot index so the filler can Acquire() immediately.
|
||||
for (uint32_t i = 0; i < slot_count; i++) {
|
||||
pool.free_ring_->Push(i);
|
||||
pool.free_ring_->push(i);
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
FrameSlotPool FrameSlotPool::Attach(void *mem)
|
||||
FrameSlotPool FrameSlotPool::attach(void *mem)
|
||||
{
|
||||
FrameSlotPool pool;
|
||||
pool.base_ = reinterpret_cast<uint8_t *>(mem);
|
||||
pool.header_ = reinterpret_cast<Header *>(pool.base_);
|
||||
|
||||
if (pool.header_->magic != kMagic) {
|
||||
if (pool.header_->magic != k_magic) {
|
||||
// Caller will see IsValid() == false via a null header reset.
|
||||
pool.header_ = nullptr;
|
||||
pool.base_ = nullptr;
|
||||
@@ -115,9 +115,9 @@ FrameSlotPool FrameSlotPool::Attach(void *mem)
|
||||
}
|
||||
|
||||
pool.free_ring_ =
|
||||
SpscRingBuffer::Attach(pool.base_ + pool.header_->free_ring_offset);
|
||||
SpscRingBuffer::attach(pool.base_ + pool.header_->free_ring_offset);
|
||||
pool.ready_ring_ =
|
||||
SpscRingBuffer::Attach(pool.base_ + pool.header_->ready_ring_offset);
|
||||
SpscRingBuffer::attach(pool.base_ + pool.header_->ready_ring_offset);
|
||||
pool.meta_ = reinterpret_cast<FrameSlotMeta *>(pool.base_ +
|
||||
pool.header_->meta_offset);
|
||||
pool.data_ = pool.base_ + pool.header_->data_offset;
|
||||
@@ -135,44 +135,44 @@ size_t FrameSlotPool::slot_data_bytes() const
|
||||
return header_ ? size_t(header_->slot_data_bytes) : 0;
|
||||
}
|
||||
|
||||
bool FrameSlotPool::Acquire(uint32_t *index)
|
||||
bool FrameSlotPool::acquire(uint32_t *index)
|
||||
{
|
||||
return free_ring_->Pop(index);
|
||||
return free_ring_->pop(index);
|
||||
}
|
||||
|
||||
void *FrameSlotPool::SlotData(uint32_t index)
|
||||
void *FrameSlotPool::slot_data(uint32_t index)
|
||||
{
|
||||
return data_ + size_t(index) * AlignUp(slot_data_bytes(), kAlign);
|
||||
return data_ + size_t(index) * align_up(slot_data_bytes(), k_align);
|
||||
}
|
||||
|
||||
const void *FrameSlotPool::SlotData(uint32_t index) const
|
||||
const void *FrameSlotPool::slot_data(uint32_t index) const
|
||||
{
|
||||
return data_ + size_t(index) * AlignUp(slot_data_bytes(), kAlign);
|
||||
return data_ + size_t(index) * align_up(slot_data_bytes(), k_align);
|
||||
}
|
||||
|
||||
FrameSlotMeta *FrameSlotPool::Meta(uint32_t index)
|
||||
FrameSlotMeta *FrameSlotPool::meta(uint32_t index)
|
||||
{
|
||||
return &meta_[index];
|
||||
}
|
||||
|
||||
const FrameSlotMeta *FrameSlotPool::Meta(uint32_t index) const
|
||||
const FrameSlotMeta *FrameSlotPool::meta(uint32_t index) const
|
||||
{
|
||||
return &meta_[index];
|
||||
}
|
||||
|
||||
bool FrameSlotPool::Publish(uint32_t index)
|
||||
bool FrameSlotPool::publish(uint32_t index)
|
||||
{
|
||||
return ready_ring_->Push(index);
|
||||
return ready_ring_->push(index);
|
||||
}
|
||||
|
||||
bool FrameSlotPool::Consume(uint32_t *index)
|
||||
bool FrameSlotPool::consume(uint32_t *index)
|
||||
{
|
||||
return ready_ring_->Pop(index);
|
||||
return ready_ring_->pop(index);
|
||||
}
|
||||
|
||||
bool FrameSlotPool::Release(uint32_t index)
|
||||
bool FrameSlotPool::release(uint32_t index)
|
||||
{
|
||||
return free_ring_->Push(index);
|
||||
return free_ring_->push(index);
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef IPC_FRAMESLOTPOOL_H
|
||||
#define IPC_FRAMESLOTPOOL_H
|
||||
#ifndef OAK_IPC_FRAMESLOTPOOL_H
|
||||
#define OAK_IPC_FRAMESLOTPOOL_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@@ -36,7 +36,7 @@ namespace ipc
|
||||
*
|
||||
* Trivially-copyable POD that lives in shared memory alongside the pixel data. Carries everything
|
||||
* the consumer needs to reconstruct an olive::Frame without any out-of-band information. We store
|
||||
* the rational timestamp as an explicit numerator/denominator pair to stay POD (olive::rational is
|
||||
* the Rational timestamp as an explicit numerator/denominator pair to stay POD (olive::Rational is
|
||||
* not guaranteed shared-memory-safe).
|
||||
*/
|
||||
struct FrameSlotMeta {
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
/**
|
||||
* @brief Total bytes a region must provide to back a pool of `slot_count` x `slot_data_bytes`.
|
||||
*/
|
||||
static size_t BytesNeeded(uint32_t slot_count, size_t slot_data_bytes);
|
||||
static size_t bytes_needed(uint32_t slot_count, size_t slot_data_bytes);
|
||||
|
||||
/**
|
||||
* @brief Lay out and initialize a brand-new pool over `mem` (owner side, once).
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
* Initializes both rings, seeds the free ring with every slot index, and zeroes metadata.
|
||||
* `mem` must provide at least BytesNeeded(slot_count, slot_data_bytes) bytes.
|
||||
*/
|
||||
static FrameSlotPool Create(void *mem, uint32_t slot_count,
|
||||
static FrameSlotPool create(void *mem, uint32_t slot_count,
|
||||
size_t slot_data_bytes);
|
||||
|
||||
/**
|
||||
@@ -98,9 +98,9 @@ public:
|
||||
*
|
||||
* Reads slot_count/slot_data_bytes from the in-memory header written by Create().
|
||||
*/
|
||||
static FrameSlotPool Attach(void *mem);
|
||||
static FrameSlotPool attach(void *mem);
|
||||
|
||||
bool IsValid() const
|
||||
bool is_valid() const
|
||||
{
|
||||
return header_ != nullptr;
|
||||
}
|
||||
@@ -113,37 +113,37 @@ public:
|
||||
/**
|
||||
* @brief Take ownership of a free slot. Returns false (and leaves *index untouched) if none free.
|
||||
*/
|
||||
bool Acquire(uint32_t *index);
|
||||
bool acquire(uint32_t *index);
|
||||
|
||||
/**
|
||||
* @brief Pointer to a slot's pixel data block (slot_data_bytes available).
|
||||
*/
|
||||
void *SlotData(uint32_t index);
|
||||
void *slot_data(uint32_t index);
|
||||
|
||||
/**
|
||||
* @brief Mutable metadata for a slot. Filler writes this before Publish().
|
||||
*/
|
||||
FrameSlotMeta *Meta(uint32_t index);
|
||||
FrameSlotMeta *meta(uint32_t index);
|
||||
|
||||
/**
|
||||
* @brief Publish a filled slot to the drainer. Must follow a successful Acquire() of `index`.
|
||||
*/
|
||||
bool Publish(uint32_t index);
|
||||
bool publish(uint32_t index);
|
||||
|
||||
// ---- Drainer side ----
|
||||
|
||||
/**
|
||||
* @brief Take the next published slot. Returns false if nothing is ready.
|
||||
*/
|
||||
bool Consume(uint32_t *index);
|
||||
bool consume(uint32_t *index);
|
||||
|
||||
/**
|
||||
* @brief Return a consumed slot to the free pool for reuse. Must follow Consume() of `index`.
|
||||
*/
|
||||
bool Release(uint32_t index);
|
||||
bool release(uint32_t index);
|
||||
|
||||
const FrameSlotMeta *Meta(uint32_t index) const;
|
||||
const void *SlotData(uint32_t index) const;
|
||||
const FrameSlotMeta *meta(uint32_t index) const;
|
||||
const void *slot_data(uint32_t index) const;
|
||||
|
||||
public:
|
||||
FrameSlotPool() = default;
|
||||
@@ -160,11 +160,11 @@ private:
|
||||
uint64_t data_offset;
|
||||
};
|
||||
|
||||
static constexpr uint32_t kMagic = 0x4F4B5350; // 'OKSP'
|
||||
static constexpr uint32_t k_magic = 0x4F4B5350; // 'OKSP'
|
||||
|
||||
// Ring capacity must exceed slot_count by one because a ring can hold at most capacity-1 entries
|
||||
// and we need to be able to enqueue every slot at once.
|
||||
static uint32_t RingCapacity(uint32_t slot_count)
|
||||
static uint32_t ring_capacity(uint32_t slot_count)
|
||||
{
|
||||
return slot_count + 1;
|
||||
}
|
||||
@@ -180,4 +180,4 @@ private:
|
||||
} // namespace ipc
|
||||
} // namespace olive
|
||||
|
||||
#endif // IPC_FRAMESLOTPOOL_H
|
||||
#endif // OAK_IPC_FRAMESLOTPOOL_H
|
||||
@@ -29,14 +29,14 @@ namespace olive
|
||||
namespace ipc
|
||||
{
|
||||
|
||||
bool WriteMessage(QIODevice *device, const QJsonObject &obj)
|
||||
bool write_message(QIODevice *device, const QJsonObject &obj)
|
||||
{
|
||||
QByteArray line = QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||
line.append('\n');
|
||||
return device->write(line) == line.size();
|
||||
}
|
||||
|
||||
bool ReadMessage(QByteArray *buffer, QJsonObject *out, bool *ok)
|
||||
bool read_message(QByteArray *buffer, QJsonObject *out, bool *ok)
|
||||
{
|
||||
while (true) {
|
||||
const int newline = buffer->indexOf('\n');
|
||||
@@ -72,10 +72,10 @@ bool ReadMessage(QByteArray *buffer, QJsonObject *out, bool *ok)
|
||||
|
||||
// ---- HandshakeMsg ---------------------------------------------------------------------------
|
||||
|
||||
QJsonObject HandshakeMsg::ToJson() const
|
||||
QJsonObject HandshakeMsg::to_json() const
|
||||
{
|
||||
QJsonObject o;
|
||||
o["type"] = msgtype::kHandshake;
|
||||
o["type"] = msgtype::k_handshake;
|
||||
o["protocol_version"] = protocol_version;
|
||||
o["shm_key"] = shm_key;
|
||||
o["input_shm_key"] = input_shm_key;
|
||||
@@ -86,9 +86,9 @@ QJsonObject HandshakeMsg::ToJson() const
|
||||
return o;
|
||||
}
|
||||
|
||||
bool HandshakeMsg::FromJson(const QJsonObject &o, HandshakeMsg *out)
|
||||
bool HandshakeMsg::from_json(const QJsonObject &o, HandshakeMsg *out)
|
||||
{
|
||||
if (o["type"].toString() != QLatin1String(msgtype::kHandshake)) {
|
||||
if (o["type"].toString() != QLatin1String(msgtype::k_handshake)) {
|
||||
return false;
|
||||
}
|
||||
out->protocol_version = o["protocol_version"].toInt();
|
||||
@@ -103,10 +103,10 @@ bool HandshakeMsg::FromJson(const QJsonObject &o, HandshakeMsg *out)
|
||||
|
||||
// ---- RenderFrameMsg -------------------------------------------------------------------------
|
||||
|
||||
QJsonObject RenderFrameMsg::ToJson() const
|
||||
QJsonObject RenderFrameMsg::to_json() const
|
||||
{
|
||||
QJsonObject o;
|
||||
o["type"] = msgtype::kRenderFrame;
|
||||
o["type"] = msgtype::k_render_frame;
|
||||
o["ticket"] = double(ticket_id);
|
||||
o["node"] = node_uuid;
|
||||
o["time_num"] = double(time_num);
|
||||
@@ -133,9 +133,9 @@ QJsonObject RenderFrameMsg::ToJson() const
|
||||
return o;
|
||||
}
|
||||
|
||||
bool RenderFrameMsg::FromJson(const QJsonObject &o, RenderFrameMsg *out)
|
||||
bool RenderFrameMsg::from_json(const QJsonObject &o, RenderFrameMsg *out)
|
||||
{
|
||||
if (o["type"].toString() != QLatin1String(msgtype::kRenderFrame)) {
|
||||
if (o["type"].toString() != QLatin1String(msgtype::k_render_frame)) {
|
||||
return false;
|
||||
}
|
||||
out->ticket_id = qint64(o["ticket"].toDouble());
|
||||
@@ -169,18 +169,18 @@ bool RenderFrameMsg::FromJson(const QJsonObject &o, RenderFrameMsg *out)
|
||||
|
||||
// ---- FrameReadyMsg --------------------------------------------------------------------------
|
||||
|
||||
QJsonObject FrameReadyMsg::ToJson() const
|
||||
QJsonObject FrameReadyMsg::to_json() const
|
||||
{
|
||||
QJsonObject o;
|
||||
o["type"] = msgtype::kFrameReady;
|
||||
o["type"] = msgtype::k_frame_ready;
|
||||
o["ticket"] = double(ticket_id);
|
||||
o["slot"] = output_slot;
|
||||
return o;
|
||||
}
|
||||
|
||||
bool FrameReadyMsg::FromJson(const QJsonObject &o, FrameReadyMsg *out)
|
||||
bool FrameReadyMsg::from_json(const QJsonObject &o, FrameReadyMsg *out)
|
||||
{
|
||||
if (o["type"].toString() != QLatin1String(msgtype::kFrameReady)) {
|
||||
if (o["type"].toString() != QLatin1String(msgtype::k_frame_ready)) {
|
||||
return false;
|
||||
}
|
||||
out->ticket_id = qint64(o["ticket"].toDouble());
|
||||
@@ -190,17 +190,17 @@ bool FrameReadyMsg::FromJson(const QJsonObject &o, FrameReadyMsg *out)
|
||||
|
||||
// ---- CancelMsg ------------------------------------------------------------------------------
|
||||
|
||||
QJsonObject CancelMsg::ToJson() const
|
||||
QJsonObject CancelMsg::to_json() const
|
||||
{
|
||||
QJsonObject o;
|
||||
o["type"] = msgtype::kCancel;
|
||||
o["type"] = msgtype::k_cancel;
|
||||
o["ticket"] = double(ticket_id);
|
||||
return o;
|
||||
}
|
||||
|
||||
bool CancelMsg::FromJson(const QJsonObject &o, CancelMsg *out)
|
||||
bool CancelMsg::from_json(const QJsonObject &o, CancelMsg *out)
|
||||
{
|
||||
if (o["type"].toString() != QLatin1String(msgtype::kCancel)) {
|
||||
if (o["type"].toString() != QLatin1String(msgtype::k_cancel)) {
|
||||
return false;
|
||||
}
|
||||
out->ticket_id = qint64(o["ticket"].toDouble());
|
||||
@@ -209,17 +209,17 @@ bool CancelMsg::FromJson(const QJsonObject &o, CancelMsg *out)
|
||||
|
||||
// ---- LoadGraphMsg ---------------------------------------------------------------------------
|
||||
|
||||
QJsonObject LoadGraphMsg::ToJson() const
|
||||
QJsonObject LoadGraphMsg::to_json() const
|
||||
{
|
||||
QJsonObject o;
|
||||
o["type"] = msgtype::kLoadGraph;
|
||||
o["type"] = msgtype::k_load_graph;
|
||||
o["path"] = path;
|
||||
return o;
|
||||
}
|
||||
|
||||
bool LoadGraphMsg::FromJson(const QJsonObject &o, LoadGraphMsg *out)
|
||||
bool LoadGraphMsg::from_json(const QJsonObject &o, LoadGraphMsg *out)
|
||||
{
|
||||
if (o["type"].toString() != QLatin1String(msgtype::kLoadGraph)) {
|
||||
if (o["type"].toString() != QLatin1String(msgtype::k_load_graph)) {
|
||||
return false;
|
||||
}
|
||||
out->path = o["path"].toString();
|
||||
|
||||
+23
-23
@@ -18,8 +18,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef IPC_IPCMESSAGE_H
|
||||
#define IPC_IPCMESSAGE_H
|
||||
#ifndef OAK_IPC_IPCMESSAGE_H
|
||||
#define OAK_IPC_IPCMESSAGE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <QByteArray>
|
||||
@@ -55,14 +55,14 @@ namespace ipc
|
||||
*/
|
||||
namespace msgtype
|
||||
{
|
||||
constexpr const char *kHandshake = "handshake";
|
||||
constexpr const char *kLoadGraph = "load_graph";
|
||||
constexpr const char *kRenderFrame = "render_frame";
|
||||
constexpr const char *kFrameReady = "frame_ready";
|
||||
constexpr const char *kCancel = "cancel";
|
||||
constexpr const char *kGraphUpdate = "graph_update";
|
||||
constexpr const char *kShutdown = "shutdown";
|
||||
constexpr const char *kError = "error";
|
||||
constexpr const char *k_handshake = "handshake";
|
||||
constexpr const char *k_load_graph = "load_graph";
|
||||
constexpr const char *k_render_frame = "render_frame";
|
||||
constexpr const char *k_frame_ready = "frame_ready";
|
||||
constexpr const char *k_cancel = "cancel";
|
||||
constexpr const char *k_graph_update = "graph_update";
|
||||
constexpr const char *k_shutdown = "shutdown";
|
||||
constexpr const char *k_error = "error";
|
||||
} // namespace msgtype
|
||||
|
||||
/**
|
||||
@@ -71,7 +71,7 @@ constexpr const char *kError = "error";
|
||||
* Serializes `obj` to compact JSON, appends '\n', and writes the whole line in one call. Returns
|
||||
* true only if the full line was written.
|
||||
*/
|
||||
bool WriteMessage(QIODevice *device, const QJsonObject &obj);
|
||||
bool write_message(QIODevice *device, const QJsonObject &obj);
|
||||
|
||||
/**
|
||||
* @brief Pull one complete NDJSON line out of `buffer` and parse it.
|
||||
@@ -82,7 +82,7 @@ bool WriteMessage(QIODevice *device, const QJsonObject &obj);
|
||||
* and continue rather than wedge. Supports the typical "append bytes as they arrive, then drain
|
||||
* complete lines" reader loop on a pipe.
|
||||
*/
|
||||
bool ReadMessage(QByteArray *buffer, QJsonObject *out, bool *ok = nullptr);
|
||||
bool read_message(QByteArray *buffer, QJsonObject *out, bool *ok = nullptr);
|
||||
|
||||
// ---- Typed message builders / parsers -------------------------------------------------------
|
||||
//
|
||||
@@ -100,8 +100,8 @@ struct HandshakeMsg {
|
||||
qint64 slot_data_bytes = 0; ///< Per-output-slot pixel block size.
|
||||
qint64 input_slot_data_bytes = 0; ///< Per-input-slot pixel block size.
|
||||
|
||||
QJsonObject ToJson() const;
|
||||
static bool FromJson(const QJsonObject &o, HandshakeMsg *out);
|
||||
QJsonObject to_json() const;
|
||||
static bool from_json(const QJsonObject &o, HandshakeMsg *out);
|
||||
};
|
||||
|
||||
struct RenderFrameMsg {
|
||||
@@ -129,33 +129,33 @@ struct RenderFrameMsg {
|
||||
QString color_view;
|
||||
QString color_look;
|
||||
|
||||
QJsonObject ToJson() const;
|
||||
static bool FromJson(const QJsonObject &o, RenderFrameMsg *out);
|
||||
QJsonObject to_json() const;
|
||||
static bool from_json(const QJsonObject &o, RenderFrameMsg *out);
|
||||
};
|
||||
|
||||
struct FrameReadyMsg {
|
||||
qint64 ticket_id = 0;
|
||||
int output_slot = 0; ///< Index into the worker->main output FrameSlotPool.
|
||||
|
||||
QJsonObject ToJson() const;
|
||||
static bool FromJson(const QJsonObject &o, FrameReadyMsg *out);
|
||||
QJsonObject to_json() const;
|
||||
static bool from_json(const QJsonObject &o, FrameReadyMsg *out);
|
||||
};
|
||||
|
||||
struct CancelMsg {
|
||||
qint64 ticket_id = 0;
|
||||
|
||||
QJsonObject ToJson() const;
|
||||
static bool FromJson(const QJsonObject &o, CancelMsg *out);
|
||||
QJsonObject to_json() const;
|
||||
static bool from_json(const QJsonObject &o, CancelMsg *out);
|
||||
};
|
||||
|
||||
struct LoadGraphMsg {
|
||||
QString path; ///< Temporary file holding the serialized node graph.
|
||||
|
||||
QJsonObject ToJson() const;
|
||||
static bool FromJson(const QJsonObject &o, LoadGraphMsg *out);
|
||||
QJsonObject to_json() const;
|
||||
static bool from_json(const QJsonObject &o, LoadGraphMsg *out);
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace olive
|
||||
|
||||
#endif // IPC_IPCMESSAGE_H
|
||||
#endif // OAK_IPC_IPCMESSAGE_H
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace ipc
|
||||
SharedMemoryRegion::SharedMemoryRegion()
|
||||
: size_(0)
|
||||
, data_(nullptr)
|
||||
, mode_(kAttach)
|
||||
, mode_(k_attach)
|
||||
#if defined(Q_OS_WIN)
|
||||
, handle_(nullptr)
|
||||
#else
|
||||
@@ -52,10 +52,10 @@ SharedMemoryRegion::SharedMemoryRegion()
|
||||
|
||||
SharedMemoryRegion::~SharedMemoryRegion()
|
||||
{
|
||||
Close();
|
||||
close();
|
||||
}
|
||||
|
||||
QString SharedMemoryRegion::MakeKey(qint64 owner_pid, int worker_index)
|
||||
QString SharedMemoryRegion::make_key(qint64 owner_pid, int worker_index)
|
||||
{
|
||||
return QStringLiteral("olive-rw-%1-%2").arg(owner_pid).arg(worker_index);
|
||||
}
|
||||
@@ -131,9 +131,9 @@ void SharedMemoryRegion::Close()
|
||||
|
||||
#else // POSIX
|
||||
|
||||
bool SharedMemoryRegion::Open(const QString &key, size_t size, Mode mode)
|
||||
bool SharedMemoryRegion::open(const QString &key, size_t size, Mode mode)
|
||||
{
|
||||
Close();
|
||||
close();
|
||||
|
||||
key_ = key;
|
||||
size_ = size;
|
||||
@@ -144,7 +144,7 @@ bool SharedMemoryRegion::Open(const QString &key, size_t size, Mode mode)
|
||||
const QByteArray name_bytes = shm_name_.toUtf8();
|
||||
|
||||
int oflag = O_RDWR;
|
||||
if (mode == kCreate) {
|
||||
if (mode == k_create) {
|
||||
oflag |= O_CREAT | O_EXCL;
|
||||
// Clear any stale segment left by a crashed previous run with the same name.
|
||||
shm_unlink(name_bytes.constData());
|
||||
@@ -157,7 +157,7 @@ bool SharedMemoryRegion::Open(const QString &key, size_t size, Mode mode)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode == kCreate) {
|
||||
if (mode == k_create) {
|
||||
if (ftruncate(fd_, off_t(size)) != 0) {
|
||||
error_ = QStringLiteral("ftruncate failed: %1")
|
||||
.arg(QString::fromUtf8(strerror(errno)));
|
||||
@@ -195,19 +195,19 @@ bool SharedMemoryRegion::Open(const QString &key, size_t size, Mode mode)
|
||||
data_ = nullptr;
|
||||
::close(fd_);
|
||||
fd_ = -1;
|
||||
if (mode == kCreate) {
|
||||
if (mode == k_create) {
|
||||
shm_unlink(name_bytes.constData());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode == kCreate) {
|
||||
if (mode == k_create) {
|
||||
memset(data_, 0, size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SharedMemoryRegion::Close()
|
||||
void SharedMemoryRegion::close()
|
||||
{
|
||||
if (data_) {
|
||||
munmap(data_, size_);
|
||||
@@ -217,7 +217,7 @@ void SharedMemoryRegion::Close()
|
||||
::close(fd_);
|
||||
fd_ = -1;
|
||||
}
|
||||
if (mode_ == kCreate && !shm_name_.isEmpty()) {
|
||||
if (mode_ == k_create && !shm_name_.isEmpty()) {
|
||||
// Only the owner unlinks, so the name is freed once both sides have unmapped.
|
||||
shm_unlink(shm_name_.toUtf8().constData());
|
||||
shm_name_.clear();
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef IPC_SHAREDMEMORYREGION_H
|
||||
#define IPC_SHAREDMEMORYREGION_H
|
||||
#ifndef OAK_IPC_SHAREDMEMORYREGION_H
|
||||
#define OAK_IPC_SHAREDMEMORYREGION_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <QString>
|
||||
@@ -46,9 +46,9 @@ class SharedMemoryRegion {
|
||||
public:
|
||||
enum Mode {
|
||||
/// Create (and own) the segment. Fails if it already exists; unlinks on destruction.
|
||||
kCreate,
|
||||
k_create,
|
||||
/// Attach to a segment created by the peer. Does not unlink on destruction.
|
||||
kAttach
|
||||
k_attach
|
||||
};
|
||||
|
||||
SharedMemoryRegion();
|
||||
@@ -63,14 +63,14 @@ public:
|
||||
* `key` is a short identifier (no leading slash needed; the platform prefix is added internally).
|
||||
* Returns true on success. On failure, error() carries a human-readable reason.
|
||||
*/
|
||||
bool Open(const QString &key, size_t size, Mode mode);
|
||||
bool open(const QString &key, size_t size, Mode mode);
|
||||
|
||||
/**
|
||||
* @brief Unmap and (if owner) unlink the segment. Called automatically by the destructor.
|
||||
*/
|
||||
void Close();
|
||||
void close();
|
||||
|
||||
bool IsValid() const
|
||||
bool is_valid() const
|
||||
{
|
||||
return data_ != nullptr;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
*
|
||||
* Centralized so the owner and the spawned worker agree on the same name.
|
||||
*/
|
||||
static QString MakeKey(qint64 owner_pid, int worker_index);
|
||||
static QString make_key(qint64 owner_pid, int worker_index);
|
||||
|
||||
private:
|
||||
QString key_;
|
||||
@@ -120,4 +120,4 @@ private:
|
||||
} // namespace ipc
|
||||
} // namespace olive
|
||||
|
||||
#endif // IPC_SHAREDMEMORYREGION_H
|
||||
#endif // OAK_IPC_SHAREDMEMORYREGION_H
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef IPC_SPSCRINGBUFFER_H
|
||||
#define IPC_SPSCRINGBUFFER_H
|
||||
#ifndef OAK_IPC_SPSCRINGBUFFER_H
|
||||
#define OAK_IPC_SPSCRINGBUFFER_H
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
* intended to be placement-style initialization performed exactly once by whichever process owns
|
||||
* the segment's creation; the peer process uses Attach() instead.
|
||||
*/
|
||||
static SpscRingBuffer *Create(void *mem, uint32_t capacity)
|
||||
static SpscRingBuffer *create(void *mem, uint32_t capacity)
|
||||
{
|
||||
auto *self = reinterpret_cast<SpscRingBuffer *>(mem);
|
||||
self->capacity_ = capacity;
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
*
|
||||
* No writes are performed; the cursors and capacity are assumed already set by Create().
|
||||
*/
|
||||
static SpscRingBuffer *Attach(void *mem)
|
||||
static SpscRingBuffer *attach(void *mem)
|
||||
{
|
||||
return reinterpret_cast<SpscRingBuffer *>(mem);
|
||||
}
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
/**
|
||||
* @brief Total bytes required to hold the header plus `capacity` index slots.
|
||||
*/
|
||||
static size_t BytesNeeded(uint32_t capacity)
|
||||
static size_t bytes_needed(uint32_t capacity)
|
||||
{
|
||||
return sizeof(SpscRingBuffer) + size_t(capacity) * sizeof(uint32_t);
|
||||
}
|
||||
@@ -93,10 +93,10 @@ public:
|
||||
/**
|
||||
* @brief Producer side: enqueue an index. Returns false if the buffer is full.
|
||||
*/
|
||||
bool Push(uint32_t value)
|
||||
bool push(uint32_t value)
|
||||
{
|
||||
const uint32_t head = head_.load(std::memory_order_relaxed);
|
||||
const uint32_t next = Increment(head);
|
||||
const uint32_t next = increment(head);
|
||||
|
||||
// Buffer is full if advancing head would collide with the consumer's tail.
|
||||
if (next == tail_.load(std::memory_order_acquire)) {
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
/**
|
||||
* @brief Consumer side: dequeue an index into `out`. Returns false if the buffer is empty.
|
||||
*/
|
||||
bool Pop(uint32_t *out)
|
||||
bool pop(uint32_t *out)
|
||||
{
|
||||
const uint32_t tail = tail_.load(std::memory_order_relaxed);
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
}
|
||||
|
||||
*out = slot_array()[tail];
|
||||
tail_.store(Increment(tail), std::memory_order_release);
|
||||
tail_.store(increment(tail), std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -131,14 +131,14 @@ public:
|
||||
* Safe to call from either side, but the value may be stale the instant it returns. Intended for
|
||||
* metrics/backpressure heuristics, not for correctness decisions.
|
||||
*/
|
||||
uint32_t SizeApprox() const
|
||||
uint32_t size_approx() const
|
||||
{
|
||||
const uint32_t head = head_.load(std::memory_order_acquire);
|
||||
const uint32_t tail = tail_.load(std::memory_order_acquire);
|
||||
return (head + capacity_ - tail) % capacity_;
|
||||
}
|
||||
|
||||
bool IsEmptyApprox() const
|
||||
bool is_empty_approx() const
|
||||
{
|
||||
return head_.load(std::memory_order_acquire) ==
|
||||
tail_.load(std::memory_order_acquire);
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t Increment(uint32_t index) const
|
||||
uint32_t increment(uint32_t index) const
|
||||
{
|
||||
// capacity_ is small and this avoids requiring a power-of-two capacity.
|
||||
return (index + 1) % capacity_;
|
||||
@@ -182,4 +182,4 @@ private:
|
||||
} // namespace ipc
|
||||
} // namespace olive
|
||||
|
||||
#endif // IPC_SPSCRINGBUFFER_H
|
||||
#endif // OAK_IPC_SPSCRINGBUFFER_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef ACCELERATEDJOB_H
|
||||
#define ACCELERATEDJOB_H
|
||||
#ifndef OAK_ACCELERATEDJOB_H
|
||||
#define OAK_ACCELERATEDJOB_H
|
||||
|
||||
#include "node/param.h"
|
||||
#include "node/valuedatabase.h"
|
||||
@@ -36,22 +36,22 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual NodeValue Get(const QString &input) const
|
||||
virtual NodeValue get(const QString &input) const
|
||||
{
|
||||
return value_map_.value(input);
|
||||
}
|
||||
|
||||
virtual void Insert(const QString &input, const NodeValueRow &row)
|
||||
virtual void insert(const QString &input, const NodeValueRow &row)
|
||||
{
|
||||
value_map_.insert(input, row.value(input));
|
||||
}
|
||||
|
||||
virtual void Insert(const QString &input, const NodeValue &value)
|
||||
virtual void insert(const QString &input, const NodeValue &value)
|
||||
{
|
||||
value_map_.insert(input, value);
|
||||
}
|
||||
|
||||
virtual void Insert(const NodeValueRow &row)
|
||||
virtual void insert(const NodeValueRow &row)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
value_map_.insert(row);
|
||||
@@ -62,11 +62,11 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual const NodeValueRow &GetValues() const
|
||||
virtual const NodeValueRow &get_values() const
|
||||
{
|
||||
return value_map_;
|
||||
}
|
||||
virtual NodeValueRow &GetValues()
|
||||
virtual NodeValueRow &get_values()
|
||||
{
|
||||
return value_map_;
|
||||
}
|
||||
@@ -77,4 +77,4 @@ protected:
|
||||
|
||||
}
|
||||
|
||||
#endif // ACCELERATEDJOB_H
|
||||
#endif // OAK_ACCELERATEDJOB_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef CACHEJOB_H
|
||||
#define CACHEJOB_H
|
||||
#ifndef OAK_CACHEJOB_H
|
||||
#define OAK_CACHEJOB_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
@@ -39,20 +39,20 @@ public:
|
||||
filename_ = filename;
|
||||
}
|
||||
|
||||
const QString &GetFilename() const
|
||||
const QString &get_filename() const
|
||||
{
|
||||
return filename_;
|
||||
}
|
||||
void SetFilename(const QString &s)
|
||||
void set_filename(const QString &s)
|
||||
{
|
||||
filename_ = s;
|
||||
}
|
||||
|
||||
const NodeValue &GetFallback() const
|
||||
const NodeValue &get_fallback() const
|
||||
{
|
||||
return fallback_;
|
||||
}
|
||||
void SetFallback(const NodeValue &val)
|
||||
void set_fallback(const NodeValue &val)
|
||||
{
|
||||
fallback_ = val;
|
||||
}
|
||||
@@ -65,4 +65,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // CACHEJOB_H
|
||||
#endif // OAK_CACHEJOB_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef COLORTRANSFORMJOB_H
|
||||
#define COLORTRANSFORMJOB_H
|
||||
#ifndef OAK_COLORTRANSFORMJOB_H
|
||||
#define OAK_COLORTRANSFORMJOB_H
|
||||
|
||||
#include <QMatrix4x4>
|
||||
#include <QString>
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
{
|
||||
processor_ = nullptr;
|
||||
custom_shader_src_ = nullptr;
|
||||
input_alpha_association_ = kAlphaNone;
|
||||
input_alpha_association_ = k_alpha_none;
|
||||
clear_destination_ = true;
|
||||
force_opaque_ = false;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
ColorTransformJob(const NodeValueRow &row)
|
||||
: ColorTransformJob()
|
||||
{
|
||||
Insert(row);
|
||||
insert(row);
|
||||
}
|
||||
|
||||
QString id() const
|
||||
@@ -61,98 +61,98 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void SetOverrideID(const QString &id)
|
||||
void set_override_id(const QString &id)
|
||||
{
|
||||
id_ = id;
|
||||
}
|
||||
|
||||
const NodeValue &GetInputTexture() const
|
||||
const NodeValue &get_input_texture() const
|
||||
{
|
||||
return input_texture_;
|
||||
}
|
||||
void SetInputTexture(const NodeValue &tex)
|
||||
void set_input_texture(const NodeValue &tex)
|
||||
{
|
||||
input_texture_ = tex;
|
||||
}
|
||||
void SetInputTexture(TexturePtr tex)
|
||||
void set_input_texture(TexturePtr tex)
|
||||
{
|
||||
Q_ASSERT(!tex->IsDummy());
|
||||
input_texture_ = NodeValue(NodeValue::kTexture, tex);
|
||||
Q_ASSERT(!tex->is_dummy());
|
||||
input_texture_ = NodeValue(NodeValue::k_texture, tex);
|
||||
}
|
||||
|
||||
ColorProcessorPtr GetColorProcessor() const
|
||||
ColorProcessorPtr get_color_processor() const
|
||||
{
|
||||
return processor_;
|
||||
}
|
||||
void SetColorProcessor(ColorProcessorPtr p)
|
||||
void set_color_processor(ColorProcessorPtr p)
|
||||
{
|
||||
processor_ = p;
|
||||
}
|
||||
|
||||
const AlphaAssociated &GetInputAlphaAssociation() const
|
||||
const AlphaAssociated &get_input_alpha_association() const
|
||||
{
|
||||
return input_alpha_association_;
|
||||
}
|
||||
void SetInputAlphaAssociation(const AlphaAssociated &e)
|
||||
void set_input_alpha_association(const AlphaAssociated &e)
|
||||
{
|
||||
input_alpha_association_ = e;
|
||||
}
|
||||
|
||||
const Node *CustomShaderSource() const
|
||||
const Node *custom_shader_source() const
|
||||
{
|
||||
return custom_shader_src_;
|
||||
}
|
||||
const QString &CustomShaderID() const
|
||||
const QString &custom_shader_id() const
|
||||
{
|
||||
return custom_shader_id_;
|
||||
}
|
||||
void SetNeedsCustomShader(const Node *node, const QString &id = QString())
|
||||
void set_needs_custom_shader(const Node *node, const QString &id = QString())
|
||||
{
|
||||
custom_shader_src_ = node;
|
||||
custom_shader_id_ = id;
|
||||
}
|
||||
|
||||
bool IsClearDestinationEnabled() const
|
||||
bool is_clear_destination_enabled() const
|
||||
{
|
||||
return clear_destination_;
|
||||
}
|
||||
void SetClearDestinationEnabled(bool e)
|
||||
void set_clear_destination_enabled(bool e)
|
||||
{
|
||||
clear_destination_ = e;
|
||||
}
|
||||
|
||||
const QMatrix4x4 &GetTransformMatrix() const
|
||||
const QMatrix4x4 &get_transform_matrix() const
|
||||
{
|
||||
return matrix_;
|
||||
}
|
||||
void SetTransformMatrix(const QMatrix4x4 &m)
|
||||
void set_transform_matrix(const QMatrix4x4 &m)
|
||||
{
|
||||
matrix_ = m;
|
||||
}
|
||||
|
||||
const QMatrix4x4 &GetCropMatrix() const
|
||||
const QMatrix4x4 &get_crop_matrix() const
|
||||
{
|
||||
return crop_matrix_;
|
||||
}
|
||||
void SetCropMatrix(const QMatrix4x4 &m)
|
||||
void set_crop_matrix(const QMatrix4x4 &m)
|
||||
{
|
||||
crop_matrix_ = m;
|
||||
}
|
||||
|
||||
const QString &GetFunctionName() const
|
||||
const QString &get_function_name() const
|
||||
{
|
||||
return function_name_;
|
||||
}
|
||||
void SetFunctionName(const QString &function_name = QString())
|
||||
void set_function_name(const QString &function_name = QString())
|
||||
{
|
||||
function_name_ = function_name;
|
||||
};
|
||||
|
||||
bool GetForceOpaque() const
|
||||
bool get_force_opaque() const
|
||||
{
|
||||
return force_opaque_;
|
||||
}
|
||||
void SetForceOpaque(bool e)
|
||||
void set_force_opaque(bool e)
|
||||
{
|
||||
force_opaque_ = e;
|
||||
}
|
||||
@@ -181,4 +181,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // COLORTRANSFORMJOB_H
|
||||
#endif // OAK_COLORTRANSFORMJOB_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef FOOTAGEJOB_H
|
||||
#define FOOTAGEJOB_H
|
||||
#ifndef OAK_FOOTAGEJOB_H
|
||||
#define OAK_FOOTAGEJOB_H
|
||||
|
||||
#include "node/project/footage/footage.h"
|
||||
|
||||
@@ -30,13 +30,13 @@ namespace olive
|
||||
class FootageJob : public AcceleratedJob {
|
||||
public:
|
||||
FootageJob()
|
||||
: type_(Track::kNone)
|
||||
: type_(Track::k_none)
|
||||
{
|
||||
}
|
||||
|
||||
FootageJob(const TimeRange &time, const QString &decoder,
|
||||
const QString &filename, Track::Type type,
|
||||
const rational &length, LoopMode loop_mode)
|
||||
const Rational &length, LoopMode loop_mode)
|
||||
: time_(time)
|
||||
, decoder_(decoder)
|
||||
, filename_(filename)
|
||||
@@ -120,12 +120,12 @@ public:
|
||||
cache_path_ = p;
|
||||
}
|
||||
|
||||
const rational &length() const
|
||||
const Rational &length() const
|
||||
{
|
||||
return length_;
|
||||
}
|
||||
|
||||
void set_length(const rational &length)
|
||||
void set_length(const Rational &length)
|
||||
{
|
||||
length_ = length;
|
||||
}
|
||||
@@ -167,7 +167,7 @@ private:
|
||||
|
||||
QString cache_path_;
|
||||
|
||||
rational length_;
|
||||
Rational length_;
|
||||
|
||||
LoopMode loop_mode_;
|
||||
};
|
||||
@@ -176,4 +176,4 @@ private:
|
||||
|
||||
Q_DECLARE_METATYPE(olive::FootageJob)
|
||||
|
||||
#endif // FOOTAGEJOB_H
|
||||
#endif // OAK_FOOTAGEJOB_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef GENERATEJOB_H
|
||||
#define GENERATEJOB_H
|
||||
#ifndef OAK_GENERATEJOB_H
|
||||
#define OAK_GENERATEJOB_H
|
||||
|
||||
#include "acceleratedjob.h"
|
||||
#include "codec/frame.h"
|
||||
@@ -34,10 +34,10 @@ public:
|
||||
GenerateJob(const NodeValueRow &row)
|
||||
: GenerateJob()
|
||||
{
|
||||
Insert(row);
|
||||
insert(row);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // GENERATEJOB_H
|
||||
#endif // OAK_GENERATEJOB_H
|
||||
|
||||
+14
-14
@@ -17,10 +17,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PLUGINJOB_H
|
||||
#define PLUGINJOB_H
|
||||
#ifndef OAK_PLUGINJOB_H
|
||||
#define OAK_PLUGINJOB_H
|
||||
#include "acceleratedjob.h"
|
||||
#include "pluginSupport/OlivePluginInstance.h"
|
||||
#include "pluginSupport/oliveplugininstance.h"
|
||||
#include "olive/core/util/rational.h"
|
||||
|
||||
#include <any>
|
||||
@@ -33,19 +33,19 @@ namespace plugin
|
||||
|
||||
class PluginJob : public AcceleratedJob {
|
||||
public:
|
||||
explicit PluginJob(const OFX::Host::ImageEffect::Instance *pluginInstance,
|
||||
explicit PluginJob(const OFX::Host::ImageEffect::Instance *plugin_instance,
|
||||
const PluginNode *node, NodeValueRow row,
|
||||
const olive::core::rational &time)
|
||||
const olive::core::Rational &time)
|
||||
: AcceleratedJob()
|
||||
, time_seconds_(time.toDouble())
|
||||
, time_seconds_(time.to_double())
|
||||
{
|
||||
this->pluginInstance_ = pluginInstance;
|
||||
this->pluginInstance_ = plugin_instance;
|
||||
this->node_ = node;
|
||||
Insert(row);
|
||||
insert(row);
|
||||
}
|
||||
explicit PluginJob(const OFX::Host::ImageEffect::Instance *pluginInstance,
|
||||
explicit PluginJob(const OFX::Host::ImageEffect::Instance *plugin_instance,
|
||||
const PluginNode *node, NodeValueRow row)
|
||||
: PluginJob(pluginInstance, node, row, olive::core::rational(0))
|
||||
: PluginJob(plugin_instance, node, row, olive::core::Rational(0))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
return const_cast<PluginNode *>(node_);
|
||||
}
|
||||
|
||||
OFX::Host::ImageEffect::Instance *pluginInstance()
|
||||
OFX::Host::ImageEffect::Instance *plugin_instance()
|
||||
{
|
||||
return const_cast<OFX::Host::ImageEffect::Instance *>(pluginInstance_);
|
||||
}
|
||||
@@ -67,9 +67,9 @@ public:
|
||||
private:
|
||||
const OFX::Host::ImageEffect::Instance *pluginInstance_ = nullptr;
|
||||
|
||||
QHash<OfxTime, QHash<QString, std::any>> paramsOnTime;
|
||||
QHash<OfxTime, QHash<QString, std::any>> paramsOnTime_;
|
||||
|
||||
QHash<QString, std::any> params;
|
||||
QHash<QString, std::any> params_;
|
||||
|
||||
const PluginNode *node_ = nullptr;
|
||||
double time_seconds_ = 0.0;
|
||||
@@ -78,4 +78,4 @@ private:
|
||||
} // plugin
|
||||
} // olive
|
||||
|
||||
#endif //PLUGINJOB_H
|
||||
#endif //OAK_PLUGINJOB_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef SAMPLEJOB_H
|
||||
#define SAMPLEJOB_H
|
||||
#ifndef OAK_SAMPLEJOB_H
|
||||
#define OAK_SAMPLEJOB_H
|
||||
|
||||
#include "acceleratedjob.h"
|
||||
|
||||
@@ -35,14 +35,14 @@ public:
|
||||
|
||||
SampleJob(const TimeRange &time, const NodeValue &value)
|
||||
{
|
||||
samples_ = value.toSamples();
|
||||
samples_ = value.to_samples();
|
||||
time_ = time;
|
||||
}
|
||||
|
||||
SampleJob(const TimeRange &time, const QString &from,
|
||||
const NodeValueRow &row)
|
||||
{
|
||||
samples_ = row[from].toSamples();
|
||||
samples_ = row[from].to_samples();
|
||||
time_ = time;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
return samples_;
|
||||
}
|
||||
|
||||
bool HasSamples() const
|
||||
bool has_samples() const
|
||||
{
|
||||
return samples_.is_allocated();
|
||||
}
|
||||
@@ -71,4 +71,4 @@ private:
|
||||
|
||||
Q_DECLARE_METATYPE(olive::SampleJob)
|
||||
|
||||
#endif // SAMPLEJOB_H
|
||||
#endif // OAK_SAMPLEJOB_H
|
||||
|
||||
+18
-18
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef SHADERJOB_H
|
||||
#define SHADERJOB_H
|
||||
#ifndef OAK_SHADERJOB_H
|
||||
#define OAK_SHADERJOB_H
|
||||
|
||||
#include <QMatrix4x4>
|
||||
#include <QVector>
|
||||
@@ -42,66 +42,66 @@ public:
|
||||
ShaderJob(const NodeValueRow &row)
|
||||
: ShaderJob()
|
||||
{
|
||||
Insert(row);
|
||||
insert(row);
|
||||
}
|
||||
|
||||
const QString &GetShaderID() const
|
||||
const QString &get_shader_id() const
|
||||
{
|
||||
return shader_id_;
|
||||
}
|
||||
|
||||
void SetShaderID(const QString &id)
|
||||
void set_shader_id(const QString &id)
|
||||
{
|
||||
shader_id_ = id;
|
||||
}
|
||||
|
||||
void SetIterations(int iterations, const NodeInput &iterative_input)
|
||||
void set_iterations(int iterations, const NodeInput &iterative_input)
|
||||
{
|
||||
SetIterations(iterations, iterative_input.input());
|
||||
set_iterations(iterations, iterative_input.input());
|
||||
}
|
||||
|
||||
void SetIterations(int iterations, const QString &iterative_input)
|
||||
void set_iterations(int iterations, const QString &iterative_input)
|
||||
{
|
||||
iterations_ = iterations;
|
||||
iterative_input_ = iterative_input;
|
||||
}
|
||||
|
||||
int GetIterationCount() const
|
||||
int get_iteration_count() const
|
||||
{
|
||||
return iterations_;
|
||||
}
|
||||
|
||||
const QString &GetIterativeInput() const
|
||||
const QString &get_iterative_input() const
|
||||
{
|
||||
return iterative_input_;
|
||||
}
|
||||
|
||||
Texture::Interpolation GetInterpolation(const QString &id) const
|
||||
Texture::Interpolation get_interpolation(const QString &id) const
|
||||
{
|
||||
return interpolation_.value(id, Texture::kDefaultInterpolation);
|
||||
return interpolation_.value(id, Texture::k_default_interpolation);
|
||||
}
|
||||
|
||||
const QHash<QString, Texture::Interpolation> &GetInterpolationMap() const
|
||||
const QHash<QString, Texture::Interpolation> &get_interpolation_map() const
|
||||
{
|
||||
return interpolation_;
|
||||
}
|
||||
|
||||
void SetInterpolation(const NodeInput &input, Texture::Interpolation interp)
|
||||
void set_interpolation(const NodeInput &input, Texture::Interpolation interp)
|
||||
{
|
||||
interpolation_.insert(input.input(), interp);
|
||||
}
|
||||
|
||||
void SetInterpolation(const QString &id, Texture::Interpolation interp)
|
||||
void set_interpolation(const QString &id, Texture::Interpolation interp)
|
||||
{
|
||||
interpolation_.insert(id, interp);
|
||||
}
|
||||
|
||||
void SetVertexCoordinates(const QVector<float> &vertex_coords)
|
||||
void set_vertex_coordinates(const QVector<float> &vertex_coords)
|
||||
{
|
||||
vertex_overrides_ = vertex_coords;
|
||||
}
|
||||
|
||||
const QVector<float> &GetVertexCoordinates()
|
||||
const QVector<float> &get_vertex_coordinates()
|
||||
{
|
||||
return vertex_overrides_;
|
||||
}
|
||||
@@ -120,4 +120,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // SHADERJOB_H
|
||||
#endif // OAK_SHADERJOB_H
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOPMODE_H
|
||||
#define LOOPMODE_H
|
||||
#ifndef OAK_LOOPMODE_H
|
||||
#define OAK_LOOPMODE_H
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
enum class LoopMode { kLoopModeOff, kLoopModeLoop, kLoopModeClamp };
|
||||
enum class LoopMode { k_loop_mode_off, k_loop_mode_loop, k_loop_mode_clamp };
|
||||
|
||||
}
|
||||
|
||||
#endif // LOOPMODE_H
|
||||
#endif // OAK_LOOPMODE_H
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
bool LUTLibrary::IsSupportedExtension(const QString &suffix)
|
||||
bool LUTLibrary::is_supported_extension(const QString &suffix)
|
||||
{
|
||||
QString s = suffix;
|
||||
if (s.startsWith(QLatin1Char('.'))) {
|
||||
@@ -40,9 +40,9 @@ bool LUTLibrary::IsSupportedExtension(const QString &suffix)
|
||||
return lower == QStringLiteral("cube") || lower == QStringLiteral("3dl");
|
||||
}
|
||||
|
||||
QStringList LUTLibrary::GetDirectories()
|
||||
QStringList LUTLibrary::get_directories()
|
||||
{
|
||||
const QString serialized = OLIVE_CONFIG("LUTLibraryPaths").toString();
|
||||
const QString serialized = OAK_CONFIG("LUTLibraryPaths").toString();
|
||||
|
||||
QStringList dirs = serialized.split(QLatin1Char(';'), Qt::SkipEmptyParts);
|
||||
for (QString &dir : dirs) {
|
||||
@@ -51,7 +51,7 @@ QStringList LUTLibrary::GetDirectories()
|
||||
return dirs;
|
||||
}
|
||||
|
||||
void LUTLibrary::SetDirectories(const QStringList &dirs)
|
||||
void LUTLibrary::set_directories(const QStringList &dirs)
|
||||
{
|
||||
QStringList cleaned;
|
||||
for (const QString &dir : dirs) {
|
||||
@@ -61,19 +61,19 @@ void LUTLibrary::SetDirectories(const QStringList &dirs)
|
||||
}
|
||||
}
|
||||
|
||||
Config::Current()[QStringLiteral("LUTLibraryPaths")] =
|
||||
Config::current()[QStringLiteral("LUTLibraryPaths")] =
|
||||
cleaned.join(QLatin1Char(';'));
|
||||
}
|
||||
|
||||
QStringList LUTLibrary::GetLutFiles()
|
||||
QStringList LUTLibrary::get_lut_files()
|
||||
{
|
||||
QStringList files;
|
||||
|
||||
static const QStringList kFilters = { QStringLiteral("*.cube"),
|
||||
static const QStringList k_filters = { QStringLiteral("*.cube"),
|
||||
QStringLiteral("*.3dl") };
|
||||
|
||||
for (const QString &dir : GetDirectories()) {
|
||||
QDirIterator it(dir, kFilters, QDir::Files,
|
||||
for (const QString &dir : get_directories()) {
|
||||
QDirIterator it(dir, k_filters, QDir::Files,
|
||||
QDirIterator::Subdirectories);
|
||||
while (it.hasNext()) {
|
||||
files.append(it.next());
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LUTLIBRARY_H
|
||||
#define LUTLIBRARY_H
|
||||
#ifndef OAK_LUTLIBRARY_H
|
||||
#define OAK_LUTLIBRARY_H
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
@@ -41,18 +41,18 @@ public:
|
||||
* @brief Returns true if the given file suffix is a supported LUT
|
||||
* extension (.cube or .3dl, case-insensitive, leading dot tolerated)
|
||||
*/
|
||||
static bool IsSupportedExtension(const QString &suffix);
|
||||
static bool is_supported_extension(const QString &suffix);
|
||||
|
||||
/**
|
||||
* @brief The directories that make up the LUT library
|
||||
*/
|
||||
static QStringList GetDirectories();
|
||||
static QStringList get_directories();
|
||||
|
||||
/**
|
||||
* @brief Replaces the LUT library directories and saves them to the
|
||||
* application config
|
||||
*/
|
||||
static void SetDirectories(const QStringList &dirs);
|
||||
static void set_directories(const QStringList &dirs);
|
||||
|
||||
/**
|
||||
* @brief All supported LUT files found under the library directories
|
||||
@@ -60,9 +60,9 @@ public:
|
||||
* Directories are scanned recursively. Files in earlier directories
|
||||
* are listed first.
|
||||
*/
|
||||
static QStringList GetLutFiles();
|
||||
static QStringList get_lut_files();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LUTLIBRARY_H
|
||||
#endif // OAK_LUTLIBRARY_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef MANAGEDCOLOR_H
|
||||
#define MANAGEDCOLOR_H
|
||||
#ifndef OAK_MANAGEDCOLOR_H
|
||||
#define OAK_MANAGEDCOLOR_H
|
||||
|
||||
#include <olive/core/core.h>
|
||||
|
||||
@@ -52,4 +52,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // MANAGEDCOLOR_H
|
||||
#endif // OAK_MANAGEDCOLOR_H
|
||||
|
||||
@@ -16,23 +16,23 @@ namespace
|
||||
class BackendOpenGLRenderer : public olive::OpenGLRenderer {
|
||||
public:
|
||||
using olive::OpenGLRenderer::OpenGLRenderer;
|
||||
using olive::OpenGLRenderer::Blit;
|
||||
using olive::OpenGLRenderer::CreateNativeTexture;
|
||||
using olive::OpenGLRenderer::DestroyInternal;
|
||||
using olive::OpenGLRenderer::DestroyNativeTexture;
|
||||
using olive::OpenGLRenderer::AttachTextureAsDestination;
|
||||
using olive::OpenGLRenderer::DetachTextureAsDestination;
|
||||
using olive::OpenGLRenderer::blit;
|
||||
using olive::OpenGLRenderer::create_native_texture;
|
||||
using olive::OpenGLRenderer::destroy_internal;
|
||||
using olive::OpenGLRenderer::destroy_native_texture;
|
||||
using olive::OpenGLRenderer::attach_texture_as_destination;
|
||||
using olive::OpenGLRenderer::detach_texture_as_destination;
|
||||
};
|
||||
|
||||
// Converts the opaque C ABI handle back to the C++ renderer used internally.
|
||||
BackendOpenGLRenderer *Renderer(OakRenderBackendHandle handle)
|
||||
BackendOpenGLRenderer *renderer(OakRenderBackendHandle handle)
|
||||
{
|
||||
return static_cast<BackendOpenGLRenderer *>(handle);
|
||||
}
|
||||
|
||||
// Interprets ABI QVariant payloads without copying; both modules are built
|
||||
// against the same Qt/C++ ABI in this first-generation dynamic backend.
|
||||
const QVariant &VariantRef(const void *variant)
|
||||
const QVariant &variant_ref(const void *variant)
|
||||
{
|
||||
return *static_cast<const QVariant *>(variant);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ oak_renderer_create(void *parent)
|
||||
OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_destroy(OakRenderBackendHandle handle)
|
||||
{
|
||||
delete Renderer(handle);
|
||||
delete renderer(handle);
|
||||
}
|
||||
|
||||
// Reports static OpenGL backend capabilities to the adapter.
|
||||
@@ -62,11 +62,11 @@ oak_renderer_get_info(OakRenderBackendHandle handle,
|
||||
return false;
|
||||
}
|
||||
out_info->abi_version = 1;
|
||||
out_info->kind = OAK_RENDER_BACKEND_OPENGL;
|
||||
out_info->kind = oak_render_backend_opengl;
|
||||
out_info->capabilities =
|
||||
OAK_RENDER_BACKEND_CAP_TEXTURES | OAK_RENDER_BACKEND_CAP_SHADERS |
|
||||
OAK_RENDER_BACKEND_CAP_BLIT | OAK_RENDER_BACKEND_CAP_READBACK |
|
||||
OAK_RENDER_BACKEND_CAP_VIEWER_CONTEXT;
|
||||
oak_render_backend_cap_textures | oak_render_backend_cap_shaders |
|
||||
oak_render_backend_cap_blit | oak_render_backend_cap_readback |
|
||||
oak_render_backend_cap_viewer_context;
|
||||
out_info->name = "opengl";
|
||||
out_info->status = "available";
|
||||
return true;
|
||||
@@ -83,35 +83,35 @@ oak_renderer_is_available(OakRenderBackendHandle handle)
|
||||
// Initializes an offscreen OpenGL context for non-viewer users.
|
||||
OAK_RENDER_BACKEND_EXPORT bool oak_renderer_init(OakRenderBackendHandle handle)
|
||||
{
|
||||
return Renderer(handle)->Init();
|
||||
return renderer(handle)->init();
|
||||
}
|
||||
|
||||
// Initializes the backend against a caller-owned viewer OpenGL context.
|
||||
OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_init_with_context(OakRenderBackendHandle handle, void *context)
|
||||
{
|
||||
Renderer(handle)->Init(static_cast<QOpenGLContext *>(context));
|
||||
renderer(handle)->init(static_cast<QOpenGLContext *>(context));
|
||||
}
|
||||
|
||||
// Runs renderer post-initialization once the GL context is available.
|
||||
OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_post_init(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->PostInit();
|
||||
renderer(handle)->post_init();
|
||||
}
|
||||
|
||||
// Releases post-init OpenGL surface/context state.
|
||||
OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_post_destroy(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->PostDestroy();
|
||||
renderer(handle)->post_destroy();
|
||||
}
|
||||
|
||||
// Releases renderer-owned GL resources before object destruction.
|
||||
OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_destroy_internal(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->DestroyInternal();
|
||||
renderer(handle)->destroy_internal();
|
||||
}
|
||||
|
||||
// Clears either the widget framebuffer or a texture destination.
|
||||
@@ -119,7 +119,7 @@ OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_clear_destination(OakRenderBackendHandle handle, void *texture,
|
||||
double r, double g, double b, double a)
|
||||
{
|
||||
Renderer(handle)->ClearDestination(static_cast<olive::Texture *>(texture),
|
||||
renderer(handle)->clear_destination(static_cast<olive::Texture *>(texture),
|
||||
r, g, b, a);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ OAK_RENDER_BACKEND_EXPORT void oak_renderer_create_native_texture(
|
||||
int channel_count, const void *data, int linesize, void *out_variant)
|
||||
{
|
||||
*static_cast<QVariant *>(out_variant) =
|
||||
Renderer(handle)->CreateNativeTexture(
|
||||
renderer(handle)->create_native_texture(
|
||||
width, height, depth,
|
||||
static_cast<olive::PixelFormat::Format>(format), channel_count,
|
||||
data, linesize);
|
||||
@@ -140,7 +140,7 @@ OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_destroy_native_texture(OakRenderBackendHandle handle,
|
||||
const void *variant)
|
||||
{
|
||||
Renderer(handle)->DestroyNativeTexture(VariantRef(variant));
|
||||
renderer(handle)->destroy_native_texture(variant_ref(variant));
|
||||
}
|
||||
|
||||
// Compiles an OpenGL shader program and returns its QVariant handle.
|
||||
@@ -149,7 +149,7 @@ oak_renderer_create_native_shader(OakRenderBackendHandle handle,
|
||||
const void *shader_code, void *out_variant)
|
||||
{
|
||||
*static_cast<QVariant *>(out_variant) =
|
||||
Renderer(handle)->CreateNativeShader(
|
||||
renderer(handle)->create_native_shader(
|
||||
*static_cast<const olive::ShaderCode *>(shader_code));
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_destroy_native_shader(OakRenderBackendHandle handle,
|
||||
const void *variant)
|
||||
{
|
||||
Renderer(handle)->DestroyNativeShader(VariantRef(variant));
|
||||
renderer(handle)->destroy_native_shader(variant_ref(variant));
|
||||
}
|
||||
|
||||
// Uploads CPU pixel data into an OpenGL texture.
|
||||
@@ -167,8 +167,8 @@ oak_renderer_upload_to_texture(OakRenderBackendHandle handle,
|
||||
const void *variant, const void *video_params,
|
||||
const void *data, int linesize)
|
||||
{
|
||||
Renderer(handle)->UploadToTexture(
|
||||
VariantRef(variant),
|
||||
renderer(handle)->upload_to_texture(
|
||||
variant_ref(variant),
|
||||
*static_cast<const olive::VideoParams *>(video_params), data, linesize);
|
||||
}
|
||||
|
||||
@@ -177,15 +177,15 @@ OAK_RENDER_BACKEND_EXPORT void oak_renderer_download_from_texture(
|
||||
OakRenderBackendHandle handle, const void *variant,
|
||||
const void *video_params, void *data, int linesize)
|
||||
{
|
||||
Renderer(handle)->DownloadFromTexture(
|
||||
VariantRef(variant),
|
||||
renderer(handle)->download_from_texture(
|
||||
variant_ref(variant),
|
||||
*static_cast<const olive::VideoParams *>(video_params), data, linesize);
|
||||
}
|
||||
|
||||
// Flushes/waits for pending OpenGL work as required by the renderer.
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_flush(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->Flush();
|
||||
renderer(handle)->flush();
|
||||
}
|
||||
|
||||
// Reads one pixel from an OpenGL texture.
|
||||
@@ -195,7 +195,7 @@ oak_renderer_get_pixel_from_texture(OakRenderBackendHandle handle,
|
||||
void *out_color)
|
||||
{
|
||||
*static_cast<olive::Color *>(out_color) =
|
||||
Renderer(handle)->GetPixelFromTexture(
|
||||
renderer(handle)->get_pixel_from_texture(
|
||||
static_cast<olive::Texture *>(texture),
|
||||
*static_cast<const QPointF *>(point));
|
||||
}
|
||||
@@ -207,8 +207,8 @@ OAK_RENDER_BACKEND_EXPORT void oak_renderer_blit(OakRenderBackendHandle handle,
|
||||
const void *destination_params,
|
||||
bool clear_destination)
|
||||
{
|
||||
Renderer(handle)->Blit(
|
||||
VariantRef(shader), *static_cast<olive::AcceleratedJob *>(job),
|
||||
renderer(handle)->blit(
|
||||
variant_ref(shader), *static_cast<olive::AcceleratedJob *>(job),
|
||||
static_cast<olive::Texture *>(destination),
|
||||
*static_cast<const olive::VideoParams *>(destination_params),
|
||||
clear_destination);
|
||||
@@ -218,7 +218,7 @@ OAK_RENDER_BACKEND_EXPORT void oak_renderer_blit(OakRenderBackendHandle handle,
|
||||
OAK_RENDER_BACKEND_EXPORT void *
|
||||
oak_renderer_opengl_context(OakRenderBackendHandle handle)
|
||||
{
|
||||
return Renderer(handle)->context();
|
||||
return renderer(handle)->context();
|
||||
}
|
||||
|
||||
// Binds an output texture for OFX OpenGL rendering.
|
||||
@@ -226,12 +226,12 @@ OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_attach_output_texture(OakRenderBackendHandle handle,
|
||||
const void *texture_id)
|
||||
{
|
||||
Renderer(handle)->AttachTextureAsDestination(VariantRef(texture_id));
|
||||
renderer(handle)->attach_texture_as_destination(variant_ref(texture_id));
|
||||
}
|
||||
|
||||
// Detaches any OFX OpenGL output texture binding.
|
||||
OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_detach_output_texture(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->DetachTextureAsDestination();
|
||||
renderer(handle)->detach_texture_as_destination();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef OPENGLCONTEXTPROVIDER_H
|
||||
#define OPENGLCONTEXTPROVIDER_H
|
||||
#ifndef OAK_OPENGLCONTEXTPROVIDER_H
|
||||
#define OAK_OPENGLCONTEXTPROVIDER_H
|
||||
|
||||
class QOpenGLContext;
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace olive
|
||||
class OpenGLContextProvider {
|
||||
public:
|
||||
virtual ~OpenGLContextProvider() = default;
|
||||
virtual QOpenGLContext *OpenGLContext() const = 0;
|
||||
virtual QOpenGLContext *open_gl_context() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OPENGLCONTEXTPROVIDER_H
|
||||
#endif // OAK_OPENGLCONTEXTPROVIDER_H
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
const int OpenGLRenderer::kTextureCacheMaxSize = 5000;
|
||||
const int OpenGLRenderer::k_texture_cache_max_size = 5000;
|
||||
|
||||
const QVector<GLfloat> blit_vertices = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f,
|
||||
0.0f, 1.0f, 1.0f, 0.0f,
|
||||
@@ -73,9 +73,9 @@ private:
|
||||
QOpenGLFunctions *functions_;
|
||||
};
|
||||
|
||||
#define PRINT_GL_ERRORS ErrorPrinter __e(__FUNCTION__, functions_)
|
||||
#define OAK_PRINT_GL_ERRORS ErrorPrinter __e(__FUNCTION__, functions_)
|
||||
|
||||
#define GL_PREAMBLE //QMutexLocker __l(&global_opengl_mutex);
|
||||
#define OAK_GL_PREAMBLE //QMutexLocker __l(&global_opengl_mutex);
|
||||
|
||||
//QMutex global_opengl_mutex;
|
||||
|
||||
@@ -90,11 +90,11 @@ OpenGLRenderer::OpenGLRenderer(QObject *parent)
|
||||
|
||||
OpenGLRenderer::~OpenGLRenderer()
|
||||
{
|
||||
Destroy();
|
||||
PostDestroy();
|
||||
destroy();
|
||||
post_destroy();
|
||||
}
|
||||
|
||||
void OpenGLRenderer::Init(QOpenGLContext *existing_ctx)
|
||||
void OpenGLRenderer::init(QOpenGLContext *existing_ctx)
|
||||
{
|
||||
if (context_) {
|
||||
qCritical() << "Can't initialize already initialized OpenGLRenderer";
|
||||
@@ -104,9 +104,9 @@ void OpenGLRenderer::Init(QOpenGLContext *existing_ctx)
|
||||
context_ = existing_ctx;
|
||||
}
|
||||
|
||||
bool OpenGLRenderer::Init()
|
||||
bool OpenGLRenderer::init()
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
OAK_GL_PREAMBLE;
|
||||
|
||||
if (context_) {
|
||||
qCritical() << "Can't initialize already initialized OpenGLRenderer";
|
||||
@@ -125,7 +125,7 @@ bool OpenGLRenderer::Init()
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::PostDestroy()
|
||||
void OpenGLRenderer::post_destroy()
|
||||
{
|
||||
// Destroy surface if we created it
|
||||
if (surface_.isValid()) {
|
||||
@@ -133,9 +133,9 @@ void OpenGLRenderer::PostDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::PostInit()
|
||||
void OpenGLRenderer::post_init()
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
OAK_GL_PREAMBLE;
|
||||
|
||||
if (!context_) {
|
||||
qWarning() << __FUNCTION__ << "called without an OpenGL context";
|
||||
@@ -162,12 +162,12 @@ void OpenGLRenderer::PostInit()
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DestroyInternal()
|
||||
void OpenGLRenderer::destroy_internal()
|
||||
{
|
||||
// context_ is guarded: if a caller-owned context was already destroyed,
|
||||
// this is null and there is nothing GL-side left to release.
|
||||
if (context_) {
|
||||
GL_PREAMBLE;
|
||||
OAK_GL_PREAMBLE;
|
||||
|
||||
if (functions_ && framebuffer_) {
|
||||
functions_->glDeleteFramebuffers(1, &framebuffer_);
|
||||
@@ -186,33 +186,33 @@ void OpenGLRenderer::DestroyInternal()
|
||||
functions_ = nullptr;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::ClearDestination(Texture *texture, double r, double g,
|
||||
void OpenGLRenderer::clear_destination(Texture *texture, double r, double g,
|
||||
double b, double a)
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
OAK_GL_PREAMBLE;
|
||||
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
if (!ensure_context_current(__FUNCTION__)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (texture) {
|
||||
AttachTextureAsDestination(texture->id());
|
||||
attach_texture_as_destination(texture->id());
|
||||
}
|
||||
|
||||
ClearDestinationInternal(r, g, b, a);
|
||||
clear_destination_internal(r, g, b, a);
|
||||
|
||||
if (texture) {
|
||||
DetachTextureAsDestination();
|
||||
detach_texture_as_destination();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant OpenGLRenderer::CreateNativeTexture(int width, int height, int depth,
|
||||
QVariant OpenGLRenderer::create_native_texture(int width, int height, int depth,
|
||||
PixelFormat format,
|
||||
int channel_count,
|
||||
const void *data, int linesize)
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
OAK_GL_PREAMBLE;
|
||||
if (!ensure_context_current(__FUNCTION__)) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
@@ -237,13 +237,13 @@ QVariant OpenGLRenderer::CreateNativeTexture(int width, int height, int depth,
|
||||
|
||||
if (is_3d) {
|
||||
context_->extraFunctions()->glTexImage3D(
|
||||
target, 0, GetInternalFormat(format, channel_count), width, height,
|
||||
depth, 0, GetPixelFormat(channel_count), GetPixelType(format),
|
||||
target, 0, get_internal_format(format, channel_count), width, height,
|
||||
depth, 0, get_pixel_format(channel_count), get_pixel_type(format),
|
||||
data);
|
||||
} else {
|
||||
functions_->glTexImage2D(
|
||||
target, 0, GetInternalFormat(format, channel_count), width, height,
|
||||
0, GetPixelFormat(channel_count), GetPixelType(format), data);
|
||||
target, 0, get_internal_format(format, channel_count), width, height,
|
||||
0, get_pixel_format(channel_count), get_pixel_type(format), data);
|
||||
}
|
||||
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
@@ -253,9 +253,9 @@ QVariant OpenGLRenderer::CreateNativeTexture(int width, int height, int depth,
|
||||
return texture;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::AttachTextureAsDestination(const QVariant &texture)
|
||||
void OpenGLRenderer::attach_texture_as_destination(const QVariant &texture)
|
||||
{
|
||||
PRINT_GL_ERRORS;
|
||||
OAK_PRINT_GL_ERRORS;
|
||||
|
||||
if (!framebuffer_) {
|
||||
functions_->glGenFramebuffers(1, &framebuffer_);
|
||||
@@ -267,7 +267,7 @@ void OpenGLRenderer::AttachTextureAsDestination(const QVariant &texture)
|
||||
0);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DetachTextureAsDestination()
|
||||
void OpenGLRenderer::detach_texture_as_destination()
|
||||
{
|
||||
// QOpenGLWidget renders to a non-zero default FBO.
|
||||
const GLuint default_fbo = context_ ? context_->defaultFramebufferObject() :
|
||||
@@ -275,9 +275,9 @@ void OpenGLRenderer::DetachTextureAsDestination()
|
||||
functions_->glBindFramebuffer(GL_FRAMEBUFFER, default_fbo);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DestroyNativeTexture(QVariant texture)
|
||||
void OpenGLRenderer::destroy_native_texture(QVariant texture)
|
||||
{
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
if (!ensure_context_current(__FUNCTION__)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -288,18 +288,18 @@ void OpenGLRenderer::DestroyNativeTexture(QVariant texture)
|
||||
}
|
||||
}
|
||||
|
||||
QVariant OpenGLRenderer::CreateNativeShader(ShaderCode code)
|
||||
QVariant OpenGLRenderer::create_native_shader(ShaderCode code)
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
OAK_GL_PREAMBLE;
|
||||
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
if (!ensure_context_current(__FUNCTION__)) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
PRINT_GL_ERRORS;
|
||||
OAK_PRINT_GL_ERRORS;
|
||||
|
||||
GLuint vert = CompileShader(GL_VERTEX_SHADER, code.vert_code());
|
||||
GLuint frag = CompileShader(GL_FRAGMENT_SHADER, code.frag_code());
|
||||
GLuint vert = compile_shader(GL_VERTEX_SHADER, code.vert_code());
|
||||
GLuint frag = compile_shader(GL_FRAGMENT_SHADER, code.frag_code());
|
||||
|
||||
GLuint program = 0;
|
||||
|
||||
@@ -324,11 +324,11 @@ QVariant OpenGLRenderer::CreateNativeShader(ShaderCode code)
|
||||
return program;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DestroyNativeShader(QVariant shader)
|
||||
void OpenGLRenderer::destroy_native_shader(QVariant shader)
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
OAK_GL_PREAMBLE;
|
||||
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
if (!ensure_context_current(__FUNCTION__)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -336,11 +336,11 @@ void OpenGLRenderer::DestroyNativeShader(QVariant shader)
|
||||
functions_->glDeleteProgram(program);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::UploadToTexture(const QVariant &handle,
|
||||
void OpenGLRenderer::upload_to_texture(const QVariant &handle,
|
||||
const VideoParams &p, const void *data,
|
||||
int linesize)
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
OAK_GL_PREAMBLE;
|
||||
|
||||
GLuint t = handle.value<GLuint>();
|
||||
|
||||
@@ -358,18 +358,18 @@ void OpenGLRenderer::UploadToTexture(const QVariant &handle,
|
||||
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
|
||||
|
||||
{
|
||||
PRINT_GL_ERRORS;
|
||||
OAK_PRINT_GL_ERRORS;
|
||||
|
||||
if (!is_3d) {
|
||||
functions_->glTexSubImage2D(tex_type, 0, 0, 0, p.effective_width(),
|
||||
p.effective_height(),
|
||||
GetPixelFormat(p.channel_count()),
|
||||
GetPixelType(p.format()), data);
|
||||
get_pixel_format(p.channel_count()),
|
||||
get_pixel_type(p.format()), data);
|
||||
} else {
|
||||
context_->extraFunctions()->glTexSubImage3D(
|
||||
tex_type, 0, 0, 0, 0, p.effective_width(), p.effective_height(),
|
||||
p.effective_depth(), GetPixelFormat(p.channel_count()),
|
||||
GetPixelType(p.format()), data);
|
||||
p.effective_depth(), get_pixel_format(p.channel_count()),
|
||||
get_pixel_type(p.format()), data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,13 +378,13 @@ void OpenGLRenderer::UploadToTexture(const QVariant &handle,
|
||||
functions_->glBindTexture(tex_type, current_tex);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::DownloadFromTexture(const QVariant &id,
|
||||
void OpenGLRenderer::download_from_texture(const QVariant &id,
|
||||
const VideoParams &p, void *data,
|
||||
int linesize)
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
OAK_GL_PREAMBLE;
|
||||
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
if (!ensure_context_current(__FUNCTION__)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -397,12 +397,12 @@ void OpenGLRenderer::DownloadFromTexture(const QVariant &id,
|
||||
GLint current_tex;
|
||||
functions_->glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_tex);
|
||||
|
||||
AttachTextureAsDestination(id);
|
||||
attach_texture_as_destination(id);
|
||||
|
||||
GLenum status = functions_->glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
qWarning() << "DownloadFromTexture framebuffer incomplete" << status;
|
||||
DetachTextureAsDestination();
|
||||
detach_texture_as_destination();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -412,30 +412,30 @@ void OpenGLRenderer::DownloadFromTexture(const QVariant &id,
|
||||
functions_->glFinish();
|
||||
|
||||
{
|
||||
PRINT_GL_ERRORS;
|
||||
OAK_PRINT_GL_ERRORS;
|
||||
functions_->glReadPixels(0, 0, p.effective_width(),
|
||||
p.effective_height(),
|
||||
GetPixelFormat(p.channel_count()),
|
||||
GetPixelType(p.format()), data);
|
||||
get_pixel_format(p.channel_count()),
|
||||
get_pixel_type(p.format()), data);
|
||||
}
|
||||
|
||||
functions_->glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
|
||||
DetachTextureAsDestination();
|
||||
detach_texture_as_destination();
|
||||
|
||||
functions_->glBindTexture(GL_TEXTURE_2D, current_tex);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::Flush()
|
||||
void OpenGLRenderer::flush()
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
OAK_GL_PREAMBLE;
|
||||
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
if (!ensure_context_current(__FUNCTION__)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(OAK_RENDER_BACKEND_PLUGIN)
|
||||
if (OLIVE_CONFIG("UseGLFinish").toBool()) {
|
||||
if (OAK_CONFIG("UseGLFinish").toBool()) {
|
||||
functions_->glFinish();
|
||||
return;
|
||||
}
|
||||
@@ -454,52 +454,52 @@ void OpenGLRenderer::Flush()
|
||||
|
||||
// Adapts the generic Renderer output attachment hook to OpenGL's framebuffer
|
||||
// attachment path used by OFX OpenGL rendering.
|
||||
void OpenGLRenderer::AttachOutputTexture(olive::Texture *texture)
|
||||
void OpenGLRenderer::attach_output_texture(olive::Texture *texture)
|
||||
{
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
if (!ensure_context_current(__FUNCTION__)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (texture) {
|
||||
AttachTextureAsDestination(texture->id());
|
||||
attach_texture_as_destination(texture->id());
|
||||
}
|
||||
}
|
||||
|
||||
// Clears the framebuffer attachment installed by AttachOutputTexture().
|
||||
void OpenGLRenderer::DetachOutputTexture()
|
||||
void OpenGLRenderer::detach_output_texture()
|
||||
{
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
if (!ensure_context_current(__FUNCTION__)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DetachTextureAsDestination();
|
||||
detach_texture_as_destination();
|
||||
}
|
||||
|
||||
Color OpenGLRenderer::GetPixelFromTexture(Texture *texture, const QPointF &pt)
|
||||
Color OpenGLRenderer::get_pixel_from_texture(Texture *texture, const QPointF &pt)
|
||||
{
|
||||
if (!texture || !EnsureContextCurrent(__FUNCTION__)) {
|
||||
if (!texture || !ensure_context_current(__FUNCTION__)) {
|
||||
return Color();
|
||||
}
|
||||
|
||||
AttachTextureAsDestination(texture->id());
|
||||
attach_texture_as_destination(texture->id());
|
||||
|
||||
QByteArray data(VideoParams::GetBytesPerPixel(texture->format(),
|
||||
QByteArray data(VideoParams::get_bytes_per_pixel(texture->format(),
|
||||
texture->channel_count()),
|
||||
Qt::Uninitialized);
|
||||
|
||||
functions_->glReadPixels(pt.x(), pt.y(), 1, 1,
|
||||
GetPixelFormat(texture->channel_count()),
|
||||
GetPixelType(texture->format()), data.data());
|
||||
get_pixel_format(texture->channel_count()),
|
||||
get_pixel_type(texture->format()), data.data());
|
||||
|
||||
Color c = Color::fromData(data.data(), texture->format(),
|
||||
Color c = Color::from_data(data.data(), texture->format(),
|
||||
texture->channel_count());
|
||||
|
||||
if (texture->channel_count() == VideoParams::kRGBChannelCount) {
|
||||
if (texture->channel_count() == VideoParams::k_rgb_channel_count) {
|
||||
// No alpha channel, set to 1.0
|
||||
c.set_alpha(1.0);
|
||||
}
|
||||
|
||||
DetachTextureAsDestination();
|
||||
detach_texture_as_destination();
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -509,12 +509,12 @@ struct TextureToBind {
|
||||
Texture::Interpolation interpolation;
|
||||
};
|
||||
|
||||
void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
void OpenGLRenderer::blit(QVariant s, AcceleratedJob &a_job,
|
||||
Texture *destination, VideoParams destination_params,
|
||||
bool clear_destination)
|
||||
{
|
||||
GL_PREAMBLE;
|
||||
if (!EnsureContextCurrent(__FUNCTION__)) {
|
||||
OAK_GL_PREAMBLE;
|
||||
if (!ensure_context_current(__FUNCTION__)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -534,8 +534,8 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
|
||||
functions_->glUseProgram(shader);
|
||||
|
||||
for (auto it = job.GetValues().constBegin();
|
||||
it != job.GetValues().constEnd(); it++) {
|
||||
for (auto it = job.get_values().constBegin();
|
||||
it != job.get_values().constEnd(); it++) {
|
||||
// See if the shader has takes this parameter as an input
|
||||
GLint variable_location = functions_->glGetUniformLocation(
|
||||
shader, it.key().toUtf8().constData());
|
||||
@@ -553,52 +553,52 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
}
|
||||
|
||||
switch (value.type()) {
|
||||
case NodeValue::kInt:
|
||||
case NodeValue::k_int:
|
||||
// kInt technically specifies a LongLong, but OpenGL doesn't support those. This may lead to
|
||||
// over/underflows if the number is large enough, but the likelihood of that is quite low.
|
||||
functions_->glUniform1i(variable_location, value.toInt());
|
||||
functions_->glUniform1i(variable_location, value.to_int());
|
||||
break;
|
||||
case NodeValue::kFloat:
|
||||
case NodeValue::k_float:
|
||||
// kFloat technically specifies a double but as above, OpenGL doesn't support those.
|
||||
functions_->glUniform1f(variable_location, value.toDouble());
|
||||
functions_->glUniform1f(variable_location, value.to_double());
|
||||
break;
|
||||
case NodeValue::kVec2: {
|
||||
QVector2D v = value.toVec2();
|
||||
case NodeValue::k_vec2: {
|
||||
QVector2D v = value.to_vec2();
|
||||
functions_->glUniform2fv(variable_location, 1,
|
||||
reinterpret_cast<const GLfloat *>(&v));
|
||||
break;
|
||||
}
|
||||
case NodeValue::kVec3: {
|
||||
QVector3D v = value.toVec3();
|
||||
case NodeValue::k_vec3: {
|
||||
QVector3D v = value.to_vec3();
|
||||
functions_->glUniform3fv(variable_location, 1,
|
||||
reinterpret_cast<const GLfloat *>(&v));
|
||||
break;
|
||||
}
|
||||
case NodeValue::kVec4: {
|
||||
QVector4D v = value.toVec4();
|
||||
case NodeValue::k_vec4: {
|
||||
QVector4D v = value.to_vec4();
|
||||
functions_->glUniform4fv(variable_location, 1,
|
||||
reinterpret_cast<const GLfloat *>(&v));
|
||||
break;
|
||||
}
|
||||
case NodeValue::kMatrix:
|
||||
case NodeValue::k_matrix:
|
||||
functions_->glUniformMatrix4fv(variable_location, 1, false,
|
||||
value.toMatrix().constData());
|
||||
value.to_matrix().constData());
|
||||
break;
|
||||
case NodeValue::kCombo:
|
||||
functions_->glUniform1i(variable_location, value.toInt());
|
||||
case NodeValue::k_combo:
|
||||
functions_->glUniform1i(variable_location, value.to_int());
|
||||
break;
|
||||
case NodeValue::kColor: {
|
||||
Color color = value.toColor();
|
||||
case NodeValue::k_color: {
|
||||
Color color = value.to_color();
|
||||
functions_->glUniform4f(variable_location, color.red(),
|
||||
color.green(), color.blue(),
|
||||
color.alpha());
|
||||
break;
|
||||
}
|
||||
case NodeValue::kBoolean:
|
||||
functions_->glUniform1i(variable_location, value.toBool());
|
||||
case NodeValue::k_boolean:
|
||||
functions_->glUniform1i(variable_location, value.to_bool());
|
||||
break;
|
||||
case NodeValue::kTexture: {
|
||||
TexturePtr texture = value.toTexture();
|
||||
case NodeValue::k_texture: {
|
||||
TexturePtr texture = value.to_texture();
|
||||
|
||||
// Set value to bound texture
|
||||
functions_->glUniform1i(variable_location,
|
||||
@@ -607,7 +607,7 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
texture_index_map.insert(it.key(), textures_to_bind.size());
|
||||
|
||||
textures_to_bind.append(
|
||||
{ texture, job.GetInterpolation(it.key()) });
|
||||
{ texture, job.get_interpolation(it.key()) });
|
||||
|
||||
// Set enable flag if shader wants it
|
||||
GLuint tex_id = texture ? texture->id().value<GLuint>() : 0;
|
||||
@@ -621,18 +621,18 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeValue::kSamples:
|
||||
case NodeValue::kText:
|
||||
case NodeValue::kRational:
|
||||
case NodeValue::kFont:
|
||||
case NodeValue::kFile:
|
||||
case NodeValue::kVideoParams:
|
||||
case NodeValue::kAudioParams:
|
||||
case NodeValue::kSubtitleParams:
|
||||
case NodeValue::kBezier:
|
||||
case NodeValue::kBinary:
|
||||
case NodeValue::kNone:
|
||||
case NodeValue::kDataTypeCount:
|
||||
case NodeValue::k_samples:
|
||||
case NodeValue::k_text:
|
||||
case NodeValue::k_rational:
|
||||
case NodeValue::k_font:
|
||||
case NodeValue::k_file:
|
||||
case NodeValue::k_video_params:
|
||||
case NodeValue::k_audio_params:
|
||||
case NodeValue::k_subtitle_params:
|
||||
case NodeValue::k_bezier:
|
||||
case NodeValue::k_binary:
|
||||
case NodeValue::k_none:
|
||||
case NodeValue::k_data_type_count:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -652,7 +652,7 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
functions_->glBindTexture(target, tex_id);
|
||||
|
||||
if (tex_id) {
|
||||
PrepareInputTexture(target, t.interpolation);
|
||||
prepare_input_texture(target, t.interpolation);
|
||||
|
||||
if (texture->channel_count() == 1 &&
|
||||
destination_params.channel_count() != 1) {
|
||||
@@ -673,7 +673,7 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
if (mvpmat_location > -1) {
|
||||
functions_->glUniformMatrix4fv(
|
||||
mvpmat_location, 1, false,
|
||||
job.Get(QStringLiteral("ove_mvpmat")).toMatrix().constData());
|
||||
job.get(QStringLiteral("ove_mvpmat")).to_matrix().constData());
|
||||
}
|
||||
|
||||
// Set the viewport to the "physical" resolution of the destination
|
||||
@@ -681,51 +681,51 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
destination_params.effective_height());
|
||||
|
||||
// Bind vertex array object
|
||||
QOpenGLVertexArrayObject vao_;
|
||||
vao_.create();
|
||||
vao_.bind();
|
||||
QOpenGLVertexArrayObject vao;
|
||||
vao.create();
|
||||
vao.bind();
|
||||
|
||||
// Set buffers
|
||||
QOpenGLBuffer vert_vbo_;
|
||||
vert_vbo_.create();
|
||||
vert_vbo_.bind();
|
||||
QOpenGLBuffer vert_vbo;
|
||||
vert_vbo.create();
|
||||
vert_vbo.bind();
|
||||
// If the job has vertex coordinate overrides use them instead of the defaults.
|
||||
if (!job.GetVertexCoordinates().isEmpty()) {
|
||||
Q_ASSERT(job.GetVertexCoordinates().size() == 18);
|
||||
vert_vbo_.allocate(job.GetVertexCoordinates().constData(),
|
||||
job.GetVertexCoordinates().size() *
|
||||
if (!job.get_vertex_coordinates().isEmpty()) {
|
||||
Q_ASSERT(job.get_vertex_coordinates().size() == 18);
|
||||
vert_vbo.allocate(job.get_vertex_coordinates().constData(),
|
||||
job.get_vertex_coordinates().size() *
|
||||
sizeof(float));
|
||||
} else {
|
||||
vert_vbo_.allocate(blit_vertices.constData(),
|
||||
vert_vbo.allocate(blit_vertices.constData(),
|
||||
blit_vertices.size() * sizeof(GLfloat));
|
||||
}
|
||||
vert_vbo_.release();
|
||||
vert_vbo.release();
|
||||
|
||||
QOpenGLBuffer frag_vbo_;
|
||||
frag_vbo_.create();
|
||||
frag_vbo_.bind();
|
||||
frag_vbo_.allocate(blit_texcoords.constData(),
|
||||
QOpenGLBuffer frag_vbo;
|
||||
frag_vbo.create();
|
||||
frag_vbo.bind();
|
||||
frag_vbo.allocate(blit_texcoords.constData(),
|
||||
blit_texcoords.size() * sizeof(GLfloat));
|
||||
frag_vbo_.release();
|
||||
frag_vbo.release();
|
||||
|
||||
GLint vertex_location =
|
||||
functions_->glGetAttribLocation(shader, "a_position");
|
||||
if (vertex_location != -1) {
|
||||
vert_vbo_.bind();
|
||||
vert_vbo.bind();
|
||||
functions_->glEnableVertexAttribArray(vertex_location);
|
||||
functions_->glVertexAttribPointer(vertex_location, 3, GL_FLOAT,
|
||||
GL_FALSE, 0, nullptr);
|
||||
vert_vbo_.release();
|
||||
vert_vbo.release();
|
||||
}
|
||||
|
||||
GLint tex_location =
|
||||
functions_->glGetAttribLocation(shader, "a_texcoord");
|
||||
if (tex_location != -1) {
|
||||
frag_vbo_.bind();
|
||||
frag_vbo.bind();
|
||||
functions_->glEnableVertexAttribArray(tex_location);
|
||||
functions_->glVertexAttribPointer(tex_location, 2, GL_FLOAT,
|
||||
GL_FALSE, 0, nullptr);
|
||||
frag_vbo_.release();
|
||||
frag_vbo.release();
|
||||
}
|
||||
|
||||
// Some shaders optimize through multiple iterations which requires ping-ponging textures
|
||||
@@ -735,8 +735,8 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
// textures. We can still use the destination as the last iteration, but we'll need textures
|
||||
// for the iterative process.
|
||||
int real_iteration_count;
|
||||
if (job.GetIterationCount() > 1 && !job.GetIterativeInput().isEmpty()) {
|
||||
real_iteration_count = job.GetIterationCount();
|
||||
if (job.get_iteration_count() > 1 && !job.get_iterative_input().isEmpty()) {
|
||||
real_iteration_count = job.get_iteration_count();
|
||||
} else {
|
||||
real_iteration_count = 1;
|
||||
}
|
||||
@@ -744,11 +744,11 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
TexturePtr output_tex, input_tex;
|
||||
if (real_iteration_count > 1) {
|
||||
// Create one texture to bounce off
|
||||
output_tex = CreateTexture(destination_params);
|
||||
output_tex = create_texture(destination_params);
|
||||
|
||||
if (real_iteration_count > 2) {
|
||||
// Create a second texture bounce off
|
||||
input_tex = CreateTexture(destination_params);
|
||||
input_tex = create_texture(destination_params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -765,33 +765,33 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
// This is the last iteration, draw to the destination
|
||||
if (destination) {
|
||||
// If we have a destination texture, draw to it
|
||||
AttachTextureAsDestination(destination->id());
|
||||
attach_texture_as_destination(destination->id());
|
||||
} else if (iteration > 0) {
|
||||
// Otherwise, if we were iterating before, detach texture now
|
||||
DetachTextureAsDestination();
|
||||
detach_texture_as_destination();
|
||||
}
|
||||
|
||||
// Clear the destination if the caller requested it
|
||||
if (clear_destination) {
|
||||
ClearDestinationInternal();
|
||||
clear_destination_internal();
|
||||
}
|
||||
} else {
|
||||
// Always draw to output_tex, which gets swapped with input_tex every iteration
|
||||
AttachTextureAsDestination(output_tex->id());
|
||||
attach_texture_as_destination(output_tex->id());
|
||||
}
|
||||
|
||||
if (iteration > 0) {
|
||||
// If this is not the first iteration, replace the iterative texture with the one we
|
||||
// last drew
|
||||
const QString &iterative_input = job.GetIterativeInput();
|
||||
const QString &iterative_input = job.get_iterative_input();
|
||||
functions_->glActiveTexture(
|
||||
GL_TEXTURE0 + texture_index_map.value(iterative_input));
|
||||
functions_->glBindTexture(GL_TEXTURE_2D,
|
||||
input_tex->id().value<GLuint>());
|
||||
|
||||
// At this time, we only support iterating 2D textures
|
||||
PrepareInputTexture(GL_TEXTURE_2D,
|
||||
job.GetInterpolation(iterative_input));
|
||||
prepare_input_texture(GL_TEXTURE_2D,
|
||||
job.get_interpolation(iterative_input));
|
||||
}
|
||||
|
||||
// Swap so that the next iteration, the texture we draw now will be the input texture next
|
||||
@@ -799,7 +799,7 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
|
||||
// Blit this texture through this shader
|
||||
{
|
||||
PRINT_GL_ERRORS;
|
||||
OAK_PRINT_GL_ERRORS;
|
||||
functions_->glDrawArrays(GL_TRIANGLES, 0,
|
||||
blit_vertices.size() / 3);
|
||||
}
|
||||
@@ -807,7 +807,7 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
|
||||
if (destination) {
|
||||
// Reset framebuffer to default if we were drawing to a texture
|
||||
DetachTextureAsDestination();
|
||||
detach_texture_as_destination();
|
||||
}
|
||||
|
||||
// Release any textures we bound before
|
||||
@@ -824,18 +824,18 @@ void OpenGLRenderer::Blit(QVariant s, AcceleratedJob &a_job,
|
||||
functions_->glUseProgram(0);
|
||||
|
||||
// Release vertex array object
|
||||
frag_vbo_.destroy();
|
||||
vert_vbo_.destroy();
|
||||
vao_.release();
|
||||
vao_.destroy();
|
||||
frag_vbo.destroy();
|
||||
vert_vbo.destroy();
|
||||
vao.release();
|
||||
vao.destroy();
|
||||
} catch (std::bad_cast e) {
|
||||
}
|
||||
}
|
||||
|
||||
GLint OpenGLRenderer::GetInternalFormat(PixelFormat format, int channel_layout)
|
||||
GLint OpenGLRenderer::get_internal_format(PixelFormat format, int channel_layout)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::U8:
|
||||
case PixelFormat::u8:
|
||||
switch (channel_layout) {
|
||||
case 1:
|
||||
return GL_R8;
|
||||
@@ -847,12 +847,12 @@ GLint OpenGLRenderer::GetInternalFormat(PixelFormat format, int channel_layout)
|
||||
return GL_RGBA8;
|
||||
}
|
||||
break;
|
||||
case PixelFormat::U10:
|
||||
case PixelFormat::u10:
|
||||
if (channel_layout == 4) {
|
||||
return GL_RGB10_A2;
|
||||
}
|
||||
break;
|
||||
case PixelFormat::U16:
|
||||
case PixelFormat::u16:
|
||||
switch (channel_layout) {
|
||||
case 1:
|
||||
return GL_R16;
|
||||
@@ -864,7 +864,7 @@ GLint OpenGLRenderer::GetInternalFormat(PixelFormat format, int channel_layout)
|
||||
return GL_RGBA16;
|
||||
}
|
||||
break;
|
||||
case PixelFormat::F16:
|
||||
case PixelFormat::f16:
|
||||
switch (channel_layout) {
|
||||
case 1:
|
||||
return GL_R16F;
|
||||
@@ -876,7 +876,7 @@ GLint OpenGLRenderer::GetInternalFormat(PixelFormat format, int channel_layout)
|
||||
return GL_RGBA16F;
|
||||
}
|
||||
break;
|
||||
case PixelFormat::F32:
|
||||
case PixelFormat::f32:
|
||||
switch (channel_layout) {
|
||||
case 1:
|
||||
return GL_R32F;
|
||||
@@ -888,37 +888,37 @@ GLint OpenGLRenderer::GetInternalFormat(PixelFormat format, int channel_layout)
|
||||
return GL_RGBA32F;
|
||||
}
|
||||
break;
|
||||
case PixelFormat::INVALID:
|
||||
case PixelFormat::COUNT:
|
||||
case PixelFormat::invalid:
|
||||
case PixelFormat::count:
|
||||
break;
|
||||
}
|
||||
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
GLenum OpenGLRenderer::GetPixelType(PixelFormat format)
|
||||
GLenum OpenGLRenderer::get_pixel_type(PixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::U8:
|
||||
case PixelFormat::u8:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case PixelFormat::U10:
|
||||
case PixelFormat::u10:
|
||||
return GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||
case PixelFormat::U16:
|
||||
case PixelFormat::u16:
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case PixelFormat::F16:
|
||||
case PixelFormat::f16:
|
||||
return GL_HALF_FLOAT;
|
||||
case PixelFormat::F32:
|
||||
case PixelFormat::f32:
|
||||
return GL_FLOAT;
|
||||
|
||||
case PixelFormat::INVALID:
|
||||
case PixelFormat::COUNT:
|
||||
case PixelFormat::invalid:
|
||||
case PixelFormat::count:
|
||||
break;
|
||||
}
|
||||
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
GLenum OpenGLRenderer::GetPixelFormat(int channel_count)
|
||||
GLenum OpenGLRenderer::get_pixel_format(int channel_count)
|
||||
{
|
||||
switch (channel_count) {
|
||||
case 1:
|
||||
@@ -932,19 +932,19 @@ GLenum OpenGLRenderer::GetPixelFormat(int channel_count)
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::PrepareInputTexture(GLenum target,
|
||||
void OpenGLRenderer::prepare_input_texture(GLenum target,
|
||||
Texture::Interpolation interp)
|
||||
{
|
||||
switch (interp) {
|
||||
case Texture::kNearest:
|
||||
case Texture::k_nearest:
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
case Texture::kLinear:
|
||||
case Texture::k_linear:
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
case Texture::kMipmappedLinear:
|
||||
case Texture::k_mipmapped_linear:
|
||||
functions_->glGenerateMipmap(target);
|
||||
functions_->glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
@@ -961,7 +961,7 @@ void OpenGLRenderer::PrepareInputTexture(GLenum target,
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::ClearDestinationInternal(double r, double g, double b,
|
||||
void OpenGLRenderer::clear_destination_internal(double r, double g, double b,
|
||||
double a)
|
||||
{
|
||||
if (!functions_) {
|
||||
@@ -971,7 +971,7 @@ void OpenGLRenderer::ClearDestinationInternal(double r, double g, double b,
|
||||
functions_->glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
GLuint OpenGLRenderer::CompileShader(GLenum type, const QString &code)
|
||||
GLuint OpenGLRenderer::compile_shader(GLenum type, const QString &code)
|
||||
{
|
||||
const bool is_gles = context_ && context_->isOpenGLES();
|
||||
const int major = context_ ? context_->format().majorVersion() : 0;
|
||||
@@ -993,10 +993,10 @@ GLuint OpenGLRenderer::CompileShader(GLenum type, const QString &code)
|
||||
if (base_code.isEmpty()) {
|
||||
// Use default code
|
||||
if (type == GL_FRAGMENT_SHADER) {
|
||||
base_code = FileFunctions::ReadFileAsString(
|
||||
base_code = FileFunctions::read_file_as_string(
|
||||
QStringLiteral(":/shaders/default.frag"));
|
||||
} else if (type == GL_VERTEX_SHADER) {
|
||||
base_code = FileFunctions::ReadFileAsString(
|
||||
base_code = FileFunctions::read_file_as_string(
|
||||
QStringLiteral(":/shaders/default.vert"));
|
||||
}
|
||||
}
|
||||
@@ -1064,7 +1064,7 @@ GLuint OpenGLRenderer::CompileShader(GLenum type, const QString &code)
|
||||
return shader;
|
||||
}
|
||||
|
||||
bool OpenGLRenderer::EnsureContextCurrent(const char *caller)
|
||||
bool OpenGLRenderer::ensure_context_current(const char *caller)
|
||||
{
|
||||
if (!context_) {
|
||||
qWarning() << caller << "called without an OpenGL context";
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OPENGLCONTEXT_H
|
||||
#define OPENGLCONTEXT_H
|
||||
#ifndef OAK_OPENGLCONTEXT_H
|
||||
#define OAK_OPENGLCONTEXT_H
|
||||
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLBuffer>
|
||||
@@ -44,33 +44,33 @@ public:
|
||||
|
||||
virtual ~OpenGLRenderer() override;
|
||||
|
||||
void Init(QOpenGLContext *existing_ctx);
|
||||
void init(QOpenGLContext *existing_ctx);
|
||||
|
||||
virtual bool Init() override;
|
||||
virtual bool init() override;
|
||||
|
||||
virtual void PostDestroy() override;
|
||||
virtual void post_destroy() override;
|
||||
|
||||
virtual void PostInit() override;
|
||||
virtual void post_init() override;
|
||||
|
||||
virtual void ClearDestination(olive::Texture *texture = nullptr,
|
||||
virtual void clear_destination(olive::Texture *texture = nullptr,
|
||||
double r = 0.0, double g = 0.0,
|
||||
double b = 0.0, double a = 0.0) override;
|
||||
|
||||
virtual QVariant CreateNativeShader(olive::ShaderCode code) override;
|
||||
virtual QVariant create_native_shader(olive::ShaderCode code) override;
|
||||
|
||||
virtual void DestroyNativeShader(QVariant shader) override;
|
||||
virtual void destroy_native_shader(QVariant shader) override;
|
||||
|
||||
virtual void UploadToTexture(const QVariant &handle,
|
||||
virtual void upload_to_texture(const QVariant &handle,
|
||||
const VideoParams ¶ms, const void *data,
|
||||
int linesize) override;
|
||||
|
||||
virtual void DownloadFromTexture(const QVariant &handle,
|
||||
virtual void download_from_texture(const QVariant &handle,
|
||||
const VideoParams ¶ms, void *data,
|
||||
int linesize) override;
|
||||
|
||||
virtual void Flush() override;
|
||||
virtual void flush() override;
|
||||
|
||||
virtual Color GetPixelFromTexture(olive::Texture *texture,
|
||||
virtual Color get_pixel_from_texture(olive::Texture *texture,
|
||||
const QPointF &pt) override;
|
||||
|
||||
QOpenGLContext *context() const
|
||||
@@ -78,54 +78,54 @@ public:
|
||||
return context_.data();
|
||||
}
|
||||
|
||||
virtual QOpenGLContext *OpenGLContext() const override
|
||||
virtual QOpenGLContext *open_gl_context() const override
|
||||
{
|
||||
return context();
|
||||
}
|
||||
|
||||
virtual bool IsOpenGL() const override
|
||||
virtual bool is_open_gl() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void AttachOutputTexture(olive::Texture *texture) override;
|
||||
virtual void attach_output_texture(olive::Texture *texture) override;
|
||||
|
||||
virtual void DetachOutputTexture() override;
|
||||
virtual void detach_output_texture() override;
|
||||
|
||||
bool EnsureContextCurrent(const char *caller);
|
||||
bool ensure_context_current(const char *caller);
|
||||
|
||||
protected:
|
||||
virtual void Blit(QVariant shader, olive::AcceleratedJob &job,
|
||||
virtual void blit(QVariant shader, olive::AcceleratedJob &job,
|
||||
olive::Texture *destination,
|
||||
olive::VideoParams destination_params,
|
||||
bool clear_destination) override;
|
||||
|
||||
virtual QVariant CreateNativeTexture(int width, int height, int depth,
|
||||
virtual QVariant create_native_texture(int width, int height, int depth,
|
||||
PixelFormat format, int channel_count,
|
||||
const void *data = nullptr,
|
||||
int linesize = 0) override;
|
||||
|
||||
virtual void DestroyNativeTexture(QVariant texture) override;
|
||||
virtual void destroy_native_texture(QVariant texture) override;
|
||||
|
||||
virtual void DestroyInternal() override;
|
||||
virtual void destroy_internal() override;
|
||||
|
||||
void AttachTextureAsDestination(const QVariant &texture);
|
||||
void attach_texture_as_destination(const QVariant &texture);
|
||||
|
||||
void DetachTextureAsDestination();
|
||||
void detach_texture_as_destination();
|
||||
|
||||
private:
|
||||
static GLint GetInternalFormat(PixelFormat format, int channel_layout);
|
||||
static GLint get_internal_format(PixelFormat format, int channel_layout);
|
||||
|
||||
static GLenum GetPixelType(PixelFormat format);
|
||||
static GLenum get_pixel_type(PixelFormat format);
|
||||
|
||||
static GLenum GetPixelFormat(int channel_count);
|
||||
static GLenum get_pixel_format(int channel_count);
|
||||
|
||||
void PrepareInputTexture(GLenum target, Texture::Interpolation interp);
|
||||
void prepare_input_texture(GLenum target, Texture::Interpolation interp);
|
||||
|
||||
void ClearDestinationInternal(double r = 0.0, double g = 0.0,
|
||||
void clear_destination_internal(double r = 0.0, double g = 0.0,
|
||||
double b = 0.0, double a = 0.0);
|
||||
|
||||
GLuint CompileShader(GLenum type, const QString &code);
|
||||
GLuint compile_shader(GLenum type, const QString &code);
|
||||
|
||||
// Guarded pointer: viewer contexts are owned by the widget that created
|
||||
// them and may be destroyed before this renderer (e.g. when a QOpenGLWidget
|
||||
@@ -156,9 +156,9 @@ private:
|
||||
|
||||
QMap<GLuint, TextureCacheKey> texture_params_;
|
||||
|
||||
static const int kTextureCacheMaxSize;
|
||||
static const int k_texture_cache_max_size;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OPENGLCONTEXT_H
|
||||
#endif // OAK_OPENGLCONTEXT_H
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
void PlaybackCache::Invalidate(const TimeRange &r)
|
||||
void PlaybackCache::invalidate(const TimeRange &r)
|
||||
{
|
||||
if (r.in() == r.out()) {
|
||||
qWarning() << "Tried to invalidate zero-length range";
|
||||
@@ -44,10 +44,10 @@ void PlaybackCache::Invalidate(const TimeRange &r)
|
||||
|
||||
InvalidateEvent(r);
|
||||
|
||||
emit Invalidated(r);
|
||||
emit invalidated(r);
|
||||
|
||||
if (saving_enabled_) {
|
||||
SaveState();
|
||||
save_state();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,20 +56,20 @@ Node *PlaybackCache::parent() const
|
||||
return dynamic_cast<Node *>(QObject::parent());
|
||||
}
|
||||
|
||||
QDir PlaybackCache::GetThisCacheDirectory() const
|
||||
QDir PlaybackCache::get_this_cache_directory() const
|
||||
{
|
||||
return GetThisCacheDirectory(GetCacheDirectory(), GetUuid());
|
||||
return get_this_cache_directory(get_cache_directory(), get_uuid());
|
||||
}
|
||||
|
||||
QDir PlaybackCache::GetThisCacheDirectory(const QString &cache_path,
|
||||
QDir PlaybackCache::get_this_cache_directory(const QString &cache_path,
|
||||
const QUuid &cache_id)
|
||||
{
|
||||
return QDir(cache_path).filePath(cache_id.toString());
|
||||
}
|
||||
|
||||
void PlaybackCache::LoadState()
|
||||
void PlaybackCache::load_state()
|
||||
{
|
||||
QDir cache_dir = GetThisCacheDirectory();
|
||||
QDir cache_dir = get_this_cache_directory();
|
||||
QFile f(cache_dir.filePath(QStringLiteral("state")));
|
||||
|
||||
if (!f.exists()) {
|
||||
@@ -102,8 +102,8 @@ void PlaybackCache::LoadState()
|
||||
s >> out_num;
|
||||
s >> out_den;
|
||||
|
||||
validated_.insert(TimeRange(rational(in_num, in_den),
|
||||
rational(out_num, out_den)));
|
||||
validated_.insert(TimeRange(Rational(in_num, in_den),
|
||||
Rational(out_num, out_den)));
|
||||
}
|
||||
|
||||
s >> pass_count;
|
||||
@@ -117,8 +117,8 @@ void PlaybackCache::LoadState()
|
||||
s >> out_den;
|
||||
s >> id;
|
||||
|
||||
Passthrough p = TimeRange(rational(in_num, in_den),
|
||||
rational(out_num, out_den));
|
||||
Passthrough p = TimeRange(Rational(in_num, in_den),
|
||||
Rational(out_num, out_den));
|
||||
p.cache = id;
|
||||
passthroughs_.push_back(p);
|
||||
}
|
||||
@@ -133,20 +133,20 @@ void PlaybackCache::LoadState()
|
||||
}
|
||||
}
|
||||
|
||||
void PlaybackCache::SaveState()
|
||||
void PlaybackCache::save_state()
|
||||
{
|
||||
if (!DiskManager::instance()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDir cache_dir = GetThisCacheDirectory();
|
||||
QDir cache_dir = get_this_cache_directory();
|
||||
QFile f(cache_dir.filePath(QStringLiteral("state")));
|
||||
if (validated_.isEmpty() && passthroughs_.empty()) {
|
||||
if (f.exists()) {
|
||||
f.remove();
|
||||
}
|
||||
} else {
|
||||
if (FileFunctions::DirectoryIsValid(cache_dir)) {
|
||||
if (FileFunctions::directory_is_valid(cache_dir)) {
|
||||
if (f.open(QFile::WriteOnly)) {
|
||||
QDataStream s(&f);
|
||||
|
||||
@@ -186,19 +186,19 @@ void PlaybackCache::SaveState()
|
||||
}
|
||||
}
|
||||
|
||||
void PlaybackCache::Draw(QPainter *p, const rational &start, double scale,
|
||||
void PlaybackCache::draw(QPainter *p, const Rational &start, double scale,
|
||||
const QRect &rect) const
|
||||
{
|
||||
p->fillRect(rect, Qt::red);
|
||||
|
||||
foreach (const TimeRange &range, GetValidatedRanges()) {
|
||||
int range_left = rect.left() + (range.in() - start).toDouble() * scale;
|
||||
foreach (const TimeRange &range, get_validated_ranges()) {
|
||||
int range_left = rect.left() + (range.in() - start).to_double() * scale;
|
||||
if (range_left >= rect.right()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int range_right =
|
||||
rect.left() + (range.out() - start).toDouble() * scale;
|
||||
rect.left() + (range.out() - start).to_double() * scale;
|
||||
if (range_right < rect.left()) {
|
||||
continue;
|
||||
}
|
||||
@@ -211,45 +211,45 @@ void PlaybackCache::Draw(QPainter *p, const rational &start, double scale,
|
||||
}
|
||||
}
|
||||
|
||||
void PlaybackCache::SetPassthrough(PlaybackCache *cache)
|
||||
void PlaybackCache::set_passthrough(PlaybackCache *cache)
|
||||
{
|
||||
for (const TimeRange &r : cache->GetValidatedRanges()) {
|
||||
for (const TimeRange &r : cache->get_validated_ranges()) {
|
||||
Passthrough p = r;
|
||||
p.cache = cache->GetUuid();
|
||||
p.cache = cache->get_uuid();
|
||||
passthroughs_.push_back(p);
|
||||
}
|
||||
|
||||
passthroughs_.insert(passthroughs_.end(), cache->GetPassthroughs().begin(),
|
||||
cache->GetPassthroughs().end());
|
||||
passthroughs_.insert(passthroughs_.end(), cache->get_passthroughs().begin(),
|
||||
cache->get_passthroughs().end());
|
||||
|
||||
if (saving_enabled_) {
|
||||
SaveState();
|
||||
save_state();
|
||||
}
|
||||
}
|
||||
|
||||
void PlaybackCache::InvalidateAll()
|
||||
void PlaybackCache::invalidate_all()
|
||||
{
|
||||
Invalidate(TimeRange(0, RATIONAL_MAX));
|
||||
invalidate(TimeRange(0, RATIONAL_MAX));
|
||||
}
|
||||
|
||||
void PlaybackCache::Request(ViewerOutput *context, const TimeRange &r)
|
||||
void PlaybackCache::request(ViewerOutput *context, const TimeRange &r)
|
||||
{
|
||||
request_context_ = context;
|
||||
requested_.insert(r);
|
||||
|
||||
emit Requested(request_context_, r);
|
||||
emit requested(request_context_, r);
|
||||
}
|
||||
|
||||
void PlaybackCache::Validate(const TimeRange &r, bool signal)
|
||||
void PlaybackCache::validate(const TimeRange &r, bool signal)
|
||||
{
|
||||
validated_.insert(r);
|
||||
|
||||
if (signal) {
|
||||
emit Validated(r);
|
||||
emit validated(r);
|
||||
}
|
||||
|
||||
if (saving_enabled_) {
|
||||
SaveState();
|
||||
save_state();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,9 +257,9 @@ void PlaybackCache::InvalidateEvent(const TimeRange &)
|
||||
{
|
||||
}
|
||||
|
||||
Project *PlaybackCache::GetProject() const
|
||||
Project *PlaybackCache::get_project() const
|
||||
{
|
||||
return Project::GetProjectFromObject(this);
|
||||
return Project::get_project_from_object(this);
|
||||
}
|
||||
|
||||
PlaybackCache::PlaybackCache(QObject *parent)
|
||||
@@ -270,21 +270,21 @@ PlaybackCache::PlaybackCache(QObject *parent)
|
||||
uuid_ = QUuid::createUuid();
|
||||
}
|
||||
|
||||
void PlaybackCache::SetUuid(const QUuid &u)
|
||||
void PlaybackCache::set_uuid(const QUuid &u)
|
||||
{
|
||||
uuid_ = u;
|
||||
|
||||
LoadState();
|
||||
load_state();
|
||||
}
|
||||
|
||||
TimeRangeList PlaybackCache::GetInvalidatedRanges(TimeRange intersecting) const
|
||||
TimeRangeList PlaybackCache::get_invalidated_ranges(TimeRange intersecting) const
|
||||
{
|
||||
TimeRangeList invalidated;
|
||||
|
||||
// Prevent TimeRange from being below 0, some other behavior in Olive relies on this behavior
|
||||
// and it seemed reasonable to have safety code in here
|
||||
intersecting.set_out(qMax(rational(0), intersecting.out()));
|
||||
intersecting.set_in(qMax(rational(0), intersecting.in()));
|
||||
intersecting.set_out(qMax(Rational(0), intersecting.out()));
|
||||
intersecting.set_in(qMax(Rational(0), intersecting.in()));
|
||||
|
||||
invalidated.insert(intersecting);
|
||||
|
||||
@@ -299,19 +299,19 @@ TimeRangeList PlaybackCache::GetInvalidatedRanges(TimeRange intersecting) const
|
||||
return invalidated;
|
||||
}
|
||||
|
||||
bool PlaybackCache::HasInvalidatedRanges(const TimeRange &intersecting) const
|
||||
bool PlaybackCache::has_invalidated_ranges(const TimeRange &intersecting) const
|
||||
{
|
||||
return !validated_.contains(intersecting);
|
||||
}
|
||||
|
||||
QString PlaybackCache::GetCacheDirectory() const
|
||||
QString PlaybackCache::get_cache_directory() const
|
||||
{
|
||||
Project *project = GetProject();
|
||||
Project *project = get_project();
|
||||
|
||||
if (project) {
|
||||
return project->cache_path();
|
||||
} else {
|
||||
return DiskManager::instance()->GetDefaultCachePath();
|
||||
return DiskManager::instance()->get_default_cache_path();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+36
-36
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef PLAYBACKCACHE_H
|
||||
#define PLAYBACKCACHE_H
|
||||
#ifndef OAK_PLAYBACKCACHE_H
|
||||
#define OAK_PLAYBACKCACHE_H
|
||||
|
||||
#include <olive/core/core.h>
|
||||
#include <QDir>
|
||||
@@ -45,64 +45,64 @@ class PlaybackCache : public QObject {
|
||||
public:
|
||||
PlaybackCache(QObject *parent = nullptr);
|
||||
|
||||
const QUuid &GetUuid() const
|
||||
const QUuid &get_uuid() const
|
||||
{
|
||||
return uuid_;
|
||||
}
|
||||
void SetUuid(const QUuid &u);
|
||||
void set_uuid(const QUuid &u);
|
||||
|
||||
TimeRangeList GetInvalidatedRanges(TimeRange intersecting) const;
|
||||
TimeRangeList GetInvalidatedRanges(const rational &length) const
|
||||
TimeRangeList get_invalidated_ranges(TimeRange intersecting) const;
|
||||
TimeRangeList get_invalidated_ranges(const Rational &length) const
|
||||
{
|
||||
return GetInvalidatedRanges(TimeRange(0, length));
|
||||
return get_invalidated_ranges(TimeRange(0, length));
|
||||
}
|
||||
|
||||
bool HasInvalidatedRanges(const TimeRange &intersecting) const;
|
||||
bool HasInvalidatedRanges(const rational &length) const
|
||||
bool has_invalidated_ranges(const TimeRange &intersecting) const;
|
||||
bool has_invalidated_ranges(const Rational &length) const
|
||||
{
|
||||
return HasInvalidatedRanges(TimeRange(0, length));
|
||||
return has_invalidated_ranges(TimeRange(0, length));
|
||||
}
|
||||
|
||||
QString GetCacheDirectory() const;
|
||||
QString get_cache_directory() const;
|
||||
|
||||
void Invalidate(const TimeRange &r);
|
||||
void invalidate(const TimeRange &r);
|
||||
|
||||
bool HasValidatedRanges() const
|
||||
bool has_validated_ranges() const
|
||||
{
|
||||
return !validated_.isEmpty();
|
||||
}
|
||||
const TimeRangeList &GetValidatedRanges() const
|
||||
const TimeRangeList &get_validated_ranges() const
|
||||
{
|
||||
return validated_;
|
||||
}
|
||||
|
||||
Node *parent() const;
|
||||
|
||||
QDir GetThisCacheDirectory() const;
|
||||
static QDir GetThisCacheDirectory(const QString &cache_path,
|
||||
QDir get_this_cache_directory() const;
|
||||
static QDir get_this_cache_directory(const QString &cache_path,
|
||||
const QUuid &cache_id);
|
||||
|
||||
void LoadState();
|
||||
void SaveState();
|
||||
void load_state();
|
||||
void save_state();
|
||||
|
||||
void Draw(QPainter *painter, const rational &start, double scale,
|
||||
void draw(QPainter *painter, const Rational &start, double scale,
|
||||
const QRect &rect) const;
|
||||
|
||||
static int GetCacheIndicatorHeight()
|
||||
static int get_cache_indicator_height()
|
||||
{
|
||||
return QFontMetrics(QFont()).height() / 4;
|
||||
}
|
||||
|
||||
bool IsSavingEnabled() const
|
||||
bool is_saving_enabled() const
|
||||
{
|
||||
return saving_enabled_;
|
||||
}
|
||||
void SetSavingEnabled(bool e)
|
||||
void set_saving_enabled(bool e)
|
||||
{
|
||||
saving_enabled_ = e;
|
||||
}
|
||||
|
||||
virtual void SetPassthrough(PlaybackCache *cache);
|
||||
virtual void set_passthrough(PlaybackCache *cache);
|
||||
|
||||
QMutex *mutex()
|
||||
{
|
||||
@@ -119,39 +119,39 @@ public:
|
||||
QUuid cache;
|
||||
};
|
||||
|
||||
const std::vector<Passthrough> &GetPassthroughs() const
|
||||
const std::vector<Passthrough> &get_passthroughs() const
|
||||
{
|
||||
return passthroughs_;
|
||||
}
|
||||
|
||||
void ClearRequestRange(const TimeRange &r)
|
||||
void clear_request_range(const TimeRange &r)
|
||||
{
|
||||
requested_.remove(r);
|
||||
}
|
||||
|
||||
void ResignalRequests()
|
||||
void resignal_requests()
|
||||
{
|
||||
for (const TimeRange &r : requested_) {
|
||||
emit Requested(request_context_, r);
|
||||
emit requested(request_context_, r);
|
||||
}
|
||||
}
|
||||
|
||||
public slots:
|
||||
void InvalidateAll();
|
||||
void invalidate_all();
|
||||
|
||||
void Request(ViewerOutput *context, const TimeRange &r);
|
||||
void request(ViewerOutput *context, const TimeRange &r);
|
||||
|
||||
signals:
|
||||
void Invalidated(const TimeRange &r);
|
||||
void invalidated(const TimeRange &r);
|
||||
|
||||
void Validated(const TimeRange &r);
|
||||
void validated(const TimeRange &r);
|
||||
|
||||
void Requested(ViewerOutput *context, const TimeRange &r);
|
||||
void requested(ViewerOutput *context, const TimeRange &r);
|
||||
|
||||
void CancelAll();
|
||||
void cancel_all();
|
||||
|
||||
protected:
|
||||
void Validate(const TimeRange &r, bool signal = true);
|
||||
void validate(const TimeRange &r, bool signal = true);
|
||||
|
||||
virtual void InvalidateEvent(const TimeRange &range);
|
||||
|
||||
@@ -163,7 +163,7 @@ protected:
|
||||
{
|
||||
}
|
||||
|
||||
Project *GetProject() const;
|
||||
Project *get_project() const;
|
||||
|
||||
private:
|
||||
TimeRangeList validated_;
|
||||
@@ -184,4 +184,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // PLAYBACKCACHE_H
|
||||
#endif // OAK_PLAYBACKCACHE_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,8 +21,8 @@
|
||||
// Created by mikesolar on 25-10-19.
|
||||
//
|
||||
|
||||
#ifndef PLUGINRENDERER_H
|
||||
#define PLUGINRENDERER_H
|
||||
#ifndef OAK_PLUGINRENDERER_H
|
||||
#define OAK_PLUGINRENDERER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace detail
|
||||
{
|
||||
// 作用:将字节行跨度转换为像素跨度,便于纹理读写。
|
||||
// Purpose: Convert byte stride to pixel stride for texture I/O.
|
||||
int BytesToPixels(int byte_linesize, const olive::VideoParams ¶ms);
|
||||
int bytes_to_pixels(int byte_linesize, const olive::VideoParams ¶ms);
|
||||
}
|
||||
// 作用:OFX 插件渲染器,负责 CPU/GL 路径下的插件调用和纹理桥接。
|
||||
// Purpose: OFX plugin renderer that drives CPU/GL render paths and texture bridging.
|
||||
@@ -65,13 +65,13 @@ public:
|
||||
|
||||
// 作用:将目标纹理绑定为插件输出。
|
||||
// Purpose: Attach destination texture as OFX output.
|
||||
void AttachOutputTexture(olive::TexturePtr texture);
|
||||
void attach_output_texture(olive::TexturePtr texture);
|
||||
// 作用:解除目标纹理绑定。
|
||||
// Purpose: Detach destination texture binding.
|
||||
void DetachOutputTexture();
|
||||
void detach_output_texture();
|
||||
// 作用:执行插件渲染流程(参数配置、输入/输出、调用渲染动作)。
|
||||
// Purpose: Execute plugin render flow (params, inputs/outputs, render actions).
|
||||
void RenderPlugin(TexturePtr src, olive::plugin::PluginJob &job,
|
||||
void render_plugin(TexturePtr src, olive::plugin::PluginJob &job,
|
||||
olive::TexturePtr destination,
|
||||
olive::VideoParams destination_params,
|
||||
bool clear_destination, bool interactive);
|
||||
@@ -82,4 +82,4 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
#endif //PLUGINRENDERER_H
|
||||
#endif //OAK_PLUGINRENDERER_H
|
||||
|
||||
@@ -42,16 +42,16 @@ bool PreviewAudioDevice::isSequential() const
|
||||
return true;
|
||||
}
|
||||
|
||||
void PreviewAudioDevice::SetParams(const core::AudioParams ¶ms)
|
||||
void PreviewAudioDevice::set_params(const core::AudioParams ¶ms)
|
||||
{
|
||||
set_bytes_per_frame(params.samples_to_bytes(1));
|
||||
}
|
||||
|
||||
qint64 PreviewAudioDevice::readData(char *data, qint64 maxSize)
|
||||
qint64 PreviewAudioDevice::readData(char *data, qint64 max_size)
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
|
||||
qint64 copy_length = qMin(maxSize, qint64(buffer_.size()));
|
||||
qint64 copy_length = qMin(max_size, qint64(buffer_.size()));
|
||||
|
||||
if (copy_length) {
|
||||
qint64 new_bytes_read = bytes_read_ + copy_length;
|
||||
@@ -59,7 +59,7 @@ qint64 PreviewAudioDevice::readData(char *data, qint64 maxSize)
|
||||
if (notify_interval_ > 0) {
|
||||
if ((bytes_read_ / notify_interval_) !=
|
||||
(new_bytes_read / notify_interval_)) {
|
||||
emit Notify();
|
||||
emit notify();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef PREVIEWAUDIODEVICE_H
|
||||
#define PREVIEWAUDIODEVICE_H
|
||||
#ifndef OAK_PREVIEWAUDIODEVICE_H
|
||||
#define OAK_PREVIEWAUDIODEVICE_H
|
||||
|
||||
#include <olive/core/render/audioparams.h>
|
||||
|
||||
@@ -36,18 +36,18 @@ public:
|
||||
|
||||
virtual ~PreviewAudioDevice() override;
|
||||
|
||||
void StartQueuing();
|
||||
void start_queuing();
|
||||
|
||||
virtual bool isSequential() const override;
|
||||
|
||||
virtual qint64 readData(char *data, qint64 maxSize) override;
|
||||
virtual qint64 readData(char *data, qint64 max_size) override;
|
||||
|
||||
virtual qint64 writeData(const char *data, qint64 length) override;
|
||||
|
||||
// Derives the frame size from the audio format (bytes per sample per
|
||||
// channel * channel count). Until params are set, bytes_per_frame()
|
||||
// reports 0, i.e. "unknown".
|
||||
void SetParams(const core::AudioParams ¶ms);
|
||||
void set_params(const core::AudioParams ¶ms);
|
||||
|
||||
int bytes_per_frame() const
|
||||
{
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
void clear();
|
||||
|
||||
signals:
|
||||
void Notify();
|
||||
void notify();
|
||||
|
||||
private:
|
||||
QMutex lock_;
|
||||
@@ -83,4 +83,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // PREVIEWAUDIODEVICE_H
|
||||
#endif // OAK_PREVIEWAUDIODEVICE_H
|
||||
|
||||
+215
-215
@@ -47,66 +47,66 @@ PreviewAutoCacher::PreviewAutoCacher(QObject *parent)
|
||||
, ignore_cache_requests_(false)
|
||||
{
|
||||
copier_ = new ProjectCopier(this);
|
||||
connect(copier_, &ProjectCopier::AddedNode, this,
|
||||
&PreviewAutoCacher::ConnectToNodeCache);
|
||||
connect(copier_, &ProjectCopier::RemovedNode, this,
|
||||
&PreviewAutoCacher::DisconnectFromNodeCache);
|
||||
connect(copier_, &ProjectCopier::added_node, this,
|
||||
&PreviewAutoCacher::connect_to_node_cache);
|
||||
connect(copier_, &ProjectCopier::removed_node, this,
|
||||
&PreviewAutoCacher::disconnect_from_node_cache);
|
||||
|
||||
// Set defaults
|
||||
SetPlayhead(0);
|
||||
set_playhead(0);
|
||||
|
||||
// Wait a certain amount of time before requeuing when we receive an invalidate signal
|
||||
delayed_requeue_timer_.setInterval(OLIVE_CONFIG("AutoCacheDelay").toInt());
|
||||
delayed_requeue_timer_.setInterval(OAK_CONFIG("AutoCacheDelay").toInt());
|
||||
delayed_requeue_timer_.setSingleShot(true);
|
||||
connect(&delayed_requeue_timer_, &QTimer::timeout, this,
|
||||
&PreviewAutoCacher::TryRender);
|
||||
&PreviewAutoCacher::try_render);
|
||||
|
||||
// Catch when a conform is ready
|
||||
connect(ConformManager::instance(), &ConformManager::ConformReady, this,
|
||||
&PreviewAutoCacher::ConformFinished);
|
||||
connect(ConformManager::instance(), &ConformManager::conform_ready, this,
|
||||
&PreviewAutoCacher::conform_finished);
|
||||
}
|
||||
|
||||
PreviewAutoCacher::~PreviewAutoCacher()
|
||||
{
|
||||
// Ensure everything is cleaned up appropriately
|
||||
SetProject(nullptr);
|
||||
set_project(nullptr);
|
||||
}
|
||||
|
||||
RenderTicketPtr PreviewAutoCacher::GetSingleFrame(ViewerOutput *viewer,
|
||||
const rational &t, bool dry)
|
||||
RenderTicketPtr PreviewAutoCacher::get_single_frame(ViewerOutput *viewer,
|
||||
const Rational &t, bool dry)
|
||||
{
|
||||
return GetSingleFrame(viewer->GetConnectedTextureOutput(), viewer, t, dry);
|
||||
return get_single_frame(viewer->get_connected_texture_output(), viewer, t, dry);
|
||||
}
|
||||
|
||||
RenderTicketPtr PreviewAutoCacher::GetSingleFrame(Node *n, ViewerOutput *viewer,
|
||||
const rational &t, bool dry)
|
||||
RenderTicketPtr PreviewAutoCacher::get_single_frame(Node *n, ViewerOutput *viewer,
|
||||
const Rational &t, bool dry)
|
||||
{
|
||||
// If we have a single frame render queued (but not yet sent to the RenderManager), cancel it now
|
||||
CancelQueuedSingleFrameRender();
|
||||
cancel_queued_single_frame_render();
|
||||
|
||||
// Create a new single frame render ticket
|
||||
auto sfr = std::make_shared<RenderTicket>();
|
||||
sfr->Start();
|
||||
sfr->start();
|
||||
sfr->setProperty("time", QVariant::fromValue(t));
|
||||
sfr->setProperty("dry", dry);
|
||||
sfr->setProperty("node", QtUtils::PtrToValue(n));
|
||||
sfr->setProperty("viewer", QtUtils::PtrToValue(viewer));
|
||||
sfr->setProperty("node", QtUtils::ptr_to_value(n));
|
||||
sfr->setProperty("viewer", QtUtils::ptr_to_value(viewer));
|
||||
|
||||
// Queue it and try to render
|
||||
single_frame_render_ = sfr;
|
||||
TryRender();
|
||||
try_render();
|
||||
|
||||
return sfr;
|
||||
}
|
||||
|
||||
RenderTicketPtr PreviewAutoCacher::GetRangeOfAudio(ViewerOutput *viewer,
|
||||
RenderTicketPtr PreviewAutoCacher::get_range_of_audio(ViewerOutput *viewer,
|
||||
TimeRange range)
|
||||
{
|
||||
Node *copy = copier_->GetCopy(viewer->GetConnectedSampleOutput());
|
||||
return RenderAudio(copy, viewer, range, nullptr);
|
||||
Node *copy = copier_->get_copy(viewer->get_connected_sample_output());
|
||||
return render_audio(copy, viewer, range, nullptr);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::ClearSingleFrameRenders()
|
||||
void PreviewAutoCacher::clear_single_frame_renders()
|
||||
{
|
||||
// Snapshot the watchers as guarded pointers before doing anything that
|
||||
// might synchronously delete them (emitting Finished runs VideoRendered,
|
||||
@@ -126,18 +126,18 @@ void PreviewAutoCacher::ClearSingleFrameRenders()
|
||||
// Keep already-running workers alive: cancelling an in-flight render
|
||||
// forces the worker process to be torn down, which defeats the process
|
||||
// pool. Frames that finish late are simply ignored by the viewer.
|
||||
if (w->IsRunning()) {
|
||||
if (w->is_running()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RenderTicketPtr ticket = w->GetTicket();
|
||||
w->Cancel();
|
||||
RenderManager::instance()->RemoveTicket(ticket);
|
||||
emit ticket->Finished();
|
||||
RenderTicketPtr ticket = w->get_ticket();
|
||||
w->cancel();
|
||||
RenderManager::instance()->remove_ticket(ticket);
|
||||
emit ticket->finished();
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::ClearSingleFrameRendersThatArentRunning()
|
||||
void PreviewAutoCacher::clear_single_frame_renders_that_arent_running()
|
||||
{
|
||||
QList<QPointer<RenderTicketWatcher>> watchers;
|
||||
for (auto it = video_immediate_passthroughs_.cbegin();
|
||||
@@ -146,38 +146,38 @@ void PreviewAutoCacher::ClearSingleFrameRendersThatArentRunning()
|
||||
}
|
||||
|
||||
foreach (const QPointer<RenderTicketWatcher> &w, watchers) {
|
||||
if (!w || w->IsRunning()) {
|
||||
if (!w || w->is_running()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RenderTicketPtr ticket = w->GetTicket();
|
||||
w->Cancel();
|
||||
RenderManager::instance()->RemoveTicket(ticket);
|
||||
emit ticket->Finished();
|
||||
RenderTicketPtr ticket = w->get_ticket();
|
||||
w->cancel();
|
||||
RenderManager::instance()->remove_ticket(ticket);
|
||||
emit ticket->finished();
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::VideoInvalidatedFromCache(ViewerOutput *context,
|
||||
void PreviewAutoCacher::video_invalidated_from_cache(ViewerOutput *context,
|
||||
const TimeRange &range)
|
||||
{
|
||||
PlaybackCache *cache = static_cast<PlaybackCache *>(sender());
|
||||
|
||||
cache->ClearRequestRange(range);
|
||||
cache->clear_request_range(range);
|
||||
|
||||
VideoInvalidatedFromNode(context, cache, range);
|
||||
video_invalidated_from_node(context, cache, range);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::AudioInvalidatedFromCache(ViewerOutput *context,
|
||||
void PreviewAutoCacher::audio_invalidated_from_cache(ViewerOutput *context,
|
||||
const TimeRange &range)
|
||||
{
|
||||
PlaybackCache *cache = static_cast<PlaybackCache *>(sender());
|
||||
|
||||
cache->ClearRequestRange(range);
|
||||
cache->clear_request_range(range);
|
||||
|
||||
AudioInvalidatedFromNode(context, cache, range);
|
||||
audio_invalidated_from_node(context, cache, range);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::CancelForCache()
|
||||
void PreviewAutoCacher::cancel_for_cache()
|
||||
{
|
||||
PlaybackCache *cache = static_cast<PlaybackCache *>(sender());
|
||||
|
||||
@@ -204,7 +204,7 @@ void PreviewAutoCacher::CancelForCache()
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::AudioRendered()
|
||||
void PreviewAutoCacher::audio_rendered()
|
||||
{
|
||||
// Receive watcher
|
||||
RenderTicketWatcher *watcher = static_cast<RenderTicketWatcher *>(sender());
|
||||
@@ -214,11 +214,11 @@ void PreviewAutoCacher::AudioRendered()
|
||||
if (running_audio_tasks_.removeOne(watcher)) {
|
||||
// Assume that a "result" is a fully completed image and a non-result is a cancelled ticket
|
||||
TimeRange range = watcher->property("time").value<TimeRange>();
|
||||
Node *node = copier_->GetOriginal(
|
||||
QtUtils::ValueToPtr<Node>(watcher->property("node")));
|
||||
Node *node = copier_->get_original(
|
||||
QtUtils::value_to_ptr<Node>(watcher->property("node")));
|
||||
|
||||
if (watcher->HasResult() && node) {
|
||||
if (PlaybackCache *cache = QtUtils::ValueToPtr<PlaybackCache>(
|
||||
if (watcher->has_result() && node) {
|
||||
if (PlaybackCache *cache = QtUtils::value_to_ptr<PlaybackCache>(
|
||||
watcher->property("cache"))) {
|
||||
AudioCacheData &d = audio_cache_data_[cache];
|
||||
|
||||
@@ -229,33 +229,33 @@ void PreviewAutoCacher::AudioRendered()
|
||||
d.job_tracker.getCurrentSubRanges(range, watcher_job_time);
|
||||
|
||||
AudioVisualWaveform waveform =
|
||||
watcher->GetTicket()
|
||||
watcher->get_ticket()
|
||||
->property("waveform")
|
||||
.value<AudioVisualWaveform>();
|
||||
|
||||
SampleBuffer buf = watcher->Get().value<SampleBuffer>();
|
||||
SampleBuffer buf = watcher->get().value<SampleBuffer>();
|
||||
|
||||
bool incomplete =
|
||||
watcher->GetTicket()->property("incomplete").toBool();
|
||||
watcher->get_ticket()->property("incomplete").toBool();
|
||||
|
||||
if (AudioPlaybackCache *pcm =
|
||||
dynamic_cast<AudioPlaybackCache *>(cache)) {
|
||||
// WritePCM is tolerant to its buffer being null, it will just write silence instead
|
||||
pcm->SetParameters(buf.audio_params());
|
||||
pcm->WritePCM(range, valid_ranges,
|
||||
watcher->Get().value<SampleBuffer>());
|
||||
pcm->set_parameters(buf.audio_params());
|
||||
pcm->write_pcm(range, valid_ranges,
|
||||
watcher->get().value<SampleBuffer>());
|
||||
} else if (AudioWaveformCache *wave =
|
||||
dynamic_cast<AudioWaveformCache *>(cache)) {
|
||||
wave->SetParameters(buf.audio_params());
|
||||
wave->set_parameters(buf.audio_params());
|
||||
if (!incomplete) {
|
||||
wave->WriteWaveform(range, valid_ranges, &waveform);
|
||||
wave->write_waveform(range, valid_ranges, &waveform);
|
||||
}
|
||||
}
|
||||
|
||||
if (incomplete) {
|
||||
if (last_conform_task_ > watcher_job_time) {
|
||||
// Requeue now
|
||||
cache->Invalidate(range);
|
||||
cache->invalidate(range);
|
||||
} else {
|
||||
// Wait for conform
|
||||
d.needs_conform.insert(range);
|
||||
@@ -265,21 +265,21 @@ void PreviewAutoCacher::AudioRendered()
|
||||
}
|
||||
|
||||
// Continue rendering
|
||||
TryRender();
|
||||
try_render();
|
||||
}
|
||||
|
||||
delete watcher;
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::VideoRendered()
|
||||
void PreviewAutoCacher::video_rendered()
|
||||
{
|
||||
RenderTicketWatcher *watcher = static_cast<RenderTicketWatcher *>(sender());
|
||||
|
||||
const QStringList bad_cache_names =
|
||||
watcher->GetTicket()->property("badcache").toStringList();
|
||||
watcher->get_ticket()->property("badcache").toStringList();
|
||||
if (!bad_cache_names.empty()) {
|
||||
for (const QString &fn : bad_cache_names) {
|
||||
DiskManager::instance()->DeleteSpecificFile(fn);
|
||||
DiskManager::instance()->delete_specific_file(fn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,12 +288,12 @@ void PreviewAutoCacher::VideoRendered()
|
||||
QVector<RenderTicketPtr> tickets =
|
||||
video_immediate_passthroughs_.take(watcher);
|
||||
foreach (RenderTicketPtr t, tickets) {
|
||||
if (watcher->HasResult()) {
|
||||
if (watcher->has_result()) {
|
||||
t->setProperty("multicam_output",
|
||||
watcher->GetTicket()->property("multicam_output"));
|
||||
t->Finish(watcher->Get());
|
||||
watcher->get_ticket()->property("multicam_output"));
|
||||
t->finish(watcher->get());
|
||||
} else {
|
||||
t->Finish();
|
||||
t->finish();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,139 +301,139 @@ void PreviewAutoCacher::VideoRendered()
|
||||
// viewer switch, so we'll completely ignore this watcher
|
||||
if (running_video_tasks_.removeOne(watcher)) {
|
||||
// Assume that a "result" is a fully completed image and a non-result is a cancelled ticket
|
||||
if (watcher->HasResult()) {
|
||||
if (watcher->GetTicket()->property("cached").toBool()) {
|
||||
if (FrameHashCache *cache = QtUtils::ValueToPtr<FrameHashCache>(
|
||||
if (watcher->has_result()) {
|
||||
if (watcher->get_ticket()->property("cached").toBool()) {
|
||||
if (FrameHashCache *cache = QtUtils::value_to_ptr<FrameHashCache>(
|
||||
watcher->property("cache"))) {
|
||||
rational time = watcher->property("time").value<rational>();
|
||||
Rational time = watcher->property("time").value<Rational>();
|
||||
JobTime job = watcher->property("job").value<JobTime>();
|
||||
|
||||
if (video_cache_data_.value(cache).job_tracker.isCurrent(
|
||||
time, job)) {
|
||||
cache->ValidateTime(time);
|
||||
cache->validate_time(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Continue rendering
|
||||
TryRender();
|
||||
try_render();
|
||||
}
|
||||
|
||||
delete watcher;
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::ConnectToNodeCache(Node *node)
|
||||
void PreviewAutoCacher::connect_to_node_cache(Node *node)
|
||||
{
|
||||
if (ignore_cache_requests_) {
|
||||
return;
|
||||
}
|
||||
|
||||
connect(node->video_frame_cache(), &PlaybackCache::Requested, this,
|
||||
&PreviewAutoCacher::VideoInvalidatedFromCache);
|
||||
connect(node->video_frame_cache(), &PlaybackCache::requested, this,
|
||||
&PreviewAutoCacher::video_invalidated_from_cache);
|
||||
|
||||
connect(node->thumbnail_cache(), &PlaybackCache::Requested, this,
|
||||
&PreviewAutoCacher::VideoInvalidatedFromCache);
|
||||
connect(node->thumbnail_cache(), &PlaybackCache::requested, this,
|
||||
&PreviewAutoCacher::video_invalidated_from_cache);
|
||||
|
||||
connect(node->audio_playback_cache(), &PlaybackCache::Requested, this,
|
||||
&PreviewAutoCacher::AudioInvalidatedFromCache);
|
||||
connect(node->audio_playback_cache(), &PlaybackCache::requested, this,
|
||||
&PreviewAutoCacher::audio_invalidated_from_cache);
|
||||
|
||||
connect(node->waveform_cache(), &PlaybackCache::Requested, this,
|
||||
&PreviewAutoCacher::AudioInvalidatedFromCache);
|
||||
connect(node->waveform_cache(), &PlaybackCache::requested, this,
|
||||
&PreviewAutoCacher::audio_invalidated_from_cache);
|
||||
|
||||
connect(node->video_frame_cache(), &PlaybackCache::CancelAll, this,
|
||||
&PreviewAutoCacher::CancelForCache);
|
||||
connect(node->video_frame_cache(), &PlaybackCache::cancel_all, this,
|
||||
&PreviewAutoCacher::cancel_for_cache);
|
||||
|
||||
connect(node->audio_playback_cache(), &PlaybackCache::CancelAll, this,
|
||||
&PreviewAutoCacher::CancelForCache);
|
||||
connect(node->audio_playback_cache(), &PlaybackCache::cancel_all, this,
|
||||
&PreviewAutoCacher::cancel_for_cache);
|
||||
|
||||
node->video_frame_cache()->ResignalRequests();
|
||||
node->thumbnail_cache()->ResignalRequests();
|
||||
node->audio_playback_cache()->ResignalRequests();
|
||||
node->waveform_cache()->ResignalRequests();
|
||||
node->video_frame_cache()->resignal_requests();
|
||||
node->thumbnail_cache()->resignal_requests();
|
||||
node->audio_playback_cache()->resignal_requests();
|
||||
node->waveform_cache()->resignal_requests();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::DisconnectFromNodeCache(Node *node)
|
||||
void PreviewAutoCacher::disconnect_from_node_cache(Node *node)
|
||||
{
|
||||
disconnect(node->video_frame_cache(), &PlaybackCache::Requested, this,
|
||||
&PreviewAutoCacher::VideoInvalidatedFromCache);
|
||||
disconnect(node->video_frame_cache(), &PlaybackCache::requested, this,
|
||||
&PreviewAutoCacher::video_invalidated_from_cache);
|
||||
|
||||
disconnect(node->thumbnail_cache(), &PlaybackCache::Requested, this,
|
||||
&PreviewAutoCacher::VideoInvalidatedFromCache);
|
||||
disconnect(node->thumbnail_cache(), &PlaybackCache::requested, this,
|
||||
&PreviewAutoCacher::video_invalidated_from_cache);
|
||||
|
||||
disconnect(node->audio_playback_cache(), &PlaybackCache::Requested, this,
|
||||
&PreviewAutoCacher::AudioInvalidatedFromCache);
|
||||
disconnect(node->audio_playback_cache(), &PlaybackCache::requested, this,
|
||||
&PreviewAutoCacher::audio_invalidated_from_cache);
|
||||
|
||||
disconnect(node->waveform_cache(), &PlaybackCache::Requested, this,
|
||||
&PreviewAutoCacher::AudioInvalidatedFromCache);
|
||||
disconnect(node->waveform_cache(), &PlaybackCache::requested, this,
|
||||
&PreviewAutoCacher::audio_invalidated_from_cache);
|
||||
|
||||
disconnect(node->video_frame_cache(), &PlaybackCache::CancelAll, this,
|
||||
&PreviewAutoCacher::CancelForCache);
|
||||
disconnect(node->video_frame_cache(), &PlaybackCache::cancel_all, this,
|
||||
&PreviewAutoCacher::cancel_for_cache);
|
||||
|
||||
disconnect(node->audio_playback_cache(), &PlaybackCache::CancelAll, this,
|
||||
&PreviewAutoCacher::CancelForCache);
|
||||
disconnect(node->audio_playback_cache(), &PlaybackCache::cancel_all, this,
|
||||
&PreviewAutoCacher::cancel_for_cache);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::CancelQueuedSingleFrameRender()
|
||||
void PreviewAutoCacher::cancel_queued_single_frame_render()
|
||||
{
|
||||
if (single_frame_render_) {
|
||||
// Signal that this ticket was cancelled with no value
|
||||
single_frame_render_->Finish();
|
||||
single_frame_render_->finish();
|
||||
single_frame_render_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::StartCachingRange(const TimeRange &range,
|
||||
void PreviewAutoCacher::start_caching_range(const TimeRange &range,
|
||||
TimeRangeList *range_list,
|
||||
RenderJobTracker *tracker)
|
||||
{
|
||||
range_list->insert(range);
|
||||
tracker->insert(range, copier_->GetGraphChangeTime());
|
||||
tracker->insert(range, copier_->get_graph_change_time());
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::StartCachingVideoRange(ViewerOutput *context,
|
||||
void PreviewAutoCacher::start_caching_video_range(ViewerOutput *context,
|
||||
PlaybackCache *cache,
|
||||
const TimeRange &range)
|
||||
{
|
||||
Node *node = cache->parent();
|
||||
rational using_tb;
|
||||
Rational using_tb;
|
||||
if (ThumbnailCache *thumbs = dynamic_cast<ThumbnailCache *>(cache)) {
|
||||
using_tb = thumbs->GetTimebase();
|
||||
using_tb = thumbs->get_timebase();
|
||||
} else {
|
||||
using_tb = context->GetVideoParams().frame_rate_as_time_base();
|
||||
using_tb = context->get_video_params().frame_rate_as_time_base();
|
||||
}
|
||||
|
||||
cache->ClearRequestRange(range);
|
||||
cache->clear_request_range(range);
|
||||
|
||||
TimeRangeListFrameIterator iterator({ range }, using_tb);
|
||||
pending_video_jobs_.push_back({ node, context, cache, range, iterator });
|
||||
video_cache_data_[cache].job_tracker.insert(
|
||||
TimeRange(iterator.Snap(range.in()), range.out()),
|
||||
copier_->GetGraphChangeTime());
|
||||
TryRender();
|
||||
TimeRange(iterator.snap(range.in()), range.out()),
|
||||
copier_->get_graph_change_time());
|
||||
try_render();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::StartCachingAudioRange(ViewerOutput *context,
|
||||
void PreviewAutoCacher::start_caching_audio_range(ViewerOutput *context,
|
||||
PlaybackCache *cache,
|
||||
const TimeRange &range)
|
||||
{
|
||||
Node *node = cache->parent();
|
||||
|
||||
cache->ClearRequestRange(range);
|
||||
cache->clear_request_range(range);
|
||||
|
||||
pending_audio_jobs_.push_back({ node, context, cache, range });
|
||||
AudioCacheData &data = audio_cache_data_[cache];
|
||||
data.context = context;
|
||||
data.job_tracker.insert(range, copier_->GetGraphChangeTime());
|
||||
TryRender();
|
||||
data.job_tracker.insert(range, copier_->get_graph_change_time());
|
||||
try_render();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::VideoInvalidatedFromNode(ViewerOutput *context,
|
||||
void PreviewAutoCacher::video_invalidated_from_node(ViewerOutput *context,
|
||||
PlaybackCache *cache,
|
||||
const TimeRange &range)
|
||||
{
|
||||
// Ignore render requests if no video is present
|
||||
if (!context || !context->GetVideoParams().is_valid()) {
|
||||
if (!context || !context->get_video_params().is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -441,20 +441,20 @@ void PreviewAutoCacher::VideoInvalidatedFromNode(ViewerOutput *context,
|
||||
// want to dedicate all our rendering power to realtime feedback for the user
|
||||
//CancelVideoTasks(node);
|
||||
|
||||
cache->ClearRequestRange(range);
|
||||
cache->clear_request_range(range);
|
||||
|
||||
// If auto-cache is enabled and a slider is not being dragged, queue up to hash these frames
|
||||
if (!NodeInputDragger::IsInputBeingDragged()) {
|
||||
StartCachingVideoRange(context, cache, range);
|
||||
if (!NodeInputDragger::is_input_being_dragged()) {
|
||||
start_caching_video_range(context, cache, range);
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::AudioInvalidatedFromNode(ViewerOutput *context,
|
||||
void PreviewAutoCacher::audio_invalidated_from_node(ViewerOutput *context,
|
||||
PlaybackCache *cache,
|
||||
const TimeRange &range)
|
||||
{
|
||||
// Ignore render requests if no video is present
|
||||
if (!context || !context->GetAudioParams().is_valid()) {
|
||||
if (!context || !context->get_audio_params().is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -462,54 +462,54 @@ void PreviewAutoCacher::AudioInvalidatedFromNode(ViewerOutput *context,
|
||||
// cancelled, so some areas may end up unrendered forever
|
||||
// ClearAudioQueue();
|
||||
|
||||
cache->ClearRequestRange(range);
|
||||
cache->clear_request_range(range);
|
||||
|
||||
// If we're auto-caching audio or require realtime waveforms, we'll have to render this
|
||||
StartCachingAudioRange(context, cache, range);
|
||||
start_caching_audio_range(context, cache, range);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::SetPlayhead(const rational &playhead)
|
||||
void PreviewAutoCacher::set_playhead(const Rational &playhead)
|
||||
{
|
||||
cache_range_ =
|
||||
TimeRange(playhead - OLIVE_CONFIG("DiskCacheBehind").value<rational>(),
|
||||
playhead + OLIVE_CONFIG("DiskCacheAhead").value<rational>());
|
||||
TimeRange(playhead - OAK_CONFIG("DiskCacheBehind").value<Rational>(),
|
||||
playhead + OAK_CONFIG("DiskCacheAhead").value<Rational>());
|
||||
|
||||
TryRender();
|
||||
try_render();
|
||||
}
|
||||
|
||||
template <typename T> void CancelTasks(const T &task_list, bool and_wait)
|
||||
template <typename T> void cancel_tasks(const T &task_list, bool and_wait)
|
||||
{
|
||||
for (auto it = task_list.cbegin(); it != task_list.cend(); it++) {
|
||||
// Signal that the ticket should not be finished
|
||||
(*it)->Cancel();
|
||||
(*it)->cancel();
|
||||
}
|
||||
|
||||
if (and_wait) {
|
||||
// Wait for each ticket to finish
|
||||
for (auto it = task_list.cbegin(); it != task_list.cend(); it++) {
|
||||
(*it)->WaitForFinished();
|
||||
(*it)->wait_for_finished();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::CancelVideoTasks(bool and_wait_for_them_to_finish)
|
||||
void PreviewAutoCacher::cancel_video_tasks(bool and_wait_for_them_to_finish)
|
||||
{
|
||||
CancelTasks(running_video_tasks_, and_wait_for_them_to_finish);
|
||||
cancel_tasks(running_video_tasks_, and_wait_for_them_to_finish);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::CancelAudioTasks(bool and_wait_for_them_to_finish)
|
||||
void PreviewAutoCacher::cancel_audio_tasks(bool and_wait_for_them_to_finish)
|
||||
{
|
||||
CancelTasks(running_audio_tasks_, and_wait_for_them_to_finish);
|
||||
cancel_tasks(running_audio_tasks_, and_wait_for_them_to_finish);
|
||||
}
|
||||
|
||||
bool PreviewAutoCacher::IsRenderingCustomRange() const
|
||||
bool PreviewAutoCacher::is_rendering_custom_range() const
|
||||
{
|
||||
if (!use_custom_range_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const VideoJob &job : pending_video_jobs_) {
|
||||
if (job.range == custom_autocache_range_ && job.iterator.HasNext()) {
|
||||
if (job.range == custom_autocache_range_ && job.iterator.has_next()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -517,27 +517,27 @@ bool PreviewAutoCacher::IsRenderingCustomRange() const
|
||||
return false;
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::SetRendersPaused(bool e)
|
||||
void PreviewAutoCacher::set_renders_paused(bool e)
|
||||
{
|
||||
pause_renders_ = e;
|
||||
if (!e) {
|
||||
TryRender();
|
||||
try_render();
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::SetThumbnailsPaused(bool e)
|
||||
void PreviewAutoCacher::set_thumbnails_paused(bool e)
|
||||
{
|
||||
pause_thumbnails_ = e;
|
||||
if (!e) {
|
||||
TryRender();
|
||||
try_render();
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::TryRender()
|
||||
void PreviewAutoCacher::try_render()
|
||||
{
|
||||
delayed_requeue_timer_.stop();
|
||||
|
||||
if (copier_->HasUpdatesInQueue()) {
|
||||
if (copier_->has_updates_in_queue()) {
|
||||
// Check if we have jobs running in other threads that shouldn't be interrupted right now
|
||||
// NOTE: We don't check for downloads because, while they run in another thread, they don't
|
||||
// require any access to the graph and therefore don't risk race conditions.
|
||||
@@ -547,7 +547,7 @@ void PreviewAutoCacher::TryRender()
|
||||
}
|
||||
|
||||
// No jobs are active, we can process the update queue
|
||||
copier_->ProcessUpdateQueue();
|
||||
copier_->process_update_queue();
|
||||
}
|
||||
|
||||
if (single_frame_render_) {
|
||||
@@ -557,13 +557,13 @@ void PreviewAutoCacher::TryRender()
|
||||
single_frame_render_ = nullptr;
|
||||
|
||||
// Check if already caching this
|
||||
Node *n = QtUtils::ValueToPtr<Node>(t->property("node"));
|
||||
Node *copy = copier_->GetCopy(n);
|
||||
Node *n = QtUtils::value_to_ptr<Node>(t->property("node"));
|
||||
Node *copy = copier_->get_copy(n);
|
||||
|
||||
if (copy) {
|
||||
RenderTicketWatcher *watcher = RenderFrame(
|
||||
copy, QtUtils::ValueToPtr<ViewerOutput>(t->property("viewer")),
|
||||
t->property("time").value<rational>(), nullptr,
|
||||
RenderTicketWatcher *watcher = render_frame(
|
||||
copy, QtUtils::value_to_ptr<ViewerOutput>(t->property("viewer")),
|
||||
t->property("time").value<Rational>(), nullptr,
|
||||
t->property("dry").toBool());
|
||||
if (watcher) {
|
||||
video_immediate_passthroughs_[watcher].append(t);
|
||||
@@ -587,19 +587,19 @@ void PreviewAutoCacher::TryRender()
|
||||
while (!pending_video_jobs_.empty()) {
|
||||
VideoJob &d = pending_video_jobs_.front();
|
||||
|
||||
if (Node *copy = copier_->GetCopy(d.node)) {
|
||||
if (Node *copy = copier_->get_copy(d.node)) {
|
||||
// Queue next frames
|
||||
rational t;
|
||||
Rational t;
|
||||
while (running_video_tasks_.size() < max_tasks &&
|
||||
d.iterator.GetNext(&t)) {
|
||||
RenderFrame(copy, d.context, t, d.cache, false);
|
||||
d.iterator.get_next(&t)) {
|
||||
render_frame(copy, d.context, t, d.cache, false);
|
||||
|
||||
emit SignalCacheProxyTaskProgress(
|
||||
emit signal_cache_proxy_task_progress(
|
||||
double(d.iterator.frame_index()) /
|
||||
double(d.iterator.size()));
|
||||
|
||||
if (!d.iterator.HasNext()) {
|
||||
emit StopCacheProxyTasks();
|
||||
if (!d.iterator.has_next()) {
|
||||
emit stop_cache_proxy_tasks();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -611,7 +611,7 @@ void PreviewAutoCacher::TryRender()
|
||||
break;
|
||||
}
|
||||
|
||||
if (d.iterator.HasNext()) {
|
||||
if (d.iterator.has_next()) {
|
||||
break;
|
||||
} else {
|
||||
pending_video_jobs_.pop_front();
|
||||
@@ -627,14 +627,14 @@ void PreviewAutoCacher::TryRender()
|
||||
bool pop = true;
|
||||
|
||||
// Start job
|
||||
if (Node *copy = copier_->GetCopy(d.node)) {
|
||||
if (Node *copy = copier_->get_copy(d.node)) {
|
||||
TimeRange &queued_range = d.range;
|
||||
TimeRange use_range = queued_range;
|
||||
|
||||
if (dynamic_cast<AudioWaveformCache *>(d.cache)) {
|
||||
rational new_out = std::min(
|
||||
Rational new_out = std::min(
|
||||
use_range.in() +
|
||||
AudioVisualWaveform::kMinimumSampleRate.flipped(),
|
||||
AudioVisualWaveform::k_minimum_sample_rate.flipped(),
|
||||
use_range.out());
|
||||
|
||||
if (new_out != use_range.out()) {
|
||||
@@ -644,7 +644,7 @@ void PreviewAutoCacher::TryRender()
|
||||
}
|
||||
}
|
||||
|
||||
RenderAudio(copy, d.context, use_range, d.cache);
|
||||
render_audio(copy, d.context, use_range, d.cache);
|
||||
} else {
|
||||
qWarning()
|
||||
<< "Failed to find node copy for audio job, retrying";
|
||||
@@ -662,65 +662,65 @@ void PreviewAutoCacher::TryRender()
|
||||
}
|
||||
}
|
||||
|
||||
RenderTicketWatcher *PreviewAutoCacher::RenderFrame(Node *node,
|
||||
RenderTicketWatcher *PreviewAutoCacher::render_frame(Node *node,
|
||||
ViewerOutput *context,
|
||||
const rational &time,
|
||||
const Rational &time,
|
||||
PlaybackCache *cache,
|
||||
bool dry)
|
||||
{
|
||||
RenderTicketWatcher *watcher = new RenderTicketWatcher();
|
||||
watcher->setProperty("job",
|
||||
QVariant::fromValue(copier_->GetLastUpdateTime()));
|
||||
watcher->setProperty("cache", QtUtils::PtrToValue(cache));
|
||||
QVariant::fromValue(copier_->get_last_update_time()));
|
||||
watcher->setProperty("cache", QtUtils::ptr_to_value(cache));
|
||||
watcher->setProperty("time", QVariant::fromValue(time));
|
||||
connect(watcher, &RenderTicketWatcher::Finished, this,
|
||||
&PreviewAutoCacher::VideoRendered);
|
||||
connect(watcher, &RenderTicketWatcher::finished, this,
|
||||
&PreviewAutoCacher::video_rendered);
|
||||
|
||||
running_video_tasks_.append(watcher);
|
||||
|
||||
RenderManager::RenderVideoParams rvp(node, context->GetVideoParams(),
|
||||
context->GetAudioParams(), time,
|
||||
RenderManager::RenderVideoParams rvp(node, context->get_video_params(),
|
||||
context->get_audio_params(), time,
|
||||
copied_color_manager_,
|
||||
RenderMode::kOffline);
|
||||
RenderMode::k_offline);
|
||||
|
||||
if (FrameHashCache *frame_cache = dynamic_cast<FrameHashCache *>(cache)) {
|
||||
if (ThumbnailCache *wave_cache =
|
||||
dynamic_cast<ThumbnailCache *>(cache)) {
|
||||
Q_UNUSED(wave_cache)
|
||||
rvp.video_params.set_divider(
|
||||
VideoParams::GetDividerForTargetResolution(
|
||||
VideoParams::get_divider_for_target_resolution(
|
||||
rvp.video_params.width(), rvp.video_params.height(), 160,
|
||||
120));
|
||||
rvp.force_format = PixelFormat::F32;
|
||||
rvp.force_channel_count = VideoParams::kRGBAChannelCount;
|
||||
rvp.force_format = PixelFormat::f32;
|
||||
rvp.force_channel_count = VideoParams::k_rgba_channel_count;
|
||||
} else {
|
||||
frame_cache->SetTimebase(
|
||||
context->GetVideoParams().frame_rate_as_time_base());
|
||||
frame_cache->set_timebase(
|
||||
context->get_video_params().frame_rate_as_time_base());
|
||||
}
|
||||
|
||||
rvp.AddCache(frame_cache);
|
||||
rvp.add_cache(frame_cache);
|
||||
} else {
|
||||
// Preview/display frames are rendered at reduced precision to cut the
|
||||
// GPU->CPU readback and IPC transfer bandwidth. The internal render
|
||||
// pipeline stays F32/ACEScg; the final preview copy is packed 10-bit
|
||||
// RGBA (4 bytes/pixel) to preserve 10-bit panel precision while halving
|
||||
// bandwidth compared to F16.
|
||||
rvp.force_format = PixelFormat::U10;
|
||||
rvp.force_channel_count = VideoParams::kRGBAChannelCount;
|
||||
rvp.force_format = PixelFormat::u10;
|
||||
rvp.force_channel_count = VideoParams::k_rgba_channel_count;
|
||||
}
|
||||
|
||||
// Video playback frames are rendered out-of-process. GPU textures cannot be
|
||||
// shared across worker processes (or across independent Vulkan instances),
|
||||
// so we always request CPU frames.
|
||||
rvp.return_type = dry ? RenderManager::kNull : RenderManager::kFrame;
|
||||
rvp.return_type = dry ? RenderManager::k_null : RenderManager::k_frame;
|
||||
|
||||
// Allow using cached images for this render job
|
||||
rvp.use_cache = true;
|
||||
|
||||
// Multicam
|
||||
rvp.multicam = copier_->GetCopy(multicam_);
|
||||
rvp.multicam = copier_->get_copy(multicam_);
|
||||
|
||||
watcher->SetTicket(RenderManager::instance()->RenderFrame(rvp));
|
||||
watcher->set_ticket(RenderManager::instance()->render_frame(rvp));
|
||||
|
||||
// If the ticket finished synchronously, VideoRendered has already deleted the
|
||||
// watcher. The caller must not use this pointer in that case.
|
||||
@@ -731,47 +731,47 @@ RenderTicketWatcher *PreviewAutoCacher::RenderFrame(Node *node,
|
||||
return watcher;
|
||||
}
|
||||
|
||||
RenderTicketPtr PreviewAutoCacher::RenderAudio(Node *node,
|
||||
RenderTicketPtr PreviewAutoCacher::render_audio(Node *node,
|
||||
ViewerOutput *context,
|
||||
const TimeRange &r,
|
||||
PlaybackCache *cache)
|
||||
{
|
||||
RenderTicketWatcher *watcher = new RenderTicketWatcher();
|
||||
watcher->setProperty("job",
|
||||
QVariant::fromValue(copier_->GetLastUpdateTime()));
|
||||
watcher->setProperty("node", QtUtils::PtrToValue(node));
|
||||
watcher->setProperty("cache", QtUtils::PtrToValue(cache));
|
||||
QVariant::fromValue(copier_->get_last_update_time()));
|
||||
watcher->setProperty("node", QtUtils::ptr_to_value(node));
|
||||
watcher->setProperty("cache", QtUtils::ptr_to_value(cache));
|
||||
watcher->setProperty("time", QVariant::fromValue(r));
|
||||
connect(watcher, &RenderTicketWatcher::Finished, this,
|
||||
&PreviewAutoCacher::AudioRendered);
|
||||
connect(watcher, &RenderTicketWatcher::finished, this,
|
||||
&PreviewAutoCacher::audio_rendered);
|
||||
running_audio_tasks_.append(watcher);
|
||||
|
||||
AudioParams p = context->GetAudioParams();
|
||||
AudioParams p = context->get_audio_params();
|
||||
const bool invalid_params =
|
||||
(p.sample_rate() <= 0 || p.channel_count() <= 0);
|
||||
if (invalid_params) {
|
||||
AudioParams fallback(
|
||||
OLIVE_CONFIG("DefaultSequenceAudioFrequency").toInt(),
|
||||
OLIVE_CONFIG("DefaultSequenceAudioLayout").toULongLong(),
|
||||
ViewerOutput::kDefaultSampleFormat);
|
||||
OAK_CONFIG("DefaultSequenceAudioFrequency").toInt(),
|
||||
OAK_CONFIG("DefaultSequenceAudioLayout").toULongLong(),
|
||||
ViewerOutput::k_default_sample_format);
|
||||
p = fallback;
|
||||
}
|
||||
p.set_format(ViewerOutput::kDefaultSampleFormat);
|
||||
p.set_format(ViewerOutput::k_default_sample_format);
|
||||
|
||||
RenderManager::RenderAudioParams rap(node, r, p, RenderMode::kOffline);
|
||||
RenderManager::RenderAudioParams rap(node, r, p, RenderMode::k_offline);
|
||||
|
||||
rap.generate_waveforms = dynamic_cast<AudioWaveformCache *>(cache);
|
||||
rap.clamp = false;
|
||||
|
||||
RenderTicketPtr ticket = RenderManager::instance()->RenderAudio(rap);
|
||||
watcher->SetTicket(ticket);
|
||||
RenderTicketPtr ticket = RenderManager::instance()->render_audio(rap);
|
||||
watcher->set_ticket(ticket);
|
||||
return ticket;
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::ConformFinished()
|
||||
void PreviewAutoCacher::conform_finished()
|
||||
{
|
||||
// Got an audio conform, requeue all the audio currently needing a conform
|
||||
last_conform_task_.Acquire();
|
||||
last_conform_task_.acquire();
|
||||
|
||||
for (auto it = audio_cache_data_.begin(); it != audio_cache_data_.end();
|
||||
it++) {
|
||||
@@ -780,30 +780,30 @@ void PreviewAutoCacher::ConformFinished()
|
||||
}
|
||||
|
||||
for (const TimeRange &range : it.value().needs_conform) {
|
||||
it.key()->Request(it.value().context, range);
|
||||
it.key()->request(it.value().context, range);
|
||||
}
|
||||
it.value().needs_conform.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::CacheProxyTaskCancelled()
|
||||
void PreviewAutoCacher::cache_proxy_task_cancelled()
|
||||
{
|
||||
pending_video_jobs_.clear();
|
||||
|
||||
TryRender();
|
||||
try_render();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::ForceCacheRange(ViewerOutput *context,
|
||||
void PreviewAutoCacher::force_cache_range(ViewerOutput *context,
|
||||
const TimeRange &range)
|
||||
{
|
||||
use_custom_range_ = true;
|
||||
custom_autocache_range_ = range;
|
||||
|
||||
// Re-hash these frames and start rendering
|
||||
StartCachingVideoRange(context, context->video_frame_cache(), range);
|
||||
start_caching_video_range(context, context->video_frame_cache(), range);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::SetProject(Project *project)
|
||||
void PreviewAutoCacher::set_project(Project *project)
|
||||
{
|
||||
if (project_ == project) {
|
||||
return;
|
||||
@@ -819,31 +819,31 @@ void PreviewAutoCacher::SetProject(Project *project)
|
||||
// Handle video rendering tasks
|
||||
if (!running_video_tasks_.isEmpty()) {
|
||||
// Cancel any video tasks and wait for them to finish
|
||||
CancelVideoTasks(true);
|
||||
cancel_video_tasks(true);
|
||||
running_video_tasks_.clear();
|
||||
}
|
||||
|
||||
// Handle audio rendering tasks
|
||||
if (!running_audio_tasks_.isEmpty()) {
|
||||
// Cancel any audio tasks and wait for them to finish
|
||||
CancelAudioTasks(true);
|
||||
cancel_audio_tasks(true);
|
||||
running_audio_tasks_.clear();
|
||||
}
|
||||
|
||||
// Clear any single frame render that might be queued
|
||||
CancelQueuedSingleFrameRender();
|
||||
cancel_queued_single_frame_render();
|
||||
|
||||
// Not interested in video passthroughs anymore
|
||||
video_immediate_passthroughs_.clear();
|
||||
|
||||
// Disconnect from all node cache's
|
||||
for (auto it = copier_->GetNodeMap().cbegin();
|
||||
it != copier_->GetNodeMap().cend(); it++) {
|
||||
DisconnectFromNodeCache(it.key());
|
||||
for (auto it = copier_->get_node_map().cbegin();
|
||||
it != copier_->get_node_map().cend(); it++) {
|
||||
disconnect_from_node_cache(it.key());
|
||||
}
|
||||
|
||||
// Delete all of our copied nodes
|
||||
copier_->SetProject(nullptr);
|
||||
copier_->set_project(nullptr);
|
||||
|
||||
// Ensure all cache data is cleared
|
||||
video_cache_data_.clear();
|
||||
@@ -857,18 +857,18 @@ void PreviewAutoCacher::SetProject(Project *project)
|
||||
|
||||
if (project_) {
|
||||
// Copy graph (this should always be a Project)
|
||||
SetRendersPaused(true);
|
||||
set_renders_paused(true);
|
||||
|
||||
copier_->SetProject(project_);
|
||||
copier_->set_project(project_);
|
||||
|
||||
for (int i = 0; i < project_->nodes().size(); i++) {
|
||||
project_->nodes().at(i)->ConnectedToPreviewEvent();
|
||||
}
|
||||
|
||||
// Find copied viewer node
|
||||
copied_color_manager_ = copier_->GetCopiedProject()->color_manager();
|
||||
copied_color_manager_ = copier_->get_copied_project()->color_manager();
|
||||
|
||||
SetRendersPaused(false);
|
||||
set_renders_paused(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef AUTOCACHER_H
|
||||
#define AUTOCACHER_H
|
||||
#ifndef OAK_AUTOCACHER_H
|
||||
#define OAK_AUTOCACHER_H
|
||||
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
@@ -49,20 +49,20 @@ public:
|
||||
|
||||
virtual ~PreviewAutoCacher() override;
|
||||
|
||||
RenderTicketPtr GetSingleFrame(ViewerOutput *viewer, const rational &t,
|
||||
RenderTicketPtr get_single_frame(ViewerOutput *viewer, const Rational &t,
|
||||
bool dry = false);
|
||||
RenderTicketPtr GetSingleFrame(Node *n, ViewerOutput *viewer,
|
||||
const rational &t, bool dry = false);
|
||||
RenderTicketPtr get_single_frame(Node *n, ViewerOutput *viewer,
|
||||
const Rational &t, bool dry = false);
|
||||
|
||||
RenderTicketPtr GetRangeOfAudio(ViewerOutput *viewer, TimeRange range);
|
||||
RenderTicketPtr get_range_of_audio(ViewerOutput *viewer, TimeRange range);
|
||||
|
||||
void ClearSingleFrameRenders();
|
||||
void ClearSingleFrameRendersThatArentRunning();
|
||||
void clear_single_frame_renders();
|
||||
void clear_single_frame_renders_that_arent_running();
|
||||
|
||||
/**
|
||||
* @brief Set the viewer node to auto-cache
|
||||
*/
|
||||
void SetProject(Project *project);
|
||||
void set_project(Project *project);
|
||||
|
||||
/**
|
||||
* @brief Force a certain range to be cached
|
||||
@@ -71,12 +71,12 @@ public:
|
||||
* times they may want certain non-playhead-related time ranges to be cached (i.e. entire sequence
|
||||
* or in/out range), so that can be set here.
|
||||
*/
|
||||
void ForceCacheRange(ViewerOutput *context, const TimeRange &range);
|
||||
void force_cache_range(ViewerOutput *context, const TimeRange &range);
|
||||
|
||||
/**
|
||||
* @brief Updates the range of frames to auto-cache
|
||||
*/
|
||||
void SetPlayhead(const rational &playhead);
|
||||
void set_playhead(const Rational &playhead);
|
||||
|
||||
/**
|
||||
* @brief Call cancel on all currently running video tasks
|
||||
@@ -86,60 +86,60 @@ public:
|
||||
* up finishing the task. The RenderManager will also return "no result", which can be checked
|
||||
* with watcher->HasResult.
|
||||
*/
|
||||
void CancelVideoTasks(bool and_wait_for_them_to_finish = false);
|
||||
void CancelAudioTasks(bool and_wait_for_them_to_finish = false);
|
||||
void cancel_video_tasks(bool and_wait_for_them_to_finish = false);
|
||||
void cancel_audio_tasks(bool and_wait_for_them_to_finish = false);
|
||||
|
||||
bool IsRenderingCustomRange() const;
|
||||
bool is_rendering_custom_range() const;
|
||||
|
||||
void SetRendersPaused(bool e);
|
||||
void SetThumbnailsPaused(bool e);
|
||||
void set_renders_paused(bool e);
|
||||
void set_thumbnails_paused(bool e);
|
||||
|
||||
void SetMulticamNode(MultiCamNode *n)
|
||||
void set_multicam_node(MultiCamNode *n)
|
||||
{
|
||||
multicam_ = n;
|
||||
}
|
||||
|
||||
void SetIgnoreCacheRequests(bool e)
|
||||
void set_ignore_cache_requests(bool e)
|
||||
{
|
||||
ignore_cache_requests_ = e;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetDisplayColorProcessor(ColorProcessorPtr processor)
|
||||
void set_display_color_processor(ColorProcessorPtr processor)
|
||||
{
|
||||
display_color_processor_ = processor;
|
||||
}
|
||||
|
||||
signals:
|
||||
void StopCacheProxyTasks();
|
||||
void stop_cache_proxy_tasks();
|
||||
|
||||
void SignalCacheProxyTaskProgress(double d);
|
||||
void signal_cache_proxy_task_progress(double d);
|
||||
|
||||
private:
|
||||
void TryRender();
|
||||
void try_render();
|
||||
|
||||
RenderTicketWatcher *RenderFrame(Node *node, ViewerOutput *context,
|
||||
const rational &time, PlaybackCache *cache,
|
||||
RenderTicketWatcher *render_frame(Node *node, ViewerOutput *context,
|
||||
const Rational &time, PlaybackCache *cache,
|
||||
bool dry);
|
||||
|
||||
RenderTicketPtr RenderAudio(Node *node, ViewerOutput *context,
|
||||
RenderTicketPtr render_audio(Node *node, ViewerOutput *context,
|
||||
const TimeRange &range, PlaybackCache *cache);
|
||||
|
||||
void ConnectToNodeCache(Node *node);
|
||||
void DisconnectFromNodeCache(Node *node);
|
||||
void connect_to_node_cache(Node *node);
|
||||
void disconnect_from_node_cache(Node *node);
|
||||
|
||||
void CancelQueuedSingleFrameRender();
|
||||
void cancel_queued_single_frame_render();
|
||||
|
||||
void StartCachingRange(const TimeRange &range, TimeRangeList *range_list,
|
||||
void start_caching_range(const TimeRange &range, TimeRangeList *range_list,
|
||||
RenderJobTracker *tracker);
|
||||
void StartCachingVideoRange(ViewerOutput *context, PlaybackCache *cache,
|
||||
void start_caching_video_range(ViewerOutput *context, PlaybackCache *cache,
|
||||
const TimeRange &range);
|
||||
void StartCachingAudioRange(ViewerOutput *context, PlaybackCache *cache,
|
||||
void start_caching_audio_range(ViewerOutput *context, PlaybackCache *cache,
|
||||
const TimeRange &range);
|
||||
|
||||
void VideoInvalidatedFromNode(ViewerOutput *context, PlaybackCache *cache,
|
||||
void video_invalidated_from_node(ViewerOutput *context, PlaybackCache *cache,
|
||||
const olive::TimeRange &range);
|
||||
void AudioInvalidatedFromNode(ViewerOutput *context, PlaybackCache *cache,
|
||||
void audio_invalidated_from_node(ViewerOutput *context, PlaybackCache *cache,
|
||||
const olive::TimeRange &range);
|
||||
|
||||
Project *project_;
|
||||
@@ -208,37 +208,37 @@ private slots:
|
||||
/**
|
||||
* @brief Handler for when the NodeGraph reports a video change over a certain time range
|
||||
*/
|
||||
void VideoInvalidatedFromCache(ViewerOutput *context,
|
||||
void video_invalidated_from_cache(ViewerOutput *context,
|
||||
const olive::TimeRange &range);
|
||||
|
||||
/**
|
||||
* @brief Handler for when the NodeGraph reports a audio change over a certain time range
|
||||
*/
|
||||
void AudioInvalidatedFromCache(ViewerOutput *context,
|
||||
void audio_invalidated_from_cache(ViewerOutput *context,
|
||||
const olive::TimeRange &range);
|
||||
|
||||
void CancelForCache();
|
||||
void cancel_for_cache();
|
||||
|
||||
/**
|
||||
* @brief Handler for when the RenderManager has returned rendered audio
|
||||
*/
|
||||
void AudioRendered();
|
||||
void audio_rendered();
|
||||
|
||||
/**
|
||||
* @brief Handler for when the RenderManager has returned rendered video frames
|
||||
*/
|
||||
void VideoRendered();
|
||||
void video_rendered();
|
||||
|
||||
/**
|
||||
* @brief Generic function called whenever the frames to render need to be (re)queued
|
||||
*/
|
||||
//void RequeueFrames();
|
||||
|
||||
void ConformFinished();
|
||||
void conform_finished();
|
||||
|
||||
void CacheProxyTaskCancelled();
|
||||
void cache_proxy_task_cancelled();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // AUTOCACHER_H
|
||||
#endif // OAK_AUTOCACHER_H
|
||||
|
||||
+103
-103
@@ -35,7 +35,7 @@ ProjectCopier::ProjectCopier(QObject *parent)
|
||||
copy_->setParent(this);
|
||||
}
|
||||
|
||||
void ProjectCopier::SetProject(Project *project)
|
||||
void ProjectCopier::set_project(Project *project)
|
||||
{
|
||||
if (original_) {
|
||||
// Clear current project
|
||||
@@ -44,20 +44,20 @@ void ProjectCopier::SetProject(Project *project)
|
||||
copy_map_.clear();
|
||||
graph_update_queue_.clear();
|
||||
|
||||
disconnect(original_, &Project::NodeAdded, this,
|
||||
&ProjectCopier::QueueNodeAdd);
|
||||
disconnect(original_, &Project::NodeRemoved, this,
|
||||
&ProjectCopier::QueueNodeRemove);
|
||||
disconnect(original_, &Project::InputConnected, this,
|
||||
&ProjectCopier::QueueEdgeAdd);
|
||||
disconnect(original_, &Project::InputDisconnected, this,
|
||||
&ProjectCopier::QueueEdgeRemove);
|
||||
disconnect(original_, &Project::ValueChanged, this,
|
||||
&ProjectCopier::QueueValueChange);
|
||||
disconnect(original_, &Project::InputValueHintChanged, this,
|
||||
&ProjectCopier::QueueValueHintChange);
|
||||
disconnect(original_, &Project::SettingChanged, this,
|
||||
&ProjectCopier::QueueProjectSettingChange);
|
||||
disconnect(original_, &Project::node_added, this,
|
||||
&ProjectCopier::queue_node_add);
|
||||
disconnect(original_, &Project::node_removed, this,
|
||||
&ProjectCopier::queue_node_remove);
|
||||
disconnect(original_, &Project::input_connected, this,
|
||||
&ProjectCopier::queue_edge_add);
|
||||
disconnect(original_, &Project::input_disconnected, this,
|
||||
&ProjectCopier::queue_edge_remove);
|
||||
disconnect(original_, &Project::value_changed, this,
|
||||
&ProjectCopier::queue_value_change);
|
||||
disconnect(original_, &Project::input_value_hint_changed, this,
|
||||
&ProjectCopier::queue_value_hint_change);
|
||||
disconnect(original_, &Project::setting_changed, this,
|
||||
&ProjectCopier::queue_project_setting_change);
|
||||
}
|
||||
|
||||
original_ = project;
|
||||
@@ -70,49 +70,49 @@ void ProjectCopier::SetProject(Project *project)
|
||||
|
||||
// Add all nodes
|
||||
for (int i = 0; i < copy_->nodes().size(); i++) {
|
||||
InsertIntoCopyMap(original_->nodes().at(i), copy_->nodes().at(i));
|
||||
insert_into_copy_map(original_->nodes().at(i), copy_->nodes().at(i));
|
||||
}
|
||||
|
||||
for (int i = copy_->nodes().size(); i < original_->nodes().size();
|
||||
i++) {
|
||||
DoNodeAdd(original_->nodes().at(i));
|
||||
do_node_add(original_->nodes().at(i));
|
||||
}
|
||||
|
||||
// Add all connections
|
||||
foreach (Node *node, original_->nodes()) {
|
||||
for (auto it = node->input_connections().cbegin();
|
||||
it != node->input_connections().cend(); it++) {
|
||||
DoEdgeAdd(it->second, it->first);
|
||||
do_edge_add(it->second, it->first);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy project settings
|
||||
Project::CopySettings(original_, copy_);
|
||||
Project::copy_settings(original_, copy_);
|
||||
|
||||
// Ensure graph change value is just before the sync value
|
||||
UpdateGraphChangeValue();
|
||||
UpdateLastSyncedValue();
|
||||
update_graph_change_value();
|
||||
update_last_synced_value();
|
||||
|
||||
// Connect signals for future node additions/deletions
|
||||
connect(original_, &Project::NodeAdded, this,
|
||||
&ProjectCopier::QueueNodeAdd, Qt::DirectConnection);
|
||||
connect(original_, &Project::NodeRemoved, this,
|
||||
&ProjectCopier::QueueNodeRemove, Qt::DirectConnection);
|
||||
connect(original_, &Project::InputConnected, this,
|
||||
&ProjectCopier::QueueEdgeAdd, Qt::DirectConnection);
|
||||
connect(original_, &Project::InputDisconnected, this,
|
||||
&ProjectCopier::QueueEdgeRemove, Qt::DirectConnection);
|
||||
connect(original_, &Project::ValueChanged, this,
|
||||
&ProjectCopier::QueueValueChange, Qt::DirectConnection);
|
||||
connect(original_, &Project::InputValueHintChanged, this,
|
||||
&ProjectCopier::QueueValueHintChange, Qt::DirectConnection);
|
||||
connect(original_, &Project::SettingChanged, this,
|
||||
&ProjectCopier::QueueProjectSettingChange,
|
||||
connect(original_, &Project::node_added, this,
|
||||
&ProjectCopier::queue_node_add, Qt::DirectConnection);
|
||||
connect(original_, &Project::node_removed, this,
|
||||
&ProjectCopier::queue_node_remove, Qt::DirectConnection);
|
||||
connect(original_, &Project::input_connected, this,
|
||||
&ProjectCopier::queue_edge_add, Qt::DirectConnection);
|
||||
connect(original_, &Project::input_disconnected, this,
|
||||
&ProjectCopier::queue_edge_remove, Qt::DirectConnection);
|
||||
connect(original_, &Project::value_changed, this,
|
||||
&ProjectCopier::queue_value_change, Qt::DirectConnection);
|
||||
connect(original_, &Project::input_value_hint_changed, this,
|
||||
&ProjectCopier::queue_value_hint_change, Qt::DirectConnection);
|
||||
connect(original_, &Project::setting_changed, this,
|
||||
&ProjectCopier::queue_project_setting_change,
|
||||
Qt::DirectConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectCopier::ProcessUpdateQueue()
|
||||
void ProjectCopier::process_update_queue()
|
||||
{
|
||||
bool copy_changed = false;
|
||||
|
||||
@@ -123,26 +123,26 @@ void ProjectCopier::ProcessUpdateQueue()
|
||||
copy_changed = true;
|
||||
|
||||
switch (job.type) {
|
||||
case QueuedJob::kNodeAdded:
|
||||
DoNodeAdd(job.node);
|
||||
case QueuedJob::k_node_added:
|
||||
do_node_add(job.node);
|
||||
break;
|
||||
case QueuedJob::kNodeRemoved:
|
||||
DoNodeRemove(job.node);
|
||||
case QueuedJob::k_node_removed:
|
||||
do_node_remove(job.node);
|
||||
break;
|
||||
case QueuedJob::kEdgeAdded:
|
||||
DoEdgeAdd(job.output, job.input);
|
||||
case QueuedJob::k_edge_added:
|
||||
do_edge_add(job.output, job.input);
|
||||
break;
|
||||
case QueuedJob::kEdgeRemoved:
|
||||
DoEdgeRemove(job.output, job.input);
|
||||
case QueuedJob::k_edge_removed:
|
||||
do_edge_remove(job.output, job.input);
|
||||
break;
|
||||
case QueuedJob::kValueChanged:
|
||||
DoValueChange(job.input);
|
||||
case QueuedJob::k_value_changed:
|
||||
do_value_change(job.input);
|
||||
break;
|
||||
case QueuedJob::kValueHintChanged:
|
||||
DoValueHintChange(job.input);
|
||||
case QueuedJob::k_value_hint_changed:
|
||||
do_value_hint_change(job.input);
|
||||
break;
|
||||
case QueuedJob::kProjectSettingChanged:
|
||||
DoProjectSettingChange(job.key, job.value);
|
||||
case QueuedJob::k_project_setting_changed:
|
||||
do_project_setting_change(job.key, job.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -156,10 +156,10 @@ void ProjectCopier::ProcessUpdateQueue()
|
||||
|
||||
// Indicate that we have synchronized to this point, which is compared with the graph change
|
||||
// time to see if our copied graph is up to date
|
||||
UpdateLastSyncedValue();
|
||||
update_last_synced_value();
|
||||
}
|
||||
|
||||
void ProjectCopier::DoNodeAdd(Node *node)
|
||||
void ProjectCopier::do_node_add(Node *node)
|
||||
{
|
||||
if (dynamic_cast<NodeGroup *>(node)) {
|
||||
// Group nodes are just dummy nodes, no need to copy them
|
||||
@@ -173,25 +173,25 @@ void ProjectCopier::DoNodeAdd(Node *node)
|
||||
copy->setParent(copy_);
|
||||
|
||||
// Disable caches for copy
|
||||
copy->SetCachesEnabled(false);
|
||||
copy->set_caches_enabled(false);
|
||||
|
||||
// Copy cache UUIDs
|
||||
copy->CopyCacheUuidsFrom(node);
|
||||
copy->copy_cache_uuids_from(node);
|
||||
|
||||
// Insert into map
|
||||
InsertIntoCopyMap(node, copy);
|
||||
insert_into_copy_map(node, copy);
|
||||
|
||||
// Keep track of our nodes
|
||||
created_nodes_.append(copy);
|
||||
}
|
||||
|
||||
void ProjectCopier::DoNodeRemove(Node *node)
|
||||
void ProjectCopier::do_node_remove(Node *node)
|
||||
{
|
||||
// Find our copy and remove it
|
||||
Node *copy = copy_map_.take(node);
|
||||
|
||||
// Disconnect from node's caches
|
||||
emit RemovedNode(node);
|
||||
emit removed_node(node);
|
||||
|
||||
// Remove from created list
|
||||
created_nodes_.removeOne(copy);
|
||||
@@ -200,27 +200,27 @@ void ProjectCopier::DoNodeRemove(Node *node)
|
||||
delete copy;
|
||||
}
|
||||
|
||||
void ProjectCopier::DoEdgeAdd(Node *output, const NodeInput &input)
|
||||
void ProjectCopier::do_edge_add(Node *output, const NodeInput &input)
|
||||
{
|
||||
// Create same connection with our copied graph
|
||||
Node *our_output = copy_map_.value(output);
|
||||
Node *our_input = copy_map_.value(input.node());
|
||||
|
||||
Node::ConnectEdge(our_output,
|
||||
Node::connect_edge(our_output,
|
||||
NodeInput(our_input, input.input(), input.element()));
|
||||
}
|
||||
|
||||
void ProjectCopier::DoEdgeRemove(Node *output, const NodeInput &input)
|
||||
void ProjectCopier::do_edge_remove(Node *output, const NodeInput &input)
|
||||
{
|
||||
// Remove same connection with our copied graph
|
||||
Node *our_output = copy_map_.value(output);
|
||||
Node *our_input = copy_map_.value(input.node());
|
||||
|
||||
Node::DisconnectEdge(our_output,
|
||||
Node::disconnect_edge(our_output,
|
||||
NodeInput(our_input, input.input(), input.element()));
|
||||
}
|
||||
|
||||
void ProjectCopier::DoValueChange(const NodeInput &input)
|
||||
void ProjectCopier::do_value_change(const NodeInput &input)
|
||||
{
|
||||
if (dynamic_cast<NodeGroup *>(input.node())) {
|
||||
// Group nodes are just dummy nodes, no need to copy them
|
||||
@@ -229,11 +229,11 @@ void ProjectCopier::DoValueChange(const NodeInput &input)
|
||||
|
||||
// Copy all values to our graph
|
||||
Node *our_input = copy_map_.value(input.node());
|
||||
Node::CopyValuesOfElement(input.node(), our_input, input.input(),
|
||||
Node::copy_values_of_element(input.node(), our_input, input.input(),
|
||||
input.element());
|
||||
}
|
||||
|
||||
void ProjectCopier::DoValueHintChange(const NodeInput &input)
|
||||
void ProjectCopier::do_value_hint_change(const NodeInput &input)
|
||||
{
|
||||
if (dynamic_cast<NodeGroup *>(input.node())) {
|
||||
// Group nodes are just dummy nodes, no need to copy them
|
||||
@@ -243,42 +243,42 @@ void ProjectCopier::DoValueHintChange(const NodeInput &input)
|
||||
// Copy value hint to our graph
|
||||
Node *our_input = copy_map_.value(input.node());
|
||||
Node::ValueHint hint =
|
||||
input.node()->GetValueHintForInput(input.input(), input.element());
|
||||
our_input->SetValueHintForInput(input.input(), hint, input.element());
|
||||
input.node()->get_value_hint_for_input(input.input(), input.element());
|
||||
our_input->set_value_hint_for_input(input.input(), hint, input.element());
|
||||
}
|
||||
|
||||
void ProjectCopier::DoProjectSettingChange(const QString &key,
|
||||
void ProjectCopier::do_project_setting_change(const QString &key,
|
||||
const QString &value)
|
||||
{
|
||||
copy_->SetSetting(key, value);
|
||||
copy_->set_setting(key, value);
|
||||
}
|
||||
|
||||
void ProjectCopier::InsertIntoCopyMap(Node *node, Node *copy)
|
||||
void ProjectCopier::insert_into_copy_map(Node *node, Node *copy)
|
||||
{
|
||||
// Insert into map
|
||||
copy_map_.insert(node, copy);
|
||||
|
||||
// Copy parameters
|
||||
Node::CopyInputs(node, copy, false);
|
||||
Node::copy_inputs(node, copy, false);
|
||||
|
||||
// Sync Footage proxy state (which is not stored as a Node input)
|
||||
if (Footage *src_footage = dynamic_cast<Footage *>(node)) {
|
||||
if (dynamic_cast<Footage *>(copy)) {
|
||||
connect(src_footage, &Footage::ProxySettingsChanged, this,
|
||||
connect(src_footage, &Footage::proxy_settings_changed, this,
|
||||
[this, src_footage]() {
|
||||
SyncFootageProxySettings(src_footage);
|
||||
sync_footage_proxy_settings(src_footage);
|
||||
});
|
||||
SyncFootageProxySettings(src_footage);
|
||||
sync_footage_proxy_settings(src_footage);
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to node's cache
|
||||
emit AddedNode(node);
|
||||
emit added_node(node);
|
||||
}
|
||||
|
||||
void ProjectCopier::SyncFootageProxySettings(Footage *source)
|
||||
void ProjectCopier::sync_footage_proxy_settings(Footage *source)
|
||||
{
|
||||
Footage *copy = GetCopy(source);
|
||||
Footage *copy = get_copy(source);
|
||||
if (!copy) {
|
||||
qWarning() << "ProjectCopier::SyncFootageProxySettings: no copy for"
|
||||
<< source->filename();
|
||||
@@ -289,9 +289,9 @@ void ProjectCopier::SyncFootageProxySettings(Footage *source)
|
||||
<< "ProjectCopier::SyncFootageProxySettings:" << source->filename()
|
||||
<< "enabled=" << source->proxy_enabled() << "->"
|
||||
<< copy->proxy_enabled()
|
||||
<< "state=" << ProxyManager::ProxyStateToString(source->proxy_state());
|
||||
<< "state=" << ProxyManager::proxy_state_to_string(source->proxy_state());
|
||||
|
||||
copy->SetProxy(source->proxy_path(), source->proxy_state(),
|
||||
copy->set_proxy(source->proxy_path(), source->proxy_state(),
|
||||
source->proxy_video_stream_index(),
|
||||
source->proxy_preset_version(), source->proxy_enabled());
|
||||
|
||||
@@ -300,35 +300,35 @@ void ProjectCopier::SyncFootageProxySettings(Footage *source)
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectCopier::QueueNodeAdd(Node *node)
|
||||
void ProjectCopier::queue_node_add(Node *node)
|
||||
{
|
||||
graph_update_queue_.push_back({ QueuedJob::kNodeAdded, node, NodeInput(),
|
||||
graph_update_queue_.push_back({ QueuedJob::k_node_added, node, NodeInput(),
|
||||
nullptr, QString(), QString() });
|
||||
UpdateGraphChangeValue();
|
||||
update_graph_change_value();
|
||||
}
|
||||
|
||||
void ProjectCopier::QueueNodeRemove(Node *node)
|
||||
void ProjectCopier::queue_node_remove(Node *node)
|
||||
{
|
||||
graph_update_queue_.push_back({ QueuedJob::kNodeRemoved, node, NodeInput(),
|
||||
graph_update_queue_.push_back({ QueuedJob::k_node_removed, node, NodeInput(),
|
||||
nullptr, QString(), QString() });
|
||||
UpdateGraphChangeValue();
|
||||
update_graph_change_value();
|
||||
}
|
||||
|
||||
void ProjectCopier::QueueEdgeAdd(Node *output, const NodeInput &input)
|
||||
void ProjectCopier::queue_edge_add(Node *output, const NodeInput &input)
|
||||
{
|
||||
graph_update_queue_.push_back({ QueuedJob::kEdgeAdded, nullptr, input,
|
||||
graph_update_queue_.push_back({ QueuedJob::k_edge_added, nullptr, input,
|
||||
output, QString(), QString() });
|
||||
UpdateGraphChangeValue();
|
||||
update_graph_change_value();
|
||||
}
|
||||
|
||||
void ProjectCopier::QueueEdgeRemove(Node *output, const NodeInput &input)
|
||||
void ProjectCopier::queue_edge_remove(Node *output, const NodeInput &input)
|
||||
{
|
||||
graph_update_queue_.push_back({ QueuedJob::kEdgeRemoved, nullptr, input,
|
||||
graph_update_queue_.push_back({ QueuedJob::k_edge_removed, nullptr, input,
|
||||
output, QString(), QString() });
|
||||
UpdateGraphChangeValue();
|
||||
update_graph_change_value();
|
||||
}
|
||||
|
||||
void ProjectCopier::QueueValueChange(const NodeInput &input)
|
||||
void ProjectCopier::queue_value_change(const NodeInput &input)
|
||||
{
|
||||
/*for (auto it = graph_update_queue_.begin(); it != graph_update_queue_.end(); ) {
|
||||
if (it->type == QueuedJob::kValueChanged && it->input == input) {
|
||||
@@ -338,34 +338,34 @@ void ProjectCopier::QueueValueChange(const NodeInput &input)
|
||||
}
|
||||
}*/
|
||||
|
||||
graph_update_queue_.push_back({ QueuedJob::kValueChanged, nullptr, input,
|
||||
graph_update_queue_.push_back({ QueuedJob::k_value_changed, nullptr, input,
|
||||
nullptr, QString(), QString() });
|
||||
UpdateGraphChangeValue();
|
||||
update_graph_change_value();
|
||||
}
|
||||
|
||||
void ProjectCopier::QueueValueHintChange(const NodeInput &input)
|
||||
void ProjectCopier::queue_value_hint_change(const NodeInput &input)
|
||||
{
|
||||
graph_update_queue_.push_back({ QueuedJob::kValueHintChanged, nullptr,
|
||||
graph_update_queue_.push_back({ QueuedJob::k_value_hint_changed, nullptr,
|
||||
input, nullptr, QString(), QString() });
|
||||
UpdateGraphChangeValue();
|
||||
update_graph_change_value();
|
||||
}
|
||||
|
||||
void ProjectCopier::QueueProjectSettingChange(const QString &key,
|
||||
void ProjectCopier::queue_project_setting_change(const QString &key,
|
||||
const QString &value)
|
||||
{
|
||||
graph_update_queue_.push_back({ QueuedJob::kProjectSettingChanged, nullptr,
|
||||
graph_update_queue_.push_back({ QueuedJob::k_project_setting_changed, nullptr,
|
||||
NodeInput(), nullptr, key, value });
|
||||
UpdateGraphChangeValue();
|
||||
update_graph_change_value();
|
||||
}
|
||||
|
||||
void ProjectCopier::UpdateGraphChangeValue()
|
||||
void ProjectCopier::update_graph_change_value()
|
||||
{
|
||||
graph_changed_time_.Acquire();
|
||||
graph_changed_time_.acquire();
|
||||
}
|
||||
|
||||
void ProjectCopier::UpdateLastSyncedValue()
|
||||
void ProjectCopier::update_last_synced_value()
|
||||
{
|
||||
last_update_time_.Acquire();
|
||||
last_update_time_.acquire();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+39
-39
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef PROJECTCOPIER_H
|
||||
#define PROJECTCOPIER_H
|
||||
#ifndef OAK_PROJECTCOPIER_H
|
||||
#define OAK_PROJECTCOPIER_H
|
||||
|
||||
#include "node/project.h"
|
||||
#include "node/project/footage/footage.h"
|
||||
@@ -33,38 +33,38 @@ class ProjectCopier : public QObject {
|
||||
public:
|
||||
ProjectCopier(QObject *parent = nullptr);
|
||||
|
||||
void SetProject(Project *project);
|
||||
void set_project(Project *project);
|
||||
|
||||
template <typename T> T *GetCopy(T *original)
|
||||
template <typename T> T *get_copy(T *original)
|
||||
{
|
||||
return static_cast<T *>(copy_map_.value(original));
|
||||
}
|
||||
|
||||
template <typename T> T *GetOriginal(T *copy)
|
||||
template <typename T> T *get_original(T *copy)
|
||||
{
|
||||
return static_cast<T *>(copy_map_.key(copy));
|
||||
}
|
||||
|
||||
Project *GetCopiedProject() const
|
||||
Project *get_copied_project() const
|
||||
{
|
||||
return copy_;
|
||||
}
|
||||
|
||||
const QHash<Node *, Node *> &GetNodeMap() const
|
||||
const QHash<Node *, Node *> &get_node_map() const
|
||||
{
|
||||
return copy_map_;
|
||||
}
|
||||
|
||||
const JobTime &GetGraphChangeTime() const
|
||||
const JobTime &get_graph_change_time() const
|
||||
{
|
||||
return graph_changed_time_;
|
||||
}
|
||||
const JobTime &GetLastUpdateTime() const
|
||||
const JobTime &get_last_update_time() const
|
||||
{
|
||||
return last_update_time_;
|
||||
}
|
||||
|
||||
bool HasUpdatesInQueue() const
|
||||
bool has_updates_in_queue() const
|
||||
{
|
||||
return !graph_update_queue_.empty();
|
||||
}
|
||||
@@ -75,27 +75,27 @@ public:
|
||||
* PreviewAutoCacher staggers updates to its internal NodeGraph copy, only applying them when the
|
||||
* RenderManager is not reading from it. This function is called when such an opportunity arises.
|
||||
*/
|
||||
void ProcessUpdateQueue();
|
||||
void process_update_queue();
|
||||
|
||||
signals:
|
||||
void AddedNode(Node *n);
|
||||
void RemovedNode(Node *n);
|
||||
void added_node(Node *n);
|
||||
void removed_node(Node *n);
|
||||
|
||||
private:
|
||||
void DoNodeAdd(Node *node);
|
||||
void DoNodeRemove(Node *node);
|
||||
void DoEdgeAdd(Node *output, const NodeInput &input);
|
||||
void DoEdgeRemove(Node *output, const NodeInput &input);
|
||||
void DoValueChange(const NodeInput &input);
|
||||
void DoValueHintChange(const NodeInput &input);
|
||||
void DoProjectSettingChange(const QString &key, const QString &value);
|
||||
void do_node_add(Node *node);
|
||||
void do_node_remove(Node *node);
|
||||
void do_edge_add(Node *output, const NodeInput &input);
|
||||
void do_edge_remove(Node *output, const NodeInput &input);
|
||||
void do_value_change(const NodeInput &input);
|
||||
void do_value_hint_change(const NodeInput &input);
|
||||
void do_project_setting_change(const QString &key, const QString &value);
|
||||
|
||||
void SyncFootageProxySettings(Footage *source);
|
||||
void sync_footage_proxy_settings(Footage *source);
|
||||
|
||||
void InsertIntoCopyMap(Node *node, Node *copy);
|
||||
void insert_into_copy_map(Node *node, Node *copy);
|
||||
|
||||
void UpdateGraphChangeValue();
|
||||
void UpdateLastSyncedValue();
|
||||
void update_graph_change_value();
|
||||
void update_last_synced_value();
|
||||
|
||||
Project *original_;
|
||||
Project *copy_;
|
||||
@@ -103,13 +103,13 @@ private:
|
||||
class QueuedJob {
|
||||
public:
|
||||
enum Type {
|
||||
kNodeAdded,
|
||||
kNodeRemoved,
|
||||
kEdgeAdded,
|
||||
kEdgeRemoved,
|
||||
kValueChanged,
|
||||
kValueHintChanged,
|
||||
kProjectSettingChanged
|
||||
k_node_added,
|
||||
k_node_removed,
|
||||
k_edge_added,
|
||||
k_edge_removed,
|
||||
k_value_changed,
|
||||
k_value_hint_changed,
|
||||
k_project_setting_changed
|
||||
};
|
||||
|
||||
Type type;
|
||||
@@ -130,21 +130,21 @@ private:
|
||||
JobTime last_update_time_;
|
||||
|
||||
private slots:
|
||||
void QueueNodeAdd(Node *node);
|
||||
void queue_node_add(Node *node);
|
||||
|
||||
void QueueNodeRemove(Node *node);
|
||||
void queue_node_remove(Node *node);
|
||||
|
||||
void QueueEdgeAdd(Node *output, const NodeInput &input);
|
||||
void queue_edge_add(Node *output, const NodeInput &input);
|
||||
|
||||
void QueueEdgeRemove(Node *output, const NodeInput &input);
|
||||
void queue_edge_remove(Node *output, const NodeInput &input);
|
||||
|
||||
void QueueValueChange(const NodeInput &input);
|
||||
void queue_value_change(const NodeInput &input);
|
||||
|
||||
void QueueValueHintChange(const NodeInput &input);
|
||||
void queue_value_hint_change(const NodeInput &input);
|
||||
|
||||
void QueueProjectSettingChange(const QString &key, const QString &value);
|
||||
void queue_project_setting_change(const QString &key, const QString &value);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PROJECTCOPIER_H
|
||||
#endif // OAK_PROJECTCOPIER_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERCACHE_H
|
||||
#define RENDERCACHE_H
|
||||
#ifndef OAK_RENDERCACHE_H
|
||||
#define OAK_RENDERCACHE_H
|
||||
|
||||
#include "codec/decoder.h"
|
||||
|
||||
@@ -48,4 +48,4 @@ using ShaderCache = RenderCache<QString, QVariant>;
|
||||
|
||||
}
|
||||
|
||||
#endif // RENDERCACHE_H
|
||||
#endif // OAK_RENDERCACHE_H
|
||||
|
||||
+22
-22
@@ -43,12 +43,12 @@ Renderer::~Renderer()
|
||||
}
|
||||
}
|
||||
|
||||
TexturePtr Renderer::CreateTexture(const VideoParams ¶ms, const void *data,
|
||||
TexturePtr Renderer::create_texture(const VideoParams ¶ms, const void *data,
|
||||
int linesize)
|
||||
{
|
||||
QVariant v;
|
||||
|
||||
if (USE_TEXTURE_CACHE) {
|
||||
if (use_texture_cache) {
|
||||
QMutexLocker locker(&texture_cache_lock_);
|
||||
for (auto it = texture_cache_.begin(); it != texture_cache_.end();
|
||||
it++) {
|
||||
@@ -65,25 +65,25 @@ TexturePtr Renderer::CreateTexture(const VideoParams ¶ms, const void *data,
|
||||
}
|
||||
|
||||
if (v.isNull()) {
|
||||
v = CreateNativeTexture(params.effective_width(),
|
||||
v = create_native_texture(params.effective_width(),
|
||||
params.effective_height(),
|
||||
params.effective_depth(), params.format(),
|
||||
params.channel_count(), data, linesize);
|
||||
} else if (data) {
|
||||
UploadToTexture(v, params, data, linesize);
|
||||
upload_to_texture(v, params, data, linesize);
|
||||
} else {
|
||||
this->Flush();
|
||||
this->flush();
|
||||
}
|
||||
|
||||
return CreateTextureFromNativeHandle(v, params);
|
||||
return create_texture_from_native_handle(v, params);
|
||||
}
|
||||
|
||||
void Renderer::DestroyTexture(Texture *texture)
|
||||
void Renderer::destroy_texture(Texture *texture)
|
||||
{
|
||||
if (destroyed_) {
|
||||
return;
|
||||
}
|
||||
if (USE_TEXTURE_CACHE) {
|
||||
if (use_texture_cache) {
|
||||
// HACK: Dirty, dirty hack. OpenGL uses "contexts" to store all of its data, and each context
|
||||
// can only be used by the thread that created it. However there are also "shared contexts"
|
||||
// where assets from one context can be used in another. We use shared contexts so that
|
||||
@@ -109,28 +109,28 @@ void Renderer::DestroyTexture(Texture *texture)
|
||||
texture_cache_lock_.unlock();
|
||||
|
||||
if (QThread::currentThread() == this->thread()) {
|
||||
ClearOldTextures();
|
||||
clear_old_textures();
|
||||
}
|
||||
} else {
|
||||
DestroyNativeTexture(texture->id());
|
||||
destroy_native_texture(texture->id());
|
||||
}
|
||||
}
|
||||
|
||||
QVariant Renderer::GetDefaultShader()
|
||||
QVariant Renderer::get_default_shader()
|
||||
{
|
||||
QMutexLocker locker(&color_cache_mutex_);
|
||||
|
||||
if (default_shader_.isNull()) {
|
||||
default_shader_ = CreateNativeShader(ShaderCode(QString(), QString()));
|
||||
default_shader_ = create_native_shader(ShaderCode(QString(), QString()));
|
||||
}
|
||||
|
||||
return default_shader_;
|
||||
}
|
||||
|
||||
void Renderer::Destroy()
|
||||
void Renderer::destroy()
|
||||
{
|
||||
if (!default_shader_.isNull()) {
|
||||
DestroyNativeShader(default_shader_);
|
||||
destroy_native_shader(default_shader_);
|
||||
default_shader_.clear();
|
||||
}
|
||||
|
||||
@@ -142,19 +142,19 @@ void Renderer::Destroy()
|
||||
// be cleared while the renderer is still alive for those to be honored.
|
||||
for (auto it = color_cache_.begin(); it != color_cache_.end(); it++) {
|
||||
if (!it->compiled_shader.isNull()) {
|
||||
DestroyNativeShader(it->compiled_shader);
|
||||
destroy_native_shader(it->compiled_shader);
|
||||
}
|
||||
}
|
||||
color_cache_.clear();
|
||||
}
|
||||
|
||||
if (!interlace_texture_.isNull()) {
|
||||
DestroyNativeShader(interlace_texture_);
|
||||
destroy_native_shader(interlace_texture_);
|
||||
interlace_texture_.clear();
|
||||
}
|
||||
|
||||
for (auto it = texture_cache_.begin(); it != texture_cache_.end(); it++) {
|
||||
DestroyNativeTexture(it->handle);
|
||||
destroy_native_texture(it->handle);
|
||||
}
|
||||
texture_cache_.clear();
|
||||
|
||||
@@ -163,10 +163,10 @@ void Renderer::Destroy()
|
||||
lifetime_->alive = false;
|
||||
}
|
||||
|
||||
DestroyInternal();
|
||||
destroy_internal();
|
||||
}
|
||||
|
||||
TexturePtr Renderer::CreateTextureFromNativeHandle(const QVariant &v,
|
||||
TexturePtr Renderer::create_texture_from_native_handle(const QVariant &v,
|
||||
const VideoParams ¶ms)
|
||||
{
|
||||
if (v.isNull()) {
|
||||
@@ -176,14 +176,14 @@ TexturePtr Renderer::CreateTextureFromNativeHandle(const QVariant &v,
|
||||
return std::make_shared<Texture>(this, v, params, lifetime_);
|
||||
}
|
||||
|
||||
void Renderer::ClearOldTextures()
|
||||
void Renderer::clear_old_textures()
|
||||
{
|
||||
QMutexLocker locker(&texture_cache_lock_);
|
||||
|
||||
for (auto it = texture_cache_.begin(); it != texture_cache_.end();) {
|
||||
if (it->accessed <
|
||||
QDateTime::currentMSecsSinceEpoch() - MAX_TEXTURE_LIFE) {
|
||||
DestroyNativeTexture(it->handle);
|
||||
QDateTime::currentMSecsSinceEpoch() - max_texture_life) {
|
||||
destroy_native_texture(it->handle);
|
||||
it = texture_cache_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
|
||||
+41
-41
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERCONTEXT_H
|
||||
#define RENDERCONTEXT_H
|
||||
#ifndef OAK_RENDERCONTEXT_H
|
||||
#define OAK_RENDERCONTEXT_H
|
||||
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
@@ -51,81 +51,81 @@ public:
|
||||
Renderer(QObject *parent = nullptr);
|
||||
virtual ~Renderer() override;
|
||||
|
||||
virtual bool Init() = 0;
|
||||
virtual bool init() = 0;
|
||||
|
||||
TexturePtr CreateTexture(const VideoParams ¶ms,
|
||||
TexturePtr create_texture(const VideoParams ¶ms,
|
||||
const void *data = nullptr, int linesize = 0);
|
||||
|
||||
void DestroyTexture(Texture *texture);
|
||||
void destroy_texture(Texture *texture);
|
||||
|
||||
virtual void BlitToTexture(QVariant shader, olive::AcceleratedJob &job,
|
||||
virtual void blit_to_texture(QVariant shader, olive::AcceleratedJob &job,
|
||||
olive::Texture *destination,
|
||||
bool clear_destination = true)
|
||||
{
|
||||
Blit(shader, job, destination, destination->params(),
|
||||
blit(shader, job, destination, destination->params(),
|
||||
clear_destination);
|
||||
}
|
||||
|
||||
void Blit(QVariant shader, olive::AcceleratedJob &job,
|
||||
void blit(QVariant shader, olive::AcceleratedJob &job,
|
||||
olive::VideoParams params, bool clear_destination = true)
|
||||
{
|
||||
Blit(shader, job, nullptr, params, clear_destination);
|
||||
blit(shader, job, nullptr, params, clear_destination);
|
||||
}
|
||||
|
||||
void BlitColorManaged(const ColorTransformJob &color_job,
|
||||
void blit_color_managed(const ColorTransformJob &color_job,
|
||||
Texture *destination, const VideoParams ¶ms);
|
||||
void BlitColorManaged(const ColorTransformJob &job, Texture *destination)
|
||||
void blit_color_managed(const ColorTransformJob &job, Texture *destination)
|
||||
{
|
||||
BlitColorManaged(job, destination, destination->params());
|
||||
blit_color_managed(job, destination, destination->params());
|
||||
}
|
||||
void BlitColorManaged(const ColorTransformJob &job,
|
||||
void blit_color_managed(const ColorTransformJob &job,
|
||||
const VideoParams ¶ms)
|
||||
{
|
||||
BlitColorManaged(job, nullptr, params);
|
||||
blit_color_managed(job, nullptr, params);
|
||||
}
|
||||
|
||||
TexturePtr InterlaceTexture(TexturePtr top, TexturePtr bottom,
|
||||
TexturePtr interlace_texture(TexturePtr top, TexturePtr bottom,
|
||||
const VideoParams ¶ms);
|
||||
|
||||
QVariant GetDefaultShader();
|
||||
QVariant get_default_shader();
|
||||
|
||||
void Destroy();
|
||||
void destroy();
|
||||
|
||||
virtual void PostDestroy() = 0;
|
||||
virtual void post_destroy() = 0;
|
||||
|
||||
virtual void PostInit() = 0;
|
||||
virtual void post_init() = 0;
|
||||
|
||||
virtual void ClearDestination(olive::Texture *texture = nullptr,
|
||||
virtual void clear_destination(olive::Texture *texture = nullptr,
|
||||
double r = 0.0, double g = 0.0,
|
||||
double b = 0.0, double a = 1.0) = 0;
|
||||
|
||||
virtual QVariant CreateNativeShader(olive::ShaderCode code) = 0;
|
||||
virtual QVariant create_native_shader(olive::ShaderCode code) = 0;
|
||||
|
||||
virtual void DestroyNativeShader(QVariant shader) = 0;
|
||||
virtual void destroy_native_shader(QVariant shader) = 0;
|
||||
|
||||
virtual void UploadToTexture(const QVariant &handle,
|
||||
virtual void upload_to_texture(const QVariant &handle,
|
||||
const VideoParams ¶ms, const void *data,
|
||||
int linesize) = 0;
|
||||
|
||||
virtual void DownloadFromTexture(const QVariant &handle,
|
||||
virtual void download_from_texture(const QVariant &handle,
|
||||
const VideoParams ¶ms, void *data,
|
||||
int linesize) = 0;
|
||||
|
||||
virtual void Flush() = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
virtual Color GetPixelFromTexture(olive::Texture *texture,
|
||||
virtual Color get_pixel_from_texture(olive::Texture *texture,
|
||||
const QPointF &pt) = 0;
|
||||
std::shared_ptr<RendererLifetime> GetLifetime() const
|
||||
std::shared_ptr<RendererLifetime> get_lifetime() const
|
||||
{
|
||||
return lifetime_;
|
||||
}
|
||||
|
||||
virtual bool IsOpenGL() const
|
||||
virtual bool is_open_gl() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool IsVulkan() const
|
||||
virtual bool is_vulkan() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -137,7 +137,7 @@ public:
|
||||
* Default implementation is a no-op. OpenGL-based renderers override this
|
||||
* to bind the texture as a framebuffer render target.
|
||||
*/
|
||||
virtual void AttachOutputTexture(olive::Texture *texture)
|
||||
virtual void attach_output_texture(olive::Texture *texture)
|
||||
{
|
||||
(void)texture;
|
||||
}
|
||||
@@ -147,23 +147,23 @@ public:
|
||||
*
|
||||
* Default implementation is a no-op.
|
||||
*/
|
||||
virtual void DetachOutputTexture()
|
||||
virtual void detach_output_texture()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void Blit(QVariant shader, olive::AcceleratedJob &job,
|
||||
virtual void blit(QVariant shader, olive::AcceleratedJob &job,
|
||||
olive::Texture *destination,
|
||||
olive::VideoParams destination_params,
|
||||
bool clear_destination) = 0;
|
||||
virtual QVariant CreateNativeTexture(int width, int height, int depth,
|
||||
virtual QVariant create_native_texture(int width, int height, int depth,
|
||||
PixelFormat format, int channel_count,
|
||||
const void *data = nullptr,
|
||||
int linesize = 0) = 0;
|
||||
|
||||
virtual void DestroyNativeTexture(QVariant texture) = 0;
|
||||
virtual void destroy_native_texture(QVariant texture) = 0;
|
||||
|
||||
virtual void DestroyInternal() = 0;
|
||||
virtual void destroy_internal() = 0;
|
||||
|
||||
private:
|
||||
std::atomic<bool> destroyed_{ false };
|
||||
@@ -180,12 +180,12 @@ private:
|
||||
QVector<LUT> lut1d_textures;
|
||||
};
|
||||
|
||||
TexturePtr CreateTextureFromNativeHandle(const QVariant &v,
|
||||
TexturePtr create_texture_from_native_handle(const QVariant &v,
|
||||
const VideoParams ¶ms);
|
||||
|
||||
bool GetColorContext(const ColorTransformJob &color_job, ColorContext *ctx);
|
||||
bool get_color_context(const ColorTransformJob &color_job, ColorContext *ctx);
|
||||
|
||||
void ClearOldTextures();
|
||||
void clear_old_textures();
|
||||
|
||||
QHash<QString, ColorContext> color_cache_;
|
||||
|
||||
@@ -199,8 +199,8 @@ private:
|
||||
qint64 accessed;
|
||||
};
|
||||
|
||||
static const int MAX_TEXTURE_LIFE = 5000;
|
||||
static const bool USE_TEXTURE_CACHE = true;
|
||||
static const int max_texture_life = 5000;
|
||||
static const bool use_texture_cache = true;
|
||||
std::list<CachedTexture> texture_cache_;
|
||||
|
||||
QMutex color_cache_mutex_;
|
||||
@@ -214,4 +214,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // RENDERCONTEXT_H
|
||||
#endif // OAK_RENDERCONTEXT_H
|
||||
|
||||
@@ -46,11 +46,11 @@ void RenderJobTracker::clear()
|
||||
jobs_.clear();
|
||||
}
|
||||
|
||||
bool RenderJobTracker::isCurrent(const rational &time, JobTime job_time) const
|
||||
bool RenderJobTracker::isCurrent(const Rational &time, JobTime job_time) const
|
||||
{
|
||||
for (auto it = jobs_.crbegin(); it != jobs_.crend(); it++) {
|
||||
if (it->Contains(time)) {
|
||||
return job_time >= it->GetJobTime();
|
||||
if (it->contains(time)) {
|
||||
return job_time >= it->get_job_time();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,8 +64,8 @@ RenderJobTracker::getCurrentSubRanges(const TimeRange &range,
|
||||
TimeRangeList current_ranges;
|
||||
|
||||
for (auto it = jobs_.crbegin(); it != jobs_.crend(); it++) {
|
||||
if (job_time >= it->GetJobTime() && it->OverlapsWith(range)) {
|
||||
current_ranges.insert(it->Intersected(range));
|
||||
if (job_time >= it->get_job_time() && it->overlaps_with(range)) {
|
||||
current_ranges.insert(it->intersected(range));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERJOBTRACKER_H
|
||||
#define RENDERJOBTRACKER_H
|
||||
#ifndef OAK_RENDERJOBTRACKER_H
|
||||
#define OAK_RENDERJOBTRACKER_H
|
||||
|
||||
#include <olive/core/core.h>
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
|
||||
void clear();
|
||||
|
||||
bool isCurrent(const rational &time, JobTime job_time) const;
|
||||
bool isCurrent(const Rational &time, JobTime job_time) const;
|
||||
|
||||
TimeRangeList getCurrentSubRanges(const TimeRange &range,
|
||||
const JobTime &job_time) const;
|
||||
@@ -55,11 +55,11 @@ private:
|
||||
job_time_ = job_time;
|
||||
}
|
||||
|
||||
JobTime GetJobTime() const
|
||||
JobTime get_job_time() const
|
||||
{
|
||||
return job_time_;
|
||||
}
|
||||
void SetJobTime(JobTime jt)
|
||||
void set_job_time(JobTime jt)
|
||||
{
|
||||
job_time_ = jt;
|
||||
}
|
||||
@@ -73,4 +73,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // RENDERJOBTRACKER_H
|
||||
#endif // OAK_RENDERJOBTRACKER_H
|
||||
|
||||
@@ -41,36 +41,36 @@ namespace olive
|
||||
{
|
||||
|
||||
RenderManager *RenderManager::instance_ = nullptr;
|
||||
const rational RenderManager::kDryRunInterval = rational(10);
|
||||
const Rational RenderManager::k_dry_run_interval = Rational(10);
|
||||
|
||||
RenderManager::Backend RenderManager::BackendFromString(const QString &backend)
|
||||
RenderManager::Backend RenderManager::backend_from_string(const QString &backend)
|
||||
{
|
||||
const QString lower = backend.toLower();
|
||||
if (lower == QStringLiteral("vulkan")) {
|
||||
return kVulkan;
|
||||
return k_vulkan;
|
||||
}
|
||||
|
||||
if (lower == QStringLiteral("multiprocess")) {
|
||||
return kMultiProcess;
|
||||
return k_multi_process;
|
||||
}
|
||||
|
||||
if (lower == QStringLiteral("dummy")) {
|
||||
return kDummy;
|
||||
return k_dummy;
|
||||
}
|
||||
|
||||
return kOpenGL;
|
||||
return k_open_gl;
|
||||
}
|
||||
|
||||
QString RenderManager::BackendToString(Backend backend)
|
||||
QString RenderManager::backend_to_string(Backend backend)
|
||||
{
|
||||
switch (backend) {
|
||||
case kOpenGL:
|
||||
case k_open_gl:
|
||||
return QStringLiteral("opengl");
|
||||
case kVulkan:
|
||||
case k_vulkan:
|
||||
return QStringLiteral("vulkan");
|
||||
case kMultiProcess:
|
||||
case k_multi_process:
|
||||
return QStringLiteral("multiprocess");
|
||||
case kDummy:
|
||||
case k_dummy:
|
||||
return QStringLiteral("dummy");
|
||||
}
|
||||
|
||||
@@ -78,12 +78,12 @@ QString RenderManager::BackendToString(Backend backend)
|
||||
}
|
||||
|
||||
RenderManager::RenderManager(QObject *parent)
|
||||
: backend_(BackendFromString(OLIVE_CONFIG("GraphicsBackend").toString()))
|
||||
: backend_(backend_from_string(OAK_CONFIG("GraphicsBackend").toString()))
|
||||
, requested_backend_(backend_)
|
||||
, aggressive_gc_(0)
|
||||
, worker_pool_(nullptr)
|
||||
{
|
||||
if (backend_ == kVulkan) {
|
||||
if (backend_ == k_vulkan) {
|
||||
#ifndef OAK_ENABLE_DYNAMIC_RENDER_BACKEND
|
||||
qWarning()
|
||||
<< "Vulkan backend requested but dynamic render backend is not enabled. Falling back to OpenGL.";
|
||||
@@ -91,27 +91,27 @@ RenderManager::RenderManager(QObject *parent)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (backend_ == kOpenGL || backend_ == kVulkan) {
|
||||
if (backend_ == k_open_gl || backend_ == k_vulkan) {
|
||||
#ifdef OAK_ENABLE_DYNAMIC_RENDER_BACKEND
|
||||
auto *dynamic_renderer =
|
||||
new DynamicRenderer(BackendToString(requested_backend_));
|
||||
if (!dynamic_renderer->Load()) {
|
||||
new DynamicRenderer(backend_to_string(requested_backend_));
|
||||
if (!dynamic_renderer->load()) {
|
||||
qWarning() << "Failed to load dynamic render backend"
|
||||
<< BackendToString(requested_backend_)
|
||||
<< backend_to_string(requested_backend_)
|
||||
<< ", falling back to OpenGL";
|
||||
delete dynamic_renderer;
|
||||
backend_ = kOpenGL;
|
||||
backend_ = k_open_gl;
|
||||
context_ = new OpenGLRenderer();
|
||||
} else {
|
||||
context_ = dynamic_renderer;
|
||||
// DynamicRenderer may internally fall back (e.g. Vulkan -> OpenGL).
|
||||
// Synchronize RenderManager's view of the actual runtime backend.
|
||||
Backend actual_backend =
|
||||
BackendFromString(dynamic_renderer->backend_name());
|
||||
backend_from_string(dynamic_renderer->backend_name());
|
||||
if (actual_backend != backend_) {
|
||||
qWarning() << "Dynamic render backend fell back from"
|
||||
<< BackendToString(backend_) << "to"
|
||||
<< BackendToString(actual_backend);
|
||||
<< backend_to_string(backend_) << "to"
|
||||
<< backend_to_string(actual_backend);
|
||||
backend_ = actual_backend;
|
||||
}
|
||||
}
|
||||
@@ -127,26 +127,26 @@ RenderManager::RenderManager(QObject *parent)
|
||||
}
|
||||
|
||||
if (context_) {
|
||||
dry_run_thread_ = CreateThread();
|
||||
audio_thread_ = CreateThread();
|
||||
dry_run_thread_ = create_thread();
|
||||
audio_thread_ = create_thread();
|
||||
|
||||
waveform_threads_.resize(QThread::idealThreadCount());
|
||||
for (size_t i = 0; i < waveform_threads_.size(); i++) {
|
||||
waveform_threads_[i] = CreateThread();
|
||||
waveform_threads_[i] = create_thread();
|
||||
}
|
||||
|
||||
auto_cacher_ = new PreviewAutoCacher(this);
|
||||
|
||||
worker_pool_ = new RenderWorkerPool(
|
||||
decoder_cache_, BackendToString(requested_backend_), this);
|
||||
decoder_cache_, backend_to_string(requested_backend_), this);
|
||||
worker_pool_->start(QThread::NormalPriority);
|
||||
backend_ = kMultiProcess;
|
||||
backend_ = k_multi_process;
|
||||
}
|
||||
|
||||
decoder_clear_timer_ = new QTimer(this);
|
||||
decoder_clear_timer_->setInterval(kDecoderMaximumInactivity);
|
||||
decoder_clear_timer_->setInterval(k_decoder_maximum_inactivity);
|
||||
connect(decoder_clear_timer_, &QTimer::timeout, this,
|
||||
&RenderManager::ClearOldDecoders);
|
||||
&RenderManager::clear_old_decoders);
|
||||
decoder_clear_timer_->start();
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ RenderManager::~RenderManager()
|
||||
{
|
||||
if (context_) {
|
||||
if (worker_pool_) {
|
||||
worker_pool_->Shutdown();
|
||||
worker_pool_->shutdown();
|
||||
delete worker_pool_;
|
||||
worker_pool_ = nullptr;
|
||||
}
|
||||
@@ -167,12 +167,12 @@ RenderManager::~RenderManager()
|
||||
rt->wait();
|
||||
}
|
||||
|
||||
context_->PostDestroy();
|
||||
context_->post_destroy();
|
||||
delete context_;
|
||||
}
|
||||
}
|
||||
|
||||
RenderThread *RenderManager::CreateThread(Renderer *renderer)
|
||||
RenderThread *RenderManager::create_thread(Renderer *renderer)
|
||||
{
|
||||
auto t = new RenderThread(renderer, decoder_cache_, shader_cache_, this);
|
||||
render_threads_.push_back(t);
|
||||
@@ -180,12 +180,12 @@ RenderThread *RenderManager::CreateThread(Renderer *renderer)
|
||||
return t;
|
||||
}
|
||||
|
||||
RenderTicketPtr RenderManager::RenderFrame(const RenderVideoParams ¶ms)
|
||||
RenderTicketPtr RenderManager::render_frame(const RenderVideoParams ¶ms)
|
||||
{
|
||||
// Create ticket
|
||||
RenderTicketPtr ticket = std::make_shared<RenderTicket>();
|
||||
|
||||
ticket->setProperty("node", QtUtils::PtrToValue(params.node));
|
||||
ticket->setProperty("node", QtUtils::ptr_to_value(params.node));
|
||||
ticket->setProperty("time", QVariant::fromValue(params.time));
|
||||
ticket->setProperty("size", params.force_size);
|
||||
ticket->setProperty("matrix", params.force_matrix);
|
||||
@@ -194,9 +194,9 @@ RenderTicketPtr RenderManager::RenderFrame(const RenderVideoParams ¶ms)
|
||||
ticket->setProperty("usecache", params.use_cache);
|
||||
ticket->setProperty("channelcount", params.force_channel_count);
|
||||
ticket->setProperty("mode", params.mode);
|
||||
ticket->setProperty("type", kTypeVideo);
|
||||
ticket->setProperty("type", k_type_video);
|
||||
ticket->setProperty("colormanager",
|
||||
QtUtils::PtrToValue(params.color_manager));
|
||||
QtUtils::ptr_to_value(params.color_manager));
|
||||
ticket->setProperty("coloroutput",
|
||||
QVariant::fromValue(params.force_color_output));
|
||||
ticket->setProperty("colortransform",
|
||||
@@ -209,44 +209,44 @@ RenderTicketPtr RenderManager::RenderFrame(const RenderVideoParams ¶ms)
|
||||
ticket->setProperty("cachetimebase",
|
||||
QVariant::fromValue(params.cache_timebase));
|
||||
ticket->setProperty("cacheid", QVariant::fromValue(params.cache_id));
|
||||
ticket->setProperty("multicam", QtUtils::PtrToValue(params.multicam));
|
||||
ticket->setProperty("multicam", QtUtils::ptr_to_value(params.multicam));
|
||||
|
||||
// Video frames are always rendered by the worker pool. GPU textures cannot
|
||||
// be shared across the process boundary (or across independent Vulkan
|
||||
// instances), so texture-return requests are downgraded to CPU frames.
|
||||
RenderVideoParams worker_params = params;
|
||||
if (worker_params.return_type == ReturnType::kTexture) {
|
||||
worker_params.return_type = ReturnType::kFrame;
|
||||
if (worker_params.return_type == ReturnType::k_texture) {
|
||||
worker_params.return_type = ReturnType::k_frame;
|
||||
}
|
||||
|
||||
if (worker_params.return_type == ReturnType::kNull) {
|
||||
if (worker_params.return_type == ReturnType::k_null) {
|
||||
if (dry_run_thread_) {
|
||||
dry_run_thread_->AddTicket(ticket);
|
||||
dry_run_thread_->add_ticket(ticket);
|
||||
} else {
|
||||
// No render threads (e.g. dummy backend), finish without a result
|
||||
ticket->Finish();
|
||||
ticket->finish();
|
||||
}
|
||||
} else if (worker_pool_ &&
|
||||
worker_pool_->SubmitFrame(ticket, worker_params)) {
|
||||
worker_pool_->submit_frame(ticket, worker_params)) {
|
||||
return ticket;
|
||||
} else {
|
||||
qWarning()
|
||||
<< "RenderManager: worker pool unavailable, finishing ticket "
|
||||
"without result";
|
||||
ticket->Finish();
|
||||
ticket->finish();
|
||||
}
|
||||
|
||||
return ticket;
|
||||
}
|
||||
|
||||
RenderTicketPtr RenderManager::RenderAudio(const RenderAudioParams ¶ms)
|
||||
RenderTicketPtr RenderManager::render_audio(const RenderAudioParams ¶ms)
|
||||
{
|
||||
// Create ticket
|
||||
RenderTicketPtr ticket = std::make_shared<RenderTicket>();
|
||||
|
||||
ticket->setProperty("node", QtUtils::PtrToValue(params.node));
|
||||
ticket->setProperty("node", QtUtils::ptr_to_value(params.node));
|
||||
ticket->setProperty("time", QVariant::fromValue(params.range));
|
||||
ticket->setProperty("type", kTypeAudio);
|
||||
ticket->setProperty("type", k_type_audio);
|
||||
ticket->setProperty("enablewaveforms", params.generate_waveforms);
|
||||
ticket->setProperty("clamp", params.clamp);
|
||||
ticket->setProperty("aparam", QVariant::fromValue(params.audio_params));
|
||||
@@ -255,26 +255,26 @@ RenderTicketPtr RenderManager::RenderAudio(const RenderAudioParams ¶ms)
|
||||
if (params.generate_waveforms && !waveform_threads_.empty()) {
|
||||
size_t thread_index = last_waveform_thread_ % waveform_threads_.size();
|
||||
RenderThread *thread = waveform_threads_[thread_index];
|
||||
thread->AddTicket(ticket);
|
||||
thread->add_ticket(ticket);
|
||||
last_waveform_thread_++;
|
||||
} else if (audio_thread_) {
|
||||
audio_thread_->AddTicket(ticket);
|
||||
audio_thread_->add_ticket(ticket);
|
||||
} else {
|
||||
// No render threads (e.g. dummy backend), finish without a result
|
||||
ticket->Finish();
|
||||
ticket->finish();
|
||||
}
|
||||
|
||||
return ticket;
|
||||
}
|
||||
|
||||
bool RenderManager::RemoveTicket(RenderTicketPtr ticket)
|
||||
bool RenderManager::remove_ticket(RenderTicketPtr ticket)
|
||||
{
|
||||
if (worker_pool_ && worker_pool_->RemoveTicket(ticket)) {
|
||||
if (worker_pool_ && worker_pool_->remove_ticket(ticket)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (RenderThread *rt : render_threads_) {
|
||||
if (rt->RemoveTicket(ticket)) {
|
||||
if (rt->remove_ticket(ticket)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -282,7 +282,7 @@ bool RenderManager::RemoveTicket(RenderTicketPtr ticket)
|
||||
return false;
|
||||
}
|
||||
|
||||
void RenderManager::SetAggressiveGarbageCollection(bool enabled)
|
||||
void RenderManager::set_aggressive_garbage_collection(bool enabled)
|
||||
{
|
||||
aggressive_gc_ += enabled ? 1 : -1;
|
||||
|
||||
@@ -292,13 +292,13 @@ void RenderManager::SetAggressiveGarbageCollection(bool enabled)
|
||||
}
|
||||
|
||||
if (aggressive_gc_ > 0) {
|
||||
decoder_clear_timer_->setInterval(kDecoderMaximumInactivityAggressive);
|
||||
decoder_clear_timer_->setInterval(k_decoder_maximum_inactivity_aggressive);
|
||||
} else {
|
||||
decoder_clear_timer_->setInterval(kDecoderMaximumInactivity);
|
||||
decoder_clear_timer_->setInterval(k_decoder_maximum_inactivity);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderManager::ClearOldDecoders()
|
||||
void RenderManager::clear_old_decoders()
|
||||
{
|
||||
if (!decoder_cache_) {
|
||||
// No decoder cache exists on backends without a renderer (e.g. dummy)
|
||||
@@ -308,13 +308,13 @@ void RenderManager::ClearOldDecoders()
|
||||
QMutexLocker locker(decoder_cache_->mutex());
|
||||
|
||||
qint64 min_age =
|
||||
QDateTime::currentMSecsSinceEpoch() - kDecoderMaximumInactivity;
|
||||
QDateTime::currentMSecsSinceEpoch() - k_decoder_maximum_inactivity;
|
||||
|
||||
for (auto it = decoder_cache_->begin(); it != decoder_cache_->end();) {
|
||||
DecoderPair decoder = it.value();
|
||||
|
||||
if (decoder.decoder->GetLastAccessedTime() < min_age) {
|
||||
decoder.decoder->Close();
|
||||
if (decoder.decoder->get_last_accessed_time() < min_age) {
|
||||
decoder.decoder->close();
|
||||
it = decoder_cache_->erase(it);
|
||||
} else {
|
||||
it++;
|
||||
@@ -331,12 +331,12 @@ RenderThread::RenderThread(Renderer *renderer, DecoderCache *decoder_cache,
|
||||
, shader_cache_(shader_cache)
|
||||
{
|
||||
if (context_) {
|
||||
context_->Init();
|
||||
context_->init();
|
||||
context_->moveToThread(this);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderThread::AddTicket(RenderTicketPtr ticket)
|
||||
void RenderThread::add_ticket(RenderTicketPtr ticket)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
ticket->moveToThread(this);
|
||||
@@ -344,7 +344,7 @@ void RenderThread::AddTicket(RenderTicketPtr ticket)
|
||||
wait_.wakeOne();
|
||||
}
|
||||
|
||||
bool RenderThread::RemoveTicket(RenderTicketPtr ticket)
|
||||
bool RenderThread::remove_ticket(RenderTicketPtr ticket)
|
||||
{
|
||||
QMutexLocker locker(&mutex_);
|
||||
|
||||
@@ -367,7 +367,7 @@ void RenderThread::quit()
|
||||
void RenderThread::run()
|
||||
{
|
||||
if (context_) {
|
||||
context_->PostInit();
|
||||
context_->post_init();
|
||||
}
|
||||
|
||||
QMutexLocker locker(&mutex_);
|
||||
@@ -388,12 +388,12 @@ void RenderThread::run()
|
||||
locker.unlock();
|
||||
|
||||
// Setup the ticket for ::Process
|
||||
ticket->Start();
|
||||
ticket->start();
|
||||
|
||||
if (ticket->IsCancelled()) {
|
||||
ticket->Finish();
|
||||
if (ticket->is_cancelled()) {
|
||||
ticket->finish();
|
||||
} else {
|
||||
RenderProcessor::Process(ticket, context_, decoder_cache_,
|
||||
RenderProcessor::process(ticket, context_, decoder_cache_,
|
||||
shader_cache_);
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ void RenderThread::run()
|
||||
}
|
||||
|
||||
if (context_) {
|
||||
context_->Destroy();
|
||||
context_->destroy();
|
||||
context_->moveToThread(this->thread());
|
||||
}
|
||||
}
|
||||
|
||||
+36
-36
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERBACKEND_H
|
||||
#define RENDERBACKEND_H
|
||||
#ifndef OAK_RENDERBACKEND_H
|
||||
#define OAK_RENDERBACKEND_H
|
||||
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
@@ -45,9 +45,9 @@ public:
|
||||
RenderThread(Renderer *renderer, DecoderCache *decoder_cache,
|
||||
ShaderCache *shader_cache, QObject *parent = nullptr);
|
||||
|
||||
void AddTicket(RenderTicketPtr ticket);
|
||||
void add_ticket(RenderTicketPtr ticket);
|
||||
|
||||
bool RemoveTicket(RenderTicketPtr ticket);
|
||||
bool remove_ticket(RenderTicketPtr ticket);
|
||||
|
||||
void quit();
|
||||
|
||||
@@ -77,24 +77,24 @@ class RenderManager : public QObject {
|
||||
public:
|
||||
enum Backend {
|
||||
/// Graphics acceleration provided by OpenGL
|
||||
kOpenGL,
|
||||
k_open_gl,
|
||||
|
||||
/// Vulkan requested by the user. Falls back to OpenGL until VulkanRenderer is implemented.
|
||||
kVulkan,
|
||||
k_vulkan,
|
||||
|
||||
/// Video frames are rendered by an external oak-render-worker process.
|
||||
kMultiProcess,
|
||||
k_multi_process,
|
||||
|
||||
/// No graphics rendering - used to test core threading logic
|
||||
kDummy
|
||||
k_dummy
|
||||
};
|
||||
|
||||
static void CreateInstance()
|
||||
static void create_instance()
|
||||
{
|
||||
instance_ = new RenderManager();
|
||||
}
|
||||
|
||||
static void DestroyInstance()
|
||||
static void destroy_instance()
|
||||
{
|
||||
delete instance_;
|
||||
instance_ = nullptr;
|
||||
@@ -105,11 +105,11 @@ public:
|
||||
return instance_;
|
||||
}
|
||||
|
||||
enum ReturnType { kTexture, kFrame, kNull };
|
||||
enum ReturnType { k_texture, k_frame, k_null };
|
||||
|
||||
struct RenderVideoParams {
|
||||
RenderVideoParams(Node *n, const VideoParams &vparam,
|
||||
const AudioParams &aparam, const rational &t,
|
||||
const AudioParams &aparam, const Rational &t,
|
||||
ColorManager *colorman, RenderMode::Mode m)
|
||||
{
|
||||
node = n;
|
||||
@@ -118,8 +118,8 @@ public:
|
||||
time = t;
|
||||
color_manager = colorman;
|
||||
use_cache = false;
|
||||
return_type = kFrame;
|
||||
force_format = PixelFormat::INVALID;
|
||||
return_type = k_frame;
|
||||
force_format = PixelFormat::invalid;
|
||||
force_color_output = nullptr;
|
||||
force_color_transform = ColorTransform();
|
||||
force_size = QSize(0, 0);
|
||||
@@ -128,17 +128,17 @@ public:
|
||||
multicam = nullptr;
|
||||
}
|
||||
|
||||
void AddCache(FrameHashCache *cache)
|
||||
void add_cache(FrameHashCache *cache)
|
||||
{
|
||||
cache_dir = cache->GetCacheDirectory();
|
||||
cache_timebase = cache->GetTimebase();
|
||||
cache_id = cache->GetUuid().toString();
|
||||
cache_dir = cache->get_cache_directory();
|
||||
cache_timebase = cache->get_timebase();
|
||||
cache_id = cache->get_uuid().toString();
|
||||
}
|
||||
|
||||
Node *node;
|
||||
VideoParams video_params;
|
||||
AudioParams audio_params;
|
||||
rational time;
|
||||
Rational time;
|
||||
ColorManager *color_manager;
|
||||
bool use_cache;
|
||||
ReturnType return_type;
|
||||
@@ -146,7 +146,7 @@ public:
|
||||
MultiCamNode *multicam;
|
||||
|
||||
QString cache_dir;
|
||||
rational cache_timebase;
|
||||
Rational cache_timebase;
|
||||
QString cache_id;
|
||||
|
||||
QSize force_size;
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
ColorTransform force_color_transform;
|
||||
};
|
||||
|
||||
static const rational kDryRunInterval;
|
||||
static const Rational k_dry_run_interval;
|
||||
|
||||
/**
|
||||
* @brief Asynchronously generate a frame at a given time
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
*
|
||||
* This function is thread-safe.
|
||||
*/
|
||||
RenderTicketPtr RenderFrame(const RenderVideoParams ¶ms);
|
||||
RenderTicketPtr render_frame(const RenderVideoParams ¶ms);
|
||||
|
||||
struct RenderAudioParams {
|
||||
RenderAudioParams(Node *n, const TimeRange &time,
|
||||
@@ -196,11 +196,11 @@ public:
|
||||
*
|
||||
* This function is thread-safe.
|
||||
*/
|
||||
RenderTicketPtr RenderAudio(const RenderAudioParams ¶ms);
|
||||
RenderTicketPtr render_audio(const RenderAudioParams ¶ms);
|
||||
|
||||
bool RemoveTicket(RenderTicketPtr ticket);
|
||||
bool remove_ticket(RenderTicketPtr ticket);
|
||||
|
||||
enum TicketType { kTypeVideo, kTypeAudio };
|
||||
enum TicketType { k_type_video, k_type_audio };
|
||||
|
||||
Backend backend() const
|
||||
{
|
||||
@@ -212,21 +212,21 @@ public:
|
||||
return requested_backend_;
|
||||
}
|
||||
|
||||
static Backend BackendFromString(const QString &backend);
|
||||
static QString BackendToString(Backend backend);
|
||||
static Backend backend_from_string(const QString &backend);
|
||||
static QString backend_to_string(Backend backend);
|
||||
|
||||
PreviewAutoCacher *GetCacher() const
|
||||
PreviewAutoCacher *get_cacher() const
|
||||
{
|
||||
return auto_cacher_;
|
||||
}
|
||||
|
||||
void SetProject(Project *p)
|
||||
void set_project(Project *p)
|
||||
{
|
||||
auto_cacher_->SetProject(p);
|
||||
auto_cacher_->set_project(p);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetAggressiveGarbageCollection(bool enabled);
|
||||
void set_aggressive_garbage_collection(bool enabled);
|
||||
|
||||
signals:
|
||||
|
||||
@@ -235,7 +235,7 @@ private:
|
||||
|
||||
virtual ~RenderManager() override;
|
||||
|
||||
RenderThread *CreateThread(Renderer *renderer = nullptr);
|
||||
RenderThread *create_thread(Renderer *renderer = nullptr);
|
||||
|
||||
static RenderManager *instance_;
|
||||
|
||||
@@ -248,8 +248,8 @@ private:
|
||||
|
||||
ShaderCache *shader_cache_ = nullptr;
|
||||
|
||||
static constexpr auto kDecoderMaximumInactivityAggressive = 1000;
|
||||
static constexpr auto kDecoderMaximumInactivity = 5000;
|
||||
static constexpr auto k_decoder_maximum_inactivity_aggressive = 1000;
|
||||
static constexpr auto k_decoder_maximum_inactivity = 5000;
|
||||
|
||||
int aggressive_gc_ = 0;
|
||||
|
||||
@@ -268,11 +268,11 @@ private:
|
||||
RenderWorkerPool *worker_pool_ = nullptr;
|
||||
|
||||
private slots:
|
||||
void ClearOldDecoders();
|
||||
void clear_old_decoders();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(olive::RenderManager::TicketType)
|
||||
|
||||
#endif // RENDERBACKEND_H
|
||||
#endif // OAK_RENDERBACKEND_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERMODE_H
|
||||
#define RENDERMODE_H
|
||||
#ifndef OAK_RENDERMODE_H
|
||||
#define OAK_RENDERMODE_H
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
@@ -37,16 +37,16 @@ public:
|
||||
* This render is for realtime preview ONLY and does not need to be "perfect". Nodes can use lower-accuracy functions
|
||||
* to save performance when possible.
|
||||
*/
|
||||
kOffline,
|
||||
k_offline,
|
||||
|
||||
/**
|
||||
* This render is some sort of export or master copy and Nodes should take time/bandwidth/system resources to produce
|
||||
* a higher accuracy version.
|
||||
*/
|
||||
kOnline
|
||||
k_online
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // RENDERMODE_H
|
||||
#endif // OAK_RENDERMODE_H
|
||||
|
||||
+190
-190
@@ -34,8 +34,8 @@
|
||||
#include "node/project.h"
|
||||
#include "rendermanager.h"
|
||||
#include "render/plugin/pluginrenderer.h"
|
||||
#include "pluginSupport/OliveClip.h"
|
||||
#include "pluginSupport/OliveHost.h"
|
||||
#include "pluginSupport/oliveclip.h"
|
||||
#include "pluginSupport/olivehost.h"
|
||||
#include "render/ipc/frameslotpool.h"
|
||||
|
||||
namespace olive
|
||||
@@ -53,28 +53,28 @@ RenderProcessor::RenderProcessor(RenderTicketPtr ticket, Renderer *render_ctx,
|
||||
{
|
||||
}
|
||||
|
||||
TexturePtr RenderProcessor::GenerateTexture(const rational &time,
|
||||
const rational &frame_length)
|
||||
TexturePtr RenderProcessor::generate_texture(const Rational &time,
|
||||
const Rational &frame_length)
|
||||
{
|
||||
TimeRange range = TimeRange(time, time + frame_length);
|
||||
|
||||
NodeValueTable table;
|
||||
if (Node *node = QtUtils::ValueToPtr<Node>(ticket_->property("node"))) {
|
||||
table = GenerateTable(node, range);
|
||||
if (Node *node = QtUtils::value_to_ptr<Node>(ticket_->property("node"))) {
|
||||
table = generate_table(node, range);
|
||||
}
|
||||
|
||||
NodeValue tex_val = table.Get(NodeValue::kTexture);
|
||||
NodeValue tex_val = table.get(NodeValue::k_texture);
|
||||
|
||||
ResolveJobs(tex_val);
|
||||
resolve_jobs(tex_val);
|
||||
|
||||
return tex_val.toTexture();
|
||||
return tex_val.to_texture();
|
||||
}
|
||||
|
||||
FramePtr RenderProcessor::GenerateFrame(TexturePtr texture,
|
||||
const rational &time)
|
||||
FramePtr RenderProcessor::generate_frame(TexturePtr texture,
|
||||
const Rational &time)
|
||||
{
|
||||
// Set up output frame parameters
|
||||
VideoParams frame_params = GetCacheVideoParams();
|
||||
VideoParams frame_params = get_cache_video_params();
|
||||
|
||||
QSize frame_size = ticket_->property("size").value<QSize>();
|
||||
if (!frame_size.isNull()) {
|
||||
@@ -84,7 +84,7 @@ FramePtr RenderProcessor::GenerateFrame(TexturePtr texture,
|
||||
|
||||
PixelFormat frame_format =
|
||||
static_cast<PixelFormat::Format>(ticket_->property("format").toInt());
|
||||
if (frame_format != PixelFormat::INVALID) {
|
||||
if (frame_format != PixelFormat::invalid) {
|
||||
frame_params.set_format(frame_format);
|
||||
}
|
||||
|
||||
@@ -94,10 +94,10 @@ FramePtr RenderProcessor::GenerateFrame(TexturePtr texture,
|
||||
} else {
|
||||
frame_params.set_channel_count(texture ?
|
||||
texture->channel_count() :
|
||||
VideoParams::kRGBAChannelCount);
|
||||
VideoParams::k_rgba_channel_count);
|
||||
}
|
||||
|
||||
FramePtr frame = Frame::Create();
|
||||
FramePtr frame = Frame::create();
|
||||
frame->set_timestamp(time);
|
||||
frame->set_video_params(frame_params);
|
||||
frame->allocate();
|
||||
@@ -112,16 +112,16 @@ FramePtr RenderProcessor::GenerateFrame(TexturePtr texture,
|
||||
const VideoParams &tex_params = texture->params();
|
||||
|
||||
if (output_color_transform) {
|
||||
TexturePtr transform_tex = render_ctx_->CreateTexture(tex_params);
|
||||
TexturePtr transform_tex = render_ctx_->create_texture(tex_params);
|
||||
ColorTransformJob job;
|
||||
|
||||
job.SetColorProcessor(output_color_transform);
|
||||
job.SetInputTexture(texture);
|
||||
job.SetInputAlphaAssociation(
|
||||
OLIVE_CONFIG("ReassocLinToNonLin").toBool() ? kAlphaAssociated :
|
||||
kAlphaNone);
|
||||
job.set_color_processor(output_color_transform);
|
||||
job.set_input_texture(texture);
|
||||
job.set_input_alpha_association(
|
||||
OAK_CONFIG("ReassocLinToNonLin").toBool() ? k_alpha_associated :
|
||||
k_alpha_none);
|
||||
|
||||
render_ctx_->BlitColorManaged(job, transform_tex.get());
|
||||
render_ctx_->blit_color_managed(job, transform_tex.get());
|
||||
|
||||
texture = transform_tex;
|
||||
}
|
||||
@@ -129,26 +129,26 @@ FramePtr RenderProcessor::GenerateFrame(TexturePtr texture,
|
||||
if (tex_params.effective_width() != frame_params.effective_width() ||
|
||||
tex_params.effective_height() != frame_params.effective_height() ||
|
||||
tex_params.format() != frame_params.format()) {
|
||||
TexturePtr blit_tex = render_ctx_->CreateTexture(frame_params);
|
||||
TexturePtr blit_tex = render_ctx_->create_texture(frame_params);
|
||||
|
||||
QMatrix4x4 matrix = ticket_->property("matrix").value<QMatrix4x4>();
|
||||
|
||||
// No color transform, just blit
|
||||
ShaderJob job;
|
||||
job.Insert(QStringLiteral("ove_maintex"),
|
||||
NodeValue(NodeValue::kTexture,
|
||||
job.insert(QStringLiteral("ove_maintex"),
|
||||
NodeValue(NodeValue::k_texture,
|
||||
QVariant::fromValue(texture)));
|
||||
job.Insert(QStringLiteral("ove_mvpmat"),
|
||||
NodeValue(NodeValue::kMatrix, matrix));
|
||||
job.insert(QStringLiteral("ove_mvpmat"),
|
||||
NodeValue(NodeValue::k_matrix, matrix));
|
||||
|
||||
render_ctx_->BlitToTexture(render_ctx_->GetDefaultShader(), job,
|
||||
render_ctx_->blit_to_texture(render_ctx_->get_default_shader(), job,
|
||||
blit_tex.get());
|
||||
|
||||
// Replace texture that we're going to download in the next step
|
||||
texture = blit_tex;
|
||||
}
|
||||
|
||||
render_ctx_->DownloadFromTexture(texture->id(), texture->params(),
|
||||
render_ctx_->download_from_texture(texture->id(), texture->params(),
|
||||
frame->data(),
|
||||
frame->linesize_pixels());
|
||||
if (output_color_transform) {
|
||||
@@ -163,21 +163,21 @@ FramePtr RenderProcessor::GenerateFrame(TexturePtr texture,
|
||||
return frame;
|
||||
}
|
||||
|
||||
void RenderProcessor::Run()
|
||||
void RenderProcessor::run()
|
||||
{
|
||||
// Depending on the render ticket type, start a job
|
||||
RenderManager::TicketType type =
|
||||
ticket_->property("type").value<RenderManager::TicketType>();
|
||||
|
||||
SetCancelPointer(ticket_->GetCancelAtom());
|
||||
set_cancel_pointer(ticket_->get_cancel_atom());
|
||||
|
||||
VideoParams params = ticket_->property("vparam").value<VideoParams>();
|
||||
params.set_format(PixelFormat::F32);
|
||||
SetCacheVideoParams(params);
|
||||
SetCacheAudioParams(ticket_->property("aparam").value<AudioParams>());
|
||||
params.set_format(PixelFormat::f32);
|
||||
set_cache_video_params(params);
|
||||
set_cache_audio_params(ticket_->property("aparam").value<AudioParams>());
|
||||
|
||||
if (IsCancelled()) {
|
||||
ticket_->Finish();
|
||||
if (is_cancelled()) {
|
||||
ticket_->finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -193,40 +193,40 @@ void RenderProcessor::Run()
|
||||
*/
|
||||
|
||||
switch (type) {
|
||||
case RenderManager::kTypeVideo: {
|
||||
rational time = ticket_->property("time").value<rational>();
|
||||
case RenderManager::k_type_video: {
|
||||
Rational time = ticket_->property("time").value<Rational>();
|
||||
|
||||
rational frame_length = GetCacheVideoParams().frame_rate_as_time_base();
|
||||
if (GetCacheVideoParams().interlacing() !=
|
||||
VideoParams::kInterlaceNone) {
|
||||
Rational frame_length = get_cache_video_params().frame_rate_as_time_base();
|
||||
if (get_cache_video_params().interlacing() !=
|
||||
VideoParams::k_interlace_none) {
|
||||
frame_length /= 2;
|
||||
}
|
||||
|
||||
TexturePtr texture = GenerateTexture(time, frame_length);
|
||||
TexturePtr texture = generate_texture(time, frame_length);
|
||||
|
||||
if (!render_ctx_) {
|
||||
ticket_->Finish();
|
||||
ticket_->finish();
|
||||
} else {
|
||||
if (GetCacheVideoParams().interlacing() !=
|
||||
VideoParams::kInterlaceNone) {
|
||||
if (get_cache_video_params().interlacing() !=
|
||||
VideoParams::k_interlace_none) {
|
||||
// Get next between frame and interlace it
|
||||
TexturePtr top = texture;
|
||||
TexturePtr bottom =
|
||||
GenerateTexture(time + frame_length, frame_length);
|
||||
generate_texture(time + frame_length, frame_length);
|
||||
|
||||
if (GetCacheVideoParams().interlacing() ==
|
||||
VideoParams::kInterlacedBottomFirst) {
|
||||
if (get_cache_video_params().interlacing() ==
|
||||
VideoParams::k_interlaced_bottom_first) {
|
||||
std::swap(top, bottom);
|
||||
}
|
||||
|
||||
texture = render_ctx_->InterlaceTexture(top, bottom,
|
||||
GetCacheVideoParams());
|
||||
texture = render_ctx_->interlace_texture(top, bottom,
|
||||
get_cache_video_params());
|
||||
}
|
||||
|
||||
if (HeardCancel()) {
|
||||
if (heard_cancel()) {
|
||||
// Finish cancelled ticket with nothing since we can't guarantee the frame we generated
|
||||
// is actually "complete
|
||||
ticket_->Finish();
|
||||
ticket_->finish();
|
||||
} else {
|
||||
FramePtr frame;
|
||||
QString cache = ticket_->property("cache").toString();
|
||||
@@ -234,85 +234,85 @@ void RenderProcessor::Run()
|
||||
RenderManager::ReturnType(
|
||||
ticket_->property("return").toInt());
|
||||
|
||||
if (return_type == RenderManager::kFrame || !cache.isEmpty()) {
|
||||
if (return_type == RenderManager::k_frame || !cache.isEmpty()) {
|
||||
// Convert to CPU frame
|
||||
frame = GenerateFrame(texture, time);
|
||||
frame = generate_frame(texture, time);
|
||||
|
||||
// Save to cache if requested
|
||||
if (!cache.isEmpty()) {
|
||||
rational timebase =
|
||||
ticket_->property("cachetimebase").value<rational>();
|
||||
Rational timebase =
|
||||
ticket_->property("cachetimebase").value<Rational>();
|
||||
QUuid uuid =
|
||||
ticket_->property("cacheid").value<QUuid>();
|
||||
bool cache_result = FrameHashCache::SaveCacheFrame(
|
||||
bool cache_result = FrameHashCache::save_cache_frame(
|
||||
cache, uuid, time, timebase, frame);
|
||||
ticket_->setProperty("cached", cache_result);
|
||||
}
|
||||
}
|
||||
|
||||
if (return_type == RenderManager::kTexture) {
|
||||
if (return_type == RenderManager::k_texture) {
|
||||
// Return GPU texture
|
||||
if (!texture) {
|
||||
texture =
|
||||
render_ctx_->CreateTexture(GetCacheVideoParams());
|
||||
render_ctx_->ClearDestination(texture.get());
|
||||
render_ctx_->create_texture(get_cache_video_params());
|
||||
render_ctx_->clear_destination(texture.get());
|
||||
}
|
||||
|
||||
render_ctx_->Flush();
|
||||
ticket_->Finish(QVariant::fromValue(texture));
|
||||
render_ctx_->flush();
|
||||
ticket_->finish(QVariant::fromValue(texture));
|
||||
} else {
|
||||
ticket_->Finish(QVariant::fromValue(frame));
|
||||
ticket_->finish(QVariant::fromValue(frame));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RenderManager::kTypeAudio: {
|
||||
case RenderManager::k_type_audio: {
|
||||
TimeRange time = ticket_->property("time").value<TimeRange>();
|
||||
|
||||
NodeValueTable table;
|
||||
if (Node *node = QtUtils::ValueToPtr<Node>(ticket_->property("node"))) {
|
||||
table = GenerateTable(node, time);
|
||||
if (Node *node = QtUtils::value_to_ptr<Node>(ticket_->property("node"))) {
|
||||
table = generate_table(node, time);
|
||||
}
|
||||
|
||||
NodeValue sample_val = table.Get(NodeValue::kSamples);
|
||||
NodeValue sample_val = table.get(NodeValue::k_samples);
|
||||
|
||||
ResolveJobs(sample_val);
|
||||
resolve_jobs(sample_val);
|
||||
|
||||
SampleBuffer samples = sample_val.toSamples();
|
||||
SampleBuffer samples = sample_val.to_samples();
|
||||
if (samples.is_allocated()) {
|
||||
if (ticket_->property("clamp").toBool() && !IsCancelled()) {
|
||||
if (ticket_->property("clamp").toBool() && !is_cancelled()) {
|
||||
samples.clamp();
|
||||
}
|
||||
|
||||
if (ticket_->property("enablewaveforms").toBool() &&
|
||||
!IsCancelled()) {
|
||||
!is_cancelled()) {
|
||||
AudioVisualWaveform vis;
|
||||
vis.set_channel_count(samples.audio_params().channel_count());
|
||||
vis.OverwriteSamples(samples,
|
||||
vis.overwrite_samples(samples,
|
||||
samples.audio_params().sample_rate());
|
||||
ticket_->setProperty("waveform", QVariant::fromValue(vis));
|
||||
}
|
||||
}
|
||||
|
||||
if (HeardCancel()) {
|
||||
ticket_->Finish();
|
||||
if (heard_cancel()) {
|
||||
ticket_->finish();
|
||||
} else {
|
||||
ticket_->Finish(QVariant::fromValue(samples));
|
||||
ticket_->finish(QVariant::fromValue(samples));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Fail
|
||||
ticket_->Finish();
|
||||
ticket_->finish();
|
||||
}
|
||||
}
|
||||
|
||||
DecoderPtr
|
||||
RenderProcessor::ResolveDecoderFromInput(const QString &decoder_id,
|
||||
RenderProcessor::resolve_decoder_from_input(const QString &decoder_id,
|
||||
const Decoder::CodecStream &stream)
|
||||
{
|
||||
if (!stream.IsValid()) {
|
||||
if (!stream.is_valid()) {
|
||||
qWarning() << "Attempted to resolve the decoder of a null stream";
|
||||
return nullptr;
|
||||
}
|
||||
@@ -336,12 +336,12 @@ RenderProcessor::ResolveDecoderFromInput(const QString &decoder_id,
|
||||
dec = decoder.decoder;
|
||||
} else {
|
||||
// No decoder
|
||||
decoder.decoder = dec = Decoder::CreateFromID(decoder_id);
|
||||
decoder.decoder = dec = Decoder::create_from_id(decoder_id);
|
||||
decoder.last_modified = file_last_modified;
|
||||
decoder_cache_->insert(stream, decoder);
|
||||
locker.unlock();
|
||||
|
||||
if (!dec->Open(stream)) {
|
||||
if (!dec->open(stream)) {
|
||||
qWarning() << "Failed to open decoder for" << stream.filename()
|
||||
<< "::" << stream.stream();
|
||||
return nullptr;
|
||||
@@ -349,35 +349,35 @@ RenderProcessor::ResolveDecoderFromInput(const QString &decoder_id,
|
||||
|
||||
if (!render_ctx_) {
|
||||
// Assume dry run and increment access time
|
||||
decoder.decoder->IncrementAccessTime(
|
||||
RenderManager::kDryRunInterval.toDouble() * 1000);
|
||||
decoder.decoder->increment_access_time(
|
||||
RenderManager::k_dry_run_interval.to_double() * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
return dec;
|
||||
}
|
||||
|
||||
NodeValueDatabase RenderProcessor::GenerateDatabase(const Node *node,
|
||||
NodeValueDatabase RenderProcessor::generate_database(const Node *node,
|
||||
const TimeRange &range)
|
||||
{
|
||||
NodeValueDatabase db = super::GenerateDatabase(node, range);
|
||||
NodeValueDatabase db = super::generate_database(node, range);
|
||||
|
||||
if (const MultiCamNode *multicam =
|
||||
dynamic_cast<const MultiCamNode *>(node)) {
|
||||
if (QtUtils::ValueToPtr<MultiCamNode>(ticket_->property("multicam")) ==
|
||||
if (QtUtils::value_to_ptr<MultiCamNode>(ticket_->property("multicam")) ==
|
||||
multicam) {
|
||||
int sz = multicam->GetSourceCount();
|
||||
int sz = multicam->get_source_count();
|
||||
QVector<TexturePtr> multicam_tex(sz);
|
||||
for (int i = 0; i < sz; i++) {
|
||||
NodeValueTable t =
|
||||
GenerateTable(multicam->GetConnectedRenderOutput(
|
||||
multicam->kSourcesInput, i),
|
||||
generate_table(multicam->get_connected_render_output(
|
||||
multicam->k_sources_input, i),
|
||||
range, multicam);
|
||||
NodeValue val = GenerateRowValueElement(
|
||||
multicam, multicam->kSourcesInput, i, &t, range);
|
||||
ResolveJobs(val);
|
||||
NodeValue val = generate_row_value_element(
|
||||
multicam, multicam->k_sources_input, i, &t, range);
|
||||
resolve_jobs(val);
|
||||
|
||||
multicam_tex[i] = val.toTexture();
|
||||
multicam_tex[i] = val.to_texture();
|
||||
}
|
||||
ticket_->setProperty("multicam_output",
|
||||
QVariant::fromValue(multicam_tex));
|
||||
@@ -387,20 +387,20 @@ NodeValueDatabase RenderProcessor::GenerateDatabase(const Node *node,
|
||||
return db;
|
||||
}
|
||||
|
||||
void RenderProcessor::Process(RenderTicketPtr ticket, Renderer *render_ctx,
|
||||
void RenderProcessor::process(RenderTicketPtr ticket, Renderer *render_ctx,
|
||||
DecoderCache *decoder_cache,
|
||||
ShaderCache *shader_cache)
|
||||
{
|
||||
RenderProcessor p(ticket, render_ctx, decoder_cache, shader_cache);
|
||||
p.Run();
|
||||
p.run();
|
||||
}
|
||||
|
||||
void RenderProcessor::ProcessVideoFootage(TexturePtr destination,
|
||||
void RenderProcessor::process_video_footage(TexturePtr destination,
|
||||
const FootageJob *stream,
|
||||
const rational &input_time)
|
||||
const Rational &input_time)
|
||||
{
|
||||
if (ticket_->property("type").value<RenderManager::TicketType>() !=
|
||||
RenderManager::kTypeVideo) {
|
||||
RenderManager::k_type_video) {
|
||||
// Video cannot contribute to audio, so we do nothing here
|
||||
return;
|
||||
}
|
||||
@@ -411,12 +411,12 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination,
|
||||
VideoParams stream_data = stream->video_params();
|
||||
|
||||
ColorManager *color_manager =
|
||||
QtUtils::ValueToPtr<ColorManager>(ticket_->property("colormanager"));
|
||||
QtUtils::value_to_ptr<ColorManager>(ticket_->property("colormanager"));
|
||||
|
||||
QString using_colorspace = stream_data.colorspace();
|
||||
|
||||
if (using_colorspace.isEmpty() && color_manager) {
|
||||
using_colorspace = color_manager->GetDefaultInputColorSpace();
|
||||
using_colorspace = color_manager->get_default_input_color_space();
|
||||
}
|
||||
|
||||
if (using_colorspace.isEmpty()) {
|
||||
@@ -426,37 +426,37 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination,
|
||||
|
||||
auto blit_color_managed = [&](const TexturePtr &unmanaged_texture,
|
||||
const VideoParams &texture_params) {
|
||||
if (!render_ctx_ || !unmanaged_texture || IsCancelled()) {
|
||||
if (!render_ctx_ || !unmanaged_texture || is_cancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We convert to our rendering pixel format, since that will always be float-based which
|
||||
// is necessary for correct color conversion
|
||||
ColorProcessorPtr processor =
|
||||
ColorProcessor::Create(color_manager, using_colorspace,
|
||||
color_manager->GetReferenceColorSpace());
|
||||
ColorProcessor::create(color_manager, using_colorspace,
|
||||
color_manager->get_reference_color_space());
|
||||
|
||||
ColorTransformJob job;
|
||||
job.SetColorProcessor(processor);
|
||||
job.SetInputTexture(unmanaged_texture);
|
||||
job.set_color_processor(processor);
|
||||
job.set_input_texture(unmanaged_texture);
|
||||
|
||||
if (texture_params.channel_count() != VideoParams::kRGBAChannelCount ||
|
||||
if (texture_params.channel_count() != VideoParams::k_rgba_channel_count ||
|
||||
texture_params.colorspace() ==
|
||||
color_manager->GetReferenceColorSpace()) {
|
||||
job.SetInputAlphaAssociation(kAlphaNone);
|
||||
color_manager->get_reference_color_space()) {
|
||||
job.set_input_alpha_association(k_alpha_none);
|
||||
} else if (texture_params.premultiplied_alpha()) {
|
||||
job.SetInputAlphaAssociation(kAlphaAssociated);
|
||||
job.set_input_alpha_association(k_alpha_associated);
|
||||
} else {
|
||||
job.SetInputAlphaAssociation(kAlphaUnassociated);
|
||||
job.set_input_alpha_association(k_alpha_unassociated);
|
||||
}
|
||||
|
||||
render_ctx_->BlitColorManaged(job, destination.get());
|
||||
render_ctx_->blit_color_managed(job, destination.get());
|
||||
// macOS TBDR: ensure tile writeback completes before the texture
|
||||
// is read back in a potentially different shared OpenGL context.
|
||||
render_ctx_->Flush();
|
||||
render_ctx_->flush();
|
||||
};
|
||||
|
||||
auto *input_pool = QtUtils::ValueToPtr<ipc::FrameSlotPool>(
|
||||
auto *input_pool = QtUtils::value_to_ptr<ipc::FrameSlotPool>(
|
||||
ticket_->property("ipc_input_pool"));
|
||||
int input_slot = -1;
|
||||
const QVariantList input_slots =
|
||||
@@ -481,7 +481,7 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination,
|
||||
return;
|
||||
}
|
||||
|
||||
const ipc::FrameSlotMeta *meta = input_pool->Meta(uint32_t(input_slot));
|
||||
const ipc::FrameSlotMeta *meta = input_pool->meta(uint32_t(input_slot));
|
||||
if (meta && meta->width > 0 && meta->height > 0 &&
|
||||
meta->data_size > 0 &&
|
||||
meta->data_size <= int(input_pool->slot_data_bytes())) {
|
||||
@@ -506,13 +506,13 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination,
|
||||
using_colorspace = ipc_colorspace;
|
||||
}
|
||||
|
||||
const int bytes_per_pixel = input_params.GetBytesPerPixel();
|
||||
const int bytes_per_pixel = input_params.get_bytes_per_pixel();
|
||||
const int linesize_pixels = bytes_per_pixel > 0 ?
|
||||
meta->linesize / bytes_per_pixel :
|
||||
input_params.effective_width();
|
||||
|
||||
const void *slot_data = input_pool->SlotData(uint32_t(input_slot));
|
||||
TexturePtr unmanaged_texture = render_ctx_->CreateTexture(
|
||||
const void *slot_data = input_pool->slot_data(uint32_t(input_slot));
|
||||
TexturePtr unmanaged_texture = render_ctx_->create_texture(
|
||||
input_params, slot_data, linesize_pixels);
|
||||
|
||||
blit_color_managed(unmanaged_texture, input_params);
|
||||
@@ -532,7 +532,7 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination,
|
||||
|
||||
const bool use_proxy =
|
||||
static_cast<RenderMode::Mode>(ticket_->property("mode").toInt()) ==
|
||||
RenderMode::kOffline &&
|
||||
RenderMode::k_offline &&
|
||||
stream->has_proxy() && QFileInfo::exists(stream->proxy_filename());
|
||||
const QString decode_filename = use_proxy ? stream->proxy_filename() :
|
||||
stream->filename();
|
||||
@@ -542,30 +542,30 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination,
|
||||
stream_data.stream_index();
|
||||
|
||||
Decoder::CodecStream default_codec_stream(decode_filename, stream_index,
|
||||
GetCurrentBlock());
|
||||
get_current_block());
|
||||
|
||||
DecoderPtr decoder = nullptr;
|
||||
|
||||
switch (stream_data.video_type()) {
|
||||
case VideoParams::kVideoTypeVideo:
|
||||
case VideoParams::kVideoTypeStill:
|
||||
decoder = ResolveDecoderFromInput(decoder_id, default_codec_stream);
|
||||
case VideoParams::k_video_type_video:
|
||||
case VideoParams::k_video_type_still:
|
||||
decoder = resolve_decoder_from_input(decoder_id, default_codec_stream);
|
||||
break;
|
||||
case VideoParams::kVideoTypeImageSequence: {
|
||||
case VideoParams::k_video_type_image_sequence: {
|
||||
if (render_ctx_) {
|
||||
// Since image sequences involve multiple files, we don't engage the decoder cache
|
||||
decoder = Decoder::CreateFromID(decoder_id);
|
||||
decoder = Decoder::create_from_id(decoder_id);
|
||||
|
||||
QString frame_filename;
|
||||
|
||||
int64_t frame_number =
|
||||
stream_data.get_time_in_timebase_units(input_time);
|
||||
frame_filename = Decoder::TransformImageSequenceFileName(
|
||||
frame_filename = Decoder::transform_image_sequence_file_name(
|
||||
decode_filename, frame_number);
|
||||
|
||||
// Decoder will close automatically since it's a stream_ptr
|
||||
decoder->Open(Decoder::CodecStream(frame_filename, stream_index,
|
||||
GetCurrentBlock()));
|
||||
decoder->open(Decoder::CodecStream(frame_filename, stream_index,
|
||||
get_current_block()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -576,7 +576,7 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination,
|
||||
p.divider = stream->video_params().divider();
|
||||
p.maximum_format = destination->format();
|
||||
|
||||
if (!IsCancelled()) {
|
||||
if (!is_cancelled()) {
|
||||
VideoParams tex_params = stream->video_params();
|
||||
|
||||
if (tex_params.is_valid()) {
|
||||
@@ -584,16 +584,16 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination,
|
||||
|
||||
p.renderer = render_ctx_;
|
||||
p.time =
|
||||
(stream_data.video_type() == VideoParams::kVideoTypeVideo) ?
|
||||
(stream_data.video_type() == VideoParams::k_video_type_video) ?
|
||||
input_time :
|
||||
Decoder::kAnyTimecode;
|
||||
p.cancelled = GetCancelPointer();
|
||||
Decoder::k_any_timecode;
|
||||
p.cancelled = get_cancel_pointer();
|
||||
p.force_range = stream_data.color_range();
|
||||
p.src_interlacing = stream_data.interlacing();
|
||||
|
||||
unmanaged_texture = decoder->RetrieveVideo(p);
|
||||
unmanaged_texture = decoder->retrieve_video(p);
|
||||
|
||||
if (!IsCancelled() && unmanaged_texture) {
|
||||
if (!is_cancelled() && unmanaged_texture) {
|
||||
blit_color_managed(unmanaged_texture, stream_data);
|
||||
}
|
||||
}
|
||||
@@ -601,7 +601,7 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination,
|
||||
}
|
||||
}
|
||||
|
||||
void RenderProcessor::ProcessAudioFootage(SampleBuffer &destination,
|
||||
void RenderProcessor::process_audio_footage(SampleBuffer &destination,
|
||||
const FootageJob *stream,
|
||||
const TimeRange &input_time)
|
||||
{
|
||||
@@ -615,7 +615,7 @@ void RenderProcessor::ProcessAudioFootage(SampleBuffer &destination,
|
||||
// audio) for offline renders only, never for export
|
||||
const bool use_proxy =
|
||||
static_cast<RenderMode::Mode>(ticket_->property("mode").toInt()) ==
|
||||
RenderMode::kOffline &&
|
||||
RenderMode::k_offline &&
|
||||
stream->has_proxy() && QFileInfo::exists(stream->proxy_filename());
|
||||
const QString decode_filename = use_proxy ? stream->proxy_filename() :
|
||||
stream->filename();
|
||||
@@ -625,25 +625,25 @@ void RenderProcessor::ProcessAudioFootage(SampleBuffer &destination,
|
||||
stream->proxy_stream_index() :
|
||||
stream->audio_params().stream_index();
|
||||
|
||||
DecoderPtr decoder = ResolveDecoderFromInput(
|
||||
DecoderPtr decoder = resolve_decoder_from_input(
|
||||
decoder_id,
|
||||
Decoder::CodecStream(decode_filename, stream_index, nullptr));
|
||||
|
||||
if (decoder) {
|
||||
const AudioParams &audio_params = GetCacheAudioParams();
|
||||
const AudioParams &audio_params = get_cache_audio_params();
|
||||
|
||||
Decoder::RetrieveAudioStatus status = decoder->RetrieveAudio(
|
||||
Decoder::RetrieveAudioStatus status = decoder->retrieve_audio(
|
||||
destination, input_time, audio_params, stream->cache_path(),
|
||||
loop_mode(),
|
||||
static_cast<RenderMode::Mode>(ticket_->property("mode").toInt()));
|
||||
|
||||
if (status == Decoder::kWaitingForConform) {
|
||||
if (status == Decoder::k_waiting_for_conform) {
|
||||
ticket_->setProperty("incomplete", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderProcessor::ProcessShader(TexturePtr destination, const Node *node,
|
||||
void RenderProcessor::process_shader(TexturePtr destination, const Node *node,
|
||||
const ShaderJob *job)
|
||||
{
|
||||
if (!render_ctx_) {
|
||||
@@ -651,7 +651,7 @@ void RenderProcessor::ProcessShader(TexturePtr destination, const Node *node,
|
||||
}
|
||||
|
||||
QString full_shader_id =
|
||||
QStringLiteral("%1:%2").arg(node->id(), job->GetShaderID());
|
||||
QStringLiteral("%1:%2").arg(node->id(), job->get_shader_id());
|
||||
|
||||
QMutexLocker locker(shader_cache_->mutex());
|
||||
|
||||
@@ -659,8 +659,8 @@ void RenderProcessor::ProcessShader(TexturePtr destination, const Node *node,
|
||||
|
||||
if (shader.isNull()) {
|
||||
// Since we have shader code, compile it now
|
||||
shader = render_ctx_->CreateNativeShader(
|
||||
node->GetShaderCode(job->GetShaderID()));
|
||||
shader = render_ctx_->create_native_shader(
|
||||
node->get_shader_code(job->get_shader_id()));
|
||||
|
||||
if (shader.isNull()) {
|
||||
// Couldn't find or build the shader required
|
||||
@@ -673,11 +673,11 @@ void RenderProcessor::ProcessShader(TexturePtr destination, const Node *node,
|
||||
locker.unlock();
|
||||
|
||||
// Run shader
|
||||
render_ctx_->BlitToTexture(shader, const_cast<ShaderJob &>(*job),
|
||||
render_ctx_->blit_to_texture(shader, const_cast<ShaderJob &>(*job),
|
||||
destination.get());
|
||||
}
|
||||
|
||||
void RenderProcessor::ProcessSamples(SampleBuffer &destination,
|
||||
void RenderProcessor::process_samples(SampleBuffer &destination,
|
||||
const Node *node, const TimeRange &range,
|
||||
const SampleJob &job)
|
||||
{
|
||||
@@ -687,32 +687,32 @@ void RenderProcessor::ProcessSamples(SampleBuffer &destination,
|
||||
|
||||
NodeValueRow value_db;
|
||||
|
||||
const AudioParams &audio_params = GetCacheAudioParams();
|
||||
const AudioParams &audio_params = get_cache_audio_params();
|
||||
|
||||
for (size_t i = 0; i < job.samples().sample_count(); i++) {
|
||||
// Calculate the exact rational time at this sample
|
||||
// Calculate the exact Rational time at this sample
|
||||
double sample_to_second =
|
||||
static_cast<double>(i) /
|
||||
static_cast<double>(audio_params.sample_rate());
|
||||
|
||||
rational this_sample_time =
|
||||
rational::fromDouble(range.in().toDouble() + sample_to_second);
|
||||
Rational this_sample_time =
|
||||
Rational::from_double(range.in().to_double() + sample_to_second);
|
||||
|
||||
// Update all non-sample and non-footage inputs
|
||||
for (auto j = job.GetValues().constBegin();
|
||||
j != job.GetValues().constEnd(); j++) {
|
||||
for (auto j = job.get_values().constBegin();
|
||||
j != job.get_values().constEnd(); j++) {
|
||||
TimeRange r = TimeRange(this_sample_time, this_sample_time);
|
||||
NodeValueTable value = ProcessInput(node, j.key(), r);
|
||||
NodeValueTable value = process_input(node, j.key(), r);
|
||||
|
||||
value_db.insert(j.key(),
|
||||
GenerateRowValue(node, j.key(), &value, r));
|
||||
generate_row_value(node, j.key(), &value, r));
|
||||
}
|
||||
|
||||
node->ProcessSamples(value_db, job.samples(), destination, i);
|
||||
node->process_samples(value_db, job.samples(), destination, i);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderProcessor::ProcessColorTransform(TexturePtr destination,
|
||||
void RenderProcessor::process_color_transform(TexturePtr destination,
|
||||
const Node *node,
|
||||
const ColorTransformJob *job)
|
||||
{
|
||||
@@ -720,10 +720,10 @@ void RenderProcessor::ProcessColorTransform(TexturePtr destination,
|
||||
return;
|
||||
}
|
||||
|
||||
render_ctx_->BlitColorManaged(*job, destination.get());
|
||||
render_ctx_->blit_color_managed(*job, destination.get());
|
||||
}
|
||||
|
||||
void RenderProcessor::ProcessFrameGeneration(TexturePtr destination,
|
||||
void RenderProcessor::process_frame_generation(TexturePtr destination,
|
||||
const Node *node,
|
||||
const GenerateJob *job)
|
||||
{
|
||||
@@ -731,17 +731,17 @@ void RenderProcessor::ProcessFrameGeneration(TexturePtr destination,
|
||||
return;
|
||||
}
|
||||
|
||||
FramePtr frame = Frame::Create();
|
||||
FramePtr frame = Frame::create();
|
||||
|
||||
frame->set_video_params(destination->params());
|
||||
frame->allocate();
|
||||
|
||||
node->GenerateFrame(frame, *job);
|
||||
node->generate_frame(frame, *job);
|
||||
|
||||
destination->Upload(frame->data(), frame->linesize_pixels());
|
||||
destination->upload(frame->data(), frame->linesize_pixels());
|
||||
}
|
||||
|
||||
TexturePtr RenderProcessor::ProcessPluginJob(TexturePtr texture,
|
||||
TexturePtr RenderProcessor::process_plugin_job(TexturePtr texture,
|
||||
TexturePtr destination,
|
||||
const Node *node)
|
||||
{
|
||||
@@ -761,13 +761,13 @@ TexturePtr RenderProcessor::ProcessPluginJob(TexturePtr texture,
|
||||
return destination;
|
||||
}
|
||||
|
||||
NodeValueRow &values = plugin_job->GetValues();
|
||||
NodeValueRow &values = plugin_job->get_values();
|
||||
|
||||
auto is_usable_texture = [](const TexturePtr &tex) {
|
||||
if (!tex) {
|
||||
return false;
|
||||
}
|
||||
if (!tex->IsDummy() && tex->renderer()) {
|
||||
if (!tex->is_dummy() && tex->renderer()) {
|
||||
return true;
|
||||
}
|
||||
AVFramePtr frame = tex->frame();
|
||||
@@ -777,10 +777,10 @@ TexturePtr RenderProcessor::ProcessPluginJob(TexturePtr texture,
|
||||
TexturePtr src = nullptr;
|
||||
QString effect_input_id;
|
||||
if (plugin_job->node()) {
|
||||
effect_input_id = plugin_job->node()->GetEffectInputID();
|
||||
effect_input_id = plugin_job->node()->get_effect_input_id();
|
||||
}
|
||||
if (!effect_input_id.isEmpty()) {
|
||||
if (TexturePtr effect_tex = values.value(effect_input_id).toTexture();
|
||||
if (TexturePtr effect_tex = values.value(effect_input_id).to_texture();
|
||||
is_usable_texture(effect_tex)) {
|
||||
src = effect_tex;
|
||||
}
|
||||
@@ -788,19 +788,19 @@ TexturePtr RenderProcessor::ProcessPluginJob(TexturePtr texture,
|
||||
if (!src) {
|
||||
const QString source_key =
|
||||
QString::fromUtf8(kOfxImageEffectSimpleSourceClipName);
|
||||
if (TexturePtr source_tex = values.value(source_key).toTexture();
|
||||
if (TexturePtr source_tex = values.value(source_key).to_texture();
|
||||
is_usable_texture(source_tex)) {
|
||||
src = source_tex;
|
||||
} else if (TexturePtr effect_tex =
|
||||
values.value(plugin::kTextureInput).toTexture();
|
||||
values.value(plugin::k_texture_input).to_texture();
|
||||
is_usable_texture(effect_tex)) {
|
||||
src = effect_tex;
|
||||
}
|
||||
}
|
||||
if (!src) {
|
||||
for (auto it = values.cbegin(); it != values.cend(); ++it) {
|
||||
if (it.value().type() == NodeValue::kTexture) {
|
||||
if (TexturePtr any_tex = it.value().toTexture();
|
||||
if (it.value().type() == NodeValue::k_texture) {
|
||||
if (TexturePtr any_tex = it.value().to_texture();
|
||||
is_usable_texture(any_tex)) {
|
||||
src = any_tex;
|
||||
break;
|
||||
@@ -809,15 +809,15 @@ TexturePtr RenderProcessor::ProcessPluginJob(TexturePtr texture,
|
||||
}
|
||||
}
|
||||
|
||||
plugin_renderer.RenderPlugin(src, *plugin_job, destination,
|
||||
plugin_renderer.render_plugin(src, *plugin_job, destination,
|
||||
destination->params(), true, false);
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
TexturePtr RenderProcessor::ProcessVideoCacheJob(const CacheJob *val)
|
||||
TexturePtr RenderProcessor::process_video_cache_job(const CacheJob *val)
|
||||
{
|
||||
FramePtr frame = FrameHashCache::LoadCacheFrame(val->GetFilename());
|
||||
FramePtr frame = FrameHashCache::load_cache_frame(val->get_filename());
|
||||
if (frame) {
|
||||
// Auto-detect and discard black/empty cached frames (macOS TBDR artifact)
|
||||
bool all_black = true;
|
||||
@@ -835,37 +835,37 @@ TexturePtr RenderProcessor::ProcessVideoCacheJob(const CacheJob *val)
|
||||
}
|
||||
if (all_black) {
|
||||
qWarning() << "[CACHE] Discarding black cached frame:"
|
||||
<< val->GetFilename()
|
||||
<< "time=" << frame->timestamp().toDouble()
|
||||
<< val->get_filename()
|
||||
<< "time=" << frame->timestamp().to_double()
|
||||
<< "size=" << frame->allocated_size();
|
||||
QFile::remove(val->GetFilename());
|
||||
QFile::remove(val->get_filename());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TexturePtr tex = CreateTexture(frame->video_params());
|
||||
TexturePtr tex = create_texture(frame->video_params());
|
||||
if (tex) {
|
||||
tex->Upload(frame->data(), frame->linesize_pixels());
|
||||
tex->upload(frame->data(), frame->linesize_pixels());
|
||||
return tex;
|
||||
}
|
||||
} else {
|
||||
QStringList s = ticket_->property("badcache").toStringList();
|
||||
s.append(val->GetFilename());
|
||||
s.append(val->get_filename());
|
||||
ticket_->setProperty("badcache", s);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TexturePtr RenderProcessor::CreateTexture(const VideoParams &p)
|
||||
TexturePtr RenderProcessor::create_texture(const VideoParams &p)
|
||||
{
|
||||
if (render_ctx_) {
|
||||
return render_ctx_->CreateTexture(p);
|
||||
return render_ctx_->create_texture(p);
|
||||
} else {
|
||||
return super::CreateTexture(p);
|
||||
return super::create_texture(p);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderProcessor::ConvertToReferenceSpace(TexturePtr destination,
|
||||
void RenderProcessor::convert_to_reference_space(TexturePtr destination,
|
||||
TexturePtr source,
|
||||
const QString &input_cs)
|
||||
{
|
||||
@@ -874,23 +874,23 @@ void RenderProcessor::ConvertToReferenceSpace(TexturePtr destination,
|
||||
}
|
||||
|
||||
ColorManager *color_manager =
|
||||
QtUtils::ValueToPtr<ColorManager>(ticket_->property("colormanager"));
|
||||
ColorProcessorPtr cp = ColorProcessor::Create(
|
||||
color_manager, input_cs, color_manager->GetReferenceColorSpace());
|
||||
QtUtils::value_to_ptr<ColorManager>(ticket_->property("colormanager"));
|
||||
ColorProcessorPtr cp = ColorProcessor::create(
|
||||
color_manager, input_cs, color_manager->get_reference_color_space());
|
||||
|
||||
ColorTransformJob ctj;
|
||||
|
||||
ctj.SetColorProcessor(cp);
|
||||
ctj.SetInputTexture(source);
|
||||
ctj.SetInputAlphaAssociation(kAlphaAssociated);
|
||||
ctj.set_color_processor(cp);
|
||||
ctj.set_input_texture(source);
|
||||
ctj.set_input_alpha_association(k_alpha_associated);
|
||||
|
||||
render_ctx_->BlitColorManaged(ctj, destination.get());
|
||||
render_ctx_->blit_color_managed(ctj, destination.get());
|
||||
}
|
||||
|
||||
bool RenderProcessor::UseCache() const
|
||||
bool RenderProcessor::use_cache() const
|
||||
{
|
||||
return static_cast<RenderMode::Mode>(ticket_->property("mode").toInt()) ==
|
||||
RenderMode::kOffline;
|
||||
RenderMode::k_offline;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERPROCESSOR_H
|
||||
#define RENDERPROCESSOR_H
|
||||
#ifndef OAK_RENDERPROCESSOR_H
|
||||
#define OAK_RENDERPROCESSOR_H
|
||||
|
||||
#include "node/block/clip/clip.h"
|
||||
#include <memory>
|
||||
@@ -39,10 +39,10 @@ class PluginRenderer;
|
||||
|
||||
class RenderProcessor : public NodeTraverser {
|
||||
public:
|
||||
virtual NodeValueDatabase GenerateDatabase(const Node *node,
|
||||
virtual NodeValueDatabase generate_database(const Node *node,
|
||||
const TimeRange &range) override;
|
||||
|
||||
static void Process(RenderTicketPtr ticket, Renderer *render_ctx,
|
||||
static void process(RenderTicketPtr ticket, Renderer *render_ctx,
|
||||
DecoderCache *decoder_cache, ShaderCache *shader_cache);
|
||||
|
||||
struct RenderedWaveform {
|
||||
@@ -53,60 +53,60 @@ public:
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual void ProcessVideoFootage(TexturePtr destination,
|
||||
virtual void process_video_footage(TexturePtr destination,
|
||||
const FootageJob *stream,
|
||||
const rational &input_time) override;
|
||||
const Rational &input_time) override;
|
||||
|
||||
virtual void ProcessAudioFootage(SampleBuffer &destination,
|
||||
virtual void process_audio_footage(SampleBuffer &destination,
|
||||
const FootageJob *stream,
|
||||
const TimeRange &input_time) override;
|
||||
|
||||
virtual void ProcessShader(TexturePtr destination, const Node *node,
|
||||
virtual void process_shader(TexturePtr destination, const Node *node,
|
||||
const ShaderJob *job) override;
|
||||
|
||||
virtual void ProcessSamples(SampleBuffer &destination, const Node *node,
|
||||
virtual void process_samples(SampleBuffer &destination, const Node *node,
|
||||
const TimeRange &range,
|
||||
const SampleJob &job) override;
|
||||
|
||||
virtual void ProcessColorTransform(TexturePtr destination, const Node *node,
|
||||
virtual void process_color_transform(TexturePtr destination, const Node *node,
|
||||
const ColorTransformJob *job) override;
|
||||
|
||||
virtual void ProcessFrameGeneration(TexturePtr destination,
|
||||
virtual void process_frame_generation(TexturePtr destination,
|
||||
const Node *node,
|
||||
const GenerateJob *job) override;
|
||||
|
||||
virtual TexturePtr ProcessPluginJob(TexturePtr texture,
|
||||
virtual TexturePtr process_plugin_job(TexturePtr texture,
|
||||
TexturePtr destination,
|
||||
const Node *node) override;
|
||||
|
||||
virtual TexturePtr ProcessVideoCacheJob(const CacheJob *val) override;
|
||||
virtual TexturePtr process_video_cache_job(const CacheJob *val) override;
|
||||
|
||||
virtual TexturePtr CreateTexture(const VideoParams &p) override;
|
||||
virtual TexturePtr create_texture(const VideoParams &p) override;
|
||||
|
||||
virtual SampleBuffer CreateSampleBuffer(const AudioParams ¶ms,
|
||||
virtual SampleBuffer create_sample_buffer(const AudioParams ¶ms,
|
||||
int sample_count) override
|
||||
{
|
||||
return SampleBuffer(params, sample_count);
|
||||
}
|
||||
|
||||
virtual void ConvertToReferenceSpace(TexturePtr destination,
|
||||
virtual void convert_to_reference_space(TexturePtr destination,
|
||||
TexturePtr source,
|
||||
const QString &input_cs) override;
|
||||
|
||||
virtual bool UseCache() const override;
|
||||
virtual bool use_cache() const override;
|
||||
|
||||
private:
|
||||
RenderProcessor(RenderTicketPtr ticket, Renderer *render_ctx,
|
||||
DecoderCache *decoder_cache, ShaderCache *shader_cache);
|
||||
|
||||
TexturePtr GenerateTexture(const rational &time,
|
||||
const rational &frame_length);
|
||||
TexturePtr generate_texture(const Rational &time,
|
||||
const Rational &frame_length);
|
||||
|
||||
FramePtr GenerateFrame(TexturePtr texture, const rational &time);
|
||||
FramePtr generate_frame(TexturePtr texture, const Rational &time);
|
||||
|
||||
void Run();
|
||||
void run();
|
||||
|
||||
DecoderPtr ResolveDecoderFromInput(const QString &decoder_id,
|
||||
DecoderPtr resolve_decoder_from_input(const QString &decoder_id,
|
||||
const Decoder::CodecStream &stream);
|
||||
|
||||
RenderTicketPtr ticket_;
|
||||
@@ -124,4 +124,4 @@ private:
|
||||
|
||||
Q_DECLARE_METATYPE(olive::RenderProcessor::RenderedWaveform)
|
||||
|
||||
#endif // RENDERPROCESSOR_H
|
||||
#endif // OAK_RENDERPROCESSOR_H
|
||||
|
||||
+32
-32
@@ -31,14 +31,14 @@ RenderTicket::RenderTicket()
|
||||
{
|
||||
}
|
||||
|
||||
void RenderTicket::WaitForFinished(QMutex *mutex)
|
||||
void RenderTicket::wait_for_finished(QMutex *mutex)
|
||||
{
|
||||
if (is_running_) {
|
||||
wait_.wait(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTicket::Start()
|
||||
void RenderTicket::start()
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
|
||||
@@ -47,33 +47,33 @@ void RenderTicket::Start()
|
||||
result_.clear();
|
||||
}
|
||||
|
||||
void RenderTicket::Finish()
|
||||
void RenderTicket::finish()
|
||||
{
|
||||
FinishInternal(false, QVariant());
|
||||
finish_internal(false, QVariant());
|
||||
}
|
||||
|
||||
void RenderTicket::Finish(QVariant result)
|
||||
void RenderTicket::finish(QVariant result)
|
||||
{
|
||||
FinishInternal(true, result);
|
||||
finish_internal(true, result);
|
||||
}
|
||||
|
||||
QVariant RenderTicket::Get()
|
||||
QVariant RenderTicket::get()
|
||||
{
|
||||
WaitForFinished();
|
||||
wait_for_finished();
|
||||
|
||||
// We don't have to mutex around this because there is no way to write to `result_` after
|
||||
// the ticket has finished and the above function blocks the calling thread until it is finished
|
||||
return result_;
|
||||
}
|
||||
|
||||
void RenderTicket::WaitForFinished()
|
||||
void RenderTicket::wait_for_finished()
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
|
||||
WaitForFinished(&lock_);
|
||||
wait_for_finished(&lock_);
|
||||
}
|
||||
|
||||
bool RenderTicket::IsRunning(bool lock)
|
||||
bool RenderTicket::is_running(bool lock)
|
||||
{
|
||||
if (lock) {
|
||||
lock_.lock();
|
||||
@@ -88,7 +88,7 @@ bool RenderTicket::IsRunning(bool lock)
|
||||
return running;
|
||||
}
|
||||
|
||||
int RenderTicket::GetFinishCount(bool lock)
|
||||
int RenderTicket::get_finish_count(bool lock)
|
||||
{
|
||||
if (lock) {
|
||||
lock_.lock();
|
||||
@@ -103,14 +103,14 @@ int RenderTicket::GetFinishCount(bool lock)
|
||||
return count;
|
||||
}
|
||||
|
||||
bool RenderTicket::HasResult()
|
||||
bool RenderTicket::has_result()
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
|
||||
return has_result_;
|
||||
}
|
||||
|
||||
void RenderTicket::FinishInternal(bool has_result, QVariant result)
|
||||
void RenderTicket::finish_internal(bool has_result, QVariant result)
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
|
||||
@@ -126,7 +126,7 @@ void RenderTicket::FinishInternal(bool has_result, QVariant result)
|
||||
|
||||
locker.unlock();
|
||||
|
||||
emit Finished();
|
||||
emit finished();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ RenderTicketWatcher::RenderTicketWatcher(QObject *parent)
|
||||
{
|
||||
}
|
||||
|
||||
void RenderTicketWatcher::SetTicket(RenderTicketPtr ticket)
|
||||
void RenderTicketWatcher::set_ticket(RenderTicketPtr ticket)
|
||||
{
|
||||
if (ticket_) {
|
||||
qCritical() << "Tried to set a ticket on a RenderTicketWatcher twice";
|
||||
@@ -153,62 +153,62 @@ void RenderTicketWatcher::SetTicket(RenderTicketPtr ticket)
|
||||
// Lock ticket so we can query if it's already finished by the time this code runs
|
||||
QMutexLocker locker(ticket->lock());
|
||||
|
||||
connect(ticket_.get(), &RenderTicket::Finished, this,
|
||||
&RenderTicketWatcher::TicketFinished);
|
||||
connect(ticket_.get(), &RenderTicket::finished, this,
|
||||
&RenderTicketWatcher::ticket_finished);
|
||||
|
||||
if (!ticket_->IsRunning(false) && ticket_->GetFinishCount(false) > 0) {
|
||||
if (!ticket_->is_running(false) && ticket_->get_finish_count(false) > 0) {
|
||||
// Ticket has already finished before, so we emit a signal asynchronously
|
||||
// to avoid deleting this watcher before the caller has a chance to use
|
||||
// the returned pointer.
|
||||
QMetaObject::invokeMethod(this, &RenderTicketWatcher::TicketFinished,
|
||||
QMetaObject::invokeMethod(this, &RenderTicketWatcher::ticket_finished,
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderTicketWatcher::IsRunning()
|
||||
bool RenderTicketWatcher::is_running()
|
||||
{
|
||||
if (ticket_) {
|
||||
return ticket_->IsRunning();
|
||||
return ticket_->is_running();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTicketWatcher::WaitForFinished()
|
||||
void RenderTicketWatcher::wait_for_finished()
|
||||
{
|
||||
if (ticket_) {
|
||||
ticket_->WaitForFinished();
|
||||
ticket_->wait_for_finished();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant RenderTicketWatcher::Get()
|
||||
QVariant RenderTicketWatcher::get()
|
||||
{
|
||||
if (ticket_) {
|
||||
return ticket_->Get();
|
||||
return ticket_->get();
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderTicketWatcher::HasResult()
|
||||
bool RenderTicketWatcher::has_result()
|
||||
{
|
||||
if (ticket_) {
|
||||
return ticket_->HasResult();
|
||||
return ticket_->has_result();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTicketWatcher::Cancel()
|
||||
void RenderTicketWatcher::cancel()
|
||||
{
|
||||
if (ticket_) {
|
||||
ticket_->Cancel();
|
||||
ticket_->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTicketWatcher::TicketFinished()
|
||||
void RenderTicketWatcher::ticket_finished()
|
||||
{
|
||||
emit Finished(this);
|
||||
emit finished(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+23
-23
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERTICKET_H
|
||||
#define RENDERTICKET_H
|
||||
#ifndef OAK_RENDERTICKET_H
|
||||
#define OAK_RENDERTICKET_H
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QMutex>
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
* This function is thread safe, unless `lock` is set to false. Then the caller has responsibility
|
||||
* of locking the mutex before and unlocking after this function is called.
|
||||
*/
|
||||
bool IsRunning(bool lock = true);
|
||||
bool is_running(bool lock = true);
|
||||
|
||||
/**
|
||||
* @brief Determine how many times ticket has been finished
|
||||
@@ -52,27 +52,27 @@ public:
|
||||
* This function is thread safe, unless `lock` is set to false. Then the caller has responsibility
|
||||
* of locking the mutex before and unlocking after this function is called.
|
||||
*/
|
||||
int GetFinishCount(bool lock = true);
|
||||
int get_finish_count(bool lock = true);
|
||||
|
||||
/**
|
||||
* @brief Check if this ticket has a result
|
||||
*
|
||||
* If this ticket is running, this will always return false.
|
||||
*/
|
||||
bool HasResult();
|
||||
bool has_result();
|
||||
|
||||
/**
|
||||
* @brief Get value, if any
|
||||
*/
|
||||
QVariant Get();
|
||||
QVariant get();
|
||||
|
||||
/**
|
||||
* @brief Wait for ticket to be finished
|
||||
*
|
||||
* If this ticket is not running, this function returns immediately.
|
||||
*/
|
||||
void WaitForFinished();
|
||||
void WaitForFinished(QMutex *mutex);
|
||||
void wait_for_finished();
|
||||
void wait_for_finished(QMutex *mutex);
|
||||
|
||||
/**
|
||||
* @brief Access this ticket's mutex
|
||||
@@ -90,30 +90,30 @@ public:
|
||||
*
|
||||
* If any value is set, it is cleared.
|
||||
*/
|
||||
void Start();
|
||||
void start();
|
||||
|
||||
/**
|
||||
* @brief Finish ticket with no value
|
||||
*
|
||||
* Sets ticket to no longer running and assume it has received no result.
|
||||
*/
|
||||
void Finish();
|
||||
void finish();
|
||||
|
||||
/**
|
||||
* @brief Finish ticket with value
|
||||
*
|
||||
* Sets ticket to no longer running and provide a value generated by the operation requested.
|
||||
*/
|
||||
void Finish(QVariant result);
|
||||
void finish(QVariant result);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Emitted when finish has been called by any means (either cancelled or with a result)
|
||||
*/
|
||||
void Finished();
|
||||
void finished();
|
||||
|
||||
private:
|
||||
void FinishInternal(bool has_result, QVariant result);
|
||||
void finish_internal(bool has_result, QVariant result);
|
||||
|
||||
bool is_running_;
|
||||
|
||||
@@ -135,35 +135,35 @@ class RenderTicketWatcher : public QObject {
|
||||
public:
|
||||
RenderTicketWatcher(QObject *parent = nullptr);
|
||||
|
||||
RenderTicketPtr GetTicket() const
|
||||
RenderTicketPtr get_ticket() const
|
||||
{
|
||||
return ticket_;
|
||||
}
|
||||
|
||||
void SetTicket(RenderTicketPtr ticket);
|
||||
void set_ticket(RenderTicketPtr ticket);
|
||||
|
||||
bool IsRunning();
|
||||
bool is_running();
|
||||
|
||||
void WaitForFinished();
|
||||
void wait_for_finished();
|
||||
|
||||
QVariant Get();
|
||||
QVariant get();
|
||||
|
||||
bool HasResult();
|
||||
bool has_result();
|
||||
|
||||
void Cancel();
|
||||
void cancel();
|
||||
|
||||
signals:
|
||||
void Finished(RenderTicketWatcher *watcher);
|
||||
void finished(RenderTicketWatcher *watcher);
|
||||
|
||||
private:
|
||||
RenderTicketPtr ticket_;
|
||||
|
||||
private slots:
|
||||
void TicketFinished();
|
||||
void ticket_finished();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(olive::RenderTicketPtr)
|
||||
|
||||
#endif // RENDERTICKET_H
|
||||
#endif // OAK_RENDERTICKET_H
|
||||
|
||||
+231
-232
File diff suppressed because it is too large
Load Diff
@@ -18,8 +18,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERWORKERPOOL_H
|
||||
#define RENDERWORKERPOOL_H
|
||||
#ifndef OAK_RENDERWORKERPOOL_H
|
||||
#define OAK_RENDERWORKERPOOL_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QMutex>
|
||||
@@ -52,12 +52,12 @@ public:
|
||||
QObject *parent = nullptr);
|
||||
~RenderWorkerPool() override;
|
||||
|
||||
bool SubmitFrame(RenderTicketPtr ticket,
|
||||
bool submit_frame(RenderTicketPtr ticket,
|
||||
const RenderManager::RenderVideoParams ¶ms);
|
||||
|
||||
bool RemoveTicket(RenderTicketPtr ticket);
|
||||
bool remove_ticket(RenderTicketPtr ticket);
|
||||
|
||||
void Shutdown();
|
||||
void shutdown();
|
||||
|
||||
protected:
|
||||
void run() override;
|
||||
@@ -78,10 +78,10 @@ private:
|
||||
};
|
||||
|
||||
enum class JobResult {
|
||||
kFinished,
|
||||
kRetryableFailure,
|
||||
kFatalFailure,
|
||||
kCancelled
|
||||
k_finished,
|
||||
k_retryable_failure,
|
||||
k_fatal_failure,
|
||||
k_cancelled
|
||||
};
|
||||
|
||||
struct ActiveJob {
|
||||
@@ -113,41 +113,41 @@ private:
|
||||
QString path;
|
||||
};
|
||||
|
||||
bool PrepareJob(RenderTicketPtr ticket,
|
||||
bool prepare_job(RenderTicketPtr ticket,
|
||||
const RenderManager::RenderVideoParams ¶ms, Job *job);
|
||||
bool WriteGraphSnapshot(Project *project, QString *path);
|
||||
bool IsSupported(const RenderManager::RenderVideoParams ¶ms) const;
|
||||
bool write_graph_snapshot(Project *project, QString *path);
|
||||
bool is_supported(const RenderManager::RenderVideoParams ¶ms) const;
|
||||
|
||||
void WorkerLoop(int worker_index,
|
||||
void worker_loop(int worker_index,
|
||||
std::vector<std::unique_ptr<PooledWorker>> *local_pool);
|
||||
void ProcessJob(const Job &job, int worker_index,
|
||||
void process_job(const Job &job, int worker_index,
|
||||
std::vector<std::unique_ptr<PooledWorker>> *local_pool);
|
||||
JobResult ProcessJobAttempt(const Job &job, int worker_index,
|
||||
JobResult process_job_attempt(const Job &job, int worker_index,
|
||||
int attempt_index, PooledWorker *worker);
|
||||
void FinishWithFrame(RenderTicketPtr ticket, const ipc::FrameSlotPool &pool,
|
||||
void finish_with_frame(RenderTicketPtr ticket, const ipc::FrameSlotPool &pool,
|
||||
uint32_t slot);
|
||||
void CleanupGraphFile(const QString &path);
|
||||
void AddGraphPathRef(const QString &path);
|
||||
void AddGraphPathRefLocked(const QString &path);
|
||||
void ReleaseGraphPathRef(const QString &path);
|
||||
void ReleaseGraphPathRefLocked(const QString &path);
|
||||
void SetGraphPathCached(const QString &path, bool cached);
|
||||
void SetGraphPathCachedLocked(const QString &path, bool cached);
|
||||
void CancelActiveProcess(qint64 process_id);
|
||||
void SetActiveWorker(int worker_index, RenderTicketPtr ticket,
|
||||
void cleanup_graph_file(const QString &path);
|
||||
void add_graph_path_ref(const QString &path);
|
||||
void add_graph_path_ref_locked(const QString &path);
|
||||
void release_graph_path_ref(const QString &path);
|
||||
void release_graph_path_ref_locked(const QString &path);
|
||||
void set_graph_path_cached(const QString &path, bool cached);
|
||||
void set_graph_path_cached_locked(const QString &path, bool cached);
|
||||
void cancel_active_process(qint64 process_id);
|
||||
void set_active_worker(int worker_index, RenderTicketPtr ticket,
|
||||
QProcess *worker, qint64 ticket_id);
|
||||
void ClearActiveWorker(int worker_index, qint64 process_id);
|
||||
int WorkerCount() const;
|
||||
void clear_active_worker(int worker_index, qint64 process_id);
|
||||
int worker_count() const;
|
||||
|
||||
std::unique_ptr<PooledWorker>
|
||||
AcquireWorker(std::vector<std::unique_ptr<PooledWorker>> *local_pool,
|
||||
acquire_worker(std::vector<std::unique_ptr<PooledWorker>> *local_pool,
|
||||
const QString &graph_path);
|
||||
void ReturnWorker(std::vector<std::unique_ptr<PooledWorker>> *local_pool,
|
||||
void return_worker(std::vector<std::unique_ptr<PooledWorker>> *local_pool,
|
||||
std::unique_ptr<PooledWorker> worker, bool keep_alive);
|
||||
void ShutdownWorker(PooledWorker *worker);
|
||||
void shutdown_worker(PooledWorker *worker);
|
||||
void
|
||||
ShutdownLocalPool(std::vector<std::unique_ptr<PooledWorker>> *local_pool);
|
||||
void ClearGraphCache();
|
||||
shutdown_local_pool(std::vector<std::unique_ptr<PooledWorker>> *local_pool);
|
||||
void clear_graph_cache();
|
||||
|
||||
DecoderCache *decoder_cache_;
|
||||
QString gpu_backend_;
|
||||
@@ -160,14 +160,14 @@ private:
|
||||
QHash<QString, int> graph_path_ref_count_;
|
||||
QSet<QString> cached_graph_paths_;
|
||||
|
||||
static constexpr uint32_t kOutputSlots = 2;
|
||||
static constexpr int kMaxAttempts = 2;
|
||||
static constexpr int kMaxWidth = 4096;
|
||||
static constexpr int kMaxHeight = 2160;
|
||||
static constexpr int kWorkerIdleTimeoutMs = 30000;
|
||||
static constexpr int kWorkerMaxUses = 100;
|
||||
static constexpr uint32_t k_output_slots = 2;
|
||||
static constexpr int k_max_attempts = 2;
|
||||
static constexpr int k_max_width = 4096;
|
||||
static constexpr int k_max_height = 2160;
|
||||
static constexpr int k_worker_idle_timeout_ms = 30000;
|
||||
static constexpr int k_worker_max_uses = 100;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // RENDERWORKERPOOL_H
|
||||
#endif // OAK_RENDERWORKERPOOL_H
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef SHADERCODE_H
|
||||
#define SHADERCODE_H
|
||||
#ifndef OAK_SHADERCODE_H
|
||||
#define OAK_SHADERCODE_H
|
||||
|
||||
#include "common/filefunctions.h"
|
||||
|
||||
@@ -62,4 +62,4 @@ private:
|
||||
|
||||
}
|
||||
|
||||
#endif // SHADERCODE_H
|
||||
#endif // OAK_SHADERCODE_H
|
||||
|
||||
@@ -28,24 +28,24 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
QString SubtitleParams::GenerateASSHeader()
|
||||
QString SubtitleParams::generate_ass_header()
|
||||
{
|
||||
// NOTE: We'll probably implement more customization as we support ASS better. Right now, we only
|
||||
// natively support SRT and only make this header because FFmpeg requires it.
|
||||
static const int kAssDefaultPlayResX = 384;
|
||||
static const int kAssDefaultPlayResY = 288;
|
||||
static const QString kAssDefaultFont = QStringLiteral("Arial");
|
||||
static const int kAssDefaultFontSize = 16;
|
||||
static const int kAssDefaultPrimaryColor = 0xFFFFFF; // White
|
||||
static const int kAssDefaultSecondaryColor = 0xFFFFFF; // White
|
||||
static const int kAssDefaultOutlineColor = 0x000000; // Black
|
||||
static const int kAssDefaultBackColor = 0x000000; // Black
|
||||
static const int kAssBold = 0;
|
||||
static const int kAssItalic = 0;
|
||||
static const int kAssUnderline = 0;
|
||||
static const int kAssStrike = 0;
|
||||
static const int kAssBorderStyle = 1;
|
||||
static const int kAssAlignment = 2;
|
||||
static const int k_ass_default_play_res_x = 384;
|
||||
static const int k_ass_default_play_res_y = 288;
|
||||
static const QString k_ass_default_font = QStringLiteral("Arial");
|
||||
static const int k_ass_default_font_size = 16;
|
||||
static const int k_ass_default_primary_color = 0xFFFFFF; // White
|
||||
static const int k_ass_default_secondary_color = 0xFFFFFF; // White
|
||||
static const int k_ass_default_outline_color = 0x000000; // Black
|
||||
static const int k_ass_default_back_color = 0x000000; // Black
|
||||
static const int k_ass_bold = 0;
|
||||
static const int k_ass_italic = 0;
|
||||
static const int k_ass_underline = 0;
|
||||
static const int k_ass_strike = 0;
|
||||
static const int k_ass_border_style = 1;
|
||||
static const int k_ass_alignment = 2;
|
||||
|
||||
QString ass_code;
|
||||
|
||||
@@ -56,9 +56,9 @@ QString SubtitleParams::GenerateASSHeader()
|
||||
QCoreApplication::applicationVersion()));
|
||||
ass_code.append(QStringLiteral("ScriptType: v4.00+\r\n"));
|
||||
ass_code.append(QStringLiteral("PlayResX: %1\r\n")
|
||||
.arg(QString::number(kAssDefaultPlayResX)));
|
||||
.arg(QString::number(k_ass_default_play_res_x)));
|
||||
ass_code.append(QStringLiteral("PlayResY: %1\r\n")
|
||||
.arg(QString::number(kAssDefaultPlayResY)));
|
||||
.arg(QString::number(k_ass_default_play_res_y)));
|
||||
ass_code.append(QStringLiteral("ScaledBorderAndShadow: yes\r\n"));
|
||||
ass_code.append(QStringLiteral("\r\n"));
|
||||
|
||||
@@ -81,20 +81,20 @@ QString SubtitleParams::GenerateASSHeader()
|
||||
|
||||
// Font{name,size}
|
||||
ass_code.append(QStringLiteral("%1,%2,").arg(
|
||||
kAssDefaultFont, QString::number(kAssDefaultFontSize)));
|
||||
k_ass_default_font, QString::number(k_ass_default_font_size)));
|
||||
|
||||
// {Primary,Secondary,Outline,Back}Colour
|
||||
ass_code.append(QStringLiteral("&H%1,&H%2,&H%3,&H%4,")
|
||||
.arg(QString::number(kAssDefaultPrimaryColor, 16),
|
||||
QString::number(kAssDefaultSecondaryColor, 16),
|
||||
QString::number(kAssDefaultOutlineColor, 16),
|
||||
QString::number(kAssDefaultBackColor, 16)));
|
||||
.arg(QString::number(k_ass_default_primary_color, 16),
|
||||
QString::number(k_ass_default_secondary_color, 16),
|
||||
QString::number(k_ass_default_outline_color, 16),
|
||||
QString::number(k_ass_default_back_color, 16)));
|
||||
|
||||
// Bold, Italic, Underline, StrikeOut
|
||||
ass_code.append(
|
||||
QStringLiteral("%1,%2,%3,%4,")
|
||||
.arg(QString::number(kAssBold), QString::number(kAssItalic),
|
||||
QString::number(kAssUnderline), QString::number(kAssStrike)));
|
||||
.arg(QString::number(k_ass_bold), QString::number(k_ass_italic),
|
||||
QString::number(k_ass_underline), QString::number(k_ass_strike)));
|
||||
|
||||
// Scale{X,Y}
|
||||
ass_code.append(QStringLiteral("100,100,"));
|
||||
@@ -104,11 +104,11 @@ QString SubtitleParams::GenerateASSHeader()
|
||||
|
||||
// BorderStyle, Outline, Shadow
|
||||
ass_code.append(
|
||||
QStringLiteral("%1,1,0,").arg(QString::number(kAssBorderStyle)));
|
||||
QStringLiteral("%1,1,0,").arg(QString::number(k_ass_border_style)));
|
||||
|
||||
// Alignment, Margin[LRV]
|
||||
ass_code.append(
|
||||
QStringLiteral("%1,10,10,10,").arg(QString::number(kAssAlignment)));
|
||||
QStringLiteral("%1,10,10,10,").arg(QString::number(k_ass_alignment)));
|
||||
|
||||
// Encoding
|
||||
ass_code.append(QStringLiteral("0\r\n"));
|
||||
@@ -120,28 +120,28 @@ QString SubtitleParams::GenerateASSHeader()
|
||||
return ass_code;
|
||||
}
|
||||
|
||||
void SubtitleParams::Load(QXmlStreamReader *reader)
|
||||
void SubtitleParams::load(QXmlStreamReader *reader)
|
||||
{
|
||||
this->clear();
|
||||
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
while (xml_read_next_start_element(reader)) {
|
||||
if (reader->name() == QStringLiteral("streamindex")) {
|
||||
set_stream_index(reader->readElementText().toInt());
|
||||
} else if (reader->name() == QStringLiteral("enabled")) {
|
||||
set_enabled(reader->readElementText().toInt());
|
||||
} else if (reader->name() == QStringLiteral("subtitles")) {
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
while (xml_read_next_start_element(reader)) {
|
||||
if (reader->name() == QStringLiteral("subtitle")) {
|
||||
rational in, out;
|
||||
Rational in, out;
|
||||
QString text;
|
||||
|
||||
XMLAttributeLoop(reader, attr)
|
||||
{
|
||||
if (attr.name() == QStringLiteral("in")) {
|
||||
in = rational::fromString(
|
||||
in = Rational::from_string(
|
||||
attr.value().toString().toStdString());
|
||||
} else if (attr.name() == QStringLiteral("out")) {
|
||||
out = rational::fromString(
|
||||
out = Rational::from_string(
|
||||
attr.value().toString().toStdString());
|
||||
}
|
||||
}
|
||||
@@ -159,7 +159,7 @@ void SubtitleParams::Load(QXmlStreamReader *reader)
|
||||
}
|
||||
}
|
||||
|
||||
void SubtitleParams::Save(QXmlStreamWriter *writer) const
|
||||
void SubtitleParams::save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeTextElement(QStringLiteral("streamindex"),
|
||||
QString::number(stream_index_));
|
||||
@@ -171,10 +171,10 @@ void SubtitleParams::Save(QXmlStreamWriter *writer) const
|
||||
writer->writeStartElement(QStringLiteral("subtitle"));
|
||||
writer->writeAttribute(
|
||||
QStringLiteral("in"),
|
||||
QString::fromStdString(it->time().in().toString()));
|
||||
QString::fromStdString(it->time().in().to_string()));
|
||||
writer->writeAttribute(
|
||||
QStringLiteral("out"),
|
||||
QString::fromStdString(it->time().out().toString()));
|
||||
QString::fromStdString(it->time().out().to_string()));
|
||||
writer->writeCharacters(it->text());
|
||||
writer->writeEndElement(); // subtitle
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef SUBTITLEPARAMS_H
|
||||
#define SUBTITLEPARAMS_H
|
||||
#ifndef OAK_SUBTITLEPARAMS_H
|
||||
#define OAK_SUBTITLEPARAMS_H
|
||||
|
||||
#include <olive/core/core.h>
|
||||
#include <QRect>
|
||||
@@ -75,18 +75,18 @@ public:
|
||||
enabled_ = true;
|
||||
}
|
||||
|
||||
static QString GenerateASSHeader();
|
||||
static QString generate_ass_header();
|
||||
|
||||
void Load(QXmlStreamReader *reader);
|
||||
void load(QXmlStreamReader *reader);
|
||||
|
||||
void Save(QXmlStreamWriter *writer) const;
|
||||
void save(QXmlStreamWriter *writer) const;
|
||||
|
||||
bool is_valid() const
|
||||
{
|
||||
return !this->empty();
|
||||
}
|
||||
|
||||
rational duration() const
|
||||
Rational duration() const
|
||||
{
|
||||
if (this->empty()) {
|
||||
return 0;
|
||||
@@ -124,4 +124,4 @@ private:
|
||||
Q_DECLARE_METATYPE(olive::Subtitle)
|
||||
Q_DECLARE_METATYPE(olive::SubtitleParams)
|
||||
|
||||
#endif // SUBTITLEPARAMS_H
|
||||
#endif // OAK_SUBTITLEPARAMS_H
|
||||
|
||||
+10
-10
@@ -27,13 +27,13 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
const Texture::Interpolation Texture::kDefaultInterpolation =
|
||||
Texture::kMipmappedLinear;
|
||||
const Texture::Interpolation Texture::k_default_interpolation =
|
||||
Texture::k_mipmapped_linear;
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
if (IsRendererAlive()) {
|
||||
renderer_->DestroyTexture(this);
|
||||
if (is_renderer_alive()) {
|
||||
renderer_->destroy_texture(this);
|
||||
}
|
||||
|
||||
if (job_) {
|
||||
@@ -41,17 +41,17 @@ Texture::~Texture()
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::Upload(void *data, int linesize)
|
||||
void Texture::upload(void *data, int linesize)
|
||||
{
|
||||
if (IsRendererAlive()) {
|
||||
renderer_->UploadToTexture(this->id(), this->params(), data, linesize);
|
||||
if (is_renderer_alive()) {
|
||||
renderer_->upload_to_texture(this->id(), this->params(), data, linesize);
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::Download(void *data, int linesize)
|
||||
void Texture::download(void *data, int linesize)
|
||||
{
|
||||
if (IsRendererAlive()) {
|
||||
renderer_->DownloadFromTexture(this->id(), this->params(), data,
|
||||
if (is_renderer_alive()) {
|
||||
renderer_->download_from_texture(this->id(), this->params(), data,
|
||||
linesize);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-15
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef RENDERTEXTURE_H
|
||||
#define RENDERTEXTURE_H
|
||||
#ifndef OAK_RENDERTEXTURE_H
|
||||
#define OAK_RENDERTEXTURE_H
|
||||
|
||||
#include "common/avframeptr.h"
|
||||
|
||||
@@ -44,9 +44,9 @@ using TexturePtr = std::shared_ptr<Texture>;
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
enum Interpolation { kNearest, kLinear, kMipmappedLinear };
|
||||
enum Interpolation { k_nearest, k_linear, k_mipmapped_linear };
|
||||
|
||||
static const Interpolation kDefaultInterpolation;
|
||||
static const Interpolation k_default_interpolation;
|
||||
|
||||
/**
|
||||
* @brief Construct a dummy texture with no renderer backend
|
||||
@@ -93,21 +93,21 @@ public:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static TexturePtr Job(const VideoParams &p, const T &j)
|
||||
static TexturePtr job(const VideoParams &p, const T &j)
|
||||
{
|
||||
return std::make_shared<Texture>(p, j);
|
||||
}
|
||||
|
||||
template <typename T> TexturePtr toJob(const T &job)
|
||||
template <typename T> TexturePtr to_job(const T &job)
|
||||
{
|
||||
return Texture::Job(params_, job);
|
||||
return Texture::job(params_, job);
|
||||
}
|
||||
|
||||
void Upload(void *data, int linesize);
|
||||
void upload(void *data, int linesize);
|
||||
|
||||
void Download(void *data, int linesize);
|
||||
void download(void *data, int linesize);
|
||||
|
||||
bool IsDummy() const
|
||||
bool is_dummy() const
|
||||
{
|
||||
return !renderer_;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
return params_.divider();
|
||||
}
|
||||
|
||||
const rational &pixel_aspect_ratio() const
|
||||
const Rational &pixel_aspect_ratio() const
|
||||
{
|
||||
return params_.pixel_aspect_ratio();
|
||||
}
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
return renderer_;
|
||||
}
|
||||
|
||||
bool IsJob() const
|
||||
bool is_job() const
|
||||
{
|
||||
return job_;
|
||||
}
|
||||
@@ -160,7 +160,7 @@ public:
|
||||
{
|
||||
return job_;
|
||||
}
|
||||
void handleFrame(AVFramePtr ptr)
|
||||
void handle_frame(AVFramePtr ptr)
|
||||
{
|
||||
frame_ = ptr;
|
||||
}
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool IsRendererAlive() const
|
||||
bool is_renderer_alive() const
|
||||
{
|
||||
return renderer_ &&
|
||||
(!renderer_lifetime_ || renderer_lifetime_->alive.load());
|
||||
@@ -192,4 +192,4 @@ private:
|
||||
|
||||
Q_DECLARE_METATYPE(olive::TexturePtr)
|
||||
|
||||
#endif // RENDERTEXTURE_H
|
||||
#endif // OAK_RENDERTEXTURE_H
|
||||
|
||||
+97
-97
@@ -32,41 +32,41 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
const int VideoParams::kInternalChannelCount = kRGBAChannelCount;
|
||||
const int VideoParams::k_internal_channel_count = k_rgba_channel_count;
|
||||
|
||||
const rational VideoParams::kPixelAspectSquare(1);
|
||||
const rational VideoParams::kPixelAspectNTSCStandard(8, 9);
|
||||
const rational VideoParams::kPixelAspectNTSCWidescreen(32, 27);
|
||||
const rational VideoParams::kPixelAspectPALStandard(16, 15);
|
||||
const rational VideoParams::kPixelAspectPALWidescreen(64, 45);
|
||||
const rational VideoParams::kPixelAspect1080Anamorphic(4, 3);
|
||||
const Rational VideoParams::k_pixel_aspect_square(1);
|
||||
const Rational VideoParams::k_pixel_aspect_ntsc_standard(8, 9);
|
||||
const Rational VideoParams::k_pixel_aspect_ntsc_widescreen(32, 27);
|
||||
const Rational VideoParams::k_pixel_aspect_pal_standard(16, 15);
|
||||
const Rational VideoParams::k_pixel_aspect_pal_widescreen(64, 45);
|
||||
const Rational VideoParams::k_pixel_aspect1080_anamorphic(4, 3);
|
||||
|
||||
const QVector<rational> VideoParams::kSupportedFrameRates = {
|
||||
rational(10, 1), // 10 FPS
|
||||
rational(15, 1), // 15 FPS
|
||||
rational(24000, 1001), // 23.976 FPS
|
||||
rational(24, 1), // 24 FPS
|
||||
rational(25, 1), // 25 FPS
|
||||
rational(30000, 1001), // 29.97 FPS
|
||||
rational(30, 1), // 30 FPS
|
||||
rational(48000, 1001), // 47.952 FPS
|
||||
rational(48, 1), // 48 FPS
|
||||
rational(50, 1), // 50 FPS
|
||||
rational(60000, 1001), // 59.94 FPS
|
||||
rational(60, 1) // 60 FPS
|
||||
const QVector<Rational> VideoParams::k_supported_frame_rates = {
|
||||
Rational(10, 1), // 10 FPS
|
||||
Rational(15, 1), // 15 FPS
|
||||
Rational(24000, 1001), // 23.976 FPS
|
||||
Rational(24, 1), // 24 FPS
|
||||
Rational(25, 1), // 25 FPS
|
||||
Rational(30000, 1001), // 29.97 FPS
|
||||
Rational(30, 1), // 30 FPS
|
||||
Rational(48000, 1001), // 47.952 FPS
|
||||
Rational(48, 1), // 48 FPS
|
||||
Rational(50, 1), // 50 FPS
|
||||
Rational(60000, 1001), // 59.94 FPS
|
||||
Rational(60, 1) // 60 FPS
|
||||
};
|
||||
|
||||
const QVector<int> VideoParams::kSupportedDividers = {
|
||||
const QVector<int> VideoParams::k_supported_dividers = {
|
||||
1, 2, 3, 4, 6, 8, 12, 16
|
||||
};
|
||||
|
||||
const QVector<rational> VideoParams::kStandardPixelAspects = {
|
||||
VideoParams::kPixelAspectSquare,
|
||||
VideoParams::kPixelAspectNTSCStandard,
|
||||
VideoParams::kPixelAspectNTSCWidescreen,
|
||||
VideoParams::kPixelAspectPALStandard,
|
||||
VideoParams::kPixelAspectPALWidescreen,
|
||||
VideoParams::kPixelAspect1080Anamorphic
|
||||
const QVector<Rational> VideoParams::k_standard_pixel_aspects = {
|
||||
VideoParams::k_pixel_aspect_square,
|
||||
VideoParams::k_pixel_aspect_ntsc_standard,
|
||||
VideoParams::k_pixel_aspect_ntsc_widescreen,
|
||||
VideoParams::k_pixel_aspect_pal_standard,
|
||||
VideoParams::k_pixel_aspect_pal_widescreen,
|
||||
VideoParams::k_pixel_aspect1080_anamorphic
|
||||
};
|
||||
|
||||
VideoParams::VideoParams()
|
||||
@@ -74,10 +74,10 @@ VideoParams::VideoParams()
|
||||
, height_(0)
|
||||
, depth_(0)
|
||||
, time_base_(0)
|
||||
, format_(PixelFormat::INVALID)
|
||||
, format_(PixelFormat::invalid)
|
||||
, channel_count_(0)
|
||||
, pixel_aspect_ratio_(1)
|
||||
, interlacing_(Interlacing::kInterlaceNone)
|
||||
, interlacing_(Interlacing::k_interlace_none)
|
||||
, divider_(1)
|
||||
{
|
||||
calculate_effective_size();
|
||||
@@ -86,7 +86,7 @@ VideoParams::VideoParams()
|
||||
}
|
||||
|
||||
VideoParams::VideoParams(int width, int height, PixelFormat format,
|
||||
int nb_channels, const rational &pixel_aspect_ratio,
|
||||
int nb_channels, const Rational &pixel_aspect_ratio,
|
||||
Interlacing interlacing, int divider)
|
||||
: width_(width)
|
||||
, height_(height)
|
||||
@@ -103,7 +103,7 @@ VideoParams::VideoParams(int width, int height, PixelFormat format,
|
||||
}
|
||||
|
||||
VideoParams::VideoParams(int width, int height, int depth, PixelFormat format,
|
||||
int nb_channels, const rational &pixel_aspect_ratio,
|
||||
int nb_channels, const Rational &pixel_aspect_ratio,
|
||||
VideoParams::Interlacing interlacing, int divider)
|
||||
: width_(width)
|
||||
, height_(height)
|
||||
@@ -119,20 +119,20 @@ VideoParams::VideoParams(int width, int height, int depth, PixelFormat format,
|
||||
set_defaults_for_footage();
|
||||
}
|
||||
|
||||
void VideoParams::set_channel_count(const std::string &ofxComponent)
|
||||
void VideoParams::set_channel_count(const std::string &ofx_component)
|
||||
{
|
||||
if (ofxComponent == kOfxImageComponentAlpha) {
|
||||
if (ofx_component == kOfxImageComponentAlpha) {
|
||||
channel_count_ = 1;
|
||||
} else if (ofxComponent == kOfxImageComponentRGB) {
|
||||
channel_count_ = kRGBChannelCount;
|
||||
} else if (ofxComponent == kOfxImageComponentRGBA) {
|
||||
channel_count_ = kRGBAChannelCount;
|
||||
} else if (ofx_component == kOfxImageComponentRGB) {
|
||||
channel_count_ = k_rgb_channel_count;
|
||||
} else if (ofx_component == kOfxImageComponentRGBA) {
|
||||
channel_count_ = k_rgba_channel_count;
|
||||
}
|
||||
}
|
||||
|
||||
VideoParams::VideoParams(int width, int height, const rational &time_base,
|
||||
VideoParams::VideoParams(int width, int height, const Rational &time_base,
|
||||
PixelFormat format, int nb_channels,
|
||||
const rational &pixel_aspect_ratio,
|
||||
const Rational &pixel_aspect_ratio,
|
||||
Interlacing interlacing, int divider)
|
||||
: width_(width)
|
||||
, height_(height)
|
||||
@@ -159,14 +159,14 @@ int VideoParams::generate_auto_divider(qint64 width, qint64 height)
|
||||
double squared_divider = double(megapixels) / double(target_res);
|
||||
double divider = qSqrt(squared_divider);
|
||||
|
||||
if (divider <= kSupportedDividers.first()) {
|
||||
return kSupportedDividers.first();
|
||||
} else if (divider >= kSupportedDividers.last()) {
|
||||
return kSupportedDividers.last();
|
||||
if (divider <= k_supported_dividers.first()) {
|
||||
return k_supported_dividers.first();
|
||||
} else if (divider >= k_supported_dividers.last()) {
|
||||
return k_supported_dividers.last();
|
||||
} else {
|
||||
for (int i = 1; i < kSupportedDividers.size(); i++) {
|
||||
int prev_divider = kSupportedDividers.at(i - 1);
|
||||
int next_divider = kSupportedDividers.at(i);
|
||||
for (int i = 1; i < k_supported_dividers.size(); i++) {
|
||||
int prev_divider = k_supported_dividers.at(i - 1);
|
||||
int next_divider = k_supported_dividers.at(i);
|
||||
|
||||
if (divider >= prev_divider && divider <= next_divider) {
|
||||
double prev_diff = qAbs(prev_divider - divider);
|
||||
@@ -199,36 +199,36 @@ bool VideoParams::operator!=(const VideoParams &rhs) const
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
int VideoParams::GetBytesPerChannel(PixelFormat format)
|
||||
int VideoParams::get_bytes_per_channel(PixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::INVALID:
|
||||
case PixelFormat::COUNT:
|
||||
case PixelFormat::invalid:
|
||||
case PixelFormat::count:
|
||||
break;
|
||||
case PixelFormat::U8:
|
||||
case PixelFormat::u8:
|
||||
return 1;
|
||||
case PixelFormat::U10:
|
||||
case PixelFormat::u10:
|
||||
return 0; // packed format, use GetBytesPerPixel instead
|
||||
case PixelFormat::U16:
|
||||
case PixelFormat::F16:
|
||||
case PixelFormat::u16:
|
||||
case PixelFormat::f16:
|
||||
return 2;
|
||||
case PixelFormat::F32:
|
||||
case PixelFormat::f32:
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VideoParams::GetBytesPerPixel(PixelFormat format, int channels)
|
||||
int VideoParams::get_bytes_per_pixel(PixelFormat format, int channels)
|
||||
{
|
||||
if (format == PixelFormat::U10) {
|
||||
if (format == PixelFormat::u10) {
|
||||
// Packed 10-bit RGBA10A2: 4 bytes per RGBA pixel regardless of channel count
|
||||
return channels == VideoParams::kRGBAChannelCount ? 4 : 0;
|
||||
return channels == VideoParams::k_rgba_channel_count ? 4 : 0;
|
||||
}
|
||||
return GetBytesPerChannel(format) * channels;
|
||||
return get_bytes_per_channel(format) * channels;
|
||||
}
|
||||
|
||||
QString VideoParams::GetNameForDivider(int div)
|
||||
QString VideoParams::get_name_for_divider(int div)
|
||||
{
|
||||
if (div == 1) {
|
||||
return QCoreApplication::translate("VideoParams", "Full");
|
||||
@@ -237,23 +237,23 @@ QString VideoParams::GetNameForDivider(int div)
|
||||
}
|
||||
}
|
||||
|
||||
QString VideoParams::GetFormatName(PixelFormat format)
|
||||
QString VideoParams::get_format_name(PixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::U8:
|
||||
case PixelFormat::u8:
|
||||
return QCoreApplication::translate("VideoParams", "8-bit");
|
||||
case PixelFormat::U10:
|
||||
case PixelFormat::u10:
|
||||
return QCoreApplication::translate("VideoParams", "10-bit Packed");
|
||||
case PixelFormat::U16:
|
||||
case PixelFormat::u16:
|
||||
return QCoreApplication::translate("VideoParams", "16-bit Integer");
|
||||
case PixelFormat::F16:
|
||||
case PixelFormat::f16:
|
||||
return QCoreApplication::translate("VideoParams",
|
||||
"Half-Float (16-bit)");
|
||||
case PixelFormat::F32:
|
||||
case PixelFormat::f32:
|
||||
return QCoreApplication::translate("VideoParams",
|
||||
"Full-Float (32-bit)");
|
||||
case PixelFormat::INVALID:
|
||||
case PixelFormat::COUNT:
|
||||
case PixelFormat::invalid:
|
||||
case PixelFormat::count:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ QString VideoParams::GetFormatName(PixelFormat format)
|
||||
.arg(static_cast<int>(format), 0, 16);
|
||||
}
|
||||
|
||||
int VideoParams::GetDividerForTargetResolution(int src_width, int src_height,
|
||||
int VideoParams::get_divider_for_target_resolution(int src_width, int src_height,
|
||||
int dst_width, int dst_height)
|
||||
{
|
||||
int divider = 0;
|
||||
@@ -270,8 +270,8 @@ int VideoParams::GetDividerForTargetResolution(int src_width, int src_height,
|
||||
do {
|
||||
divider++;
|
||||
|
||||
test_width = VideoParams::GetScaledDimension(src_width, divider);
|
||||
test_height = VideoParams::GetScaledDimension(src_height, divider);
|
||||
test_width = VideoParams::get_scaled_dimension(src_width, divider);
|
||||
test_height = VideoParams::get_scaled_dimension(src_height, divider);
|
||||
} while (test_width > dst_width || test_height > dst_height);
|
||||
|
||||
return divider;
|
||||
@@ -279,10 +279,10 @@ int VideoParams::GetDividerForTargetResolution(int src_width, int src_height,
|
||||
|
||||
void VideoParams::calculate_effective_size()
|
||||
{
|
||||
effective_width_ = GetScaledDimension(width(), divider_);
|
||||
effective_height_ = GetScaledDimension(height(), divider_);
|
||||
effective_width_ = get_scaled_dimension(width(), divider_);
|
||||
effective_height_ = get_scaled_dimension(height(), divider_);
|
||||
effective_depth_ = (depth() == 1) ? depth() :
|
||||
GetScaledDimension(depth(), divider_);
|
||||
get_scaled_dimension(depth(), divider_);
|
||||
calculate_square_pixel_width();
|
||||
}
|
||||
|
||||
@@ -298,19 +298,19 @@ void VideoParams::set_defaults_for_footage()
|
||||
{
|
||||
enabled_ = true;
|
||||
stream_index_ = 0;
|
||||
video_type_ = kVideoTypeVideo;
|
||||
video_type_ = k_video_type_video;
|
||||
start_time_ = 0;
|
||||
duration_ = 0;
|
||||
premultiplied_alpha_ = false;
|
||||
x_ = 0;
|
||||
y_ = 0;
|
||||
color_range_ = kColorRangeDefault;
|
||||
color_range_ = k_color_range_default;
|
||||
}
|
||||
|
||||
void VideoParams::calculate_square_pixel_width()
|
||||
{
|
||||
if (pixel_aspect_ratio_.denominator() != 0) {
|
||||
par_width_ = qRound(width_ * pixel_aspect_ratio_.toDouble());
|
||||
par_width_ = qRound(width_ * pixel_aspect_ratio_.to_double());
|
||||
} else {
|
||||
par_width_ = width_;
|
||||
}
|
||||
@@ -319,17 +319,17 @@ void VideoParams::calculate_square_pixel_width()
|
||||
bool VideoParams::is_valid() const
|
||||
{
|
||||
return (width() > 0 && height() > 0 && !pixel_aspect_ratio_.isNull() &&
|
||||
format_ > PixelFormat::INVALID && format_ < PixelFormat::COUNT &&
|
||||
format_ > PixelFormat::invalid && format_ < PixelFormat::count &&
|
||||
channel_count_ > 0);
|
||||
}
|
||||
|
||||
QString VideoParams::FrameRateToString(const rational &frame_rate)
|
||||
QString VideoParams::frame_rate_to_string(const Rational &frame_rate)
|
||||
{
|
||||
return QCoreApplication::translate("VideoParams", "%1 FPS")
|
||||
.arg(frame_rate.toDouble());
|
||||
.arg(frame_rate.to_double());
|
||||
}
|
||||
|
||||
QStringList VideoParams::GetStandardPixelAspectRatioNames()
|
||||
QStringList VideoParams::get_standard_pixel_aspect_ratio_names()
|
||||
{
|
||||
QStringList strings = {
|
||||
QCoreApplication::translate("VideoParams", "Square Pixels (%1)"),
|
||||
@@ -342,25 +342,25 @@ QStringList VideoParams::GetStandardPixelAspectRatioNames()
|
||||
|
||||
// Format each
|
||||
for (int i = 0; i < strings.size(); i++) {
|
||||
strings.replace(i, FormatPixelAspectRatioString(
|
||||
strings.at(i), kStandardPixelAspects.at(i)));
|
||||
strings.replace(i, format_pixel_aspect_ratio_string(
|
||||
strings.at(i), k_standard_pixel_aspects.at(i)));
|
||||
}
|
||||
|
||||
return strings;
|
||||
}
|
||||
|
||||
QString VideoParams::FormatPixelAspectRatioString(const QString &format,
|
||||
const rational &ratio)
|
||||
QString VideoParams::format_pixel_aspect_ratio_string(const QString &format,
|
||||
const Rational &ratio)
|
||||
{
|
||||
return format.arg(QString::number(ratio.toDouble(), 'f', 4));
|
||||
return format.arg(QString::number(ratio.to_double(), 'f', 4));
|
||||
}
|
||||
|
||||
int VideoParams::GetScaledDimension(int dim, int divider)
|
||||
int VideoParams::get_scaled_dimension(int dim, int divider)
|
||||
{
|
||||
return dim / divider;
|
||||
}
|
||||
|
||||
int64_t VideoParams::get_time_in_timebase_units(const rational &time) const
|
||||
int64_t VideoParams::get_time_in_timebase_units(const Rational &time) const
|
||||
{
|
||||
if (time_base_.isNull()) {
|
||||
return INT64_MIN; // AV_NOPTS_VALUE
|
||||
@@ -369,9 +369,9 @@ int64_t VideoParams::get_time_in_timebase_units(const rational &time) const
|
||||
return Timecode::time_to_timestamp(time, time_base_) + start_time_;
|
||||
}
|
||||
|
||||
void VideoParams::Load(QXmlStreamReader *reader)
|
||||
void VideoParams::load(QXmlStreamReader *reader)
|
||||
{
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
while (xml_read_next_start_element(reader)) {
|
||||
if (reader->name() == QStringLiteral("width")) {
|
||||
set_width(reader->readElementText().toInt());
|
||||
} else if (reader->name() == QStringLiteral("height")) {
|
||||
@@ -380,7 +380,7 @@ void VideoParams::Load(QXmlStreamReader *reader)
|
||||
set_depth(reader->readElementText().toInt());
|
||||
} else if (reader->name() == QStringLiteral("timebase")) {
|
||||
set_time_base(
|
||||
rational::fromString(reader->readElementText().toStdString()));
|
||||
Rational::from_string(reader->readElementText().toStdString()));
|
||||
} else if (reader->name() == QStringLiteral("format")) {
|
||||
set_format(static_cast<PixelFormat::Format>(
|
||||
reader->readElementText().toInt()));
|
||||
@@ -388,7 +388,7 @@ void VideoParams::Load(QXmlStreamReader *reader)
|
||||
set_channel_count(reader->readElementText().toInt());
|
||||
} else if (reader->name() == QStringLiteral("pixelaspectratio")) {
|
||||
set_pixel_aspect_ratio(
|
||||
rational::fromString(reader->readElementText().toStdString()));
|
||||
Rational::from_string(reader->readElementText().toStdString()));
|
||||
} else if (reader->name() == QStringLiteral("interlacing")) {
|
||||
set_interlacing(static_cast<VideoParams::Interlacing>(
|
||||
reader->readElementText().toInt()));
|
||||
@@ -407,7 +407,7 @@ void VideoParams::Load(QXmlStreamReader *reader)
|
||||
reader->readElementText().toInt()));
|
||||
} else if (reader->name() == QStringLiteral("framerate")) {
|
||||
set_frame_rate(
|
||||
rational::fromString(reader->readElementText().toStdString()));
|
||||
Rational::from_string(reader->readElementText().toStdString()));
|
||||
} else if (reader->name() == QStringLiteral("starttime")) {
|
||||
set_start_time(reader->readElementText().toLongLong());
|
||||
} else if (reader->name() == QStringLiteral("duration")) {
|
||||
@@ -425,21 +425,21 @@ void VideoParams::Load(QXmlStreamReader *reader)
|
||||
}
|
||||
}
|
||||
|
||||
void VideoParams::Save(QXmlStreamWriter *writer) const
|
||||
void VideoParams::save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeTextElement(QStringLiteral("width"), QString::number(width_));
|
||||
writer->writeTextElement(QStringLiteral("height"),
|
||||
QString::number(height_));
|
||||
writer->writeTextElement(QStringLiteral("depth"), QString::number(depth_));
|
||||
writer->writeTextElement(QStringLiteral("timebase"),
|
||||
QString::fromStdString(time_base_.toString()));
|
||||
QString::fromStdString(time_base_.to_string()));
|
||||
writer->writeTextElement(QStringLiteral("format"),
|
||||
QString::number(format_));
|
||||
writer->writeTextElement(QStringLiteral("channelcount"),
|
||||
QString::number(channel_count_));
|
||||
writer->writeTextElement(
|
||||
QStringLiteral("pixelaspectratio"),
|
||||
QString::fromStdString(pixel_aspect_ratio_.toString()));
|
||||
QString::fromStdString(pixel_aspect_ratio_.to_string()));
|
||||
writer->writeTextElement(QStringLiteral("interlacing"),
|
||||
QString::number(interlacing_));
|
||||
writer->writeTextElement(QStringLiteral("divider"),
|
||||
@@ -453,7 +453,7 @@ void VideoParams::Save(QXmlStreamWriter *writer) const
|
||||
writer->writeTextElement(QStringLiteral("videotype"),
|
||||
QString::number(video_type_));
|
||||
writer->writeTextElement(QStringLiteral("framerate"),
|
||||
QString::fromStdString(frame_rate_.toString()));
|
||||
QString::fromStdString(frame_rate_.to_string()));
|
||||
writer->writeTextElement(QStringLiteral("starttime"),
|
||||
QString::number(start_time_));
|
||||
writer->writeTextElement(QStringLiteral("duration"),
|
||||
|
||||
+64
-64
@@ -19,8 +19,8 @@
|
||||
|
||||
***/
|
||||
|
||||
#ifndef VIDEOPARAMS_H
|
||||
#define VIDEOPARAMS_H
|
||||
#ifndef OAK_VIDEOPARAMS_H
|
||||
#define OAK_VIDEOPARAMS_H
|
||||
|
||||
#include <olive/core/core.h>
|
||||
#include <QVector2D>
|
||||
@@ -36,30 +36,30 @@ using namespace core;
|
||||
class VideoParams {
|
||||
public:
|
||||
enum Interlacing {
|
||||
kInterlaceNone,
|
||||
kInterlacedTopFirst,
|
||||
kInterlacedBottomFirst
|
||||
k_interlace_none,
|
||||
k_interlaced_top_first,
|
||||
k_interlaced_bottom_first
|
||||
};
|
||||
|
||||
enum Type { kVideoTypeVideo, kVideoTypeStill, kVideoTypeImageSequence };
|
||||
enum Type { k_video_type_video, k_video_type_still, k_video_type_image_sequence };
|
||||
enum ColorRange {
|
||||
kColorRangeLimited, // 16_235
|
||||
kColorRangeFull, // 0-255
|
||||
k_color_range_limited, // 16_235
|
||||
k_color_range_full, // 0-255
|
||||
|
||||
kColorRangeDefault = kColorRangeLimited
|
||||
k_color_range_default = k_color_range_limited
|
||||
};
|
||||
|
||||
VideoParams();
|
||||
VideoParams(int width, int height, PixelFormat format, int nb_channels,
|
||||
const rational &pixel_aspect_ratio = 1,
|
||||
Interlacing interlacing = kInterlaceNone, int divider = 1);
|
||||
const Rational &pixel_aspect_ratio = 1,
|
||||
Interlacing interlacing = k_interlace_none, int divider = 1);
|
||||
VideoParams(int width, int height, int depth, PixelFormat format,
|
||||
int nb_channels, const rational &pixel_aspect_ratio = 1,
|
||||
Interlacing interlacing = kInterlaceNone, int divider = 1);
|
||||
VideoParams(int width, int height, const rational &time_base,
|
||||
int nb_channels, const Rational &pixel_aspect_ratio = 1,
|
||||
Interlacing interlacing = k_interlace_none, int divider = 1);
|
||||
VideoParams(int width, int height, const Rational &time_base,
|
||||
PixelFormat format, int nb_channels,
|
||||
const rational &pixel_aspect_ratio = 1,
|
||||
Interlacing interlacing = kInterlaceNone, int divider = 1);
|
||||
const Rational &pixel_aspect_ratio = 1,
|
||||
Interlacing interlacing = k_interlace_none, int divider = 1);
|
||||
|
||||
int width() const
|
||||
{
|
||||
@@ -117,17 +117,17 @@ public:
|
||||
return depth_ > 1;
|
||||
}
|
||||
|
||||
const rational &time_base() const
|
||||
const Rational &time_base() const
|
||||
{
|
||||
return time_base_;
|
||||
}
|
||||
|
||||
void set_time_base(const rational &r)
|
||||
void set_time_base(const Rational &r)
|
||||
{
|
||||
time_base_ = r;
|
||||
}
|
||||
|
||||
rational frame_rate_as_time_base() const
|
||||
Rational frame_rate_as_time_base() const
|
||||
{
|
||||
return frame_rate_.flipped();
|
||||
}
|
||||
@@ -177,13 +177,13 @@ public:
|
||||
{
|
||||
channel_count_ = c;
|
||||
}
|
||||
void set_channel_count(const std::string &ofxComponent);
|
||||
const rational &pixel_aspect_ratio() const
|
||||
void set_channel_count(const std::string &ofx_component);
|
||||
const Rational &pixel_aspect_ratio() const
|
||||
{
|
||||
return pixel_aspect_ratio_;
|
||||
}
|
||||
|
||||
void set_pixel_aspect_ratio(const rational &r)
|
||||
void set_pixel_aspect_ratio(const Rational &r)
|
||||
{
|
||||
pixel_aspect_ratio_ = r;
|
||||
validate_pixel_aspect_ratio();
|
||||
@@ -206,67 +206,67 @@ public:
|
||||
bool operator==(const VideoParams &rhs) const;
|
||||
bool operator!=(const VideoParams &rhs) const;
|
||||
|
||||
static int GetBytesPerChannel(PixelFormat format);
|
||||
int GetBytesPerChannel() const
|
||||
static int get_bytes_per_channel(PixelFormat format);
|
||||
int get_bytes_per_channel() const
|
||||
{
|
||||
return GetBytesPerChannel(format_);
|
||||
return get_bytes_per_channel(format_);
|
||||
}
|
||||
|
||||
static int GetBytesPerPixel(PixelFormat format, int channels);
|
||||
int GetBytesPerPixel() const
|
||||
static int get_bytes_per_pixel(PixelFormat format, int channels);
|
||||
int get_bytes_per_pixel() const
|
||||
{
|
||||
return GetBytesPerPixel(format_, channel_count_);
|
||||
return get_bytes_per_pixel(format_, channel_count_);
|
||||
}
|
||||
|
||||
static int GetBufferSize(int width, int height, PixelFormat format,
|
||||
static int get_buffer_size(int width, int height, PixelFormat format,
|
||||
int channels)
|
||||
{
|
||||
return width * height * GetBytesPerPixel(format, channels);
|
||||
return width * height * get_bytes_per_pixel(format, channels);
|
||||
}
|
||||
int GetBufferSize() const
|
||||
int get_buffer_size() const
|
||||
{
|
||||
return GetBufferSize(width_, height_, format_, channel_count_);
|
||||
return get_buffer_size(width_, height_, format_, channel_count_);
|
||||
}
|
||||
|
||||
static QString GetNameForDivider(int div);
|
||||
static QString get_name_for_divider(int div);
|
||||
|
||||
static bool FormatIsFloat(PixelFormat format)
|
||||
static bool format_is_float(PixelFormat format)
|
||||
{
|
||||
return format.is_float();
|
||||
}
|
||||
|
||||
static QString GetFormatName(PixelFormat format);
|
||||
static QString get_format_name(PixelFormat format);
|
||||
|
||||
static int GetDividerForTargetResolution(int src_width, int src_height,
|
||||
static int get_divider_for_target_resolution(int src_width, int src_height,
|
||||
int dst_width, int dst_height);
|
||||
|
||||
static const int kInternalChannelCount;
|
||||
static const int k_internal_channel_count;
|
||||
|
||||
static const rational kPixelAspectSquare;
|
||||
static const rational kPixelAspectNTSCStandard;
|
||||
static const rational kPixelAspectNTSCWidescreen;
|
||||
static const rational kPixelAspectPALStandard;
|
||||
static const rational kPixelAspectPALWidescreen;
|
||||
static const rational kPixelAspect1080Anamorphic;
|
||||
static const Rational k_pixel_aspect_square;
|
||||
static const Rational k_pixel_aspect_ntsc_standard;
|
||||
static const Rational k_pixel_aspect_ntsc_widescreen;
|
||||
static const Rational k_pixel_aspect_pal_standard;
|
||||
static const Rational k_pixel_aspect_pal_widescreen;
|
||||
static const Rational k_pixel_aspect1080_anamorphic;
|
||||
|
||||
static const QVector<rational> kSupportedFrameRates;
|
||||
static const QVector<rational> kStandardPixelAspects;
|
||||
static const QVector<int> kSupportedDividers;
|
||||
static const QVector<Rational> k_supported_frame_rates;
|
||||
static const QVector<Rational> k_standard_pixel_aspects;
|
||||
static const QVector<int> k_supported_dividers;
|
||||
|
||||
static const int kHSVChannelCount = 3;
|
||||
static const int kRGBChannelCount = 3;
|
||||
static const int kRGBAChannelCount = 4;
|
||||
static const int k_hsv_channel_count = 3;
|
||||
static const int k_rgb_channel_count = 3;
|
||||
static const int k_rgba_channel_count = 4;
|
||||
|
||||
/**
|
||||
* @brief Convert rational frame rate (i.e. flipped timebase) to a user-friendly string
|
||||
* @brief Convert Rational frame rate (i.e. flipped timebase) to a user-friendly string
|
||||
*/
|
||||
static QString FrameRateToString(const rational &frame_rate);
|
||||
static QString frame_rate_to_string(const Rational &frame_rate);
|
||||
|
||||
static QStringList GetStandardPixelAspectRatioNames();
|
||||
static QString FormatPixelAspectRatioString(const QString &format,
|
||||
const rational &ratio);
|
||||
static QStringList get_standard_pixel_aspect_ratio_names();
|
||||
static QString format_pixel_aspect_ratio_string(const QString &format,
|
||||
const Rational &ratio);
|
||||
|
||||
static int GetScaledDimension(int dim, int divider);
|
||||
static int get_scaled_dimension(int dim, int divider);
|
||||
|
||||
bool enabled() const
|
||||
{
|
||||
@@ -319,12 +319,12 @@ public:
|
||||
video_type_ = t;
|
||||
}
|
||||
|
||||
const rational &frame_rate() const
|
||||
const Rational &frame_rate() const
|
||||
{
|
||||
return frame_rate_;
|
||||
}
|
||||
|
||||
void set_frame_rate(const rational &frame_rate)
|
||||
void set_frame_rate(const Rational &frame_rate)
|
||||
{
|
||||
frame_rate_ = frame_rate;
|
||||
}
|
||||
@@ -378,11 +378,11 @@ public:
|
||||
color_range_ = color_range;
|
||||
}
|
||||
|
||||
int64_t get_time_in_timebase_units(const rational &time) const;
|
||||
int64_t get_time_in_timebase_units(const Rational &time) const;
|
||||
|
||||
void Load(QXmlStreamReader *reader);
|
||||
void load(QXmlStreamReader *reader);
|
||||
|
||||
void Save(QXmlStreamWriter *writer) const;
|
||||
void save(QXmlStreamWriter *writer) const;
|
||||
|
||||
private:
|
||||
void calculate_effective_size();
|
||||
@@ -396,13 +396,13 @@ private:
|
||||
int width_;
|
||||
int height_;
|
||||
int depth_;
|
||||
rational time_base_;
|
||||
Rational time_base_;
|
||||
|
||||
PixelFormat format_;
|
||||
|
||||
int channel_count_;
|
||||
|
||||
rational pixel_aspect_ratio_;
|
||||
Rational pixel_aspect_ratio_;
|
||||
|
||||
Interlacing interlacing_;
|
||||
|
||||
@@ -417,7 +417,7 @@ private:
|
||||
bool enabled_;
|
||||
int stream_index_;
|
||||
Type video_type_;
|
||||
rational frame_rate_;
|
||||
Rational frame_rate_;
|
||||
int64_t start_time_;
|
||||
int64_t duration_;
|
||||
bool premultiplied_alpha_;
|
||||
@@ -432,4 +432,4 @@ private:
|
||||
Q_DECLARE_METATYPE(olive::VideoParams)
|
||||
Q_DECLARE_METATYPE(olive::VideoParams::Interlacing)
|
||||
|
||||
#endif // VIDEOPARAMS_H
|
||||
#endif // OAK_VIDEOPARAMS_H
|
||||
|
||||
@@ -17,21 +17,21 @@ namespace
|
||||
class BackendVulkanRenderer : public olive::VulkanRenderer {
|
||||
public:
|
||||
using olive::VulkanRenderer::VulkanRenderer;
|
||||
using olive::VulkanRenderer::Blit;
|
||||
using olive::VulkanRenderer::CreateNativeTexture;
|
||||
using olive::VulkanRenderer::DestroyInternal;
|
||||
using olive::VulkanRenderer::DestroyNativeTexture;
|
||||
using olive::VulkanRenderer::blit;
|
||||
using olive::VulkanRenderer::create_native_texture;
|
||||
using olive::VulkanRenderer::destroy_internal;
|
||||
using olive::VulkanRenderer::destroy_native_texture;
|
||||
};
|
||||
|
||||
// Converts the opaque C ABI handle back to the C++ Vulkan renderer.
|
||||
BackendVulkanRenderer *Renderer(OakRenderBackendHandle handle)
|
||||
BackendVulkanRenderer *renderer(OakRenderBackendHandle handle)
|
||||
{
|
||||
return static_cast<BackendVulkanRenderer *>(handle);
|
||||
}
|
||||
|
||||
// Interprets ABI QVariant payloads without copying; this ABI version assumes
|
||||
// the host and backend are built with the same Qt/C++ ABI.
|
||||
const QVariant &VariantRef(const void *variant)
|
||||
const QVariant &variant_ref(const void *variant)
|
||||
{
|
||||
return *static_cast<const QVariant *>(variant);
|
||||
}
|
||||
@@ -49,7 +49,7 @@ oak_renderer_create(void *parent)
|
||||
OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_destroy(OakRenderBackendHandle handle)
|
||||
{
|
||||
delete Renderer(handle);
|
||||
delete renderer(handle);
|
||||
}
|
||||
|
||||
// Reports Vulkan backend capabilities and runtime availability status.
|
||||
@@ -61,12 +61,12 @@ oak_renderer_get_info(OakRenderBackendHandle handle,
|
||||
return false;
|
||||
}
|
||||
out_info->abi_version = 1;
|
||||
out_info->kind = OAK_RENDER_BACKEND_VULKAN;
|
||||
out_info->kind = oak_render_backend_vulkan;
|
||||
out_info->capabilities =
|
||||
OAK_RENDER_BACKEND_CAP_TEXTURES | OAK_RENDER_BACKEND_CAP_SHADERS |
|
||||
OAK_RENDER_BACKEND_CAP_BLIT | OAK_RENDER_BACKEND_CAP_READBACK;
|
||||
oak_render_backend_cap_textures | oak_render_backend_cap_shaders |
|
||||
oak_render_backend_cap_blit | oak_render_backend_cap_readback;
|
||||
out_info->name = "vulkan";
|
||||
out_info->status = Renderer(handle)->IsAvailable() ? "available" :
|
||||
out_info->status = renderer(handle)->is_available() ? "available" :
|
||||
"unavailable";
|
||||
return true;
|
||||
}
|
||||
@@ -76,21 +76,21 @@ oak_renderer_get_info(OakRenderBackendHandle handle,
|
||||
OAK_RENDER_BACKEND_EXPORT bool
|
||||
oak_renderer_is_available(OakRenderBackendHandle handle)
|
||||
{
|
||||
auto *r = Renderer(handle);
|
||||
if (!r || r->IsAvailable()) {
|
||||
return r && r->IsAvailable();
|
||||
auto *r = renderer(handle);
|
||||
if (!r || r->is_available()) {
|
||||
return r && r->is_available();
|
||||
}
|
||||
// Try to initialize if not already available
|
||||
if (r->Init()) {
|
||||
r->PostInit();
|
||||
if (r->init()) {
|
||||
r->post_init();
|
||||
}
|
||||
return r->IsAvailable();
|
||||
return r->is_available();
|
||||
}
|
||||
|
||||
// Initializes the Vulkan device path.
|
||||
OAK_RENDER_BACKEND_EXPORT bool oak_renderer_init(OakRenderBackendHandle handle)
|
||||
{
|
||||
return Renderer(handle)->Init();
|
||||
return renderer(handle)->init();
|
||||
}
|
||||
|
||||
// Vulkan does not use a QOpenGLContext; the argument is accepted for ABI parity.
|
||||
@@ -98,28 +98,28 @@ OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_init_with_context(OakRenderBackendHandle handle, void *context)
|
||||
{
|
||||
Q_UNUSED(context)
|
||||
Renderer(handle)->Init();
|
||||
renderer(handle)->init();
|
||||
}
|
||||
|
||||
// Creates reusable Vulkan resources after device initialization.
|
||||
OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_post_init(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->PostInit();
|
||||
renderer(handle)->post_init();
|
||||
}
|
||||
|
||||
// Reserved for API symmetry; Vulkan cleanup is handled by destroy_internal.
|
||||
OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_post_destroy(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->PostDestroy();
|
||||
renderer(handle)->post_destroy();
|
||||
}
|
||||
|
||||
// Releases all Vulkan resources owned by the renderer.
|
||||
OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_destroy_internal(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->DestroyInternal();
|
||||
renderer(handle)->destroy_internal();
|
||||
}
|
||||
|
||||
// Clears a Vulkan texture destination.
|
||||
@@ -127,7 +127,7 @@ OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_clear_destination(OakRenderBackendHandle handle, void *texture,
|
||||
double r, double g, double b, double a)
|
||||
{
|
||||
Renderer(handle)->ClearDestination(static_cast<olive::Texture *>(texture),
|
||||
renderer(handle)->clear_destination(static_cast<olive::Texture *>(texture),
|
||||
r, g, b, a);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ OAK_RENDER_BACKEND_EXPORT void oak_renderer_create_native_texture(
|
||||
int channel_count, const void *data, int linesize, void *out_variant)
|
||||
{
|
||||
*static_cast<QVariant *>(out_variant) =
|
||||
Renderer(handle)->CreateNativeTexture(
|
||||
renderer(handle)->create_native_texture(
|
||||
width, height, depth,
|
||||
static_cast<olive::PixelFormat::Format>(format), channel_count,
|
||||
data, linesize);
|
||||
@@ -148,7 +148,7 @@ OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_destroy_native_texture(OakRenderBackendHandle handle,
|
||||
const void *variant)
|
||||
{
|
||||
Renderer(handle)->DestroyNativeTexture(VariantRef(variant));
|
||||
renderer(handle)->destroy_native_texture(variant_ref(variant));
|
||||
}
|
||||
|
||||
// Compiles a Vulkan shader and returns its QVariant handle.
|
||||
@@ -157,7 +157,7 @@ oak_renderer_create_native_shader(OakRenderBackendHandle handle,
|
||||
const void *shader_code, void *out_variant)
|
||||
{
|
||||
*static_cast<QVariant *>(out_variant) =
|
||||
Renderer(handle)->CreateNativeShader(
|
||||
renderer(handle)->create_native_shader(
|
||||
*static_cast<const olive::ShaderCode *>(shader_code));
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ OAK_RENDER_BACKEND_EXPORT void
|
||||
oak_renderer_destroy_native_shader(OakRenderBackendHandle handle,
|
||||
const void *variant)
|
||||
{
|
||||
Renderer(handle)->DestroyNativeShader(VariantRef(variant));
|
||||
renderer(handle)->destroy_native_shader(variant_ref(variant));
|
||||
}
|
||||
|
||||
// Uploads CPU pixel data into a Vulkan texture.
|
||||
@@ -175,8 +175,8 @@ oak_renderer_upload_to_texture(OakRenderBackendHandle handle,
|
||||
const void *variant, const void *video_params,
|
||||
const void *data, int linesize)
|
||||
{
|
||||
Renderer(handle)->UploadToTexture(
|
||||
VariantRef(variant),
|
||||
renderer(handle)->upload_to_texture(
|
||||
variant_ref(variant),
|
||||
*static_cast<const olive::VideoParams *>(video_params), data, linesize);
|
||||
}
|
||||
|
||||
@@ -185,15 +185,15 @@ OAK_RENDER_BACKEND_EXPORT void oak_renderer_download_from_texture(
|
||||
OakRenderBackendHandle handle, const void *variant,
|
||||
const void *video_params, void *data, int linesize)
|
||||
{
|
||||
Renderer(handle)->DownloadFromTexture(
|
||||
VariantRef(variant),
|
||||
renderer(handle)->download_from_texture(
|
||||
variant_ref(variant),
|
||||
*static_cast<const olive::VideoParams *>(video_params), data, linesize);
|
||||
}
|
||||
|
||||
// Waits for all queued Vulkan work to finish.
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_flush(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->Flush();
|
||||
renderer(handle)->flush();
|
||||
}
|
||||
|
||||
// Reads one pixel from a Vulkan texture.
|
||||
@@ -203,7 +203,7 @@ oak_renderer_get_pixel_from_texture(OakRenderBackendHandle handle,
|
||||
void *out_color)
|
||||
{
|
||||
*static_cast<olive::Color *>(out_color) =
|
||||
Renderer(handle)->GetPixelFromTexture(
|
||||
renderer(handle)->get_pixel_from_texture(
|
||||
static_cast<olive::Texture *>(texture),
|
||||
*static_cast<const QPointF *>(point));
|
||||
}
|
||||
@@ -215,8 +215,8 @@ OAK_RENDER_BACKEND_EXPORT void oak_renderer_blit(OakRenderBackendHandle handle,
|
||||
const void *destination_params,
|
||||
bool clear_destination)
|
||||
{
|
||||
Renderer(handle)->Blit(
|
||||
VariantRef(shader), *static_cast<olive::AcceleratedJob *>(job),
|
||||
renderer(handle)->blit(
|
||||
variant_ref(shader), *static_cast<olive::AcceleratedJob *>(job),
|
||||
static_cast<olive::Texture *>(destination),
|
||||
*static_cast<const olive::VideoParams *>(destination_params),
|
||||
clear_destination);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,8 +18,8 @@
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef VULKANRENDERER_H
|
||||
#define VULKANRENDERER_H
|
||||
#ifndef OAK_VULKANRENDERER_H
|
||||
#define OAK_VULKANRENDERER_H
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
@@ -42,67 +42,67 @@ public:
|
||||
|
||||
// Creates the Vulkan instance, logical device, command pool, and descriptor
|
||||
// pool required for offscreen rendering.
|
||||
virtual bool Init() override;
|
||||
virtual bool init() override;
|
||||
// Creates reusable GPU resources that require a fully initialized device.
|
||||
virtual void PostInit() override;
|
||||
virtual void post_init() override;
|
||||
// Reserved for symmetry with OpenGLRenderer; Vulkan cleanup is handled by
|
||||
// DestroyInternal().
|
||||
virtual void PostDestroy() override;
|
||||
virtual void post_destroy() override;
|
||||
|
||||
// Clears either a texture render target or the currently bound output target.
|
||||
virtual void ClearDestination(olive::Texture *texture = nullptr,
|
||||
virtual void clear_destination(olive::Texture *texture = nullptr,
|
||||
double r = 0.0, double g = 0.0,
|
||||
double b = 0.0, double a = 0.0) override;
|
||||
|
||||
// Compiles GLSL to SPIR-V, creates shader modules, and prepares descriptor
|
||||
// metadata for later blits.
|
||||
virtual QVariant CreateNativeShader(olive::ShaderCode code) override;
|
||||
virtual QVariant create_native_shader(olive::ShaderCode code) override;
|
||||
// Destroys shader modules, descriptor layout, pipeline layout, and cached
|
||||
// pipelines associated with a shader handle.
|
||||
virtual void DestroyNativeShader(QVariant shader) override;
|
||||
virtual void destroy_native_shader(QVariant shader) override;
|
||||
|
||||
// Uploads CPU pixel data to a Vulkan image via a staging buffer.
|
||||
virtual void UploadToTexture(const QVariant &handle,
|
||||
virtual void upload_to_texture(const QVariant &handle,
|
||||
const VideoParams ¶ms, const void *data,
|
||||
int linesize) override;
|
||||
// Downloads a Vulkan image to CPU memory via a staging buffer.
|
||||
virtual void DownloadFromTexture(const QVariant &handle,
|
||||
virtual void download_from_texture(const QVariant &handle,
|
||||
const VideoParams ¶ms, void *data,
|
||||
int linesize) override;
|
||||
|
||||
// Waits for outstanding device work to complete.
|
||||
virtual void Flush() override;
|
||||
virtual void flush() override;
|
||||
|
||||
virtual bool IsVulkan() const override
|
||||
virtual bool is_vulkan() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reads a single texture pixel using a one-pixel transfer readback.
|
||||
virtual Color GetPixelFromTexture(olive::Texture *texture,
|
||||
virtual Color get_pixel_from_texture(olive::Texture *texture,
|
||||
const QPointF &pt) override;
|
||||
|
||||
bool IsAvailable() const
|
||||
bool is_available() const
|
||||
{
|
||||
return device_ != VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Runs one or more fullscreen shader passes into the destination texture.
|
||||
virtual void Blit(QVariant shader, olive::AcceleratedJob &job,
|
||||
virtual void blit(QVariant shader, olive::AcceleratedJob &job,
|
||||
olive::Texture *destination,
|
||||
VideoParams destination_params,
|
||||
bool clear_destination) override;
|
||||
// Creates a Vulkan image/view/memory bundle and optionally uploads initial
|
||||
// pixel data.
|
||||
virtual QVariant CreateNativeTexture(int width, int height, int depth,
|
||||
virtual QVariant create_native_texture(int width, int height, int depth,
|
||||
PixelFormat format, int channel_count,
|
||||
const void *data = nullptr,
|
||||
int linesize = 0) override;
|
||||
// Releases a Vulkan texture bundle.
|
||||
virtual void DestroyNativeTexture(QVariant texture) override;
|
||||
virtual void destroy_native_texture(QVariant texture) override;
|
||||
// Releases all Vulkan device resources owned by this renderer.
|
||||
virtual void DestroyInternal() override;
|
||||
virtual void destroy_internal() override;
|
||||
|
||||
private:
|
||||
struct VulkanTexture;
|
||||
@@ -111,113 +111,113 @@ private:
|
||||
struct StagingBuffer;
|
||||
|
||||
// Creates the Vulkan instance used for all offscreen work.
|
||||
bool CreateInstance();
|
||||
bool create_instance();
|
||||
// Creates the debug messenger when validation layers are available.
|
||||
bool CreateDebugMessenger();
|
||||
bool create_debug_messenger();
|
||||
// Destroys the debug messenger before the instance is destroyed.
|
||||
void DestroyDebugMessenger();
|
||||
void destroy_debug_messenger();
|
||||
// Validation layer callback; logs errors/warnings so synchronization issues
|
||||
// are visible before they become GPU hangs.
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL
|
||||
DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
|
||||
void *pUserData);
|
||||
debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT message_type,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT *p_callback_data,
|
||||
void *p_user_data);
|
||||
// Chooses a graphics-capable physical device and creates the logical device.
|
||||
bool CreateDevice();
|
||||
bool create_device();
|
||||
// Creates a command pool for short-lived command buffers.
|
||||
bool CreateCommandPool();
|
||||
bool create_command_pool();
|
||||
// Creates the descriptor pool used for per-blit UBO/sampler sets.
|
||||
bool CreateDescriptorPool();
|
||||
bool create_descriptor_pool();
|
||||
// Uploads the fullscreen quad vertex buffer used by BlitPass().
|
||||
bool CreateVertexBuffer();
|
||||
bool create_vertex_buffer();
|
||||
// Creates the persistent linear sampler.
|
||||
bool CreateLinearSampler();
|
||||
bool create_linear_sampler();
|
||||
// Creates the persistent nearest-neighbor sampler.
|
||||
bool CreateNearestSampler();
|
||||
bool create_nearest_sampler();
|
||||
// Returns the persistent sampler matching the requested interpolation mode.
|
||||
VkSampler GetSampler(Texture::Interpolation interpolation) const;
|
||||
VkSampler get_sampler(Texture::Interpolation interpolation) const;
|
||||
// Allocates a host-visible staging buffer for upload/download transfers.
|
||||
bool CreateStagingBuffer(VkDeviceSize size, VkBuffer *out_buffer,
|
||||
bool create_staging_buffer(VkDeviceSize size, VkBuffer *out_buffer,
|
||||
VkDeviceMemory *out_memory);
|
||||
// Destroys a staging buffer pair allocated by CreateStagingBuffer().
|
||||
void DestroyStagingBuffer(VkBuffer buffer, VkDeviceMemory memory);
|
||||
void destroy_staging_buffer(VkBuffer buffer, VkDeviceMemory memory);
|
||||
|
||||
// Begins a one-shot command buffer and records it immediately.
|
||||
VkCommandBuffer BeginOneTimeCommands();
|
||||
VkCommandBuffer begin_one_time_commands();
|
||||
// Submits and waits for a one-shot command buffer.
|
||||
void EndOneTimeCommands(VkCommandBuffer cmd);
|
||||
void end_one_time_commands(VkCommandBuffer cmd);
|
||||
|
||||
// Emits an image memory barrier for the subset of layouts this renderer uses.
|
||||
void TransitionImageLayout(VkCommandBuffer cmd, VkImage image,
|
||||
void transition_image_layout(VkCommandBuffer cmd, VkImage image,
|
||||
VkImageLayout old_layout,
|
||||
VkImageLayout new_layout);
|
||||
// Records a tightly packed buffer-to-image copy.
|
||||
void CopyBufferToImage(VkCommandBuffer cmd, VkBuffer buffer, VkImage image,
|
||||
void copy_buffer_to_image(VkCommandBuffer cmd, VkBuffer buffer, VkImage image,
|
||||
uint32_t width, uint32_t height, uint32_t depth);
|
||||
// Records an image-to-buffer copy, optionally reading one pixel offset.
|
||||
void CopyImageToBuffer(VkCommandBuffer cmd, VkImage image, VkBuffer buffer,
|
||||
void copy_image_to_buffer(VkCommandBuffer cmd, VkImage image, VkBuffer buffer,
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t offset_x = 0, uint32_t offset_y = 0);
|
||||
|
||||
// Converts Oak pixel format/channel metadata to a preferred Vulkan format.
|
||||
VkFormat PixelFormatToVkFormat(PixelFormat format, int channel_count) const;
|
||||
VkFormat pixel_format_to_vk_format(PixelFormat format, int channel_count) const;
|
||||
// Picks a color-attachment-capable format, falling back from RGB to RGBA
|
||||
// where drivers do not support 3-channel render targets.
|
||||
VkFormat PickRenderableFormat(PixelFormat format, int channel_count) const;
|
||||
VkFormat pick_renderable_format(PixelFormat format, int channel_count) const;
|
||||
// Checks whether a format can be used as a render target.
|
||||
bool IsColorAttachmentSupported(VkFormat format) const;
|
||||
bool is_color_attachment_supported(VkFormat format) const;
|
||||
// Returns the packed byte size for supported VkFormat values.
|
||||
int GetVkFormatBytesPerPixel(VkFormat format) const;
|
||||
int get_vk_format_bytes_per_pixel(VkFormat format) const;
|
||||
// Returns the alpha fill value used when expanding RGB data to RGBA.
|
||||
float GetFormatMaxAlpha(PixelFormat format) const;
|
||||
float get_format_max_alpha(PixelFormat format) const;
|
||||
// Repackages tightly packed pixels when the requested CPU channel count
|
||||
// differs from the selected GPU format channel count.
|
||||
void CopyPixelsWithChannelConversion(const void *src, void *dst, int width,
|
||||
void copy_pixels_with_channel_conversion(const void *src, void *dst, int width,
|
||||
int height, int depth,
|
||||
int src_channels, int dst_channels,
|
||||
PixelFormat format) const;
|
||||
// Rounds a size up to the requested alignment.
|
||||
VkDeviceSize AlignSize(VkDeviceSize size, VkDeviceSize alignment) const;
|
||||
VkDeviceSize align_size(VkDeviceSize size, VkDeviceSize alignment) const;
|
||||
|
||||
// Finds a Vulkan memory type matching the requested properties.
|
||||
uint32_t FindMemoryType(uint32_t type_filter,
|
||||
uint32_t find_memory_type(uint32_t type_filter,
|
||||
VkMemoryPropertyFlags properties) const;
|
||||
|
||||
// Compiles GLSL source into SPIR-V using shaderc when available.
|
||||
bool CompileGlslToSpv(const QString &glsl, VkShaderStageFlagBits stage,
|
||||
bool compile_glsl_to_spv(const QString &glsl, VkShaderStageFlagBits stage,
|
||||
QByteArray *out_spv);
|
||||
// Rewrites an Oak GLSL shader into Vulkan-compatible GLSL.
|
||||
QString ConvertGlslToVulkan(const QString &glsl,
|
||||
QString convert_glsl_to_vulkan(const QString &glsl,
|
||||
VkShaderStageFlagBits stage);
|
||||
// Ensures a shader declares a Vulkan-compatible GLSL version.
|
||||
QString EnsureGlslVersion450(const QString &glsl) const;
|
||||
QString ensure_glsl_version450(const QString &glsl) const;
|
||||
// Extracts uniforms and sampler names from GLSL declarations.
|
||||
void ExtractUniforms(const QString &glsl,
|
||||
void extract_uniforms(const QString &glsl,
|
||||
QVector<UniformInfo> *out_uniforms,
|
||||
QVector<QString> *out_samplers) const;
|
||||
// Computes std140 offsets and total UBO size for extracted uniforms.
|
||||
void ComputeUniformLayout(QVector<UniformInfo> *uniforms) const;
|
||||
void compute_uniform_layout(QVector<UniformInfo> *uniforms) const;
|
||||
// Builds the generated uniform block used by rewritten shaders.
|
||||
QString BuildUboBlock(const QVector<UniformInfo> &uniforms) const;
|
||||
QString build_ubo_block(const QVector<UniformInfo> &uniforms) const;
|
||||
// Rewrites standalone uniforms and samplers into explicit UBO/sampler
|
||||
// bindings accepted by Vulkan GLSL.
|
||||
QString
|
||||
RewriteShaderWithUbo(const QString &glsl,
|
||||
rewrite_shader_with_ubo(const QString &glsl,
|
||||
const QVector<UniformInfo> &all_uniforms,
|
||||
const QHash<QString, int> &sampler_bindings) const;
|
||||
// Returns std140 storage size for a supported GLSL type.
|
||||
VkDeviceSize GetStd140Size(const QString &type) const;
|
||||
VkDeviceSize get_std140_size(const QString &type) const;
|
||||
// Returns std140 alignment for a supported GLSL type.
|
||||
VkDeviceSize GetStd140Alignment(const QString &type) const;
|
||||
VkDeviceSize get_std140_alignment(const QString &type) const;
|
||||
|
||||
// Creates or retrieves the graphics pipeline for a shader/render format pair.
|
||||
bool CreatePipelineForShader(VulkanShader *shader,
|
||||
bool create_pipeline_for_shader(VulkanShader *shader,
|
||||
const VideoParams &dest_params,
|
||||
VkFormat render_pass_format);
|
||||
|
||||
// Caches simple single-color-attachment render passes by format/clear mode.
|
||||
VkRenderPass GetOrCreateRenderPass(VkFormat format, bool clear);
|
||||
VkRenderPass get_or_create_render_pass(VkFormat format, bool clear);
|
||||
|
||||
struct TextureBinding {
|
||||
QString name;
|
||||
@@ -226,7 +226,7 @@ private:
|
||||
};
|
||||
|
||||
// Executes one fullscreen pass with the provided texture bindings and UBO.
|
||||
void BlitPass(VulkanShader *shader, VulkanTexture *dest_tex,
|
||||
void blit_pass(VulkanShader *shader, VulkanTexture *dest_tex,
|
||||
const QVector<TextureBinding> &bindings,
|
||||
const QByteArray &ubo_data,
|
||||
const VideoParams &destination_params, bool clear_destination,
|
||||
@@ -269,9 +269,9 @@ private:
|
||||
quint64 next_shader_id_ = 1;
|
||||
QHash<quint64, VulkanShader *> shaders_;
|
||||
|
||||
static const int kMaxDescriptorSets = 1024;
|
||||
static const int k_max_descriptor_sets = 1024;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // VULKANRENDERER_H
|
||||
#endif // OAK_VULKANRENDERER_H
|
||||
|
||||
+160
-160
@@ -66,7 +66,7 @@ namespace
|
||||
{
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
void PrintBacktrace(int sig)
|
||||
void print_backtrace(int sig)
|
||||
{
|
||||
void *array[50];
|
||||
size_t size = backtrace(array, 50);
|
||||
@@ -77,12 +77,12 @@ void PrintBacktrace(int sig)
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr int kProtocolVersion = 1;
|
||||
constexpr int kDefaultWidth = 1920;
|
||||
constexpr int kDefaultHeight = 1080;
|
||||
constexpr int kDefaultFrameRate = 24;
|
||||
constexpr int k_protocol_version = 1;
|
||||
constexpr int k_default_width = 1920;
|
||||
constexpr int k_default_height = 1080;
|
||||
constexpr int k_default_frame_rate = 24;
|
||||
|
||||
void InstallSurfaceFormat()
|
||||
void install_surface_format()
|
||||
{
|
||||
QSurfaceFormat format;
|
||||
format.setVersion(3, 2);
|
||||
@@ -91,17 +91,17 @@ void InstallSurfaceFormat()
|
||||
QSurfaceFormat::setDefaultFormat(format);
|
||||
}
|
||||
|
||||
void LogError(const QString &message)
|
||||
void log_error(const QString &message)
|
||||
{
|
||||
const QByteArray line = QByteArray("worker: ") + message.toUtf8() + '\n';
|
||||
fwrite(line.constData(), 1, size_t(line.size()), stderr);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
QJsonObject ErrorMessage(const QString &message, qint64 ticket_id = 0)
|
||||
QJsonObject error_message(const QString &message, qint64 ticket_id = 0)
|
||||
{
|
||||
QJsonObject o;
|
||||
o["type"] = olive::ipc::msgtype::kError;
|
||||
o["type"] = olive::ipc::msgtype::k_error;
|
||||
o["message"] = message;
|
||||
if (ticket_id) {
|
||||
o["ticket"] = double(ticket_id);
|
||||
@@ -120,13 +120,13 @@ public:
|
||||
~RenderWorker()
|
||||
{
|
||||
project_.reset();
|
||||
olive::ProjectSerializer::Destroy();
|
||||
olive::DiskManager::DestroyInstance();
|
||||
olive::FrameManager::DestroyInstance();
|
||||
olive::NodeFactory::Destroy();
|
||||
olive::ProjectSerializer::destroy();
|
||||
olive::DiskManager::destroy_instance();
|
||||
olive::FrameManager::destroy_instance();
|
||||
olive::NodeFactory::destroy();
|
||||
}
|
||||
|
||||
bool InitializeRuntime()
|
||||
bool initialize_runtime()
|
||||
{
|
||||
// Create a minimal Core instance so that code paths calling Core::instance()
|
||||
// (e.g. ViewerOutput::data for timecode display) do not dereference null.
|
||||
@@ -135,19 +135,19 @@ public:
|
||||
new olive::Core(olive::Core::CoreParams());
|
||||
}
|
||||
|
||||
olive::Config::Load();
|
||||
olive::NodeFactory::Initialize();
|
||||
olive::ColorManager::SetUpDefaultConfig();
|
||||
olive::FrameManager::CreateInstance();
|
||||
olive::DiskManager::CreateInstance();
|
||||
olive::ProjectSerializer::Initialize();
|
||||
olive::Config::load();
|
||||
olive::NodeFactory::initialize();
|
||||
olive::ColorManager::set_up_default_config();
|
||||
olive::FrameManager::create_instance();
|
||||
olive::DiskManager::create_instance();
|
||||
olive::ProjectSerializer::initialize();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SendStartupHandshake()
|
||||
bool send_startup_handshake()
|
||||
{
|
||||
olive::ipc::HandshakeMsg hs;
|
||||
hs.protocol_version = kProtocolVersion;
|
||||
hs.protocol_version = k_protocol_version;
|
||||
hs.shm_key = QString();
|
||||
hs.input_shm_key = QString();
|
||||
hs.input_slots = 0;
|
||||
@@ -155,12 +155,12 @@ public:
|
||||
hs.slot_data_bytes = 0;
|
||||
hs.input_slot_data_bytes = 0;
|
||||
|
||||
QJsonObject handshake = hs.ToJson();
|
||||
QJsonObject handshake = hs.to_json();
|
||||
QOpenGLContext *ctx = nullptr;
|
||||
#ifdef OAK_ENABLE_DYNAMIC_RENDER_BACKEND
|
||||
if (auto *dynamic_renderer =
|
||||
dynamic_cast<olive::DynamicRenderer *>(renderer_)) {
|
||||
ctx = dynamic_renderer->OpenGLContext();
|
||||
ctx = dynamic_renderer->open_gl_context();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -172,52 +172,52 @@ public:
|
||||
handshake["gl_minor"] = fmt.minorVersion();
|
||||
}
|
||||
|
||||
return Write(handshake);
|
||||
return write(handshake);
|
||||
}
|
||||
|
||||
bool Handle(const QJsonObject &message)
|
||||
bool handle(const QJsonObject &message)
|
||||
{
|
||||
const QString type = message["type"].toString();
|
||||
|
||||
if (type == QLatin1String(olive::ipc::msgtype::kHandshake)) {
|
||||
if (type == QLatin1String(olive::ipc::msgtype::k_handshake)) {
|
||||
olive::ipc::HandshakeMsg hs;
|
||||
if (!olive::ipc::HandshakeMsg::FromJson(message, &hs)) {
|
||||
return Write(
|
||||
ErrorMessage(QStringLiteral("invalid handshake message")));
|
||||
if (!olive::ipc::HandshakeMsg::from_json(message, &hs)) {
|
||||
return write(
|
||||
error_message(QStringLiteral("invalid handshake message")));
|
||||
}
|
||||
return AttachOutputPool(hs);
|
||||
return attach_output_pool(hs);
|
||||
}
|
||||
|
||||
if (type == QLatin1String(olive::ipc::msgtype::kLoadGraph)) {
|
||||
if (type == QLatin1String(olive::ipc::msgtype::k_load_graph)) {
|
||||
olive::ipc::LoadGraphMsg load;
|
||||
if (!olive::ipc::LoadGraphMsg::FromJson(message, &load)) {
|
||||
return Write(
|
||||
ErrorMessage(QStringLiteral("invalid load_graph message")));
|
||||
if (!olive::ipc::LoadGraphMsg::from_json(message, &load)) {
|
||||
return write(
|
||||
error_message(QStringLiteral("invalid load_graph message")));
|
||||
}
|
||||
return LoadGraph(load.path);
|
||||
return load_graph(load.path);
|
||||
}
|
||||
|
||||
if (type == QLatin1String(olive::ipc::msgtype::kRenderFrame)) {
|
||||
if (type == QLatin1String(olive::ipc::msgtype::k_render_frame)) {
|
||||
olive::ipc::RenderFrameMsg render;
|
||||
if (!olive::ipc::RenderFrameMsg::FromJson(message, &render)) {
|
||||
return Write(ErrorMessage(
|
||||
if (!olive::ipc::RenderFrameMsg::from_json(message, &render)) {
|
||||
return write(error_message(
|
||||
QStringLiteral("invalid render_frame message")));
|
||||
}
|
||||
return RenderFrame(render);
|
||||
return render_frame(render);
|
||||
}
|
||||
|
||||
if (type == QLatin1String(olive::ipc::msgtype::kCancel)) {
|
||||
if (type == QLatin1String(olive::ipc::msgtype::k_cancel)) {
|
||||
// Stage 5 wires cancellation into in-flight jobs. Stage 2 has only synchronous single-frame work.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == QLatin1String(olive::ipc::msgtype::kShutdown)) {
|
||||
if (type == QLatin1String(olive::ipc::msgtype::k_shutdown)) {
|
||||
shutdown_requested_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return Write(
|
||||
ErrorMessage(QStringLiteral("unknown message type: %1").arg(type)));
|
||||
return write(
|
||||
error_message(QStringLiteral("unknown message type: %1").arg(type)));
|
||||
}
|
||||
|
||||
bool shutdown_requested() const
|
||||
@@ -226,67 +226,67 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool Write(const QJsonObject &message)
|
||||
bool write(const QJsonObject &message)
|
||||
{
|
||||
const bool ok = olive::ipc::WriteMessage(out_, message);
|
||||
const bool ok = olive::ipc::write_message(out_, message);
|
||||
out_->flush();
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool AttachOutputPool(const olive::ipc::HandshakeMsg &hs)
|
||||
bool attach_output_pool(const olive::ipc::HandshakeMsg &hs)
|
||||
{
|
||||
if (hs.protocol_version != kProtocolVersion) {
|
||||
return Write(
|
||||
ErrorMessage(QStringLiteral("unsupported protocol version %1")
|
||||
if (hs.protocol_version != k_protocol_version) {
|
||||
return write(
|
||||
error_message(QStringLiteral("unsupported protocol version %1")
|
||||
.arg(hs.protocol_version)));
|
||||
}
|
||||
|
||||
if (hs.shm_key.isEmpty() || hs.output_slots <= 0 ||
|
||||
hs.slot_data_bytes <= 0) {
|
||||
return Write(ErrorMessage(QStringLiteral(
|
||||
return write(error_message(QStringLiteral(
|
||||
"handshake missing output shared-memory geometry")));
|
||||
}
|
||||
|
||||
const size_t bytes = olive::ipc::FrameSlotPool::BytesNeeded(
|
||||
const size_t bytes = olive::ipc::FrameSlotPool::bytes_needed(
|
||||
uint32_t(hs.output_slots), size_t(hs.slot_data_bytes));
|
||||
if (!output_region_.Open(hs.shm_key, bytes,
|
||||
olive::ipc::SharedMemoryRegion::kAttach)) {
|
||||
return Write(ErrorMessage(
|
||||
if (!output_region_.open(hs.shm_key, bytes,
|
||||
olive::ipc::SharedMemoryRegion::k_attach)) {
|
||||
return write(error_message(
|
||||
QStringLiteral("failed to attach shared memory: %1")
|
||||
.arg(output_region_.error())));
|
||||
}
|
||||
|
||||
output_pool_ = olive::ipc::FrameSlotPool::Attach(output_region_.data());
|
||||
if (!output_pool_->IsValid()) {
|
||||
output_region_.Close();
|
||||
output_pool_ = olive::ipc::FrameSlotPool::attach(output_region_.data());
|
||||
if (!output_pool_->is_valid()) {
|
||||
output_region_.close();
|
||||
output_pool_.reset();
|
||||
return Write(ErrorMessage(QStringLiteral(
|
||||
return write(error_message(QStringLiteral(
|
||||
"shared memory does not contain a frame slot pool")));
|
||||
}
|
||||
|
||||
input_pool_.reset();
|
||||
input_region_.Close();
|
||||
input_region_.close();
|
||||
if (hs.input_slots > 0) {
|
||||
if (hs.input_shm_key.isEmpty() || hs.input_slot_data_bytes <= 0) {
|
||||
return Write(ErrorMessage(QStringLiteral(
|
||||
return write(error_message(QStringLiteral(
|
||||
"handshake missing input shared-memory geometry")));
|
||||
}
|
||||
|
||||
const size_t input_bytes = olive::ipc::FrameSlotPool::BytesNeeded(
|
||||
const size_t input_bytes = olive::ipc::FrameSlotPool::bytes_needed(
|
||||
uint32_t(hs.input_slots), size_t(hs.input_slot_data_bytes));
|
||||
if (!input_region_.Open(hs.input_shm_key, input_bytes,
|
||||
olive::ipc::SharedMemoryRegion::kAttach)) {
|
||||
return Write(ErrorMessage(
|
||||
if (!input_region_.open(hs.input_shm_key, input_bytes,
|
||||
olive::ipc::SharedMemoryRegion::k_attach)) {
|
||||
return write(error_message(
|
||||
QStringLiteral("failed to attach input shared memory: %1")
|
||||
.arg(input_region_.error())));
|
||||
}
|
||||
|
||||
input_pool_ =
|
||||
olive::ipc::FrameSlotPool::Attach(input_region_.data());
|
||||
if (!input_pool_->IsValid()) {
|
||||
input_region_.Close();
|
||||
olive::ipc::FrameSlotPool::attach(input_region_.data());
|
||||
if (!input_pool_->is_valid()) {
|
||||
input_region_.close();
|
||||
input_pool_.reset();
|
||||
return Write(ErrorMessage(QStringLiteral(
|
||||
return write(error_message(QStringLiteral(
|
||||
"input shared memory does not contain a frame slot pool")));
|
||||
}
|
||||
}
|
||||
@@ -294,24 +294,24 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadGraph(const QString &path)
|
||||
bool load_graph(const QString &path)
|
||||
{
|
||||
{
|
||||
QFileInfo fi(path);
|
||||
if (!fi.exists()) {
|
||||
LogError(
|
||||
log_error(
|
||||
QStringLiteral("LoadGraph: graph file does not exist: %1")
|
||||
.arg(path));
|
||||
return Write(ErrorMessage(
|
||||
return write(error_message(
|
||||
QStringLiteral("graph file does not exist: %1").arg(path)));
|
||||
}
|
||||
if (fi.size() == 0) {
|
||||
LogError(QStringLiteral("LoadGraph: graph file is empty: %1")
|
||||
log_error(QStringLiteral("LoadGraph: graph file is empty: %1")
|
||||
.arg(path));
|
||||
return Write(ErrorMessage(
|
||||
return write(error_message(
|
||||
QStringLiteral("graph file is empty: %1").arg(path)));
|
||||
}
|
||||
LogError(
|
||||
log_error(
|
||||
QStringLiteral("LoadGraph: loading %1 (%2 bytes, readable=%3)")
|
||||
.arg(path)
|
||||
.arg(fi.size())
|
||||
@@ -324,19 +324,19 @@ private:
|
||||
// Initialize() first triggers Q_ASSERT(!root_) in Project::Load.
|
||||
|
||||
olive::ProjectSerializer::Result result =
|
||||
olive::ProjectSerializer::Load(loaded.get(), path,
|
||||
olive::ProjectSerializer::kProject);
|
||||
if (result != olive::ProjectSerializer::kSuccess) {
|
||||
return Write(
|
||||
ErrorMessage(QStringLiteral("failed to load graph %1: %2")
|
||||
.arg(path, result.GetDetails())));
|
||||
olive::ProjectSerializer::load(loaded.get(), path,
|
||||
olive::ProjectSerializer::k_project);
|
||||
if (result != olive::ProjectSerializer::k_success) {
|
||||
return write(
|
||||
error_message(QStringLiteral("failed to load graph %1: %2")
|
||||
.arg(path, result.get_details())));
|
||||
}
|
||||
|
||||
project_ = std::move(loaded);
|
||||
node_by_token_.clear();
|
||||
color_processor_cache_.clear();
|
||||
|
||||
const auto &data = result.GetLoadData();
|
||||
const auto &data = result.get_load_data();
|
||||
for (auto it = data.node_ptrs.cbegin(); it != data.node_ptrs.cend();
|
||||
++it) {
|
||||
node_by_token_.insert(QString::number(it.key()), it.value());
|
||||
@@ -351,10 +351,10 @@ private:
|
||||
QJsonObject ack;
|
||||
ack["type"] = QStringLiteral("graph_loaded");
|
||||
ack["nodes"] = node_by_token_.size();
|
||||
return Write(ack);
|
||||
return write(ack);
|
||||
}
|
||||
|
||||
olive::Node *FindNode(const QString &token) const
|
||||
olive::Node *find_node(const QString &token) const
|
||||
{
|
||||
if (olive::Node *node = node_by_token_.value(token, nullptr)) {
|
||||
return node;
|
||||
@@ -369,24 +369,24 @@ private:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool RenderFrame(const olive::ipc::RenderFrameMsg &message)
|
||||
bool render_frame(const olive::ipc::RenderFrameMsg &message)
|
||||
{
|
||||
if (!project_) {
|
||||
return Write(ErrorMessage(
|
||||
return write(error_message(
|
||||
QStringLiteral("render_frame received before load_graph"),
|
||||
message.ticket_id));
|
||||
}
|
||||
if (!output_pool_ || !output_pool_->IsValid()) {
|
||||
return Write(ErrorMessage(
|
||||
if (!output_pool_ || !output_pool_->is_valid()) {
|
||||
return write(error_message(
|
||||
QStringLiteral(
|
||||
"render_frame received before output shm handshake"),
|
||||
message.ticket_id));
|
||||
}
|
||||
|
||||
olive::Node *node = FindNode(message.node_uuid);
|
||||
olive::Node *node = find_node(message.node_uuid);
|
||||
if (!node) {
|
||||
return Write(
|
||||
ErrorMessage(QStringLiteral("render node not found: %1")
|
||||
return write(
|
||||
error_message(QStringLiteral("render node not found: %1")
|
||||
.arg(message.node_uuid),
|
||||
message.ticket_id));
|
||||
}
|
||||
@@ -397,8 +397,8 @@ private:
|
||||
QVector<int>{ message.input_slot } :
|
||||
message.input_slots;
|
||||
if (!requested_input_slots.isEmpty()) {
|
||||
if (!input_pool_ || !input_pool_->IsValid()) {
|
||||
return Write(ErrorMessage(
|
||||
if (!input_pool_ || !input_pool_->is_valid()) {
|
||||
return write(error_message(
|
||||
QStringLiteral(
|
||||
"render_frame referenced input slot without input pool"),
|
||||
message.ticket_id));
|
||||
@@ -408,65 +408,65 @@ private:
|
||||
if (requested_slot < 0 ||
|
||||
requested_slot >= int(input_pool_->slot_count())) {
|
||||
for (int slot : input_slots) {
|
||||
input_pool_->Release(uint32_t(slot));
|
||||
input_pool_->release(uint32_t(slot));
|
||||
}
|
||||
return Write(ErrorMessage(
|
||||
return write(error_message(
|
||||
QStringLiteral("input slot index out of range"),
|
||||
message.ticket_id));
|
||||
}
|
||||
|
||||
uint32_t consumed_slot = 0;
|
||||
if (!input_pool_->Consume(&consumed_slot)) {
|
||||
if (!input_pool_->consume(&consumed_slot)) {
|
||||
for (int slot : input_slots) {
|
||||
input_pool_->Release(uint32_t(slot));
|
||||
input_pool_->release(uint32_t(slot));
|
||||
}
|
||||
return Write(
|
||||
ErrorMessage(QStringLiteral("input slot was not ready"),
|
||||
return write(
|
||||
error_message(QStringLiteral("input slot was not ready"),
|
||||
message.ticket_id));
|
||||
}
|
||||
if (int(consumed_slot) != requested_slot) {
|
||||
input_pool_->Release(consumed_slot);
|
||||
input_pool_->release(consumed_slot);
|
||||
for (int slot : input_slots) {
|
||||
input_pool_->Release(uint32_t(slot));
|
||||
input_pool_->release(uint32_t(slot));
|
||||
}
|
||||
return Write(ErrorMessage(
|
||||
return write(error_message(
|
||||
QStringLiteral("input slot order mismatch"),
|
||||
message.ticket_id));
|
||||
}
|
||||
input_slots.append(int(consumed_slot));
|
||||
|
||||
const olive::ipc::FrameSlotMeta *meta =
|
||||
input_pool_->Meta(consumed_slot);
|
||||
input_pool_->meta(consumed_slot);
|
||||
if (meta) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
olive::VideoParams vparams(
|
||||
message.width > 0 ? message.width : kDefaultWidth,
|
||||
message.height > 0 ? message.height : kDefaultHeight,
|
||||
olive::rational(1, kDefaultFrameRate),
|
||||
message.width > 0 ? message.width : k_default_width,
|
||||
message.height > 0 ? message.height : k_default_height,
|
||||
olive::Rational(1, k_default_frame_rate),
|
||||
message.format >= 0 ? olive::PixelFormat::Format(message.format) :
|
||||
olive::PixelFormat::F32,
|
||||
olive::PixelFormat::f32,
|
||||
message.channel_count > 0 ? message.channel_count :
|
||||
olive::VideoParams::kRGBAChannelCount);
|
||||
olive::VideoParams::k_rgba_channel_count);
|
||||
|
||||
olive::RenderTicketPtr ticket = std::make_shared<olive::RenderTicket>();
|
||||
ticket->setProperty("node", olive::QtUtils::PtrToValue(node));
|
||||
ticket->setProperty("node", olive::QtUtils::ptr_to_value(node));
|
||||
ticket->setProperty("time",
|
||||
QVariant::fromValue(olive::rational(
|
||||
QVariant::fromValue(olive::Rational(
|
||||
int(message.time_num), int(message.time_den))));
|
||||
ticket->setProperty("size", QSize(message.width, message.height));
|
||||
ticket->setProperty("matrix", QMatrix4x4());
|
||||
ticket->setProperty("format",
|
||||
message.format >= 0 ?
|
||||
olive::PixelFormat::Format(message.format) :
|
||||
olive::PixelFormat::INVALID);
|
||||
olive::PixelFormat::invalid);
|
||||
ticket->setProperty("usecache", false);
|
||||
ticket->setProperty("channelcount", message.channel_count);
|
||||
ticket->setProperty("mode", olive::RenderMode::Mode(message.mode));
|
||||
ticket->setProperty("type", olive::RenderManager::kTypeVideo);
|
||||
ticket->setProperty("colormanager", olive::QtUtils::PtrToValue(
|
||||
ticket->setProperty("type", olive::RenderManager::k_type_video);
|
||||
ticket->setProperty("colormanager", olive::QtUtils::ptr_to_value(
|
||||
project_->color_manager()));
|
||||
|
||||
{
|
||||
@@ -489,9 +489,9 @@ private:
|
||||
} else {
|
||||
transform = olive::ColorTransform(message.color_output);
|
||||
}
|
||||
color_output = olive::ColorProcessor::Create(
|
||||
color_output = olive::ColorProcessor::create(
|
||||
project_->color_manager(),
|
||||
project_->color_manager()->GetReferenceColorSpace(),
|
||||
project_->color_manager()->get_reference_color_space(),
|
||||
transform);
|
||||
if (color_output) {
|
||||
color_processor_cache_.insert(cache_key, color_output);
|
||||
@@ -504,16 +504,16 @@ private:
|
||||
ticket->setProperty("vparam", QVariant::fromValue(vparams));
|
||||
ticket->setProperty("aparam",
|
||||
QVariant::fromValue(olive::AudioParams()));
|
||||
ticket->setProperty("return", olive::RenderManager::kFrame);
|
||||
ticket->setProperty("return", olive::RenderManager::k_frame);
|
||||
ticket->setProperty("cache", QString());
|
||||
ticket->setProperty("cachetimebase",
|
||||
QVariant::fromValue(olive::rational(1)));
|
||||
QVariant::fromValue(olive::Rational(1)));
|
||||
ticket->setProperty("cacheid", QVariant::fromValue(QUuid()));
|
||||
ticket->setProperty("multicam", olive::QtUtils::PtrToValue(
|
||||
ticket->setProperty("multicam", olive::QtUtils::ptr_to_value(
|
||||
static_cast<void *>(nullptr)));
|
||||
ticket->setProperty(
|
||||
"ipc_input_pool",
|
||||
olive::QtUtils::PtrToValue(input_pool_ ?
|
||||
olive::QtUtils::ptr_to_value(input_pool_ ?
|
||||
static_cast<void *>(&*input_pool_) :
|
||||
static_cast<void *>(nullptr)));
|
||||
QVariantList input_slot_values;
|
||||
@@ -525,44 +525,44 @@ private:
|
||||
ticket->setProperty("ipc_input_slot",
|
||||
input_slots.isEmpty() ? -1 : input_slots.front());
|
||||
|
||||
ticket->Start();
|
||||
olive::RenderProcessor::Process(ticket, renderer_, nullptr,
|
||||
ticket->start();
|
||||
olive::RenderProcessor::process(ticket, renderer_, nullptr,
|
||||
&shader_cache_);
|
||||
for (int slot : input_slots) {
|
||||
input_pool_->Release(uint32_t(slot));
|
||||
input_pool_->release(uint32_t(slot));
|
||||
}
|
||||
if (!ticket->HasResult()) {
|
||||
return Write(ErrorMessage(
|
||||
if (!ticket->has_result()) {
|
||||
return write(error_message(
|
||||
QStringLiteral("render produced no frame"), message.ticket_id));
|
||||
}
|
||||
|
||||
olive::FramePtr frame = ticket->Get().value<olive::FramePtr>();
|
||||
olive::FramePtr frame = ticket->get().value<olive::FramePtr>();
|
||||
if (!frame || !frame->is_allocated()) {
|
||||
return Write(ErrorMessage(QStringLiteral("render result was empty"),
|
||||
return write(error_message(QStringLiteral("render result was empty"),
|
||||
message.ticket_id));
|
||||
}
|
||||
|
||||
uint32_t slot = 0;
|
||||
if (!output_pool_->Acquire(&slot)) {
|
||||
return Write(
|
||||
ErrorMessage(QStringLiteral("no free output frame slot"),
|
||||
if (!output_pool_->acquire(&slot)) {
|
||||
return write(
|
||||
error_message(QStringLiteral("no free output frame slot"),
|
||||
message.ticket_id));
|
||||
}
|
||||
|
||||
const int data_size = frame->linesize_bytes() * frame->height();
|
||||
if (data_size > int(output_pool_->slot_data_bytes())) {
|
||||
output_pool_->Release(slot);
|
||||
LogError(QString("Output frame size") + QString::number(data_size));
|
||||
LogError(QString("Slot size") +
|
||||
output_pool_->release(slot);
|
||||
log_error(QString("Output frame size") + QString::number(data_size));
|
||||
log_error(QString("Slot size") +
|
||||
QString::number(output_pool_->slot_data_bytes()));
|
||||
return Write(ErrorMessage(
|
||||
return write(error_message(
|
||||
QStringLiteral("rendered frame does not fit output slot "),
|
||||
message.ticket_id));
|
||||
}
|
||||
|
||||
std::memcpy(output_pool_->SlotData(slot), frame->const_data(),
|
||||
std::memcpy(output_pool_->slot_data(slot), frame->const_data(),
|
||||
size_t(data_size));
|
||||
olive::ipc::FrameSlotMeta *meta = output_pool_->Meta(slot);
|
||||
olive::ipc::FrameSlotMeta *meta = output_pool_->meta(slot);
|
||||
meta->id = message.ticket_id;
|
||||
meta->time_num = frame->timestamp().numerator();
|
||||
meta->time_den = frame->timestamp().denominator();
|
||||
@@ -573,16 +573,16 @@ private:
|
||||
meta->linesize = frame->linesize_bytes();
|
||||
meta->data_size = data_size;
|
||||
|
||||
if (!output_pool_->Publish(slot)) {
|
||||
output_pool_->Release(slot);
|
||||
return Write(ErrorMessage(
|
||||
if (!output_pool_->publish(slot)) {
|
||||
output_pool_->release(slot);
|
||||
return write(error_message(
|
||||
QStringLiteral("failed to publish output frame slot"),
|
||||
message.ticket_id));
|
||||
}
|
||||
olive::ipc::FrameReadyMsg ready;
|
||||
ready.ticket_id = message.ticket_id;
|
||||
ready.output_slot = int(slot);
|
||||
return Write(ready.ToJson());
|
||||
return write(ready.to_json());
|
||||
}
|
||||
|
||||
olive::Renderer *renderer_;
|
||||
@@ -604,7 +604,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
|
||||
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
|
||||
InstallSurfaceFormat();
|
||||
install_surface_format();
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
@@ -625,36 +625,36 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
std::signal(SIGSEGV, PrintBacktrace);
|
||||
std::signal(SIGABRT, PrintBacktrace);
|
||||
std::signal(SIGFPE, PrintBacktrace);
|
||||
std::signal(SIGSEGV, print_backtrace);
|
||||
std::signal(SIGABRT, print_backtrace);
|
||||
std::signal(SIGFPE, print_backtrace);
|
||||
#endif
|
||||
|
||||
QFile in;
|
||||
QFile out;
|
||||
if (!in.open(stdin, QIODevice::ReadOnly | QIODevice::Unbuffered) ||
|
||||
!out.open(stdout, QIODevice::WriteOnly | QIODevice::Unbuffered)) {
|
||||
LogError(QStringLiteral("failed to open stdio control pipes"));
|
||||
log_error(QStringLiteral("failed to open stdio control pipes"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
olive::Renderer *renderer;
|
||||
#ifdef OAK_ENABLE_DYNAMIC_RENDER_BACKEND
|
||||
auto *dynamic_renderer = new olive::DynamicRenderer(backend);
|
||||
if (dynamic_renderer->Init()) {
|
||||
dynamic_renderer->PostInit();
|
||||
if (dynamic_renderer->init()) {
|
||||
dynamic_renderer->post_init();
|
||||
renderer = dynamic_renderer;
|
||||
} else {
|
||||
delete dynamic_renderer;
|
||||
qWarning() << "Failed to initialize dynamic" << backend
|
||||
<< "backend, falling back to direct OpenGL renderer";
|
||||
renderer = new olive::OpenGLRenderer();
|
||||
if (!renderer->Init()) {
|
||||
LogError(QStringLiteral("failed to initialize OpenGL renderer"));
|
||||
if (!renderer->init()) {
|
||||
log_error(QStringLiteral("failed to initialize OpenGL renderer"));
|
||||
delete renderer;
|
||||
return 1;
|
||||
}
|
||||
renderer->PostInit();
|
||||
renderer->post_init();
|
||||
}
|
||||
#else
|
||||
renderer = new olive::OpenGLRenderer();
|
||||
@@ -674,7 +674,7 @@ int main(int argc, char *argv[])
|
||||
#ifdef OAK_ENABLE_DYNAMIC_RENDER_BACKEND
|
||||
if (auto *loaded_renderer =
|
||||
dynamic_cast<olive::DynamicRenderer *>(renderer)) {
|
||||
ctx = loaded_renderer->OpenGLContext();
|
||||
ctx = loaded_renderer->open_gl_context();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -685,9 +685,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
if (!renderer_valid) {
|
||||
LogError(QStringLiteral("OpenGL context is not valid after init"));
|
||||
renderer->Destroy();
|
||||
renderer->PostDestroy();
|
||||
log_error(QStringLiteral("OpenGL context is not valid after init"));
|
||||
renderer->destroy();
|
||||
renderer->post_destroy();
|
||||
delete renderer;
|
||||
return 1;
|
||||
}
|
||||
@@ -695,7 +695,7 @@ int main(int argc, char *argv[])
|
||||
int exit_code = 0;
|
||||
{
|
||||
RenderWorker worker(renderer, &out);
|
||||
if (!worker.InitializeRuntime() || !worker.SendStartupHandshake()) {
|
||||
if (!worker.initialize_runtime() || !worker.send_startup_handshake()) {
|
||||
exit_code = 1;
|
||||
} else {
|
||||
QByteArray buffer;
|
||||
@@ -709,10 +709,10 @@ int main(int argc, char *argv[])
|
||||
while (true) {
|
||||
QJsonObject message;
|
||||
bool ok = true;
|
||||
if (!olive::ipc::ReadMessage(&buffer, &message, &ok)) {
|
||||
if (!olive::ipc::read_message(&buffer, &message, &ok)) {
|
||||
if (!ok) {
|
||||
olive::ipc::WriteMessage(
|
||||
&out, ErrorMessage(QStringLiteral(
|
||||
olive::ipc::write_message(
|
||||
&out, error_message(QStringLiteral(
|
||||
"malformed control message")));
|
||||
out.flush();
|
||||
continue;
|
||||
@@ -720,7 +720,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
|
||||
if (!worker.Handle(message)) {
|
||||
if (!worker.handle(message)) {
|
||||
exit_code = 1;
|
||||
break;
|
||||
}
|
||||
@@ -729,8 +729,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
renderer->Destroy();
|
||||
renderer->PostDestroy();
|
||||
renderer->destroy();
|
||||
renderer->post_destroy();
|
||||
delete renderer;
|
||||
|
||||
return exit_code;
|
||||
|
||||
Reference in New Issue
Block a user