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:
itsmattkc
2020-01-18 03:37:36 +11:00
parent e6b45c75c3
commit 1101b58ee8
30 changed files with 421 additions and 380 deletions
+14 -14
View File
@@ -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 &params, const SampleFormat &format) :
AudioRenderingParams::AudioRenderingParams(const AudioParams &params, 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();
+4 -4
View File
@@ -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)
+9 -11
View File
@@ -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);
+4 -2
View File
@@ -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());
}
+3 -3
View File
@@ -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);
}
+13 -4
View File
@@ -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);
}
+3 -2
View File
@@ -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);
+7 -3
View File
@@ -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_);
+11
View File
@@ -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;
+9
View File
@@ -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();
+11
View File
@@ -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;
+7
View File
@@ -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
*