Merge branch 'master' into pr/1913

This commit is contained in:
itsmattkc
2022-05-10 09:54:34 -07:00
264 changed files with 4674 additions and 2118 deletions
+34
View File
@@ -0,0 +1,34 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2021 Olive 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 ALPHAASSOC_H
#define ALPHAASSOC_H
namespace olive {
enum AlphaAssociated {
kAlphaNone,
kAlphaUnassociated,
kAlphaAssociated
};
}
#endif // ALPHAASSOC_H
+20
View File
@@ -186,6 +186,26 @@ public:
duration_ = duration;
}
static bool FormatIsPacked(Format f)
{
return f >= kPackedStart && f < kPackedEnd;
}
bool FormatIsPacked() const
{
return FormatIsPacked(format_);
}
static bool FormatIsPlanar(Format f)
{
return f >= kPlanarStart && f < kPlanarEnd;
}
bool FormatIsPlanar() const
{
return FormatIsPlanar(format_);
}
qint64 time_to_bytes(const double& time) const;
qint64 time_to_bytes(const rational& time) const;
qint64 time_to_bytes_per_channel(const double& time) const;
+4 -4
View File
@@ -58,7 +58,7 @@ void AudioPlaybackCache::SetParameters(const AudioParams &params)
emit ParametersChanged();
}
void AudioPlaybackCache::WritePCM(const TimeRange &range, const TimeRangeList &valid_ranges, SampleBufferPtr samples)
void AudioPlaybackCache::WritePCM(const TimeRange &range, const TimeRangeList &valid_ranges, const SampleBuffer &samples)
{
// Ensure if we have enough segments to write this data, creating more if not
qint64 length_diff = params_.time_to_bytes_per_channel(range.out()) - playlist_.GetLength();
@@ -72,7 +72,7 @@ void AudioPlaybackCache::WritePCM(const TimeRange &range, const TimeRangeList &v
TimeRangeList ranges_we_validated;
// Calculate buffer size per channel
qint64 buffer_size_per_channel = samples ? samples->sample_count() * params_.bytes_per_sample_per_channel() : 0;
qint64 buffer_size_per_channel = samples.sample_count() * params_.bytes_per_sample_per_channel();
// Write each valid range to the segments
foreach (const TimeRange& r, valid_ranges) {
@@ -114,7 +114,7 @@ void AudioPlaybackCache::WritePCM(const TimeRange &range, const TimeRangeList &v
if (possible_write_length > 0) {
// Assume `samples` is valid if we're here, or else `buffer_size_per_channel` and
// therefore `possible_write_length` will be 0.
seg_file.write(reinterpret_cast<const char*>(samples->data(i)) + src_offset, possible_write_length);
seg_file.write(reinterpret_cast<const char*>(samples.data(i)) + src_offset, possible_write_length);
}
if (possible_write_length < total_write_length) {
@@ -167,7 +167,7 @@ void AudioPlaybackCache::WriteSilence(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}, nullptr);
WritePCM(range, {range}, SampleBuffer());
}
void AudioPlaybackCache::ShiftEvent(const rational &from_in_time, const rational &to_in_time)
+1 -1
View File
@@ -66,7 +66,7 @@ public:
void SetParameters(const AudioParams& params);
void WritePCM(const TimeRange &range, const TimeRangeList &valid_ranges, SampleBufferPtr samples);
void WritePCM(const TimeRange &range, const TimeRangeList &valid_ranges, const SampleBuffer &samples);
void WriteWaveform(const TimeRange &range, const TimeRangeList &valid_ranges, const AudioVisualWaveform *waveform);
+47 -57
View File
@@ -27,12 +27,12 @@
namespace olive {
Color Color::fromHsv(const float &h, const float &s, const float &v)
Color Color::fromHsv(const DataType &h, const DataType &s, const DataType &v)
{
float C = s * v;
float X = C * (1.0 - abs(fmod(h / 60.0, 2.0) - 1.0));
float m = v - C;
float Rs, Gs, Bs;
DataType C = s * v;
DataType X = C * (1.0 - abs(fmod(h / 60.0, 2.0) - 1.0));
DataType m = v - C;
DataType Rs, Gs, Bs;
if(h >= 0.0 && h < 60.0) {
Rs = C;
@@ -81,11 +81,11 @@ Color::Color(const QColor &c)
set_alpha(c.alphaF());
}
void Color::toHsv(float *hue, float *sat, float *val) const
void Color::toHsv(DataType *hue, DataType *sat, DataType *val) const
{
float fCMax = qMax(qMax(red(), green()), blue());
float fCMin = qMin(qMin(red(), green()), blue());
float fDelta = fCMax - fCMin;
DataType fCMax = qMax(qMax(red(), green()), blue());
DataType fCMin = qMin(qMin(red(), green()), blue());
DataType fDelta = fCMax - fCMin;
if(fDelta > 0) {
if(fCMax == red()) {
@@ -114,31 +114,31 @@ void Color::toHsv(float *hue, float *sat, float *val) const
}
}
float Color::hsv_hue() const
Color::DataType Color::hsv_hue() const
{
float h, s, v;
DataType h, s, v;
toHsv(&h, &s, &v);
return h;
}
float Color::hsv_saturation() const
Color::DataType Color::hsv_saturation() const
{
float h, s, v;
DataType h, s, v;
toHsv(&h, &s, &v);
return s;
}
float Color::value() const
Color::DataType Color::value() const
{
float h, s, v;
DataType h, s, v;
toHsv(&h, &s, &v);
return v;
}
void Color::toHsl(float *hue, float *sat, float *lightness) const
void Color::toHsl(DataType *hue, DataType *sat, DataType *lightness) const
{
float fCMin = qMin(red(), qMin(green(), blue()));
float fCMax = qMax(red(), qMax(green(), blue()));
DataType fCMin = qMin(red(), qMin(green(), blue()));
DataType fCMax = qMax(red(), qMax(green(), blue()));
*lightness = 0.5 * (fCMin + fCMax);
@@ -176,23 +176,23 @@ void Color::toHsl(float *hue, float *sat, float *lightness) const
}
}
float Color::hsl_hue() const
Color::DataType Color::hsl_hue() const
{
float h, s, l;
DataType h, s, l;
toHsl(&h, &s, &l);
return h;
}
float Color::hsl_saturation() const
Color::DataType Color::hsl_saturation() const
{
float h, s, l;
DataType h, s, l;
toHsl(&h, &s, &l);
return s;
}
float Color::lightness() const
Color::DataType Color::lightness() const
{
float h, s, l;
DataType h, s, l;
toHsl(&h, &s, &l);
return l;
}
@@ -232,12 +232,12 @@ QColor Color::toQColor() const
return c;
}
float Color::GetRoughLuminance() const
Color::DataType Color::GetRoughLuminance() const
{
return (2*red()+blue()+3*green())/6.0;
}
const Color &Color::operator+=(const Color &rhs)
Color &Color::operator+=(const Color &rhs)
{
for (int i=0;i<VideoParams::kRGBAChannelCount;i++) {
data_[i] += rhs.data_[i];
@@ -246,7 +246,7 @@ const Color &Color::operator+=(const Color &rhs)
return *this;
}
const Color &Color::operator-=(const Color &rhs)
Color &Color::operator-=(const Color &rhs)
{
for (int i=0;i<VideoParams::kRGBAChannelCount;i++) {
data_[i] -= rhs.data_[i];
@@ -255,7 +255,25 @@ const Color &Color::operator-=(const Color &rhs)
return *this;
}
const Color &Color::operator*=(const float &rhs)
Color &Color::operator+=(const DataType &rhs)
{
for (int i=0;i<VideoParams::kRGBAChannelCount;i++) {
data_[i] += rhs;
}
return *this;
}
Color &Color::operator-=(const DataType &rhs)
{
for (int i=0;i<VideoParams::kRGBAChannelCount;i++) {
data_[i] -= rhs;
}
return *this;
}
Color &Color::operator*=(const DataType &rhs)
{
for (int i=0;i<VideoParams::kRGBAChannelCount;i++) {
data_[i] *= rhs;
@@ -264,7 +282,7 @@ const Color &Color::operator*=(const float &rhs)
return *this;
}
const Color &Color::operator/=(const float &rhs)
Color &Color::operator/=(const DataType &rhs)
{
for (int i=0;i<VideoParams::kRGBAChannelCount;i++) {
data_[i] /= rhs;
@@ -273,34 +291,6 @@ const Color &Color::operator/=(const float &rhs)
return *this;
}
Color Color::operator+(const Color &rhs) const
{
Color c(*this);
c += rhs;
return c;
}
Color Color::operator-(const Color &rhs) const
{
Color c(*this);
c -= rhs;
return c;
}
Color Color::operator*(const float &rhs) const
{
Color c(*this);
c *= rhs;
return c;
}
Color Color::operator/(const float &rhs) const
{
Color c(*this);
c /= rhs;
return c;
}
}
QDebug operator<<(QDebug debug, const olive::Color &r)
+72 -31
View File
@@ -30,11 +30,13 @@
namespace olive {
/**
* @brief High precision 32-bit float based RGBA color value
* @brief High precision 32-bit DataType based RGBA color value
*/
class Color
{
public:
using DataType = float;
Color()
{
for (int i=0;i<VideoParams::kRGBAChannelCount;i++) {
@@ -42,7 +44,7 @@ public:
}
}
Color(const float& r, const float& g, const float& b, const float& a = 1.0f)
Color(const DataType& r, const DataType& g, const DataType& b, const DataType& a = 1.0f)
{
data_[0] = r;
data_[1] = g;
@@ -59,30 +61,30 @@ public:
*
* 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 float& h, const float& s, const float &v);
static Color fromHsv(const DataType& h, const DataType& s, const DataType &v);
const float& red() const {return data_[0];}
const float& green() const {return data_[1];}
const float& blue() const {return data_[2];}
const float& alpha() const {return data_[3];}
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(float* hue, float* sat, float* val) const;
float hsv_hue() const;
float hsv_saturation() const;
float value() const;
void toHsv(DataType* hue, DataType* sat, DataType* val) const;
DataType hsv_hue() const;
DataType hsv_saturation() const;
DataType value() const;
void toHsl(float* hue, float* sat, float* lightness) const;
float hsl_hue() const;
float hsl_saturation() const;
float lightness() 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 float& red) {data_[0] = red;}
void set_green(const float& green) {data_[1] = green;}
void set_blue(const float& blue) {data_[2] = blue;}
void set_alpha(const float& alpha) {data_[3] = alpha;}
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;}
float* data() {return data_;}
const float* data() const {return data_;}
DataType* data() {return data_;}
const DataType* data() const {return data_;}
void toData(char* data, const VideoParams::Format& format, int ch_layout) const;
@@ -92,22 +94,61 @@ public:
// Suuuuper rough luminance value mostly used for UI (determining whether to overlay with black
// or white text)
float GetRoughLuminance() const;
DataType GetRoughLuminance() const;
// Assignment math operators
const Color& operator+=(const Color& rhs);
const Color& operator-=(const Color& rhs);
const Color& operator*=(const float& rhs);
const Color& operator/=(const float& rhs);
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 operator-(const Color& rhs) const;
Color operator*(const float& rhs) const;
Color operator/(const float& rhs) const;
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:
float data_[VideoParams::kRGBAChannelCount];
DataType data_[VideoParams::kRGBAChannelCount];
};
+21 -12
View File
@@ -26,7 +26,7 @@
namespace olive {
ColorProcessor::ColorProcessor(ColorManager *config, const QString &input, const ColorTransform &transform)
ColorProcessor::ColorProcessor(ColorManager *config, const QString &input, const ColorTransform &transform, Direction direction)
{
QMutexLocker locker(config->mutex());
@@ -41,6 +41,7 @@ ColorProcessor::ColorProcessor(ColorManager *config, const QString &input, const
display_transform->setSrc(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);
OCIO_SET_C_LOCALE_FOR_SCOPE;
@@ -69,13 +70,25 @@ ColorProcessor::ColorProcessor(ColorManager *config, const QString &input, const
} else {
OCIO_SET_C_LOCALE_FOR_SCOPE;
processor_ = config->GetConfig()->getProcessor(input.toUtf8(),
output.toUtf8());
try {
if (direction == kNormal) {
processor_ = config->GetConfig()->getProcessor(input.toUtf8(), output.toUtf8());
} else {
processor_ = config->GetConfig()->getProcessor(output.toUtf8(), input.toUtf8());
}
} catch (OCIO::Exception &e) {
qWarning() << "ColorProcessor exception:" << e.what();
}
}
cpu_processor_ = processor_->getDefaultCPUProcessor();
id_ = GenerateID(config, input, transform);
}
ColorProcessor::ColorProcessor(OCIO::ConstProcessorRcPtr processor)
{
processor_ = processor;
cpu_processor_ = processor_->getDefaultCPUProcessor();
}
void ColorProcessor::ConvertFrame(Frame *f)
@@ -109,18 +122,14 @@ Color ColorProcessor::ConvertColor(const Color& in)
return Color(c[0], c[1], c[2], c[3]);
}
QString ColorProcessor::GenerateID(ColorManager *config, const QString &input, const ColorTransform &transform)
ColorProcessorPtr ColorProcessor::Create(ColorManager *config, const QString& input, const ColorTransform &transform, Direction direction)
{
return QStringLiteral("%1:%2:%3:%4:%5").arg(config->GetConfigFilename(),
input,
transform.display(),
transform.view(),
transform.look());
return std::make_shared<ColorProcessor>(config, input, transform, direction);
}
ColorProcessorPtr ColorProcessor::Create(ColorManager *config, const QString& input, const ColorTransform &transform)
ColorProcessorPtr ColorProcessor::Create(OCIO::ConstProcessorRcPtr processor)
{
return std::make_shared<ColorProcessor>(config, input, transform);
return std::make_shared<ColorProcessor>(processor);
}
OCIO::ConstProcessorRcPtr ColorProcessor::GetProcessor()
+6 -8
View File
@@ -41,11 +41,13 @@ public:
kInverse
};
ColorProcessor(ColorManager* config, const QString& input, const ColorTransform& dest_space);
ColorProcessor(ColorManager* config, const QString& input, const ColorTransform& dest_space, Direction direction = kNormal);
ColorProcessor(OCIO::ConstProcessorRcPtr processor);
DISABLE_COPY_MOVE(ColorProcessor)
static ColorProcessorPtr Create(ColorManager* config, const QString& input, const ColorTransform& dest_space);
static ColorProcessorPtr Create(ColorManager* config, const QString& input, const ColorTransform& dest_space, Direction direction = kNormal);
static ColorProcessorPtr Create(OCIO::ConstProcessorRcPtr processor);
OCIO::ConstProcessorRcPtr GetProcessor();
@@ -54,20 +56,16 @@ public:
Color ConvertColor(const Color &in);
const QString& id() const
const char *id() const
{
return id_;
return processor_->getCacheID();
}
static QString GenerateID(ColorManager* config, const QString& input, const ColorTransform& dest_space);
private:
OCIO::ConstProcessorRcPtr processor_;
OCIO::ConstCPUProcessorRcPtr cpu_processor_;
QString id_;
};
using ColorProcessorChain = QVector<ColorProcessorPtr>;
+1 -1
View File
@@ -196,7 +196,7 @@ DiskCacheFolder::DiskCacheFolder(const QString &path, QObject *parent) :
{
SetPath(path);
save_timer_.setInterval(Config::Current()[QStringLiteral("DiskCacheSaveInterval")].toInt());
save_timer_.setInterval(OLIVE_CONFIG("DiskCacheSaveInterval").toInt());
connect(&save_timer_, &QTimer::timeout, this, &DiskCacheFolder::SaveDiskCacheIndex);
save_timer_.start();
}
+4 -4
View File
@@ -30,22 +30,22 @@ class AcceleratedJob {
public:
AcceleratedJob() = default;
NodeValue GetValue(const QString& input) const
NodeValue Get(const QString& input) const
{
return value_map_.value(input);
}
void InsertValue(const QString &input, const NodeValueRow &row)
void Insert(const QString &input, const NodeValueRow &row)
{
value_map_.insert(input, row.value(input));
}
void InsertValue(const QString& input, const NodeValue& value)
void Insert(const QString& input, const NodeValue& value)
{
value_map_.insert(input, value);
}
void InsertValue(const NodeValueRow &row)
void Insert(const NodeValueRow &row)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
value_map_.insert(row);
+113
View File
@@ -0,0 +1,113 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2021 Olive 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 COLORTRANSFORMJOB_H
#define COLORTRANSFORMJOB_H
#include <QMatrix4x4>
#include <QString>
#include "render/job/generatejob.h"
#include "render/alphaassoc.h"
#include "render/colorprocessor.h"
#include "render/texture.h"
namespace olive {
class Node;
class ColorTransformJob : public GenerateJob
{
public:
ColorTransformJob()
{
processor_ = nullptr;
input_texture_ = nullptr;
custom_shader_src_ = nullptr;
input_alpha_association_ = kAlphaNone;
clear_destination_ = true;
}
QString id() const
{
if (id_.isEmpty()) {
return processor_->id();
} else {
return id_;
}
}
void SetOverrideID(const QString &id) { id_ = id; }
TexturePtr GetInputTexture() const { return input_texture_; }
void SetInputTexture(TexturePtr tex) { input_texture_ = tex; }
ColorProcessorPtr GetColorProcessor() const { return processor_; }
void SetColorProcessor(ColorProcessorPtr p) { processor_ = p; }
const AlphaAssociated &GetInputAlphaAssociation() const { return input_alpha_association_; }
void SetInputAlphaAssociation(const AlphaAssociated &e) { input_alpha_association_ = e; }
const Node *CustomShaderSource() const { return custom_shader_src_; }
const QString &CustomShaderID() const { return custom_shader_id_; }
void SetNeedsCustomShader(const Node *node, const QString &id = QString())
{
custom_shader_src_ = node;
custom_shader_id_ = id;
}
bool IsClearDestinationEnabled() const { return clear_destination_; }
void SetClearDestinationEnabled(bool e) { clear_destination_ = e; }
const QMatrix4x4 &GetTransformMatrix() const { return matrix_; }
void SetTransformMatrix(const QMatrix4x4 &m) { matrix_ = m; }
const QMatrix4x4 &GetCropMatrix() const { return crop_matrix_; }
void SetCropMatrix(const QMatrix4x4 &m) { crop_matrix_ = m; }
const QString &GetFunctionName() const { return function_name_; }
void SetFunctionName(const QString &function_name = QString()) { function_name_ = function_name; };
private:
ColorProcessorPtr processor_;
QString id_;
TexturePtr input_texture_;
const Node *custom_shader_src_;
QString custom_shader_id_;
AlphaAssociated input_alpha_association_;
bool clear_destination_;
QMatrix4x4 matrix_;
QMatrix4x4 crop_matrix_;
QString function_name_;
};
}
Q_DECLARE_METATYPE(olive::ColorTransformJob)
#endif // COLORTRANSFORMJOB_H
+5 -6
View File
@@ -30,31 +30,30 @@ class SampleJob : public AcceleratedJob {
public:
SampleJob()
{
samples_ = nullptr;
}
SampleJob(const NodeValue& value)
{
samples_ = value.data().value<SampleBufferPtr>();
samples_ = value.toSamples();
}
SampleJob(const QString& from, const NodeValueRow& row)
{
samples_ = row[from].data().value<SampleBufferPtr>();
samples_ = row[from].toSamples();
}
SampleBufferPtr samples() const
const SampleBuffer &samples() const
{
return samples_;
}
bool HasSamples() const
{
return samples_ && samples_->is_allocated();
return samples_.is_allocated();
}
private:
SampleBufferPtr samples_;
SampleBuffer samples_;
};
+1
View File
@@ -25,6 +25,7 @@
#include <QVector>
#include "generatejob.h"
#include "render/colorprocessor.h"
#include "render/texture.h"
namespace olive {
+11 -11
View File
@@ -449,48 +449,48 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video
case NodeValue::kInt:
// 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.data().toInt());
functions_->glUniform1i(variable_location, value.toInt());
break;
case NodeValue::kFloat:
// kFloat technically specifies a double but as above, OpenGL doesn't support those.
functions_->glUniform1f(variable_location, value.data().toFloat());
functions_->glUniform1f(variable_location, value.toDouble());
break;
case NodeValue::kVec2:
{
QVector2D v = value.data().value<QVector2D>();
QVector2D v = value.toVec2();
functions_->glUniform2fv(variable_location, 1, reinterpret_cast<const GLfloat*>(&v));
break;
}
case NodeValue::kVec3:
{
QVector3D v = value.data().value<QVector3D>();
QVector3D v = value.toVec3();
functions_->glUniform3fv(variable_location, 1, reinterpret_cast<const GLfloat*>(&v));
break;
}
case NodeValue::kVec4:
{
QVector4D v = value.data().value<QVector4D>();
QVector4D v = value.toVec4();
functions_->glUniform4fv(variable_location, 1, reinterpret_cast<const GLfloat*>(&v));
break;
}
case NodeValue::kMatrix:
functions_->glUniformMatrix4fv(variable_location, 1, false, value.data().value<QMatrix4x4>().constData());
functions_->glUniformMatrix4fv(variable_location, 1, false, value.toMatrix().constData());
break;
case NodeValue::kCombo:
functions_->glUniform1i(variable_location, value.data().value<int>());
functions_->glUniform1i(variable_location, value.toInt());
break;
case NodeValue::kColor:
{
Color color = value.data().value<Color>();
Color color = value.toColor();
functions_->glUniform4f(variable_location, color.red(), color.green(), color.blue(), color.alpha());
break;
}
case NodeValue::kBoolean:
functions_->glUniform1i(variable_location, value.data().toBool());
functions_->glUniform1i(variable_location, value.toBool());
break;
case NodeValue::kTexture:
{
TexturePtr texture = value.data().value<TexturePtr>();
TexturePtr texture = value.toTexture();
// Set value to bound texture
functions_->glUniform1i(variable_location, textures_to_bind.size());
@@ -552,7 +552,7 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video
// Ensure matrix is set, at least to identity
GLint mvpmat_location = functions_->glGetUniformLocation(shader, "ove_mvpmat");
if (mvpmat_location > -1) {
functions_->glUniformMatrix4fv(mvpmat_location, 1, false, job.GetValue(QStringLiteral("ove_mvpmat")).data().value<QMatrix4x4>().constData());
functions_->glUniformMatrix4fv(mvpmat_location, 1, false, job.Get(QStringLiteral("ove_mvpmat")).toMatrix().constData());
}
// Set the viewport to the "physical" resolution of the destination
+33 -33
View File
@@ -48,7 +48,7 @@ PreviewAutoCacher::PreviewAutoCacher() :
SetPlayhead(0);
// Wait a certain amount of time before requeuing when we receive an invalidate signal
delayed_requeue_timer_.setInterval(Config::Current()[QStringLiteral("AutoCacheDelay")].toInt());
delayed_requeue_timer_.setInterval(OLIVE_CONFIG("AutoCacheDelay").toInt());
delayed_requeue_timer_.setSingleShot(true);
connect(&delayed_requeue_timer_, &QTimer::timeout, this, &PreviewAutoCacher::RequeueFrames);
@@ -207,7 +207,7 @@ void PreviewAutoCacher::AudioRendered()
// WritePCM is tolerant to its buffer being null, it will just write silence instead
viewer_node_->audio_playback_cache()->WritePCM(range,
valid_ranges,
watcher->Get().value<SampleBufferPtr>());
watcher->Get().value<SampleBuffer>());
}
viewer_node_->audio_playback_cache()->WriteWaveform(range, valid_ranges, &waveform);
@@ -221,39 +221,39 @@ void PreviewAutoCacher::AudioRendered()
// Wait for conform
audio_needing_conform_.insert(range);
}
}
} else{
// Retrieve visual waveforms
QVector<RenderProcessor::RenderedWaveform> waveform_list = watcher->GetTicket()->property("waveforms").value< QVector<RenderProcessor::RenderedWaveform> >();
foreach (const RenderProcessor::RenderedWaveform& waveform_info, waveform_list) {
// Find original track
ClipBlock* block = nullptr;
// Retrieve visual waveforms
QVector<RenderProcessor::RenderedWaveform> waveform_list = watcher->GetTicket()->property("waveforms").value< QVector<RenderProcessor::RenderedWaveform> >();
foreach (const RenderProcessor::RenderedWaveform& waveform_info, waveform_list) {
// Find original track
ClipBlock* block = nullptr;
for (auto it=copy_map_.cbegin(); it!=copy_map_.cend(); it++) {
if (it.value() == waveform_info.block) {
block = static_cast<ClipBlock*>(it.key());
break;
}
}
if (block && !valid_ranges.isEmpty()) {
// Generate visual waveform in this background thread
block->waveform().set_channel_count(viewer_node_->GetAudioParams().channel_count());
// Determine which of the waveform ranges we got intersects with the valid ranges
TimeRangeList intersections = valid_ranges.Intersects(waveform_info.range + block->in());
foreach (TimeRange r, intersections) {
// For each range, adjust it relative to the block and write it
r -= block->in();
if (waveform_info.silence) {
block->waveform().OverwriteSilence(r.in(), r.length());
} else {
block->waveform().OverwriteSums(waveform_info.waveform, r.in(), r.in() - waveform_info.range.in(), r.length());
for (auto it=copy_map_.cbegin(); it!=copy_map_.cend(); it++) {
if (it.value() == waveform_info.block) {
block = static_cast<ClipBlock*>(it.key());
break;
}
}
emit block->PreviewChanged();
if (block && !valid_ranges.isEmpty()) {
// Generate visual waveform in this background thread
block->waveform().set_channel_count(viewer_node_->GetAudioParams().channel_count());
// Determine which of the waveform ranges we got intersects with the valid ranges
TimeRangeList intersections = valid_ranges.Intersects(waveform_info.range + block->in());
foreach (TimeRange r, intersections) {
// For each range, adjust it relative to the block and write it
r -= block->in();
if (waveform_info.silence) {
block->waveform().OverwriteSilence(r.in(), r.length());
} else {
block->waveform().OverwriteSums(waveform_info.waveform, r.in(), r.in() - waveform_info.range.in(), r.length());
}
}
emit block->PreviewChanged();
}
}
}
}
@@ -502,8 +502,8 @@ void PreviewAutoCacher::StartCachingAudioRange(const TimeRange &range)
void PreviewAutoCacher::SetPlayhead(const rational &playhead)
{
cache_range_ = TimeRange(playhead - Config::Current()[QStringLiteral("DiskCacheBehind")].value<rational>(),
playhead + Config::Current()[QStringLiteral("DiskCacheAhead")].value<rational>());
cache_range_ = TimeRange(playhead - OLIVE_CONFIG("DiskCacheBehind").value<rational>(),
playhead + OLIVE_CONFIG("DiskCacheAhead").value<rational>());
RequeueFrames();
}
+39 -41
View File
@@ -52,16 +52,6 @@ TexturePtr Renderer::CreateTexture(const VideoParams &params, const void *data,
return CreateTexture(params, Texture::k2D, data, linesize);
}
void Renderer::BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, AlphaAssociated source_alpha_association, Texture *destination, bool clear_destination, const QMatrix4x4 &matrix, const QMatrix4x4 &crop_matrix)
{
BlitColorManagedInternal(color_processor, source, source_alpha_association, destination, destination->params(), clear_destination, matrix, crop_matrix);
}
void Renderer::BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, AlphaAssociated source_alpha_association, VideoParams params, bool clear_destination, const QMatrix4x4& matrix, const QMatrix4x4 &crop_matrix)
{
BlitColorManagedInternal(color_processor, source, source_alpha_association, nullptr, params, clear_destination, matrix, crop_matrix);
}
TexturePtr Renderer::InterlaceTexture(TexturePtr top, TexturePtr bottom, const VideoParams &params)
{
color_cache_mutex_.lock();
@@ -71,9 +61,9 @@ TexturePtr Renderer::InterlaceTexture(TexturePtr top, TexturePtr bottom, const V
color_cache_mutex_.unlock();
ShaderJob job;
job.InsertValue(QStringLiteral("top_tex_in"), NodeValue(NodeValue::kTexture, QVariant::fromValue(top)));
job.InsertValue(QStringLiteral("bottom_tex_in"), NodeValue(NodeValue::kTexture, QVariant::fromValue(bottom)));
job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, QVector2D(params.effective_width(), params.effective_height())));
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, QVector2D(params.effective_width(), params.effective_height())));
TexturePtr output = CreateTexture(params);
@@ -103,35 +93,45 @@ TexturePtr Renderer::CreateTextureFromNativeHandle(const QVariant &v, const Vide
return std::make_shared<Texture>(this, v, params, type);
}
bool Renderer::GetColorContext(ColorProcessorPtr color_processor, Renderer::ColorContext *ctx)
bool Renderer::GetColorContext(const ColorTransformJob &color_job, Renderer::ColorContext *ctx)
{
QMutexLocker locker(&color_cache_mutex_);
ColorContext& color_ctx = *ctx;
if (color_cache_.contains(color_processor->id())) {
color_ctx = color_cache_.value(color_processor->id());
QString proc_id = color_job.id();
if (color_cache_.contains(proc_id)) {
color_ctx = color_cache_.value(proc_id);
return true;
} else {
// Create shader description
const char* ocio_func_name = "OCIODisplay";
QString ocio_func_name;
if (color_job.GetFunctionName().isEmpty()) {
ocio_func_name = "OCIODisplay";
} else {
ocio_func_name = color_job.GetFunctionName();
}
auto shader_desc = OCIO::GpuShaderDesc::CreateShaderDesc();
shader_desc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_ES_3_0);
shader_desc->setFunctionName(ocio_func_name);
shader_desc->setFunctionName(ocio_func_name.toUtf8());
shader_desc->setResourcePrefix("ocio_");
// Generate shader
color_processor->GetProcessor()->getDefaultGPUProcessor()->extractGpuShaderInfo(shader_desc);
color_job.GetColorProcessor()->GetProcessor()->getDefaultGPUProcessor()->extractGpuShaderInfo(shader_desc);
// Generate shader code using OCIO stub and our auto-generated name
QString shader_frag = FileFunctions::ReadFileAsString(QStringLiteral(":shaders/colormanage.frag")).arg(
shader_desc->getShaderText(),
ocio_func_name
);
ShaderCode code;
if (const Node *shader_src = color_job.CustomShaderSource()) {
// Use shader code from associated node
code = shader_src->GetShaderCode({color_job.CustomShaderID(), shader_desc->getShaderText()});
} else {
// Generate shader code using OCIO stub and our auto-generated name
code = FileFunctions::ReadFileAsString(QStringLiteral(":shaders/colormanage.frag"));
code.set_frag_code(code.frag_code().arg(shader_desc->getShaderText()));
}
// Try to compile shader
color_ctx.compiled_shader = CreateNativeShader(ShaderCode(shader_frag,
FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/default.vert"))));
color_ctx.compiled_shader = CreateNativeShader(code);
if (color_ctx.compiled_shader.isNull()) {
return false;
@@ -199,42 +199,40 @@ bool Renderer::GetColorContext(ColorProcessorPtr color_processor, Renderer::Colo
color_ctx.lut1d_textures[i].interpolation = (interpolation == OCIO::INTERP_NEAREST) ? Texture::kNearest : Texture::kLinear;
}
color_cache_.insert(color_processor->id(), color_ctx);
color_cache_.insert(proc_id, color_ctx);
return true;
}
}
void Renderer::BlitColorManagedInternal(ColorProcessorPtr color_processor, TexturePtr source,
AlphaAssociated source_alpha_association, Texture *destination,
VideoParams params, bool clear_destination, const QMatrix4x4& matrix,
const QMatrix4x4& crop_matrix)
void Renderer::BlitColorManaged(const ColorTransformJob &color_job, Texture *destination, const VideoParams &params)
{
ColorContext color_ctx;
if (!GetColorContext(color_processor, &color_ctx)) {
if (!GetColorContext(color_job, &color_ctx)) {
return;
}
ShaderJob job;
job.InsertValue(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(source)));
job.InsertValue(QStringLiteral("ove_mvpmat"), NodeValue(NodeValue::kMatrix, matrix));
job.InsertValue(QStringLiteral("ove_cropmatrix"), NodeValue(NodeValue::kMatrix, crop_matrix.inverted()));
job.InsertValue(QStringLiteral("ove_maintex_alpha"), NodeValue(NodeValue::kInt, source_alpha_association));
job.Insert(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(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(color_job.GetValues());
job.SetAlphaChannelRequired(color_job.GetAlphaChannelRequired());
foreach (const ColorContext::LUT& l, color_ctx.lut3d_textures) {
job.InsertValue(l.name, NodeValue(NodeValue::kTexture, QVariant::fromValue(l.texture)));
job.Insert(l.name, NodeValue(NodeValue::kTexture, QVariant::fromValue(l.texture)));
job.SetInterpolation(l.name, l.interpolation);
}
foreach (const ColorContext::LUT& l, color_ctx.lut1d_textures) {
job.InsertValue(l.name, NodeValue(NodeValue::kTexture, QVariant::fromValue(l.texture)));
job.Insert(l.name, NodeValue(NodeValue::kTexture, QVariant::fromValue(l.texture)));
job.SetInterpolation(l.name, l.interpolation);
}
if (destination) {
BlitToTexture(color_ctx.compiled_shader, job, destination, clear_destination);
BlitToTexture(color_ctx.compiled_shader, job, destination, color_job.IsClearDestinationEnabled());
} else {
Blit(color_ctx.compiled_shader, job, params, clear_destination);
Blit(color_ctx.compiled_shader, job, params, color_job.IsClearDestinationEnabled());
}
}
+11 -14
View File
@@ -29,6 +29,7 @@
#include "common/timerange.h"
#include "node/node.h"
#include "render/colorprocessor.h"
#include "render/job/colortransformjob.h"
#include "render/videoparams.h"
#include "texture.h"
@@ -63,14 +64,15 @@ public:
Blit(shader, job, nullptr, params, clear_destination);
}
enum AlphaAssociated {
kAlphaNone,
kAlphaUnassociated,
kAlphaAssociated
};
void BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, AlphaAssociated source_alpha_association, Texture* destination, bool clear_destination = true, const QMatrix4x4& matrix = QMatrix4x4(), const QMatrix4x4 &crop_matrix = QMatrix4x4());
void BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, AlphaAssociated source_alpha_association, VideoParams params, bool clear_destination = true, const QMatrix4x4& matrix = QMatrix4x4(), const QMatrix4x4 &crop_matrix = QMatrix4x4());
void BlitColorManaged(const ColorTransformJob &color_job, Texture* destination, const VideoParams &params);
void BlitColorManaged(const ColorTransformJob &job, Texture* destination)
{
BlitColorManaged(job, destination, destination->params());
}
void BlitColorManaged(const ColorTransformJob &job, const VideoParams &params)
{
BlitColorManaged(job, nullptr, params);
}
TexturePtr InterlaceTexture(TexturePtr top, TexturePtr bottom, const VideoParams &params);
@@ -126,12 +128,7 @@ private:
};
bool GetColorContext(ColorProcessorPtr color_processor, ColorContext* ctx);
void BlitColorManagedInternal(ColorProcessorPtr color_processor, TexturePtr source,
AlphaAssociated source_alpha_association,
Texture* destination, VideoParams params, bool clear_destination,
const QMatrix4x4 &matrix, const QMatrix4x4 &crop_matrix);
bool GetColorContext(const ColorTransformJob &color_job, ColorContext* ctx);
QHash<QString, ColorContext> color_cache_;
+84 -65
View File
@@ -25,9 +25,7 @@
#include <QVector3D>
#include <QVector4D>
#include "audio/packedprocessor.h"
#include "audio/planarprocessor.h"
#include "audio/tempoprocessor.h"
#include "audio/audioprocessor.h"
#include "node/block/clip/clip.h"
#include "node/block/transition/transition.h"
#include "node/project/project.h"
@@ -57,11 +55,11 @@ TexturePtr RenderProcessor::GenerateTexture(const rational &time, const rational
table = GenerateTable(texture_output, viewer->GetValueHintForInput(ViewerOutput::kTextureInput), range);
}
NodeValue tex_val = table.GetWithMeta(NodeValue::kTexture);
NodeValue tex_val = table.Get(NodeValue::kTexture);
ResolveJobs(tex_val, range);
return tex_val.data().value<TexturePtr>();
return tex_val.toTexture();
}
FramePtr RenderProcessor::GenerateFrame(TexturePtr texture, const rational& time)
@@ -105,14 +103,19 @@ FramePtr RenderProcessor::GenerateFrame(TexturePtr texture, const rational& time
if (output_color_transform) {
// Yes color transform, blit color managed
render_ctx_->BlitColorManaged(output_color_transform, texture,
Config::Current()[QStringLiteral("ReassocLinToNonLin")].toBool() ? Renderer::kAlphaAssociated : Renderer::kAlphaNone,
blit_tex.get(), true, matrix);
ColorTransformJob job;
job.SetColorProcessor(output_color_transform);
job.SetInputTexture(texture);
job.SetInputAlphaAssociation(OLIVE_CONFIG("ReassocLinToNonLin").toBool() ? kAlphaAssociated : kAlphaNone);
job.SetTransformMatrix(matrix);
render_ctx_->BlitColorManaged(job, blit_tex.get());
} else {
// No color transform, just blit
ShaderJob job;
job.InsertValue(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(texture)));
job.InsertValue(QStringLiteral("ove_mvpmat"), NodeValue(NodeValue::kMatrix, matrix));
job.Insert(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(texture)));
job.Insert(QStringLiteral("ove_mvpmat"), NodeValue(NodeValue::kMatrix, matrix));
render_ctx_->BlitToTexture(default_shader_, job, blit_tex.get());
}
@@ -193,19 +196,22 @@ void RenderProcessor::Run()
table = GenerateTable(texture_output, viewer->GetValueHintForInput(ViewerOutput::kSamplesInput),time);
}
QVariant sample_variant = table.Get(NodeValue::kSamples);
SampleBufferPtr samples = sample_variant.value<SampleBufferPtr>();
if (samples && ticket_->property("enablewaveforms").toBool()) {
NodeValue sample_val = table.Get(NodeValue::kSamples);
ResolveJobs(sample_val, time);
SampleBuffer samples = sample_val.toSamples();
if (samples.is_allocated() && ticket_->property("enablewaveforms").toBool()) {
AudioVisualWaveform vis;
vis.set_channel_count(samples->audio_params().channel_count());
vis.OverwriteSamples(samples, samples->audio_params().sample_rate());
vis.set_channel_count(samples.audio_params().channel_count());
vis.OverwriteSamples(samples, samples.audio_params().sample_rate());
ticket_->setProperty("waveform", QVariant::fromValue(vis));
}
if (ticket_->IsCancelled()) {
ticket_->Finish();
} else {
ticket_->Finish(sample_variant);
ticket_->Finish(QVariant::fromValue(samples));
}
break;
}
@@ -269,9 +275,8 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
QVector<Block*> active_blocks = track->BlocksAtTimeRange(range);
// All these blocks will need to output to a buffer so we create one here
SampleBufferPtr block_range_buffer = SampleBuffer::CreateAllocated(audio_params,
audio_params.time_to_samples(range.length()));
block_range_buffer->silence();
SampleBuffer block_range_buffer(audio_params, range.length());
block_range_buffer.silence();
NodeValueTable merged_table;
@@ -286,10 +291,10 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
// Destination buffer
NodeValueTable table = GenerateTable(b, track->GetValueHintForInput(Track::kBlockInput, track->GetArrayIndexFromBlock(b)),Track::TransformRangeForBlock(b, range_for_block));
SampleBufferPtr samples_from_this_block = table.Take(NodeValue::kSamples).value<SampleBufferPtr>();
SampleBuffer samples_from_this_block = table.Take(NodeValue::kSamples).toSamples();
ClipBlock *clip_cast = dynamic_cast<ClipBlock*>(b);
if (samples_from_this_block) {
if (samples_from_this_block.is_allocated()) {
// If this is a clip, we might have extra speed/reverse information
if (clip_cast) {
double speed_value = clip_cast->speed();
@@ -297,17 +302,13 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
if (qIsNull(speed_value)) {
// Just silence, don't think there's any other practical application of 0 speed audio
samples_from_this_block->silence();
samples_from_this_block.silence();
} else if (!qFuzzyCompare(speed_value, 1.0)) {
if (clip_cast->maintain_audio_pitch()) {
PackedProcessor packer;
packer.Open(samples_from_this_block->audio_params());
AudioProcessor processor;
QByteArray packed = packer.Convert(samples_from_this_block);
if (!packed.isEmpty()) {
TempoProcessor tp;
tp.Open(samples_from_this_block->audio_params(), speed_value);
if (processor.Open(samples_from_this_block.audio_params(), samples_from_this_block.audio_params(), speed_value)) {
AudioProcessor::Buffer out;
// FIXME: This is not the best way to do this, the TempoProcessor works best
// when it's given a continuous stream of audio, which is challenging
@@ -315,33 +316,46 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
// well on export (assuming audio is all generated at once on export), but
// users may hear clicks and pops in the audio during preview due to this
// approach.
tp.Push(packed);
tp.Flush();
packed = tp.Pull();
tp.Close();
int r = processor.Convert(samples_from_this_block.to_raw_ptrs().data(), samples_from_this_block.sample_count(), nullptr);
if (!packed.isEmpty()) {
PlanarProcessor planar;
planar.Open(samples_from_this_block->audio_params());
samples_from_this_block = planar.Convert(packed);
if (r < 0) {
qCritical() << "Failed to change tempo of audio:" << r;
} else {
processor.Flush();
processor.Convert(nullptr, 0, &out);
if (!out.empty()) {
int nb_samples = out.front().size() * samples_from_this_block.audio_params().bytes_per_sample_per_channel();
if (nb_samples) {
SampleBuffer new_samples(samples_from_this_block.audio_params(), nb_samples);
for (int i=0; i<out.size(); i++) {
memcpy(new_samples.data(i), out[i].data(), out[i].size());
}
samples_from_this_block = new_samples;
}
}
}
}
} else {
// Multiply time
samples_from_this_block->speed(speed_value);
samples_from_this_block.speed(speed_value);
}
}
if (reversed) {
samples_from_this_block->reverse();
samples_from_this_block.reverse();
}
}
int copy_length = qMin(max_dest_sz, samples_from_this_block->sample_count());
int copy_length = qMin(max_dest_sz, samples_from_this_block.sample_count());
// Copy samples into destination buffer
for (int i=0; i<samples_from_this_block->audio_params().channel_count(); i++) {
block_range_buffer->set(i, samples_from_this_block->data(i), destination_offset, copy_length);
for (int i=0; i<samples_from_this_block.audio_params().channel_count(); i++) {
block_range_buffer.set(i, samples_from_this_block.data(i), destination_offset, copy_length);
}
NodeValueTable::Merge({merged_table, table});
@@ -354,7 +368,7 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
waveform_info.block = clip_cast;
waveform_info.range = range_for_block - b->in();
if (!(waveform_info.silence = !samples_from_this_block.get())) {
if (!(waveform_info.silence = !samples_from_this_block.is_allocated())) {
// Generate a visual waveform from the samples acquired from this block
AudioVisualWaveform visual_waveform;
visual_waveform.set_channel_count(audio_params.channel_count());
@@ -388,19 +402,10 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
// Check the still frame cache. On large frames such as high resolution still images, uploading
// and color managing them for every frame is a waste of time, so we implement a small cache here
// to optimize such a situation
const VideoParams& render_params = GetCacheVideoParams();
VideoParams stream_data = stream.video_params();
ColorManager* color_manager = Node::ValueToPtr<ColorManager>(ticket_->property("colormanager"));
// See if we can make this divider larger (i.e. if the fooage is smaller)
int footage_divider = render_params.divider();
while (footage_divider > 1
&& VideoParams::GetScaledDimension(stream_data.width(), footage_divider-1) < render_params.effective_width()
&& VideoParams::GetScaledDimension(stream_data.height(), footage_divider-1) < render_params.effective_height()) {
footage_divider--;
}
QString using_colorspace = stream_data.colorspace();
if (using_colorspace.isEmpty()) {
@@ -435,7 +440,7 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
if (decoder) {
Decoder::RetrieveVideoParams p;
p.divider = footage_divider;
p.divider = stream.video_params().divider();
p.src_interlacing = stream_data.interlacing();
p.dst_interlacing = GetCacheVideoParams().interlacing();
@@ -454,25 +459,27 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
using_colorspace,
color_manager->GetReferenceColorSpace());
Renderer::AlphaAssociated alpha_assoc;
ColorTransformJob job;
job.SetColorProcessor(processor);
job.SetInputTexture(unmanaged_texture);
if (stream_data.channel_count() != VideoParams::kRGBAChannelCount
|| stream_data.colorspace() == color_manager->GetReferenceColorSpace()) {
alpha_assoc = Renderer::kAlphaNone;
job.SetInputAlphaAssociation(kAlphaNone);
} else if (stream_data.premultiplied_alpha()) {
alpha_assoc = Renderer::kAlphaAssociated;
job.SetInputAlphaAssociation(kAlphaAssociated);
} else {
alpha_assoc = Renderer::kAlphaUnassociated;
job.SetInputAlphaAssociation(kAlphaUnassociated);
}
render_ctx_->BlitColorManaged(processor, unmanaged_texture,
alpha_assoc,
destination.get());
render_ctx_->BlitColorManaged(job, destination.get());
}
}
}
}
void RenderProcessor::ProcessAudioFootage(SampleBufferPtr destination, const FootageJob &stream, const TimeRange &input_time)
void RenderProcessor::ProcessAudioFootage(SampleBuffer &destination, const FootageJob &stream, const TimeRange &input_time)
{
DecoderPtr decoder = ResolveDecoderFromInput(stream.decoder(), Decoder::CodecStream(stream.filename(), stream.audio_params().stream_index()));
@@ -515,9 +522,9 @@ void RenderProcessor::ProcessShader(TexturePtr destination, const Node *node, co
render_ctx_->BlitToTexture(shader, job, destination.get());
}
void RenderProcessor::ProcessSamples(SampleBufferPtr destination, const Node *node, const TimeRange &range, const SampleJob &job)
void RenderProcessor::ProcessSamples(SampleBuffer &destination, const Node *node, const TimeRange &range, const SampleJob &job)
{
if (!job.samples() || !job.samples()->is_allocated()) {
if (!job.samples().is_allocated()) {
return;
}
@@ -525,7 +532,7 @@ void RenderProcessor::ProcessSamples(SampleBufferPtr destination, const Node *no
const AudioParams& audio_params = GetCacheAudioParams();
for (int i=0;i<job.samples()->sample_count();i++) {
for (int i=0;i<job.samples().sample_count();i++) {
// Calculate the exact rational time at this sample
double sample_to_second = static_cast<double>(i) / static_cast<double>(audio_params.sample_rate());
@@ -545,6 +552,11 @@ void RenderProcessor::ProcessSamples(SampleBufferPtr destination, const Node *no
}
}
void RenderProcessor::ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob &job)
{
render_ctx_->BlitColorManaged(job, destination.get());
}
void RenderProcessor::ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob &job)
{
FramePtr frame = Frame::Create();
@@ -566,7 +578,14 @@ void RenderProcessor::ConvertToReferenceSpace(TexturePtr destination, TexturePtr
{
ColorManager* color_manager = Node::ValueToPtr<ColorManager>(ticket_->property("colormanager"));
ColorProcessorPtr cp = ColorProcessor::Create(color_manager, input_cs, color_manager->GetReferenceColorSpace());
render_ctx_->BlitColorManaged(cp, source, Renderer::kAlphaAssociated, destination.get());
ColorTransformJob ctj;
ctj.SetColorProcessor(cp);
ctj.SetInputTexture(source);
ctj.SetInputAlphaAssociation(kAlphaAssociated);
render_ctx_->BlitColorManaged(ctj, destination.get());
}
}
+6 -4
View File
@@ -46,11 +46,13 @@ protected:
virtual void ProcessVideoFootage(TexturePtr destination, const FootageJob &stream, const rational &input_time) override;
virtual void ProcessAudioFootage(SampleBufferPtr destination, const FootageJob &stream, const TimeRange &input_time) override;
virtual void ProcessAudioFootage(SampleBuffer &destination, const FootageJob &stream, const TimeRange &input_time) override;
virtual void ProcessShader(TexturePtr destination, const Node *node, const TimeRange &range, const ShaderJob& job) override;
virtual void ProcessSamples(SampleBufferPtr destination, const Node *node, const TimeRange &range, const SampleJob &job) override;
virtual void ProcessSamples(SampleBuffer &destination, const Node *node, const TimeRange &range, const SampleJob &job) override;
virtual void ProcessColorTransform(TexturePtr destination, const Node *node, const ColorTransformJob& job) override;
virtual void ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob& job) override;
@@ -61,9 +63,9 @@ protected:
return render_ctx_->CreateTexture(p);
}
virtual SampleBufferPtr CreateSampleBuffer(const AudioParams &params, int sample_count) override
virtual SampleBuffer CreateSampleBuffer(const AudioParams &params, int sample_count) override
{
return SampleBuffer::CreateAllocated(params, sample_count);
return SampleBuffer(params, sample_count);
}
virtual void ConvertToReferenceSpace(TexturePtr destination, TexturePtr source, const QString &input_cs) override;
+4 -8
View File
@@ -33,15 +33,11 @@ public:
{
}
const QString& frag_code() const
{
return frag_code_;
}
const QString& frag_code() const { return frag_code_; }
void set_frag_code(const QString &f) { frag_code_ = f; }
const QString& vert_code() const
{
return vert_code_;
}
const QString& vert_code() const { return vert_code_; }
void set_vert_code(const QString &v) { vert_code_ = v; }
private:
QString frag_code_;