submodule: change core into nomarl folder, and move KDockWidgets into third_party.
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Olive Community Edition - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBOLIVECORE_H
|
||||
#define LIBOLIVECORE_H
|
||||
|
||||
#include "render/audioparams.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "render/samplebuffer.h"
|
||||
#include "render/sampleformat.h"
|
||||
#include "util/bezier.h"
|
||||
#include "util/color.h"
|
||||
#include "util/cpuoptimize.h"
|
||||
#include "util/log.h"
|
||||
#include "util/math.h"
|
||||
#include "util/rational.h"
|
||||
#include "util/stringutils.h"
|
||||
#include "util/tests.h"
|
||||
#include "util/timecodefunctions.h"
|
||||
#include "util/timerange.h"
|
||||
#include "util/value.h"
|
||||
|
||||
#endif // LIBOLIVECORE_H
|
||||
@@ -0,0 +1,315 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_AUDIOPARAMS_H
|
||||
#define LIBOLIVECORE_AUDIOPARAMS_H
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/channel_layout.h>
|
||||
}
|
||||
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
|
||||
#include "sampleformat.h"
|
||||
#include "../util/rational.h"
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Audio parameters class managing audio stream configuration
|
||||
*
|
||||
* CRITICAL NOTE: This class manages AVChannelLayout which contains dynamic memory
|
||||
* (custom channel maps via u.map pointer). Prior to the Rule of Three implementation,
|
||||
* shallow copies could occur when:
|
||||
* - AudioParams stored in QVector (QVector reallocations)
|
||||
* - AudioParams passed by value to RenderVideoParams
|
||||
* - AudioParams copied during Node graph duplication in ProjectCopier
|
||||
*
|
||||
* When shallow copies occurred, one copy's set_channel_layout() could free the
|
||||
* shared u.map pointer, corrupting other copies. This manifested as:
|
||||
* - channel_layouts=0x0 errors in AudioProcessor::Open()
|
||||
* - is_valid() returning false unexpectedly
|
||||
*
|
||||
* The Rule of Three (copy ctor, copy assignment, destructor) was added to ensure
|
||||
* proper deep copies of AVChannelLayout using av_channel_layout_copy().
|
||||
*/
|
||||
class AudioParams {
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor creates invalid AudioParams
|
||||
* sample_rate=0, channel_layout empty, format=INVALID
|
||||
*/
|
||||
AudioParams()
|
||||
: sample_rate_(0)
|
||||
, channel_layout_{}
|
||||
, channel_count_(0)
|
||||
, format_(SampleFormat::INVALID)
|
||||
{
|
||||
set_default_footage_parameters();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from AVChannelLayout (deep copy)
|
||||
* @param sample_rate Audio sample rate (e.g., 48000)
|
||||
* @param channel_layout FFmpeg channel layout (copied via av_channel_layout_copy)
|
||||
* @param format Sample format (e.g., SampleFormat::F32P)
|
||||
*
|
||||
* NOTE: The channel_layout parameter is deep-copied. The original can be
|
||||
* safely uninit'd after this constructor returns.
|
||||
*/
|
||||
AudioParams(const int &sample_rate, const AVChannelLayout &channel_layout,
|
||||
const SampleFormat &format)
|
||||
: sample_rate_(sample_rate)
|
||||
, channel_layout_{}
|
||||
, channel_count_(0)
|
||||
, format_(format)
|
||||
{
|
||||
set_default_footage_parameters();
|
||||
timebase_ = sample_rate_as_time_base();
|
||||
av_channel_layout_uninit(&channel_layout_);
|
||||
av_channel_layout_copy(&channel_layout_, &channel_layout);
|
||||
|
||||
// Cache channel count from the copied layout
|
||||
calculate_channel_count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor from channel layout mask
|
||||
* @param sample_rate Audio sample rate
|
||||
* @param channel_layout Channel layout mask (e.g., AV_CH_LAYOUT_STEREO)
|
||||
* @param format Sample format
|
||||
*
|
||||
* This is the most common constructor used in Olive. The mask is converted
|
||||
* to AVChannelLayout via av_channel_layout_from_mask().
|
||||
*/
|
||||
AudioParams(const int &sample_rate, uint64_t channel_layout,
|
||||
const SampleFormat &format)
|
||||
: sample_rate_(sample_rate)
|
||||
, channel_layout_{}
|
||||
, channel_count_(0)
|
||||
, format_(format)
|
||||
{
|
||||
set_default_footage_parameters();
|
||||
timebase_ = sample_rate_as_time_base();
|
||||
av_channel_layout_uninit(&channel_layout_);
|
||||
av_channel_layout_from_mask(&channel_layout_, channel_layout);
|
||||
// Cache channel count
|
||||
calculate_channel_count();
|
||||
}
|
||||
int sample_rate() const
|
||||
{
|
||||
return sample_rate_;
|
||||
}
|
||||
|
||||
void set_sample_rate(int sample_rate)
|
||||
{
|
||||
sample_rate_ = sample_rate;
|
||||
}
|
||||
|
||||
const AVChannelLayout &channel_layout() const
|
||||
{
|
||||
return channel_layout_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set channel layout from AVChannelLayout (deep copy)
|
||||
* @param channel_layout Source channel layout to copy
|
||||
*
|
||||
* CRITICAL: This function first uninitializes the current layout (freeing any
|
||||
* dynamic memory), then deep-copies the new layout. This is safe only if
|
||||
* copies are properly managed via Rule of Three.
|
||||
*
|
||||
* If called on a shallow-copied AudioParams, this would corrupt other copies
|
||||
* that share the same u.map pointer.
|
||||
*/
|
||||
void set_channel_layout(const AVChannelLayout &channel_layout)
|
||||
{
|
||||
av_channel_layout_uninit(&channel_layout_);
|
||||
av_channel_layout_copy(&channel_layout_, &channel_layout);
|
||||
calculate_channel_count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set channel layout from mask
|
||||
* @param mask Channel layout mask (e.g., AV_CH_LAYOUT_STEREO)
|
||||
*/
|
||||
void set_channel_layout(uint64_t mask)
|
||||
{
|
||||
av_channel_layout_uninit(&channel_layout_);
|
||||
av_channel_layout_from_mask(&channel_layout_, mask);
|
||||
calculate_channel_count();
|
||||
}
|
||||
rational time_base() const
|
||||
{
|
||||
return timebase_;
|
||||
}
|
||||
|
||||
void set_time_base(const rational &timebase)
|
||||
{
|
||||
timebase_ = timebase;
|
||||
}
|
||||
|
||||
rational sample_rate_as_time_base() const
|
||||
{
|
||||
return rational(1, sample_rate());
|
||||
}
|
||||
|
||||
SampleFormat format() const
|
||||
{
|
||||
return format_;
|
||||
}
|
||||
|
||||
void set_format(SampleFormat format)
|
||||
{
|
||||
format_ = format;
|
||||
}
|
||||
|
||||
bool enabled() const
|
||||
{
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
void set_enabled(bool e)
|
||||
{
|
||||
enabled_ = e;
|
||||
}
|
||||
|
||||
int stream_index() const
|
||||
{
|
||||
return stream_index_;
|
||||
}
|
||||
|
||||
void set_stream_index(int s)
|
||||
{
|
||||
stream_index_ = s;
|
||||
}
|
||||
|
||||
int64_t duration() const
|
||||
{
|
||||
return duration_;
|
||||
}
|
||||
|
||||
void set_duration(int64_t duration)
|
||||
{
|
||||
duration_ = duration;
|
||||
}
|
||||
|
||||
int64_t time_to_bytes(const double &time) const;
|
||||
int64_t time_to_bytes(const rational &time) const;
|
||||
int64_t time_to_bytes_per_channel(const double &time) const;
|
||||
int64_t time_to_bytes_per_channel(const rational &time) const;
|
||||
int64_t time_to_samples(const double &time) const;
|
||||
int64_t time_to_samples(const rational &time) const;
|
||||
int64_t samples_to_bytes(const int64_t &samples) const;
|
||||
int64_t samples_to_bytes_per_channel(const int64_t &samples) const;
|
||||
rational samples_to_time(const int64_t &samples) const;
|
||||
int64_t bytes_to_samples(const int64_t &bytes) const;
|
||||
rational bytes_to_time(const int64_t &bytes) const;
|
||||
rational bytes_per_channel_to_time(const int64_t &bytes) const;
|
||||
int channel_count() const;
|
||||
int bytes_per_sample_per_channel() const;
|
||||
int bits_per_sample() const;
|
||||
bool is_valid() const;
|
||||
|
||||
bool operator==(const AudioParams &other) const;
|
||||
bool operator!=(const AudioParams &other) const;
|
||||
|
||||
/**
|
||||
* @name Rule of Three Implementation
|
||||
*
|
||||
* These are required because AVChannelLayout (FFmpeg >= 5.0) contains a union
|
||||
* with a pointer member (u.map for custom channel maps). Without proper
|
||||
* deep copy management:
|
||||
*
|
||||
* 1. Default copy constructor: Shallow copies u.map pointer, leading to
|
||||
* double-free when original and copy are destroyed
|
||||
* 2. Default copy assignment: Same issue as copy constructor
|
||||
* 3. Default destructor: Doesn't free u.map, causing memory leaks
|
||||
*
|
||||
* The implementations use av_channel_layout_copy() and av_channel_layout_uninit()
|
||||
* for proper FFmpeg-managed memory handling.
|
||||
*
|
||||
* Context where this matters:
|
||||
* - QVector<AudioParams> in FootageDescription (vector reallocations)
|
||||
* - RenderVideoParams passing AudioParams by value
|
||||
* - ProjectCopier duplicating node graphs with audio parameters
|
||||
*/
|
||||
///@{
|
||||
AudioParams(const AudioParams &other);
|
||||
AudioParams &operator=(const AudioParams &other);
|
||||
~AudioParams();
|
||||
///@}
|
||||
|
||||
static const std::vector<uint64_t> kSupportedChannelLayouts;
|
||||
static const std::vector<int> kSupportedSampleRates;
|
||||
|
||||
private:
|
||||
void set_default_footage_parameters()
|
||||
{
|
||||
enabled_ = true;
|
||||
stream_index_ = 0;
|
||||
duration_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates channel_count_ from the current channel_layout_
|
||||
* Called after any channel layout modification.
|
||||
*/
|
||||
void calculate_channel_count();
|
||||
|
||||
int sample_rate_; ///< Audio sample rate in Hz (e.g., 48000)
|
||||
|
||||
/**
|
||||
* @brief FFmpeg channel layout structure
|
||||
*
|
||||
* WARNING: This struct contains a union with a pointer member (u.map) when
|
||||
* using custom channel layouts (order == AV_CHANNEL_ORDER_CUSTOM). The pointer
|
||||
* must be properly managed via av_channel_layout_copy/uninit.
|
||||
*
|
||||
* Layout variants:
|
||||
* - order == AV_CHANNEL_ORDER_UNSPEC: u.mask is undefined, nb_channels valid
|
||||
* - order == AV_CHANNEL_ORDER_NATIVE: u.mask contains channel bitmask
|
||||
* - order == AV_CHANNEL_ORDER_CUSTOM: u.map points to AVChannelCustom array
|
||||
*
|
||||
* Corruption symptoms:
|
||||
* - u.mask == 0 when order should be NATIVE
|
||||
* - av_channel_layout_check() returns false
|
||||
* - is_valid() returns false
|
||||
*/
|
||||
AVChannelLayout channel_layout_;
|
||||
|
||||
int channel_count_; ///< Cached channel count from layout
|
||||
|
||||
SampleFormat format_; ///< Audio sample format
|
||||
|
||||
// Footage-specific parameters (serialized with footage metadata)
|
||||
int enabled_; // Using int instead of bool fixes GCC 11 stringop-overflow issue (byte alignment)
|
||||
int stream_index_; ///< Index in the source file's stream list
|
||||
int64_t duration_; ///< Stream duration in timebase units
|
||||
rational timebase_; ///< Timebase for this audio stream
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_AUDIOPARAMS_H
|
||||
@@ -0,0 +1,132 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_PIXELFORMAT_H
|
||||
#define LIBOLIVECORE_PIXELFORMAT_H
|
||||
#include "ofxCore.h"
|
||||
#include <string>
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
class PixelFormat {
|
||||
public:
|
||||
enum Format { INVALID = -1, U8, U10, U16, F16, F32, COUNT };
|
||||
|
||||
PixelFormat(Format f = INVALID)
|
||||
{
|
||||
f_ = f;
|
||||
}
|
||||
|
||||
operator Format() const
|
||||
{
|
||||
return f_;
|
||||
}
|
||||
|
||||
static PixelFormat from_ofx(std::string ofxFormat){
|
||||
if(ofxFormat == kOfxBitDepthByte){
|
||||
return PixelFormat::U8;
|
||||
}
|
||||
else if (ofxFormat == kOfxBitDepthShort){
|
||||
return PixelFormat::U16;
|
||||
}
|
||||
else if(ofxFormat == kOfxBitDepthHalf){
|
||||
return PixelFormat::F16;
|
||||
}
|
||||
else if(ofxFormat == kOfxBitDepthFloat){
|
||||
return PixelFormat::F32;
|
||||
}
|
||||
return PixelFormat::INVALID;
|
||||
}
|
||||
static int byte_count(Format f)
|
||||
{
|
||||
switch (f) {
|
||||
case INVALID:
|
||||
case COUNT:
|
||||
break;
|
||||
case U8:
|
||||
return 1;
|
||||
case U10:
|
||||
return 4; // packed RGBA10A2, treated as 4 bytes per pixel
|
||||
case U16:
|
||||
case F16:
|
||||
return 2;
|
||||
case F32:
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *to_string() const
|
||||
{
|
||||
switch (f_) {
|
||||
case U8:
|
||||
return "u8";
|
||||
case U10:
|
||||
return "u10";
|
||||
case U16:
|
||||
return "u16";
|
||||
case F16:
|
||||
return "f16";
|
||||
case F32:
|
||||
return "f32";
|
||||
case INVALID:
|
||||
case COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
int byte_count() const
|
||||
{
|
||||
return byte_count(f_);
|
||||
}
|
||||
|
||||
static bool is_float(Format f)
|
||||
{
|
||||
switch (f) {
|
||||
case INVALID:
|
||||
case COUNT:
|
||||
case U8:
|
||||
case U10:
|
||||
case U16:
|
||||
break;
|
||||
case F16:
|
||||
case F32:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_float() const
|
||||
{
|
||||
return is_float(f_);
|
||||
}
|
||||
|
||||
private:
|
||||
Format f_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_PIXELFORMAT_H
|
||||
@@ -0,0 +1,137 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_SAMPLEBUFFER_H
|
||||
#define LIBOLIVECORE_SAMPLEBUFFER_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "audioparams.h"
|
||||
#include "../util/rational.h"
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A buffer of audio samples
|
||||
*
|
||||
* Audio samples in this structure are always stored in PLANAR (separated by channel). This is done to simplify audio
|
||||
* rendering code. This replaces the old system of using QByteArrays (containing packed audio) and while SampleBuffer
|
||||
* replaces many of those in the rendering/processing side of things, QByteArrays are currently still in use for
|
||||
* playback, including reading to and from the cache.
|
||||
*/
|
||||
class SampleBuffer {
|
||||
public:
|
||||
SampleBuffer();
|
||||
SampleBuffer(const AudioParams &audio_params, const rational &length);
|
||||
SampleBuffer(const AudioParams &audio_params, size_t samples_per_channel);
|
||||
|
||||
SampleBuffer rip_channel(int channel) const;
|
||||
std::vector<float> rip_channel_vector(int channel) const;
|
||||
|
||||
const AudioParams &audio_params() const;
|
||||
void set_audio_params(const AudioParams ¶ms);
|
||||
|
||||
const size_t &sample_count() const
|
||||
{
|
||||
return sample_count_per_channel_;
|
||||
}
|
||||
void set_sample_count(const size_t &sample_count);
|
||||
void set_sample_count(const rational &length)
|
||||
{
|
||||
set_sample_count(audio_params_.time_to_samples(length));
|
||||
}
|
||||
|
||||
float *data(int channel)
|
||||
{
|
||||
return data_[channel].data();
|
||||
}
|
||||
|
||||
const float *data(int channel) const
|
||||
{
|
||||
return data_.at(channel).data();
|
||||
}
|
||||
|
||||
std::vector<float *> to_raw_ptrs()
|
||||
{
|
||||
std::vector<float *> r(data_.size());
|
||||
for (size_t i = 0; i < r.size(); i++) {
|
||||
r[i] = data_[i].data();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int channel_count() const
|
||||
{
|
||||
return data_.size();
|
||||
}
|
||||
|
||||
bool is_allocated() const
|
||||
{
|
||||
return !data_.empty();
|
||||
}
|
||||
void allocate();
|
||||
void destroy();
|
||||
|
||||
void reverse();
|
||||
void speed(double speed);
|
||||
|
||||
void transform_volume(float f);
|
||||
void transform_volume_for_channel(int channel, float volume);
|
||||
static void transform_volume(float f, const SampleBuffer *input,
|
||||
SampleBuffer *output);
|
||||
static void transform_volume_for_channel(int channel, float volume,
|
||||
const SampleBuffer *input,
|
||||
SampleBuffer *output);
|
||||
|
||||
void transform_volume_for_sample(size_t sample_index, float volume);
|
||||
void transform_volume_for_sample_on_channel(size_t sample_index,
|
||||
int channel, float volume);
|
||||
|
||||
void clamp();
|
||||
|
||||
void silence();
|
||||
void silence(size_t start_sample, size_t end_sample);
|
||||
void silence_bytes(size_t start_byte, size_t end_byte);
|
||||
|
||||
void set(int channel, const float *data, size_t sample_offset,
|
||||
size_t sample_length);
|
||||
void set(int channel, const float *data, size_t sample_length)
|
||||
{
|
||||
set(channel, data, 0, sample_length);
|
||||
}
|
||||
|
||||
void fast_set(const SampleBuffer &other, int to, int from = -1);
|
||||
|
||||
private:
|
||||
void clamp_channel(int channel);
|
||||
|
||||
AudioParams audio_params_;
|
||||
|
||||
size_t sample_count_per_channel_;
|
||||
|
||||
std::vector<std::vector<float>> data_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_SAMPLEBUFFER_H
|
||||
@@ -0,0 +1,288 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_SAMPLEFORMAT_H
|
||||
#define LIBOLIVECORE_SAMPLEFORMAT_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
class SampleFormat {
|
||||
public:
|
||||
enum Format {
|
||||
INVALID = -1,
|
||||
|
||||
U8P,
|
||||
S16P,
|
||||
S32P,
|
||||
S64P,
|
||||
F32P,
|
||||
F64P,
|
||||
|
||||
U8,
|
||||
S16,
|
||||
S32,
|
||||
S64,
|
||||
F32,
|
||||
F64,
|
||||
|
||||
COUNT,
|
||||
|
||||
PLANAR_START = U8P,
|
||||
PACKED_START = U8,
|
||||
PLANAR_END = PACKED_START,
|
||||
PACKED_END = COUNT,
|
||||
};
|
||||
|
||||
SampleFormat(Format f = INVALID)
|
||||
{
|
||||
f_ = f;
|
||||
}
|
||||
|
||||
operator Format() const
|
||||
{
|
||||
return f_;
|
||||
}
|
||||
|
||||
static int byte_count(Format f)
|
||||
{
|
||||
switch (f) {
|
||||
case U8:
|
||||
case U8P:
|
||||
return 1;
|
||||
case S16:
|
||||
case S16P:
|
||||
return 2;
|
||||
case S32:
|
||||
case F32:
|
||||
case S32P:
|
||||
case F32P:
|
||||
return 4;
|
||||
case S64:
|
||||
case F64:
|
||||
case S64P:
|
||||
case F64P:
|
||||
return 8;
|
||||
case INVALID:
|
||||
case COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int byte_count() const
|
||||
{
|
||||
return byte_count(f_);
|
||||
}
|
||||
|
||||
static std::string to_string(Format f)
|
||||
{
|
||||
switch (f) {
|
||||
case INVALID:
|
||||
case COUNT:
|
||||
break;
|
||||
case U8:
|
||||
return "u8";
|
||||
case S16:
|
||||
return "s16";
|
||||
case S32:
|
||||
return "s32";
|
||||
case S64:
|
||||
return "s64";
|
||||
case F32:
|
||||
return "f32";
|
||||
case F64:
|
||||
return "f64";
|
||||
case U8P:
|
||||
return "u8p";
|
||||
case S16P:
|
||||
return "s16p";
|
||||
case S32P:
|
||||
return "s32p";
|
||||
case S64P:
|
||||
return "s64p";
|
||||
case F32P:
|
||||
return "f32p";
|
||||
case F64P:
|
||||
return "f64p";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return to_string(f_);
|
||||
}
|
||||
|
||||
static SampleFormat from_string(const std::string &s)
|
||||
{
|
||||
if (s.empty()) {
|
||||
return INVALID;
|
||||
} else if (s == "u8") {
|
||||
return U8;
|
||||
} else if (s == "s16") {
|
||||
return S16;
|
||||
} else if (s == "s32") {
|
||||
return S32;
|
||||
} else if (s == "s64") {
|
||||
return S64;
|
||||
} else if (s == "f32") {
|
||||
return F32;
|
||||
} else if (s == "f64") {
|
||||
return F64;
|
||||
} else if (s == "u8p") {
|
||||
return U8P;
|
||||
} else if (s == "s16p") {
|
||||
return S16P;
|
||||
} else if (s == "s32p") {
|
||||
return S32P;
|
||||
} else if (s == "s64p") {
|
||||
return S64P;
|
||||
} else if (s == "f32p") {
|
||||
return F32P;
|
||||
} else if (s == "f64p") {
|
||||
return F64P;
|
||||
} else {
|
||||
// Deprecated: sample formats used to be serialized as an integer. Handle that here, but we'll
|
||||
// probably remove that eventually.
|
||||
try {
|
||||
int i = std::stoi(s);
|
||||
if (i > INVALID && i < COUNT) {
|
||||
return static_cast<Format>(i);
|
||||
}
|
||||
} catch (const std::invalid_argument &e) {
|
||||
}
|
||||
|
||||
// Failed to deserialize from string
|
||||
return INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_packed(Format f)
|
||||
{
|
||||
return f >= PACKED_START && f < PACKED_END;
|
||||
}
|
||||
|
||||
bool is_packed() const
|
||||
{
|
||||
return is_packed(f_);
|
||||
}
|
||||
|
||||
static bool is_planar(Format f)
|
||||
{
|
||||
return f >= PLANAR_START && f < PLANAR_END;
|
||||
}
|
||||
|
||||
bool is_planar() const
|
||||
{
|
||||
return is_planar(f_);
|
||||
}
|
||||
|
||||
static SampleFormat to_packed_equivalent(SampleFormat fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
// For packed input, just return input
|
||||
case U8:
|
||||
case S16:
|
||||
case S32:
|
||||
case S64:
|
||||
case F32:
|
||||
case F64:
|
||||
return fmt;
|
||||
|
||||
// Convert to packed
|
||||
case U8P:
|
||||
return U8;
|
||||
case S16P:
|
||||
return S16;
|
||||
case S32P:
|
||||
return S32;
|
||||
case S64P:
|
||||
return S64;
|
||||
case F32P:
|
||||
return F32;
|
||||
case F64P:
|
||||
return F64;
|
||||
|
||||
case INVALID:
|
||||
case COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
SampleFormat to_packed_equivalent() const
|
||||
{
|
||||
return to_packed_equivalent(f_);
|
||||
}
|
||||
|
||||
static SampleFormat to_planar_equivalent(SampleFormat fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
// Convert to planar
|
||||
case U8:
|
||||
return U8P;
|
||||
case S16:
|
||||
return S16P;
|
||||
case S32:
|
||||
return S32P;
|
||||
case S64:
|
||||
return S64P;
|
||||
case F32:
|
||||
return F32P;
|
||||
case F64:
|
||||
return F64P;
|
||||
|
||||
// For planar input, just return input
|
||||
case U8P:
|
||||
case S16P:
|
||||
case S32P:
|
||||
case S64P:
|
||||
case F32P:
|
||||
case F64P:
|
||||
return fmt;
|
||||
|
||||
case INVALID:
|
||||
case COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
SampleFormat to_planar_equivalent() const
|
||||
{
|
||||
return to_planar_equivalent(f_);
|
||||
}
|
||||
|
||||
private:
|
||||
Format f_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_SAMPLEFORMAT_H
|
||||
@@ -0,0 +1,138 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_BEZIER_H
|
||||
#define LIBOLIVECORE_BEZIER_H
|
||||
|
||||
#include <Imath/ImathVec.h>
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
class Bezier {
|
||||
public:
|
||||
Bezier();
|
||||
Bezier(double x, double y);
|
||||
Bezier(double x, double y, double cp1_x, double cp1_y, double cp2_x,
|
||||
double cp2_y);
|
||||
|
||||
const double &x() const
|
||||
{
|
||||
return x_;
|
||||
}
|
||||
const double &y() const
|
||||
{
|
||||
return y_;
|
||||
}
|
||||
const double &cp1_x() const
|
||||
{
|
||||
return cp1_x_;
|
||||
}
|
||||
const double &cp1_y() const
|
||||
{
|
||||
return cp1_y_;
|
||||
}
|
||||
const double &cp2_x() const
|
||||
{
|
||||
return cp2_x_;
|
||||
}
|
||||
const double &cp2_y() const
|
||||
{
|
||||
return cp2_y_;
|
||||
}
|
||||
|
||||
Imath::V2d to_vec() const
|
||||
{
|
||||
return Imath::V2d(x_, y_);
|
||||
}
|
||||
|
||||
Imath::V2d control_point_1_to_vec() const
|
||||
{
|
||||
return Imath::V2d(cp1_x_, cp1_y_);
|
||||
}
|
||||
|
||||
Imath::V2d control_point_2_to_vec() const
|
||||
{
|
||||
return Imath::V2d(cp2_x_, cp2_y_);
|
||||
}
|
||||
|
||||
void set_x(const double &x)
|
||||
{
|
||||
x_ = x;
|
||||
}
|
||||
void set_y(const double &y)
|
||||
{
|
||||
y_ = y;
|
||||
}
|
||||
void set_cp1_x(const double &cp1_x)
|
||||
{
|
||||
cp1_x_ = cp1_x;
|
||||
}
|
||||
void set_cp1_y(const double &cp1_y)
|
||||
{
|
||||
cp1_y_ = cp1_y;
|
||||
}
|
||||
void set_cp2_x(const double &cp2_x)
|
||||
{
|
||||
cp2_x_ = cp2_x;
|
||||
}
|
||||
void set_cp2_y(const double &cp2_y)
|
||||
{
|
||||
cp2_y_ = cp2_y;
|
||||
}
|
||||
|
||||
static double QuadraticXtoT(double x, double a, double b, double c);
|
||||
|
||||
static double QuadraticTtoY(double a, double b, double c, double t);
|
||||
|
||||
static double QuadraticXtoY(double x, const Imath::V2d &a,
|
||||
const Imath::V2d &b, const Imath::V2d &c)
|
||||
{
|
||||
return QuadraticTtoY(a.y, b.y, c.y, QuadraticXtoT(x, a.x, b.x, c.x));
|
||||
}
|
||||
|
||||
static double CubicXtoT(double x, double a, double b, double c, double d);
|
||||
|
||||
static double CubicTtoY(double a, double b, double c, double d, double t);
|
||||
|
||||
static double CubicXtoY(double x, const Imath::V2d &a, const Imath::V2d &b,
|
||||
const Imath::V2d &c, const Imath::V2d &d)
|
||||
{
|
||||
return CubicTtoY(a.y, b.y, c.y, d.y, CubicXtoT(x, a.x, b.x, c.x, d.x));
|
||||
}
|
||||
|
||||
private:
|
||||
static double CalculateTFromX(bool cubic, double x, double a, double b,
|
||||
double c, double d);
|
||||
|
||||
double x_;
|
||||
double y_;
|
||||
|
||||
double cp1_x_;
|
||||
double cp1_y_;
|
||||
|
||||
double cp2_x_;
|
||||
double cp2_y_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_BEZIER_H
|
||||
@@ -0,0 +1,184 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_COLOR_H
|
||||
#define LIBOLIVECORE_COLOR_H
|
||||
|
||||
#include "../render/pixelformat.h"
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief High precision 32-bit DataType based RGBA color value
|
||||
*/
|
||||
class Color {
|
||||
public:
|
||||
using DataType = float;
|
||||
static constexpr unsigned int RGBA = 4;
|
||||
|
||||
Color()
|
||||
{
|
||||
for (unsigned int i = 0; i < RGBA; i++) {
|
||||
data_[i] = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
Color(const DataType &r, const DataType &g, const DataType &b,
|
||||
const DataType &a = 1.0f)
|
||||
{
|
||||
data_[0] = r;
|
||||
data_[1] = g;
|
||||
data_[2] = b;
|
||||
data_[3] = a;
|
||||
}
|
||||
|
||||
Color(const char *data, const PixelFormat &format, int ch_layout);
|
||||
|
||||
/**
|
||||
* @brief Creates a Color struct from hue/saturation/value
|
||||
*
|
||||
* Hue expects a value between 0.0 and 360.0. Saturation and Value expect a value between 0.0 and 1.0.
|
||||
*/
|
||||
static Color fromHsv(const DataType &h, const DataType &s,
|
||||
const DataType &v);
|
||||
|
||||
const DataType &red() const
|
||||
{
|
||||
return data_[0];
|
||||
}
|
||||
const DataType &green() const
|
||||
{
|
||||
return data_[1];
|
||||
}
|
||||
const DataType &blue() const
|
||||
{
|
||||
return data_[2];
|
||||
}
|
||||
const DataType &alpha() const
|
||||
{
|
||||
return data_[3];
|
||||
}
|
||||
|
||||
void toHsv(DataType *hue, DataType *sat, DataType *val) const;
|
||||
DataType hsv_hue() const;
|
||||
DataType hsv_saturation() const;
|
||||
DataType value() const;
|
||||
|
||||
void toHsl(DataType *hue, DataType *sat, DataType *lightness) const;
|
||||
DataType hsl_hue() const;
|
||||
DataType hsl_saturation() const;
|
||||
DataType lightness() const;
|
||||
|
||||
void set_red(const DataType &red)
|
||||
{
|
||||
data_[0] = red;
|
||||
}
|
||||
void set_green(const DataType &green)
|
||||
{
|
||||
data_[1] = green;
|
||||
}
|
||||
void set_blue(const DataType &blue)
|
||||
{
|
||||
data_[2] = blue;
|
||||
}
|
||||
void set_alpha(const DataType &alpha)
|
||||
{
|
||||
data_[3] = alpha;
|
||||
}
|
||||
|
||||
DataType *data()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
const DataType *data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
void toData(char *out, const PixelFormat &format,
|
||||
unsigned int nb_channels) const;
|
||||
|
||||
static Color fromData(const char *in, const PixelFormat &format,
|
||||
unsigned int nb_channels);
|
||||
|
||||
// Suuuuper rough luminance value mostly used for UI (determining whether to overlay with black
|
||||
// or white text)
|
||||
DataType GetRoughLuminance() const;
|
||||
|
||||
// Assignment math operators
|
||||
Color &operator+=(const Color &rhs);
|
||||
Color &operator-=(const Color &rhs);
|
||||
Color &operator+=(const DataType &rhs);
|
||||
Color &operator-=(const DataType &rhs);
|
||||
Color &operator*=(const DataType &rhs);
|
||||
Color &operator/=(const DataType &rhs);
|
||||
|
||||
// Binary math operators
|
||||
Color operator+(const Color &rhs) const
|
||||
{
|
||||
Color c(*this);
|
||||
c += rhs;
|
||||
return c;
|
||||
}
|
||||
|
||||
Color operator-(const Color &rhs) const
|
||||
{
|
||||
Color c(*this);
|
||||
c -= rhs;
|
||||
return c;
|
||||
}
|
||||
|
||||
Color operator+(const DataType &rhs) const
|
||||
{
|
||||
Color c(*this);
|
||||
c += rhs;
|
||||
return c;
|
||||
}
|
||||
|
||||
Color operator-(const DataType &rhs) const
|
||||
{
|
||||
Color c(*this);
|
||||
c -= rhs;
|
||||
return c;
|
||||
}
|
||||
|
||||
Color operator*(const DataType &rhs) const
|
||||
{
|
||||
Color c(*this);
|
||||
c *= rhs;
|
||||
return c;
|
||||
}
|
||||
|
||||
Color operator/(const DataType &rhs) const
|
||||
{
|
||||
Color c(*this);
|
||||
c /= rhs;
|
||||
return c;
|
||||
}
|
||||
|
||||
private:
|
||||
DataType data_[RGBA];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_COLOR_H
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Olive Community Edition - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBOLIVECORE_CPUOPTIMIZE_H
|
||||
#define LIBOLIVECORE_CPUOPTIMIZE_H
|
||||
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
#define OLIVE_PROCESSOR_X86
|
||||
#include <xmmintrin.h>
|
||||
#elif defined(__aarch64__)
|
||||
#define OLIVE_PROCESSOR_ARM
|
||||
#include "sse2neon.h"
|
||||
#endif
|
||||
|
||||
#endif // LIBOLIVECORE_CPUOPTIMIZE_H
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Olive Community Edition - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
class Log {
|
||||
public:
|
||||
Log(const char *type)
|
||||
{
|
||||
std::cerr << "[" << type << "]";
|
||||
}
|
||||
|
||||
~Log()
|
||||
{
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
template <typename T> Log &operator<<(const T &t)
|
||||
{
|
||||
std::cerr << " " << t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
static Log Debug()
|
||||
{
|
||||
return Log("DEBUG");
|
||||
}
|
||||
|
||||
static Log Info()
|
||||
{
|
||||
return Log("INFO");
|
||||
}
|
||||
|
||||
static Log Warning()
|
||||
{
|
||||
return Log("WARNING");
|
||||
}
|
||||
|
||||
static Log Error()
|
||||
{
|
||||
return Log("ERROR");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LOG_H
|
||||
@@ -0,0 +1,30 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_MATH_H
|
||||
#define LIBOLIVECORE_MATH_H
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_MATH_H
|
||||
@@ -0,0 +1,168 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_RATIONAL_H
|
||||
#define LIBOLIVECORE_RATIONAL_H
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/rational.h>
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifdef USE_OTIO
|
||||
#include <opentime/rationalTime.h>
|
||||
#endif
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
class rational {
|
||||
public:
|
||||
rational(const int &numerator = 0)
|
||||
{
|
||||
r_.num = numerator;
|
||||
r_.den = 1;
|
||||
}
|
||||
|
||||
rational(const int &numerator, const int &denominator)
|
||||
{
|
||||
r_.num = numerator;
|
||||
r_.den = denominator;
|
||||
|
||||
fix_signs();
|
||||
reduce();
|
||||
}
|
||||
|
||||
rational(const rational &rhs) = default;
|
||||
|
||||
rational(const AVRational &r)
|
||||
{
|
||||
r_ = r;
|
||||
|
||||
fix_signs();
|
||||
}
|
||||
|
||||
static rational fromDouble(const double &flt, bool *ok = nullptr);
|
||||
static rational fromString(const std::string &str, bool *ok = nullptr);
|
||||
|
||||
static const rational NaN;
|
||||
|
||||
//Assignment Operators
|
||||
const rational &operator=(const rational &rhs);
|
||||
const rational &operator+=(const rational &rhs);
|
||||
const rational &operator-=(const rational &rhs);
|
||||
const rational &operator/=(const rational &rhs);
|
||||
const rational &operator*=(const rational &rhs);
|
||||
|
||||
//Binary math operators
|
||||
rational operator+(const rational &rhs) const;
|
||||
rational operator-(const rational &rhs) const;
|
||||
rational operator/(const rational &rhs) const;
|
||||
rational operator*(const rational &rhs) const;
|
||||
|
||||
//Relational and equality operators
|
||||
bool operator<(const rational &rhs) const;
|
||||
bool operator<=(const rational &rhs) const;
|
||||
bool operator>(const rational &rhs) const;
|
||||
bool operator>=(const rational &rhs) const;
|
||||
bool operator==(const rational &rhs) const;
|
||||
bool operator!=(const rational &rhs) const;
|
||||
|
||||
//Unary operators
|
||||
const rational &operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
rational operator-() const
|
||||
{
|
||||
return rational(r_.num, -r_.den);
|
||||
}
|
||||
bool operator!() const
|
||||
{
|
||||
return !r_.num;
|
||||
}
|
||||
|
||||
//Function: convert to double
|
||||
double toDouble() const;
|
||||
|
||||
AVRational toAVRational() const;
|
||||
|
||||
#ifdef USE_OTIO
|
||||
static rational fromRationalTime(const opentime::RationalTime &t)
|
||||
{
|
||||
// Is this the best way to do this?
|
||||
return fromDouble(t.to_seconds());
|
||||
}
|
||||
|
||||
// Convert Olive rationals to opentime rationals with the given framerate (defaults to 24)
|
||||
opentime::RationalTime toRationalTime(double framerate = 24) const;
|
||||
#endif
|
||||
|
||||
// Produce "flipped" version
|
||||
rational flipped() const;
|
||||
void flip();
|
||||
|
||||
// Returns whether the rational is valid but equal to zero or not
|
||||
//
|
||||
// A NaN is always a null, but a null is not always a NaN
|
||||
bool isNull() const
|
||||
{
|
||||
return r_.num == 0;
|
||||
}
|
||||
|
||||
// Returns whether this rational is not a valid number (denominator == 0)
|
||||
bool isNaN() const
|
||||
{
|
||||
return r_.den == 0;
|
||||
}
|
||||
|
||||
const int &numerator() const
|
||||
{
|
||||
return r_.num;
|
||||
}
|
||||
const int &denominator() const
|
||||
{
|
||||
return r_.den;
|
||||
}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &out, const rational &value)
|
||||
{
|
||||
out << value.r_.num << '/' << value.r_.den;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
void fix_signs();
|
||||
void reduce();
|
||||
|
||||
AVRational r_;
|
||||
};
|
||||
|
||||
#define RATIONAL_MIN rational(INT_MIN)
|
||||
#define RATIONAL_MAX rational(INT_MAX)
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_RATIONAL_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,211 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_STRINGUTILS_H
|
||||
#define LIBOLIVECORE_STRINGUTILS_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
class StringUtils {
|
||||
public:
|
||||
/**
|
||||
* @brief Split a string into a list of strings using a specific delimiter
|
||||
*
|
||||
* @param s
|
||||
*
|
||||
* The string to split.
|
||||
*
|
||||
* @param separator
|
||||
*
|
||||
* The character to split the string on.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* A vector of strings split by the specified delimiter.
|
||||
*/
|
||||
static std::vector<std::string> split(const std::string &s, char separator);
|
||||
|
||||
/**
|
||||
* @brief Splits a string into a list of strings using regular expressions.
|
||||
*
|
||||
* @param s
|
||||
*
|
||||
* The string to split.
|
||||
*
|
||||
* @param regex
|
||||
*
|
||||
* The regular expression to split the string on.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* A vector of strings split wherever the regular expression matched.
|
||||
*/
|
||||
static std::vector<std::string> split_regex(const std::string &s,
|
||||
const std::regex ®ex);
|
||||
|
||||
/**
|
||||
* @brief Convert a string to int using a bool pointer to determine success rather than an exception
|
||||
*
|
||||
* @param s
|
||||
*
|
||||
* The string to parse an int from.
|
||||
*
|
||||
* @param base
|
||||
*
|
||||
* The base of the number in the string (usually 10, or 16 for hex).
|
||||
*
|
||||
* @param ok
|
||||
*
|
||||
* (Optional) a boolean output parameter specifying whether the conversion was successful or not.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* Either the int parsed from the string, or 0 (with *ok set to false) on parser error.
|
||||
*/
|
||||
static int to_int(const std::string &s, int base, bool *ok = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Overloaded function
|
||||
*
|
||||
* @param s
|
||||
*
|
||||
* The string to parse an int from.
|
||||
*
|
||||
* @param ok
|
||||
*
|
||||
* (Optional) a boolean output parameter specifying whether the conversion was successful or not.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* Either the int parsed from the string, or 0 (with *ok set to false) on parser error.
|
||||
*/
|
||||
static int to_int(const std::string &s, bool *ok = nullptr)
|
||||
{
|
||||
return to_int(s, 10, ok);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a number to a string with left padding
|
||||
*
|
||||
* Usually used for converting a number to a string with leading zeroes.
|
||||
*
|
||||
* @param val
|
||||
*
|
||||
* The number to convert. This is a templated function and will accept any type, e.g.
|
||||
* int/long/float/double/etc.
|
||||
*
|
||||
* @param padding
|
||||
*
|
||||
* Total desired length of the string. For example, setting this to `2` will ensure the string
|
||||
* is at least 2 characters in size, using `c` to pad the left side where necessary.
|
||||
*
|
||||
* @param c
|
||||
*
|
||||
* The character to pad with. This defaults to `0` assuming you'll be using this function to
|
||||
* create leading zeroes.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The padded string.
|
||||
*/
|
||||
template <typename T>
|
||||
static std::string to_string_leftpad(T val, size_t padding, char c = '0')
|
||||
{
|
||||
std::string s = std::to_string(val);
|
||||
|
||||
if (s.size() < padding) {
|
||||
s.insert(0, padding - s.size(), c);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Format a string
|
||||
*
|
||||
* A sprintf wrapper that returns a std::string.
|
||||
*
|
||||
* @param fmt
|
||||
*
|
||||
* The format to use.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* A formatted string in std::string form.
|
||||
*/
|
||||
static std::string format(const char *fmt, ...);
|
||||
|
||||
// trim from start (in place)
|
||||
static inline void ltrim(std::string &s)
|
||||
{
|
||||
s.erase(s.begin(),
|
||||
std::find_if(s.begin(), s.end(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}));
|
||||
}
|
||||
|
||||
// trim from end (in place)
|
||||
static inline void rtrim(std::string &s)
|
||||
{
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(),
|
||||
[](unsigned char ch) { return !std::isspace(ch); })
|
||||
.base(),
|
||||
s.end());
|
||||
}
|
||||
|
||||
// trim from both ends (in place)
|
||||
static inline void trim(std::string &s)
|
||||
{
|
||||
rtrim(s);
|
||||
ltrim(s);
|
||||
}
|
||||
|
||||
// trim from start (copying)
|
||||
static inline std::string ltrimmed(std::string s)
|
||||
{
|
||||
ltrim(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from end (copying)
|
||||
static inline std::string rtrimmed(std::string s)
|
||||
{
|
||||
rtrim(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from both ends (copying)
|
||||
static inline std::string trimmed(std::string s)
|
||||
{
|
||||
trim(s);
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_STRINGUTILS_H
|
||||
@@ -0,0 +1,62 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_TESTS_H
|
||||
#define LIBOLIVECORE_TESTS_H
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
class Tester {
|
||||
public:
|
||||
Tester() = default;
|
||||
|
||||
typedef bool (*test_t)();
|
||||
|
||||
void add(const char *name, test_t test_function)
|
||||
{
|
||||
test_names_.push_back(name);
|
||||
test_functions_.push_back(test_function);
|
||||
}
|
||||
|
||||
bool run();
|
||||
|
||||
int exec()
|
||||
{
|
||||
if (run()) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void echo(const char *fmt, ...);
|
||||
|
||||
private:
|
||||
std::list<const char *> test_names_;
|
||||
std::list<test_t> test_functions_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_TESTS_H
|
||||
@@ -0,0 +1,91 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_TIMECODEFUNCTIONS_H
|
||||
#define LIBOLIVECORE_TIMECODEFUNCTIONS_H
|
||||
|
||||
#include "rational.h"
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Functions for converting times/timecodes/timestamps
|
||||
*
|
||||
* Olive uses the following terminology through its code:
|
||||
*
|
||||
* `time` - time in seconds presented in a rational form
|
||||
* `timebase` - the base time unit of an audio/video stream in seconds
|
||||
* `timestamp` - an integer representation of a time in timebase units (in many cases is used like a frame number)
|
||||
* `timecode` a user-friendly string representation of a time according to Timecode::Display
|
||||
*/
|
||||
class Timecode {
|
||||
public:
|
||||
enum Display {
|
||||
kTimecodeDropFrame,
|
||||
kTimecodeNonDropFrame,
|
||||
kTimecodeSeconds,
|
||||
kFrames,
|
||||
kMilliseconds
|
||||
};
|
||||
|
||||
enum Rounding { kCeil, kFloor, kRound };
|
||||
|
||||
/**
|
||||
* @brief Convert a timestamp (according to a rational timebase) to a user-friendly string representation
|
||||
*/
|
||||
static std::string time_to_timecode(const rational &time,
|
||||
const rational &timebase,
|
||||
const Display &display,
|
||||
bool show_plus_if_positive = false);
|
||||
static rational timecode_to_time(std::string timecode,
|
||||
const rational &timebase,
|
||||
const Display &display,
|
||||
bool *ok = nullptr);
|
||||
|
||||
static std::string time_to_string(int64_t ms);
|
||||
|
||||
static rational snap_time_to_timebase(const rational &time,
|
||||
const rational &timebase,
|
||||
Rounding floor = kRound);
|
||||
|
||||
static int64_t time_to_timestamp(const rational &time,
|
||||
const rational &timebase,
|
||||
Rounding floor = kRound);
|
||||
static int64_t time_to_timestamp(const double &time,
|
||||
const rational &timebase,
|
||||
Rounding floor = kRound);
|
||||
|
||||
static int64_t rescale_timestamp(const int64_t &ts, const rational &source,
|
||||
const rational &dest);
|
||||
static int64_t rescale_timestamp_ceil(const int64_t &ts,
|
||||
const rational &source,
|
||||
const rational &dest);
|
||||
|
||||
static rational timestamp_to_time(const int64_t ×tamp,
|
||||
const rational &timebase);
|
||||
|
||||
static bool timebase_is_drop_frame(const rational &timebase);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_TIMECODEFUNCTIONS_H
|
||||
@@ -0,0 +1,315 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_TIMERANGE_H
|
||||
#define LIBOLIVECORE_TIMERANGE_H
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "rational.h"
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
class TimeRange {
|
||||
public:
|
||||
TimeRange() = default;
|
||||
TimeRange(const rational &in, const rational &out);
|
||||
TimeRange(const TimeRange &r)
|
||||
: TimeRange(r.in(), r.out())
|
||||
{
|
||||
}
|
||||
|
||||
TimeRange &operator=(const TimeRange &r)
|
||||
{
|
||||
set_range(r.in(), r.out());
|
||||
return *this;
|
||||
}
|
||||
|
||||
const rational &in() const;
|
||||
const rational &out() const;
|
||||
const rational &length() const;
|
||||
|
||||
void set_in(const rational &in);
|
||||
void set_out(const rational &out);
|
||||
void set_range(const rational &in, const rational &out);
|
||||
|
||||
bool operator==(const TimeRange &r) const;
|
||||
bool operator!=(const TimeRange &r) const;
|
||||
|
||||
bool OverlapsWith(const TimeRange &a, bool in_inclusive = true,
|
||||
bool out_inclusive = true) const;
|
||||
bool Contains(const TimeRange &a, bool in_inclusive = true,
|
||||
bool out_inclusive = true) const;
|
||||
bool Contains(const rational &r) const;
|
||||
|
||||
TimeRange Combined(const TimeRange &a) const;
|
||||
static TimeRange Combine(const TimeRange &a, const TimeRange &b);
|
||||
TimeRange Intersected(const TimeRange &a) const;
|
||||
static TimeRange Intersect(const TimeRange &a, const TimeRange &b);
|
||||
|
||||
TimeRange operator+(const rational &rhs) const;
|
||||
TimeRange operator-(const rational &rhs) const;
|
||||
|
||||
const TimeRange &operator+=(const rational &rhs);
|
||||
const TimeRange &operator-=(const rational &rhs);
|
||||
|
||||
std::list<TimeRange> Split(const int &chunk_size) const;
|
||||
|
||||
private:
|
||||
void normalize();
|
||||
|
||||
rational in_;
|
||||
rational out_;
|
||||
rational length_;
|
||||
};
|
||||
|
||||
class TimeRangeList {
|
||||
public:
|
||||
TimeRangeList() = default;
|
||||
|
||||
TimeRangeList(std::initializer_list<TimeRange> r)
|
||||
: array_(r)
|
||||
{
|
||||
}
|
||||
|
||||
void insert(const TimeRangeList &list_to_add);
|
||||
void insert(TimeRange range_to_add);
|
||||
|
||||
void remove(const TimeRange &remove);
|
||||
void remove(const TimeRangeList &list);
|
||||
|
||||
template <typename T>
|
||||
static void util_remove(std::vector<T> *list, const TimeRange &remove)
|
||||
{
|
||||
std::vector<T> additions;
|
||||
|
||||
for (auto it = list->begin(); it != list->end();) {
|
||||
T &compare = *it;
|
||||
|
||||
if (remove.Contains(compare)) {
|
||||
// This element is entirely encompassed in this range, remove it
|
||||
it = list->erase(it);
|
||||
} else {
|
||||
if (compare.Contains(remove, false, false)) {
|
||||
// The remove range is within this element, only choice is to split the element into two
|
||||
T new_range = compare;
|
||||
new_range.set_in(remove.out());
|
||||
compare.set_out(remove.in());
|
||||
|
||||
additions.push_back(new_range);
|
||||
break;
|
||||
} else {
|
||||
if (compare.in() < remove.in() &&
|
||||
compare.out() > remove.in()) {
|
||||
// This element's out point overlaps the range's in, we'll trim it
|
||||
compare.set_out(remove.in());
|
||||
} else if (compare.in() < remove.out() &&
|
||||
compare.out() > remove.out()) {
|
||||
// This element's in point overlaps the range's out, we'll trim it
|
||||
compare.set_in(remove.out());
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list->insert(list->end(), additions.begin(), additions.end());
|
||||
}
|
||||
|
||||
bool contains(const TimeRange &range, bool in_inclusive = true,
|
||||
bool out_inclusive = true) const;
|
||||
|
||||
bool contains(const rational &r) const
|
||||
{
|
||||
for (const TimeRange &range : array_) {
|
||||
if (range.Contains(r)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OverlapsWith(const TimeRange &r, bool in_inclusive = true,
|
||||
bool out_inclusive = true) const
|
||||
{
|
||||
for (const TimeRange &range : array_) {
|
||||
if (range.OverlapsWith(r, in_inclusive, out_inclusive)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return array_.empty();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
array_.clear();
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
return array_.size();
|
||||
}
|
||||
|
||||
void shift(const rational &diff);
|
||||
|
||||
void trim_in(const rational &diff);
|
||||
|
||||
void trim_out(const rational &diff);
|
||||
|
||||
TimeRangeList Intersects(const TimeRange &range) const;
|
||||
|
||||
using const_iterator = std::vector<TimeRange>::const_iterator;
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return array_.cbegin();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return array_.cend();
|
||||
}
|
||||
|
||||
const_iterator cbegin() const
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
const_iterator cend() const
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
const TimeRange &first() const
|
||||
{
|
||||
return array_.front();
|
||||
}
|
||||
|
||||
const TimeRange &last() const
|
||||
{
|
||||
return array_.back();
|
||||
}
|
||||
|
||||
const TimeRange &at(int index) const
|
||||
{
|
||||
return array_.at(index);
|
||||
}
|
||||
|
||||
const std::vector<TimeRange> &internal_array() const
|
||||
{
|
||||
return array_;
|
||||
}
|
||||
|
||||
bool operator==(const TimeRangeList &rhs) const
|
||||
{
|
||||
return array_ == rhs.array_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<TimeRange> array_;
|
||||
};
|
||||
|
||||
class TimeRangeListFrameIterator {
|
||||
public:
|
||||
TimeRangeListFrameIterator();
|
||||
TimeRangeListFrameIterator(const TimeRangeList &list,
|
||||
const rational &timebase);
|
||||
|
||||
rational Snap(const rational &r) const;
|
||||
|
||||
bool GetNext(rational *out);
|
||||
|
||||
bool HasNext() const;
|
||||
|
||||
std::vector<rational> ToVector() const
|
||||
{
|
||||
TimeRangeListFrameIterator copy(list_, timebase_);
|
||||
std::vector<rational> times;
|
||||
rational r;
|
||||
while (copy.GetNext(&r)) {
|
||||
times.push_back(r);
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
int size();
|
||||
|
||||
void reset()
|
||||
{
|
||||
*this = TimeRangeListFrameIterator();
|
||||
}
|
||||
|
||||
void insert(const TimeRange &range)
|
||||
{
|
||||
list_.insert(range);
|
||||
}
|
||||
|
||||
void insert(const TimeRangeList &list)
|
||||
{
|
||||
list_.insert(list);
|
||||
}
|
||||
|
||||
bool IsCustomRange() const
|
||||
{
|
||||
return custom_range_;
|
||||
}
|
||||
|
||||
void SetCustomRange(bool e)
|
||||
{
|
||||
custom_range_ = e;
|
||||
}
|
||||
|
||||
int frame_index() const
|
||||
{
|
||||
return frame_index_;
|
||||
}
|
||||
|
||||
private:
|
||||
void UpdateIndexIfNecessary();
|
||||
|
||||
TimeRangeList list_;
|
||||
|
||||
rational timebase_;
|
||||
|
||||
rational current_;
|
||||
|
||||
int range_index_;
|
||||
|
||||
int size_;
|
||||
|
||||
int frame_index_;
|
||||
|
||||
bool custom_range_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_TIMERANGE_H
|
||||
@@ -0,0 +1,96 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2023 Olive Studios LLC
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef LIBOLIVECORE_VALUE_H
|
||||
#define LIBOLIVECORE_VALUE_H
|
||||
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
namespace olive::core
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Generic type container
|
||||
*/
|
||||
class Value {
|
||||
public:
|
||||
enum Type {
|
||||
/// Null/no data
|
||||
NONE,
|
||||
|
||||
/// Signed int64
|
||||
INT,
|
||||
|
||||
/// Double-precision float
|
||||
FLOAT,
|
||||
|
||||
/// UTF-8 string
|
||||
STRING
|
||||
};
|
||||
|
||||
Value()
|
||||
{
|
||||
type_ = NONE;
|
||||
}
|
||||
|
||||
Value(int64_t v)
|
||||
{
|
||||
data_.resize(sizeof(int64_t));
|
||||
memcpy(data_.data(), &v, sizeof(int64_t));
|
||||
type_ = INT;
|
||||
}
|
||||
|
||||
Value(double v)
|
||||
{
|
||||
data_.resize(sizeof(double));
|
||||
memcpy(data_.data(), &v, sizeof(int64_t));
|
||||
type_ = FLOAT;
|
||||
}
|
||||
|
||||
Value(const char *s)
|
||||
{
|
||||
size_t sz = strlen(s);
|
||||
data_.resize(sz);
|
||||
memcpy(data_.data(), s, sz);
|
||||
type_ = STRING;
|
||||
}
|
||||
|
||||
Value(const std::string &s)
|
||||
{
|
||||
data_.resize(s.size());
|
||||
memcpy(data_.data(), s.data(), data_.size());
|
||||
type_ = STRING;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> data_;
|
||||
Type type_;
|
||||
};
|
||||
|
||||
using ValueMap = std::map<std::string, Value>;
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBOLIVECORE_VALUE_H
|
||||
Reference in New Issue
Block a user