allow setting of pixel format/ocio method/sample format in preferences
Implementation isn't perfect yet, viewer/renderer doesn't update yet when the preference is changed so a sequence needs to be re-opened for the change to take effect.
This commit is contained in:
+14
-14
@@ -27,23 +27,23 @@ const uint64_t &AudioParams::channel_layout() const
|
||||
}
|
||||
|
||||
AudioRenderingParams::AudioRenderingParams() :
|
||||
format_(SAMPLE_FMT_INVALID)
|
||||
format_(SampleFormat::SAMPLE_FMT_INVALID)
|
||||
{
|
||||
}
|
||||
|
||||
AudioRenderingParams::AudioRenderingParams(const int &sample_rate, const uint64_t &channel_layout, const SampleFormat &format) :
|
||||
AudioRenderingParams::AudioRenderingParams(const int &sample_rate, const uint64_t &channel_layout, const SampleFormat::Format &format) :
|
||||
AudioParams(sample_rate, channel_layout),
|
||||
format_(format)
|
||||
{
|
||||
}
|
||||
|
||||
AudioRenderingParams::AudioRenderingParams(const AudioParams ¶ms, const SampleFormat &format) :
|
||||
AudioRenderingParams::AudioRenderingParams(const AudioParams ¶ms, const SampleFormat::Format &format) :
|
||||
AudioParams(params),
|
||||
format_(format)
|
||||
{
|
||||
}
|
||||
|
||||
const SampleFormat &AudioRenderingParams::format() const
|
||||
const SampleFormat::Format &AudioRenderingParams::format() const
|
||||
{
|
||||
return format_;
|
||||
}
|
||||
@@ -98,18 +98,18 @@ int AudioRenderingParams::channel_count() const
|
||||
int AudioRenderingParams::bytes_per_sample_per_channel() const
|
||||
{
|
||||
switch (format_) {
|
||||
case SAMPLE_FMT_U8:
|
||||
case SampleFormat::SAMPLE_FMT_U8:
|
||||
return 1;
|
||||
case SAMPLE_FMT_S16:
|
||||
case SampleFormat::SAMPLE_FMT_S16:
|
||||
return 2;
|
||||
case SAMPLE_FMT_S32:
|
||||
case SAMPLE_FMT_FLT:
|
||||
case SampleFormat::SAMPLE_FMT_S32:
|
||||
case SampleFormat::SAMPLE_FMT_FLT:
|
||||
return 4;
|
||||
case SAMPLE_FMT_DBL:
|
||||
case SAMPLE_FMT_S64:
|
||||
case SampleFormat::SAMPLE_FMT_DBL:
|
||||
case SampleFormat::SAMPLE_FMT_S64:
|
||||
return 8;
|
||||
case SAMPLE_FMT_INVALID:
|
||||
case SAMPLE_FMT_COUNT:
|
||||
case SampleFormat::SAMPLE_FMT_INVALID:
|
||||
case SampleFormat::SAMPLE_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -125,8 +125,8 @@ bool AudioRenderingParams::is_valid() const
|
||||
{
|
||||
bool valid = (sample_rate() > 0
|
||||
&& channel_layout() > 0
|
||||
&& format_ != SAMPLE_FMT_INVALID
|
||||
&& format_ != SAMPLE_FMT_COUNT);
|
||||
&& format_ != SampleFormat::SAMPLE_FMT_INVALID
|
||||
&& format_ != SampleFormat::SAMPLE_FMT_COUNT);
|
||||
|
||||
if (!valid) {
|
||||
qWarning() << "Invalid params found:" << sample_rate() << channel_layout() << format();
|
||||
|
||||
@@ -25,8 +25,8 @@ private:
|
||||
class AudioRenderingParams : public AudioParams {
|
||||
public:
|
||||
AudioRenderingParams();
|
||||
AudioRenderingParams(const int& sample_rate, const uint64_t& channel_layout, const SampleFormat& format);
|
||||
AudioRenderingParams(const AudioParams& params, const SampleFormat& format);
|
||||
AudioRenderingParams(const int& sample_rate, const uint64_t& channel_layout, const SampleFormat::Format& format);
|
||||
AudioRenderingParams(const AudioParams& params, const SampleFormat::Format& format);
|
||||
|
||||
int time_to_bytes(const rational& time) const;
|
||||
int time_to_samples(const rational& time) const;
|
||||
@@ -37,13 +37,13 @@ public:
|
||||
int bits_per_sample() const;
|
||||
bool is_valid() const;
|
||||
|
||||
const SampleFormat& format() const;
|
||||
const SampleFormat::Format &format() const;
|
||||
|
||||
bool operator==(const AudioRenderingParams& other) const;
|
||||
bool operator!=(const AudioRenderingParams& other) const;
|
||||
|
||||
private:
|
||||
SampleFormat format_;
|
||||
SampleFormat::Format format_;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AudioRenderingParams)
|
||||
|
||||
@@ -185,17 +185,15 @@ void OpenGLTexture::CreateInternal(QOpenGLContext* create_ctx, GLuint* tex, cons
|
||||
// Allocate storage for texture
|
||||
const PixelFormat::Info& bit_depth = PixelService::GetPixelFormatInfo(format_);
|
||||
|
||||
f->glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
bit_depth.internal_format,
|
||||
width_,
|
||||
height_,
|
||||
0,
|
||||
bit_depth.pixel_format,
|
||||
bit_depth.gl_pixel_type,
|
||||
data
|
||||
);
|
||||
f->glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
bit_depth.internal_format,
|
||||
width_,
|
||||
height_,
|
||||
0,
|
||||
bit_depth.pixel_format,
|
||||
bit_depth.gl_pixel_type,
|
||||
data);
|
||||
|
||||
// Set texture filtering to bilinear
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
|
||||
@@ -71,8 +71,10 @@ void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable
|
||||
color_cache()->Add(video_stream->colorspace(), color_processor);
|
||||
}
|
||||
|
||||
ColorManager::OCIOMethod ocio_method = ColorManager::GetOCIOMethodForMode(video_params().mode());
|
||||
|
||||
// OCIO's CPU conversion is more accurate, so for online we render on CPU but offline we render GPU
|
||||
if (video_params().mode() == RenderMode::kOnline) {
|
||||
if (ocio_method == ColorManager::kOCIOAccurate) {
|
||||
// If alpha is associated, disassociate for the color transform
|
||||
if (video_stream->premultiplied_alpha()) {
|
||||
ColorManager::DisassociateAlpha(frame);
|
||||
@@ -96,7 +98,7 @@ void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable
|
||||
|
||||
OpenGLTextureCache::ReferencePtr footage_tex_ref = texture_cache_->Get(ctx_, footage_params, frame->data());
|
||||
|
||||
if (video_params().mode() == RenderMode::kOffline) {
|
||||
if (ocio_method == ColorManager::kOCIOFast) {
|
||||
if (!color_processor->IsEnabled()) {
|
||||
color_processor->Enable(ctx_, video_stream->premultiplied_alpha());
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ const char *VideoRenderBackend::GetCachedFrame(const rational &time)
|
||||
QByteArray frame_hash = frame_cache_.TimeToHash(time);
|
||||
|
||||
if (!frame_hash.isEmpty()) {
|
||||
QString fn = frame_cache_.CachePathName(frame_hash);
|
||||
QString fn = frame_cache_.CachePathName(frame_hash, params_.format());
|
||||
|
||||
if (QFileInfo::exists(fn)) {
|
||||
auto in = OIIO::ImageInput::open(fn.toStdString());
|
||||
@@ -304,7 +304,7 @@ void VideoRenderBackend::ThreadCompletedDownload(NodeDependency dep, qint64 job_
|
||||
|
||||
// Register frame with the disk manager
|
||||
if (operating_mode_ & VideoRenderWorker::kDownloadOnly) {
|
||||
DiskManager::instance()->CreatedFile(frame_cache()->CachePathName(hash), hash);
|
||||
DiskManager::instance()->CreatedFile(frame_cache()->CachePathName(hash, params_.format()), hash);
|
||||
}
|
||||
|
||||
QList<rational> hashes_with_time = frame_cache()->FramesWithHash(hash);
|
||||
@@ -322,7 +322,7 @@ void VideoRenderBackend::ThreadSkippedFrame(NodeDependency dep, qint64 job_time,
|
||||
SetWorkerBusyState(static_cast<RenderWorker*>(sender()), false);
|
||||
|
||||
if (SetFrameHash(dep, hash, job_time)
|
||||
&& frame_cache_.HasHash(hash)) {
|
||||
&& frame_cache_.HasHash(hash, params_.format())) {
|
||||
emit CachedTimeReady(dep.in(), job_time);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ void VideoRenderFrameCache::Clear()
|
||||
cache_id_.clear();
|
||||
}
|
||||
|
||||
bool VideoRenderFrameCache::HasHash(const QByteArray &hash)
|
||||
bool VideoRenderFrameCache::HasHash(const QByteArray &hash, const PixelFormat::Format& format)
|
||||
{
|
||||
return QFileInfo::exists(CachePathName(hash)) && !IsCaching(hash);
|
||||
return QFileInfo::exists(CachePathName(hash, format)) && !IsCaching(hash);
|
||||
}
|
||||
|
||||
bool VideoRenderFrameCache::IsCaching(const QByteArray &hash)
|
||||
@@ -114,12 +114,21 @@ const QMap<rational, QByteArray> &VideoRenderFrameCache::time_hash_map() const
|
||||
return time_hash_map_;
|
||||
}
|
||||
|
||||
QString VideoRenderFrameCache::CachePathName(const QByteArray &hash) const
|
||||
QString VideoRenderFrameCache::CachePathName(const QByteArray &hash, const PixelFormat::Format& pix_fmt) const
|
||||
{
|
||||
QDir this_cache_dir = QDir(GetMediaCacheLocation());
|
||||
this_cache_dir.mkpath(".");
|
||||
|
||||
QString filename = QStringLiteral("%1.exr").arg(QString(hash.toHex()));
|
||||
QString ext;
|
||||
|
||||
if (pix_fmt == PixelFormat::PIX_FMT_RGBA8) {
|
||||
// For some reason, 8-bit EXRs are extremely slow to load, so we use TIFF instead.
|
||||
ext = QStringLiteral("tiff");
|
||||
} else {
|
||||
ext = QStringLiteral("exr");
|
||||
}
|
||||
|
||||
QString filename = QStringLiteral("%1.%2").arg(QString(hash.toHex()), ext);
|
||||
|
||||
return this_cache_dir.filePath(filename);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <QMutex>
|
||||
|
||||
#include "common/rational.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
class VideoRenderFrameCache
|
||||
{
|
||||
@@ -15,7 +16,7 @@ public:
|
||||
/**
|
||||
* @brief Return whether a frame with this hash already exists
|
||||
*/
|
||||
bool HasHash(const QByteArray& hash);
|
||||
bool HasHash(const QByteArray& hash, const PixelFormat::Format &format);
|
||||
|
||||
/**
|
||||
* @brief Return whether a frame is currently being cached
|
||||
@@ -30,7 +31,7 @@ public:
|
||||
/**
|
||||
* @brief Return the path of the cached image at this time
|
||||
*/
|
||||
QString CachePathName(const QByteArray &hash) const;
|
||||
QString CachePathName(const QByteArray &hash, const PixelFormat::Format& pix_fmt) const;
|
||||
|
||||
void SetCacheID(const QString& id);
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path, con
|
||||
// Emit only the hash
|
||||
emit CompletedDownload(path, job_time, hash);
|
||||
|
||||
} else if ((operating_mode_ & kHashOnly) && frame_cache_->HasHash(hash)) {
|
||||
} else if ((operating_mode_ & kHashOnly) && frame_cache_->HasHash(hash, video_params_.format())) {
|
||||
|
||||
// We've already cached this hash, no need to continue
|
||||
emit HashAlreadyExists(path, job_time, hash);
|
||||
@@ -67,7 +67,7 @@ NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path, con
|
||||
|
||||
// If we actually have a texture, download it into the disk cache
|
||||
if ((operating_mode_ & kDownloadOnly) && !texture.isNull()) {
|
||||
Download(path, hash, texture, frame_cache_->CachePathName(hash));
|
||||
Download(path, hash, texture, frame_cache_->CachePathName(hash, video_params_.format()));
|
||||
}
|
||||
|
||||
frame_cache_->RemoveHashFromCurrentlyCaching(hash);
|
||||
@@ -212,7 +212,11 @@ void VideoRenderWorker::Download(NodeDependency dep, QByteArray hash, QVariant t
|
||||
|
||||
// Set up OIIO::ImageSpec for compressing cached images on disk
|
||||
OIIO::ImageSpec spec(video_params().effective_width(), video_params().effective_height(), kRGBAChannels, format_info.oiio_desc);
|
||||
spec.attribute("compression", "dwaa:200");
|
||||
|
||||
if (video_params_.format() != PixelFormat::PIX_FMT_RGBA8) {
|
||||
// 8-bit doesn't use EXR because EXR loading is really slow on 8-bit
|
||||
spec.attribute("compression", "dwaa:200");
|
||||
}
|
||||
|
||||
TextureToBuffer(texture, download_buffer_);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "common/define.h"
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
|
||||
ColorManager::ColorManager()
|
||||
{
|
||||
@@ -110,6 +111,16 @@ QStringList ColorManager::ListAvailableInputColorspaces(OCIO::ConstConfigRcPtr c
|
||||
return spaces;
|
||||
}
|
||||
|
||||
ColorManager::OCIOMethod ColorManager::GetOCIOMethodForMode(RenderMode::Mode mode)
|
||||
{
|
||||
return static_cast<OCIOMethod>(Core::GetPreferenceForRenderMode(mode, QStringLiteral("OCIOMethod")).toInt());
|
||||
}
|
||||
|
||||
void ColorManager::SetOCIOMethodForMode(RenderMode::Mode mode, ColorManager::OCIOMethod method)
|
||||
{
|
||||
Core::SetPreferenceForRenderMode(mode, QStringLiteral("OCIOMethod"), method);
|
||||
}
|
||||
|
||||
void ColorManager::AssociateAlphaPixFmtFilter(ColorManager::AlphaAction action, FramePtr f)
|
||||
{
|
||||
int pixel_count = f->width() * f->height() * kRGBAChannels;
|
||||
|
||||
@@ -38,6 +38,15 @@ public:
|
||||
|
||||
static QStringList ListAvailableInputColorspaces(OCIO::ConstConfigRcPtr config);
|
||||
|
||||
enum OCIOMethod {
|
||||
kOCIOFast,
|
||||
kOCIOAccurate
|
||||
};
|
||||
|
||||
static OCIOMethod GetOCIOMethodForMode(RenderMode::Mode mode);
|
||||
|
||||
static void SetOCIOMethodForMode(RenderMode::Mode mode, OCIOMethod method);
|
||||
|
||||
signals:
|
||||
void ConfigChanged();
|
||||
|
||||
|
||||
@@ -25,11 +25,22 @@
|
||||
#include <QFloat16>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "core.h"
|
||||
|
||||
PixelService::PixelService()
|
||||
{
|
||||
}
|
||||
|
||||
PixelFormat::Format PixelService::GetConfiguredFormatForMode(RenderMode::Mode mode)
|
||||
{
|
||||
return static_cast<PixelFormat::Format>(Core::GetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat")).toInt());
|
||||
}
|
||||
|
||||
void PixelService::SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format)
|
||||
{
|
||||
Core::SetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat"), format);
|
||||
}
|
||||
|
||||
PixelFormat::Info PixelService::GetPixelFormatInfo(const PixelFormat::Format &format)
|
||||
{
|
||||
PixelFormat::Info info;
|
||||
|
||||
@@ -25,12 +25,19 @@
|
||||
|
||||
#include "codec/frame.h"
|
||||
#include "pixelformat.h"
|
||||
#include "render/rendermodes.h"
|
||||
|
||||
class PixelService : public QObject {
|
||||
public:
|
||||
|
||||
PixelService();
|
||||
|
||||
/**
|
||||
* @brief Returns the configured pixel format for a given mode
|
||||
*/
|
||||
static PixelFormat::Format GetConfiguredFormatForMode(RenderMode::Mode mode);
|
||||
static void SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format);
|
||||
|
||||
/**
|
||||
* @brief Return a PixelFormatInfo containing information for a certain format
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user