diff --git a/app/audio/CMakeLists.txt b/app/audio/CMakeLists.txt
index b8b8e49a2..5b0976dc0 100644
--- a/app/audio/CMakeLists.txt
+++ b/app/audio/CMakeLists.txt
@@ -24,8 +24,6 @@ set(OLIVE_SOURCES
audio/outputdeviceproxy.cpp
audio/outputmanager.h
audio/outputmanager.cpp
- audio/sampleformat.h
- audio/sampleformat.cpp
audio/tempoprocessor.h
audio/tempoprocessor.cpp
PARENT_SCOPE
diff --git a/app/audio/audiomanager.cpp b/app/audio/audiomanager.cpp
index a0afa7cce..48daa0c9b 100644
--- a/app/audio/audiomanager.cpp
+++ b/app/audio/audiomanager.cpp
@@ -124,36 +124,8 @@ void AudioManager::SetOutputDevice(const QAudioDeviceInfo &info)
format.setChannelCount(output_params_.channel_count());
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
-
- switch (output_params_.format()) {
- case SampleFormat::SAMPLE_FMT_U8:
- format.setSampleSize(8);
- format.setSampleType(QAudioFormat::UnSignedInt);
- break;
- case SampleFormat::SAMPLE_FMT_S16:
- format.setSampleSize(16);
- format.setSampleType(QAudioFormat::SignedInt);
- break;
- case SampleFormat::SAMPLE_FMT_S32:
- format.setSampleSize(32);
- format.setSampleType(QAudioFormat::SignedInt);
- break;
- case SampleFormat::SAMPLE_FMT_S64:
- format.setSampleSize(64);
- format.setSampleType(QAudioFormat::SignedInt);
- break;
- case SampleFormat::SAMPLE_FMT_FLT:
- format.setSampleSize(32);
- format.setSampleType(QAudioFormat::Float);
- break;
- case SampleFormat::SAMPLE_FMT_DBL:
- format.setSampleSize(64);
- format.setSampleType(QAudioFormat::Float);
- break;
- case SampleFormat::SAMPLE_FMT_COUNT:
- case SampleFormat::SAMPLE_FMT_INVALID:
- abort();
- }
+ format.setSampleSize(output_params_.bits_per_sample());
+ format.setSampleType(AudioParams::GetQtSampleType(output_params_.format()));
if (info.isFormatSupported(format)) {
QMetaObject::invokeMethod(output_manager_,
diff --git a/app/audio/sampleformat.cpp b/app/audio/sampleformat.cpp
deleted file mode 100644
index 27bbbb0a4..000000000
--- a/app/audio/sampleformat.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/***
-
- Olive - Non-Linear Video Editor
- Copyright (C) 2019 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 .
-
-***/
-
-#include "sampleformat.h"
-
-#include
-
-OLIVE_NAMESPACE_ENTER
-
-const SampleFormat::Format SampleFormat::kInternalFormat = SAMPLE_FMT_FLT;
-
-QString SampleFormat::GetSampleFormatName(const SampleFormat::Format &f)
-{
- switch (f) {
- case SAMPLE_FMT_U8:
- return QCoreApplication::translate("SampleFormat", "Unsigned 8-bit");
- case SAMPLE_FMT_S16:
- return QCoreApplication::translate("SampleFormat", "Signed 16-bit");
- case SAMPLE_FMT_S32:
- return QCoreApplication::translate("SampleFormat", "Signed 32-bit");
- case SAMPLE_FMT_S64:
- return QCoreApplication::translate("SampleFormat", "Signed 64-bit");
- case SAMPLE_FMT_FLT:
- return QCoreApplication::translate("SampleFormat", "32-bit Float");
- case SAMPLE_FMT_DBL:
- return QCoreApplication::translate("SampleFormat", "64-bit Float");
- case SAMPLE_FMT_COUNT:
- case SAMPLE_FMT_INVALID:
- break;
- }
-
- return QCoreApplication::translate("SampleFormat", "Invalid");
-}
-
-OLIVE_NAMESPACE_EXIT
diff --git a/app/audio/tempoprocessor.cpp b/app/audio/tempoprocessor.cpp
index 2deda4f33..1cb56b468 100644
--- a/app/audio/tempoprocessor.cpp
+++ b/app/audio/tempoprocessor.cpp
@@ -28,7 +28,7 @@ extern "C" {
#include
-#include "codec/ffmpeg/ffmpegcommon.h"
+#include "common/ffmpegutils.h"
OLIVE_NAMESPACE_ENTER
@@ -75,7 +75,7 @@ bool TempoProcessor::Open(const AudioParams ¶ms, const double& speed)
1,
params_.sample_rate(),
params_.sample_rate(),
- FFmpegCommon::GetFFmpegSampleFormat(params_.format()),
+ FFmpegUtils::GetFFmpegSampleFormat(params_.format()),
params.channel_layout());
// Create buffer and buffersink
@@ -171,7 +171,7 @@ void TempoProcessor::Push(const char *data, int length)
// Allocate a buffer for the number of samples we got
src_frame->sample_rate = params_.sample_rate();
- src_frame->format = FFmpegCommon::GetFFmpegSampleFormat(params_.format());
+ src_frame->format = FFmpegUtils::GetFFmpegSampleFormat(params_.format());
src_frame->channel_layout = params_.channel_layout();
src_frame->nb_samples = params_.bytes_to_samples(length);
src_frame->pts = timestamp_;
diff --git a/app/codec/decoder.cpp b/app/codec/decoder.cpp
index e8a5bf71b..9841fbf4f 100644
--- a/app/codec/decoder.cpp
+++ b/app/codec/decoder.cpp
@@ -24,11 +24,11 @@
#include
#include
-#include "codec/ffmpeg/ffmpegcommon.h"
#include "codec/ffmpeg/ffmpegdecoder.h"
#include "codec/oiio/oiiodecoder.h"
#include "codec/waveinput.h"
#include "codec/waveoutput.h"
+#include "common/ffmpegutils.h"
#include "common/filefunctions.h"
#include "common/timecodefunctions.h"
#ifdef USE_OTIO
diff --git a/app/codec/encoder.h b/app/codec/encoder.h
index 2d4e2d245..9cd9547a0 100644
--- a/app/codec/encoder.h
+++ b/app/codec/encoder.h
@@ -122,9 +122,9 @@ public:
virtual void Close() = 0;
- virtual PixelFormat::Format GetDesiredPixelFormat() const
+ virtual VideoParams::Format GetDesiredPixelFormat() const
{
- return PixelFormat::PIX_FMT_INVALID;
+ return VideoParams::kFormatInvalid;
}
private:
diff --git a/app/codec/ffmpeg/CMakeLists.txt b/app/codec/ffmpeg/CMakeLists.txt
index 12267fe76..7c26e24bf 100644
--- a/app/codec/ffmpeg/CMakeLists.txt
+++ b/app/codec/ffmpeg/CMakeLists.txt
@@ -17,8 +17,6 @@
set(OLIVE_SOURCES
${OLIVE_SOURCES}
codec/ffmpeg/avframeptr.h
- codec/ffmpeg/ffmpegcommon.h
- codec/ffmpeg/ffmpegcommon.cpp
codec/ffmpeg/ffmpegdecoder.h
codec/ffmpeg/ffmpegdecoder.cpp
codec/ffmpeg/ffmpegencoder.h
diff --git a/app/codec/ffmpeg/ffmpegcommon.cpp b/app/codec/ffmpeg/ffmpegcommon.cpp
deleted file mode 100644
index cdc2554e1..000000000
--- a/app/codec/ffmpeg/ffmpegcommon.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/***
-
- Olive - Non-Linear Video Editor
- Copyright (C) 2019 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 .
-
-***/
-
-#include "ffmpegcommon.h"
-
-OLIVE_NAMESPACE_ENTER
-
-AVPixelFormat FFmpegCommon::GetCompatiblePixelFormat(const AVPixelFormat &pix_fmt)
-{
- AVPixelFormat possible_pix_fmts[] = {
- AV_PIX_FMT_RGBA,
- AV_PIX_FMT_RGBA64,
- AV_PIX_FMT_NONE
- };
-
- return avcodec_find_best_pix_fmt_of_list(possible_pix_fmts,
- pix_fmt,
- 1,
- nullptr);
-}
-
-SampleFormat::Format FFmpegCommon::GetNativeSampleFormat(const AVSampleFormat &smp_fmt)
-{
- switch (smp_fmt) {
- case AV_SAMPLE_FMT_U8:
- return SampleFormat::SAMPLE_FMT_U8;
- case AV_SAMPLE_FMT_S16:
- return SampleFormat::SAMPLE_FMT_S16;
- case AV_SAMPLE_FMT_S32:
- return SampleFormat::SAMPLE_FMT_S32;
- case AV_SAMPLE_FMT_S64:
- return SampleFormat::SAMPLE_FMT_S64;
- case AV_SAMPLE_FMT_FLT:
- return SampleFormat::SAMPLE_FMT_FLT;
- case AV_SAMPLE_FMT_DBL:
- return SampleFormat::SAMPLE_FMT_DBL;
- case AV_SAMPLE_FMT_U8P :
- case AV_SAMPLE_FMT_S16P:
- case AV_SAMPLE_FMT_S32P:
- case AV_SAMPLE_FMT_S64P:
- case AV_SAMPLE_FMT_FLTP:
- case AV_SAMPLE_FMT_DBLP:
- case AV_SAMPLE_FMT_NONE:
- case AV_SAMPLE_FMT_NB:
- break;
- }
-
- return SampleFormat::SAMPLE_FMT_INVALID;
-}
-
-AVSampleFormat FFmpegCommon::GetFFmpegSampleFormat(const SampleFormat::Format &smp_fmt)
-{
- switch (smp_fmt) {
- case SampleFormat::SAMPLE_FMT_U8:
- return AV_SAMPLE_FMT_U8;
- case SampleFormat::SAMPLE_FMT_S16:
- return AV_SAMPLE_FMT_S16;
- case SampleFormat::SAMPLE_FMT_S32:
- return AV_SAMPLE_FMT_S32;
- case SampleFormat::SAMPLE_FMT_S64:
- return AV_SAMPLE_FMT_S64;
- case SampleFormat::SAMPLE_FMT_FLT:
- return AV_SAMPLE_FMT_FLT;
- case SampleFormat::SAMPLE_FMT_DBL:
- return AV_SAMPLE_FMT_DBL;
- case SampleFormat::SAMPLE_FMT_INVALID:
- case SampleFormat::SAMPLE_FMT_COUNT:
- break;
- }
-
- return AV_SAMPLE_FMT_NONE;
-}
-
-AVPixelFormat FFmpegCommon::GetFFmpegPixelFormat(const PixelFormat::Format &pix_fmt)
-{
- switch (pix_fmt) {
- case PixelFormat::PIX_FMT_RGBA8:
- return AV_PIX_FMT_RGBA;
- case PixelFormat::PIX_FMT_RGBA16U:
- return AV_PIX_FMT_RGBA64;
- case PixelFormat::PIX_FMT_RGBA16F:
- case PixelFormat::PIX_FMT_RGBA32F:
- case PixelFormat::PIX_FMT_INVALID:
- case PixelFormat::PIX_FMT_COUNT:
- break;
- }
-
- return AV_PIX_FMT_NONE;
-}
-
-PixelFormat::Format FFmpegCommon::GetCompatiblePixelFormat(const PixelFormat::Format &pix_fmt)
-{
- switch (pix_fmt) {
- case PixelFormat::PIX_FMT_RGBA8:
- return PixelFormat::PIX_FMT_RGBA8;
- case PixelFormat::PIX_FMT_RGBA16U:
- case PixelFormat::PIX_FMT_RGBA16F:
- case PixelFormat::PIX_FMT_RGBA32F:
- return PixelFormat::PIX_FMT_RGBA16U;
- case PixelFormat::PIX_FMT_INVALID:
- case PixelFormat::PIX_FMT_COUNT:
- break;
- }
-
- return PixelFormat::PIX_FMT_INVALID;
-}
-
-OLIVE_NAMESPACE_EXIT
diff --git a/app/codec/ffmpeg/ffmpegdecoder.cpp b/app/codec/ffmpeg/ffmpegdecoder.cpp
index ac4e402b7..cdab55a67 100644
--- a/app/codec/ffmpeg/ffmpegdecoder.cpp
+++ b/app/codec/ffmpeg/ffmpegdecoder.cpp
@@ -38,13 +38,12 @@ extern "C" {
#include "codec/waveinput.h"
#include "common/define.h"
+#include "common/ffmpegutils.h"
#include "common/filefunctions.h"
#include "common/functiontimer.h"
#include "common/timecodefunctions.h"
-#include "ffmpegcommon.h"
#include "render/framehashcache.h"
#include "render/diskmanager.h"
-#include "render/pixelformat.h"
OLIVE_NAMESPACE_ENTER
@@ -73,13 +72,17 @@ bool FFmpegDecoder::OpenInternal()
if (stream()->type() == Stream::kVideo) {
// Get an Olive compatible AVPixelFormat
- ideal_pix_fmt_ = FFmpegCommon::GetCompatiblePixelFormat(static_cast(s->codecpar->format));
+ ideal_pix_fmt_ = FFmpegUtils::GetCompatiblePixelFormat(static_cast(s->codecpar->format));
// Determine which Olive native pixel format we retrieved
// Note that FFmpeg doesn't support float formats
native_pix_fmt_ = GetNativePixelFormat(ideal_pix_fmt_);
+ native_channel_count_ = GetNativeChannelCount(ideal_pix_fmt_);
- if (native_pix_fmt_ == PixelFormat::PIX_FMT_INVALID) {
+ qDebug() << "Set channel count to:" << native_channel_count_;
+
+ if (native_pix_fmt_ == VideoParams::kFormatInvalid
+ || native_channel_count_ == 0) {
qDebug() << "Failed to find valid native pixel format for" << ideal_pix_fmt_;
return false;
}
@@ -124,6 +127,7 @@ FramePtr FFmpegDecoder::RetrieveStillImage(const rational &timecode, const int &
output_frame->set_video_params(VideoParams(frame->width,
frame->height,
native_pix_fmt_,
+ native_channel_count_,
std::static_pointer_cast(stream())->pixel_aspect_ratio(),
std::static_pointer_cast(stream())->interlacing(),
divider));
@@ -172,7 +176,7 @@ FramePtr FFmpegDecoder::RetrieveVideoInternal(const rational &timecode, const in
ClearFrameCache();
// Set new frame pool parameters
- pool_.SetParameters(divided_width, divided_height, native_pix_fmt_);
+ pool_.SetParameters(divided_width, divided_height, native_pix_fmt_, native_channel_count_);
}
// Retrieve frame
@@ -184,6 +188,7 @@ FramePtr FFmpegDecoder::RetrieveVideoInternal(const rational &timecode, const in
copy->set_video_params(VideoParams(vs->width(),
vs->height(),
native_pix_fmt_,
+ native_channel_count_,
std::static_pointer_cast(stream())->pixel_aspect_ratio(),
std::static_pointer_cast(stream())->interlacing(),
divider));
@@ -328,10 +333,13 @@ FootagePtr FFmpegDecoder::Probe(const QString& filename, const QAtomicInt* cance
video_stream->set_width(avstream->codecpar->width);
video_stream->set_height(avstream->codecpar->height);
- video_stream->set_format(GetNativePixelFormat(FFmpegCommon::GetCompatiblePixelFormat(static_cast(avstream->codecpar->format))));
video_stream->set_interlacing(interlacing);
video_stream->set_pixel_aspect_ratio(pixel_aspect_ratio);
+ AVPixelFormat compatible_pix_fmt = FFmpegUtils::GetCompatiblePixelFormat(static_cast(avstream->codecpar->format));
+ video_stream->set_format(GetNativePixelFormat(compatible_pix_fmt));
+ video_stream->set_channel_count(GetNativeChannelCount(compatible_pix_fmt));
+
str = video_stream;
} else {
@@ -460,7 +468,7 @@ bool FFmpegDecoder::ConformAudioInternal(const QString &filename, const AudioPar
// Create resampling context
SwrContext* resampler = swr_alloc_set_opts(nullptr,
params.channel_layout(),
- FFmpegCommon::GetFFmpegSampleFormat(params.format()),
+ FFmpegUtils::GetFFmpegSampleFormat(params.format()),
params.sample_rate(),
channel_layout,
static_cast(instance_.avstream()->codecpar->format),
@@ -542,15 +550,31 @@ bool FFmpegDecoder::ConformAudioInternal(const QString &filename, const AudioPar
return success;
}
-PixelFormat::Format FFmpegDecoder::GetNativePixelFormat(AVPixelFormat pix_fmt)
+VideoParams::Format FFmpegDecoder::GetNativePixelFormat(AVPixelFormat pix_fmt)
{
switch (pix_fmt) {
+ case AV_PIX_FMT_RGB24:
case AV_PIX_FMT_RGBA:
- return PixelFormat::PIX_FMT_RGBA8;
+ return VideoParams::kFormatUnsigned8;
+ case AV_PIX_FMT_RGB48:
case AV_PIX_FMT_RGBA64:
- return PixelFormat::PIX_FMT_RGBA16U;
+ return VideoParams::kFormatUnsigned16;
default:
- return PixelFormat::PIX_FMT_INVALID;
+ return VideoParams::kFormatInvalid;
+ }
+}
+
+int FFmpegDecoder::GetNativeChannelCount(AVPixelFormat pix_fmt)
+{
+ switch (pix_fmt) {
+ case AV_PIX_FMT_RGB24:
+ case AV_PIX_FMT_RGB48:
+ return VideoParams::kRGBChannelCount;
+ case AV_PIX_FMT_RGBA:
+ case AV_PIX_FMT_RGBA64:
+ return VideoParams::kRGBAChannelCount;
+ default:
+ return 0;
}
}
@@ -729,7 +753,7 @@ FFmpegFramePool::ElementPtr FFmpegDecoder::RetrieveFrame(const int64_t& target_t
// Store in queue, converting to native format
uint8_t* destination_data = cached->data();
- int destination_linesize = Frame::generate_linesize_bytes(VideoParams::GetScaledDimension(instance_.avstream()->codecpar->width, divider), native_pix_fmt_);
+ int destination_linesize = Frame::generate_linesize_bytes(VideoParams::GetScaledDimension(instance_.avstream()->codecpar->width, divider), native_pix_fmt_, native_channel_count_);
FFmpegBufferToNativeBuffer(working_frame->data, working_frame->linesize, &destination_data, &destination_linesize);
// Set timestamp so this frame can be identified later
diff --git a/app/codec/ffmpeg/ffmpegdecoder.h b/app/codec/ffmpeg/ffmpegdecoder.h
index b74aa5bde..1f820d746 100644
--- a/app/codec/ffmpeg/ffmpegdecoder.h
+++ b/app/codec/ffmpeg/ffmpegdecoder.h
@@ -32,7 +32,6 @@ extern "C" {
#include
#include
-#include "audio/sampleformat.h"
#include "avframeptr.h"
#include "codec/decoder.h"
#include "codec/waveoutput.h"
@@ -126,7 +125,8 @@ private:
FramePtr RetrieveStillImage(const rational& timecode, const int& divider);
- static PixelFormat::Format GetNativePixelFormat(AVPixelFormat pix_fmt);
+ static VideoParams::Format GetNativePixelFormat(AVPixelFormat pix_fmt);
+ static int GetNativeChannelCount(AVPixelFormat pix_fmt);
static uint64_t ValidateChannelLayout(AVStream *stream);
@@ -143,7 +143,8 @@ private:
SwsContext* scale_ctx_;
int scale_divider_;
AVPixelFormat ideal_pix_fmt_;
- PixelFormat::Format native_pix_fmt_;
+ VideoParams::Format native_pix_fmt_;
+ int native_channel_count_;
FFmpegFramePool pool_;
diff --git a/app/codec/ffmpeg/ffmpegencoder.cpp b/app/codec/ffmpeg/ffmpegencoder.cpp
index c31ac6b5a..3e95937db 100644
--- a/app/codec/ffmpeg/ffmpegencoder.cpp
+++ b/app/codec/ffmpeg/ffmpegencoder.cpp
@@ -26,8 +26,7 @@ extern "C" {
#include
-#include "ffmpegcommon.h"
-#include "render/pixelformat.h"
+#include "common/ffmpegutils.h"
OLIVE_NAMESPACE_ENTER
@@ -36,7 +35,8 @@ FFmpegEncoder::FFmpegEncoder(const EncodingParams ¶ms) :
fmt_ctx_(nullptr),
video_stream_(nullptr),
video_codec_ctx_(nullptr),
- video_scale_ctx_(nullptr),
+ video_alpha_scale_ctx_(nullptr),
+ video_noalpha_scale_ctx_(nullptr),
audio_stream_(nullptr),
audio_codec_ctx_(nullptr),
audio_resample_ctx_(nullptr),
@@ -72,29 +72,49 @@ bool FFmpegEncoder::Open()
}
// This is the format we will expect frames received in Write() to be in
- PixelFormat::Format native_pixel_fmt = params().video_params().format();
+ VideoParams::Format native_pixel_fmt = params().video_params().format();
// This is the format we will need to convert the frame to for swscale to understand it
- video_conversion_fmt_ = FFmpegCommon::GetCompatiblePixelFormat(native_pixel_fmt);
+ video_conversion_fmt_ = FFmpegUtils::GetCompatiblePixelFormat(native_pixel_fmt);
// This is the equivalent pixel format above as an AVPixelFormat that swscale can understand
- AVPixelFormat src_pix_fmt = FFmpegCommon::GetFFmpegPixelFormat(video_conversion_fmt_);
+ AVPixelFormat src_alpha_pix_fmt = FFmpegUtils::GetFFmpegPixelFormat(video_conversion_fmt_,
+ VideoParams::kRGBAChannelCount);
+
+ AVPixelFormat src_noalpha_pix_fmt = FFmpegUtils::GetFFmpegPixelFormat(video_conversion_fmt_,
+ VideoParams::kRGBChannelCount);
+
+ if (src_alpha_pix_fmt == AV_PIX_FMT_NONE || src_noalpha_pix_fmt == AV_PIX_FMT_NONE) {
+ Error(QStringLiteral("Failed to find suitable pixel format for this buffer"));
+ return false;
+ }
// This is the pixel format the encoder wants to encode to
AVPixelFormat encoder_pix_fmt = video_codec_ctx_->pix_fmt;
// Set up a scaling context - if the native pixel format is not equal to the encoder's, we'll need to convert it
// before encoding. Even if we don't, this may be useful for converting between linesizes, etc.
- video_scale_ctx_ = sws_getContext(params().video_params().width(),
- params().video_params().height(),
- src_pix_fmt,
- params().video_params().width(),
- params().video_params().height(),
- encoder_pix_fmt,
- 0,
- nullptr,
- nullptr,
- nullptr);
+ video_alpha_scale_ctx_ = sws_getContext(params().video_params().width(),
+ params().video_params().height(),
+ src_alpha_pix_fmt,
+ params().video_params().width(),
+ params().video_params().height(),
+ encoder_pix_fmt,
+ 0,
+ nullptr,
+ nullptr,
+ nullptr);
+
+ video_noalpha_scale_ctx_ = sws_getContext(params().video_params().width(),
+ params().video_params().height(),
+ src_noalpha_pix_fmt,
+ params().video_params().width(),
+ params().video_params().height(),
+ encoder_pix_fmt,
+ 0,
+ nullptr,
+ nullptr,
+ nullptr);
}
// Initialize an audio stream if it's enabled
@@ -157,19 +177,22 @@ bool FFmpegEncoder::WriteFrame(FramePtr frame, rational time)
// We may need to convert this frame to a frame that swscale will understand
if (frame->format() != video_conversion_fmt_) {
- frame = PixelFormat::ConvertPixelFormat(frame, video_conversion_fmt_);
+ frame = frame->convert(video_conversion_fmt_);
}
// Use swscale context to convert formats/linesizes
input_data = frame->const_data();
input_linesize = frame->linesize_bytes();
- error_code = sws_scale(video_scale_ctx_,
+
+ error_code = sws_scale((frame->channel_count() == VideoParams::kRGBAChannelCount) ? video_alpha_scale_ctx_ : video_noalpha_scale_ctx_,
reinterpret_cast(&input_data),
&input_linesize,
0,
frame->height(),
encoded_frame->data,
encoded_frame->linesize);
+
+
if (error_code < 0) {
FFmpegError("Failed to scale frame", error_code);
goto fail;
@@ -208,7 +231,7 @@ void FFmpegEncoder::WriteAudio(AudioParams pcm_info, QIODevice* file)
audio_codec_ctx_->sample_fmt,
audio_codec_ctx_->sample_rate,
static_cast(pcm_info.channel_layout()),
- FFmpegCommon::GetFFmpegSampleFormat(pcm_info.format()),
+ FFmpegUtils::GetFFmpegSampleFormat(pcm_info.format()),
pcm_info.sample_rate(),
0,
nullptr);
@@ -300,9 +323,14 @@ void FFmpegEncoder::Close()
open_ = false;
}
- if (video_scale_ctx_) {
- sws_freeContext(video_scale_ctx_);
- video_scale_ctx_ = nullptr;
+ if (video_alpha_scale_ctx_) {
+ sws_freeContext(video_alpha_scale_ctx_);
+ video_alpha_scale_ctx_ = nullptr;
+ }
+
+ if (video_noalpha_scale_ctx_) {
+ sws_freeContext(video_noalpha_scale_ctx_);
+ video_noalpha_scale_ctx_ = nullptr;
}
if (video_codec_ctx_) {
diff --git a/app/codec/ffmpeg/ffmpegencoder.h b/app/codec/ffmpeg/ffmpegencoder.h
index e42d8137a..6b28fb62f 100644
--- a/app/codec/ffmpeg/ffmpegencoder.h
+++ b/app/codec/ffmpeg/ffmpegencoder.h
@@ -47,7 +47,7 @@ public:
virtual void Close() override;
- virtual PixelFormat::Format GetDesiredPixelFormat() const override
+ virtual VideoParams::Format GetDesiredPixelFormat() const override
{
return video_conversion_fmt_;
}
@@ -85,8 +85,9 @@ private:
AVStream* video_stream_;
AVCodecContext* video_codec_ctx_;
- SwsContext* video_scale_ctx_;
- PixelFormat::Format video_conversion_fmt_;
+ SwsContext* video_alpha_scale_ctx_;
+ SwsContext* video_noalpha_scale_ctx_;
+ VideoParams::Format video_conversion_fmt_;
AVStream* audio_stream_;
AVCodecContext* audio_codec_ctx_;
diff --git a/app/codec/ffmpeg/ffmpegframepool.cpp b/app/codec/ffmpeg/ffmpegframepool.cpp
index ac114ba12..520f5d0ac 100644
--- a/app/codec/ffmpeg/ffmpegframepool.cpp
+++ b/app/codec/ffmpeg/ffmpegframepool.cpp
@@ -28,22 +28,24 @@ FFmpegFramePool::FFmpegFramePool(int element_count) :
MemoryPool(element_count),
width_(0),
height_(0),
- format_(PixelFormat::PIX_FMT_INVALID)
+ format_(VideoParams::kFormatInvalid),
+ channel_count_(0)
{
}
-void FFmpegFramePool::SetParameters(int width, int height, PixelFormat::Format format)
+void FFmpegFramePool::SetParameters(int width, int height, VideoParams::Format format, int channel_count)
{
Clear();
width_ = width;
height_ = height;
format_ = format;
+ channel_count_ = channel_count;
}
size_t FFmpegFramePool::GetElementSize()
{
- return Frame::generate_linesize_bytes(width_, format_) * height_;
+ return Frame::generate_linesize_bytes(width_, format_, channel_count_) * height_;
}
OLIVE_NAMESPACE_EXIT
diff --git a/app/codec/ffmpeg/ffmpegframepool.h b/app/codec/ffmpeg/ffmpegframepool.h
index 8a72bb61e..f97a948d0 100644
--- a/app/codec/ffmpeg/ffmpegframepool.h
+++ b/app/codec/ffmpeg/ffmpegframepool.h
@@ -22,7 +22,6 @@
#define FFMPEGFRAMEPOOL_H
#include "common/memorypool.h"
-#include "render/pixelformat.h"
#include "render/videoparams.h"
OLIVE_NAMESPACE_ENTER
@@ -32,7 +31,7 @@ class FFmpegFramePool : public MemoryPool
public:
FFmpegFramePool(int element_count);
- void SetParameters(int width, int height, PixelFormat::Format format);
+ void SetParameters(int width, int height, VideoParams::Format format, int channel_count);
const int& width() const
{
@@ -52,7 +51,9 @@ private:
int height_;
- PixelFormat::Format format_;
+ VideoParams::Format format_;
+
+ int channel_count_;
};
diff --git a/app/codec/frame.cpp b/app/codec/frame.cpp
index 9abdac922..7d474a1c5 100644
--- a/app/codec/frame.cpp
+++ b/app/codec/frame.cpp
@@ -20,10 +20,13 @@
#include "frame.h"
+#include
#include
#include
#include
+#include "common/oiioutils.h"
+
OLIVE_NAMESPACE_ENTER
Frame::Frame() :
@@ -45,14 +48,14 @@ void Frame::set_video_params(const VideoParams ¶ms)
{
params_ = params;
- linesize_ = generate_linesize_bytes(width(), params_.format());
- linesize_pixels_ = linesize_ / PixelFormat::BytesPerPixel(params_.format());
+ linesize_ = generate_linesize_bytes(width(), params_.format(), params_.channel_count());
+ linesize_pixels_ = linesize_ / params_.GetBytesPerPixel();
}
-int Frame::generate_linesize_bytes(int width, PixelFormat::Format format)
+int Frame::generate_linesize_bytes(int width, VideoParams::Format format, int channel_count)
{
// Align to 32 bytes (not sure if this is necessary?)
- return PixelFormat::BytesPerPixel(format) * ((width + 31) & ~31);
+ return VideoParams::GetBytesPerPixel(format, channel_count) * ((width + 31) & ~31);
}
Color Frame::get_pixel(int x, int y) const
@@ -61,9 +64,9 @@ Color Frame::get_pixel(int x, int y) const
return Color();
}
- int byte_offset = y * linesize_bytes() + x * PixelFormat::BytesPerPixel(video_params().format());
+ int byte_offset = y * linesize_bytes() + x * video_params().GetBytesPerPixel();
- return Color(data_.data() + byte_offset, video_params().format());
+ return Color(data_.data() + byte_offset, video_params().format(), video_params().channel_count());
}
bool Frame::contains_pixel(int x, int y) const
@@ -77,9 +80,9 @@ void Frame::set_pixel(int x, int y, const Color &c)
return;
}
- int byte_offset = y * linesize_bytes() + x * PixelFormat::BytesPerPixel(video_params().format());
+ int byte_offset = y * linesize_bytes() + x * video_params().GetBytesPerPixel();
- c.toData(data_.data() + byte_offset, video_params().format());
+ c.toData(data_.data() + byte_offset, video_params().format(), video_params().channel_count());
}
bool Frame::allocate()
@@ -90,9 +93,40 @@ bool Frame::allocate()
return false;
}
- data_.resize(PixelFormat::GetBufferSize(params_.format(), linesize_, height()));
+ data_.resize(VideoParams::GetBufferSize(linesize_, height(), params_.format(), params_.channel_count()));
return true;
}
+FramePtr Frame::convert(VideoParams::Format format) const
+{
+ // Create new params with destination format
+ VideoParams params = params_;
+ params.set_format(format);
+
+ // Create new frame
+ FramePtr converted = Frame::Create();
+ converted->set_video_params(params);
+ converted->set_timestamp(timestamp_);
+ converted->allocate();
+
+ // Do the conversion through OIIO for convenience
+ OIIO::ImageBuf src(OIIO::ImageSpec(width(), height(),
+ channel_count(),
+ OIIOUtils::GetOIIOBaseTypeFromFormat(this->format())));
+
+ OIIOUtils::FrameToBuffer(this, &src);
+
+ OIIO::ImageBuf dst(OIIO::ImageSpec(converted->width(), converted->height(),
+ channel_count(),
+ OIIOUtils::GetOIIOBaseTypeFromFormat(format)));
+
+ if (dst.copy_pixels(src)) {
+ OIIOUtils::BufferToFrame(&dst, converted.get());
+ return converted;
+ } else {
+ return nullptr;
+ }
+}
+
OLIVE_NAMESPACE_EXIT
diff --git a/app/codec/frame.h b/app/codec/frame.h
index 8c89902b9..29fbdaac1 100644
--- a/app/codec/frame.h
+++ b/app/codec/frame.h
@@ -26,7 +26,6 @@
#include "common/rational.h"
#include "render/color.h"
-#include "render/pixelformat.h"
#include "render/videoparams.h"
OLIVE_NAMESPACE_ENTER
@@ -47,7 +46,7 @@ public:
const VideoParams& video_params() const;
void set_video_params(const VideoParams& params);
- static int generate_linesize_bytes(int width, PixelFormat::Format format);
+ static int generate_linesize_bytes(int width, VideoParams::Format format, int channel_count);
int linesize_pixels() const
{
@@ -69,11 +68,16 @@ public:
return params_.effective_height();
}
- PixelFormat::Format format() const
+ VideoParams::Format format() const
{
return params_.format();
}
+ int channel_count() const
+ {
+ return params_.channel_count();
+ }
+
Color get_pixel(int x, int y) const;
bool contains_pixel(int x, int y) const;
void set_pixel(int x, int y, const Color& c);
@@ -144,6 +148,8 @@ public:
return data_.size();
}
+ FramePtr convert(VideoParams::Format format) const;
+
private:
VideoParams params_;
diff --git a/app/codec/oiio/CMakeLists.txt b/app/codec/oiio/CMakeLists.txt
index 4843b25b1..201fd3ee7 100644
--- a/app/codec/oiio/CMakeLists.txt
+++ b/app/codec/oiio/CMakeLists.txt
@@ -16,8 +16,6 @@
set(OLIVE_SOURCES
${OLIVE_SOURCES}
- codec/oiio/oiiocommon.cpp
- codec/oiio/oiiocommon.h
codec/oiio/oiiodecoder.cpp
codec/oiio/oiiodecoder.h
PARENT_SCOPE
diff --git a/app/codec/oiio/oiiocommon.h b/app/codec/oiio/oiiocommon.h
deleted file mode 100644
index aeccc2e0d..000000000
--- a/app/codec/oiio/oiiocommon.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/***
-
- Olive - Non-Linear Video Editor
- Copyright (C) 2019 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 .
-
-***/
-
-#ifndef OIIOCOMMON_H
-#define OIIOCOMMON_H
-
-#include
-#include
-
-#include "codec/frame.h"
-#include "render/pixelformat.h"
-
-OLIVE_NAMESPACE_ENTER
-
-class OIIOCommon
-{
-public:
- static void FrameToBuffer(FramePtr frame, OIIO::ImageBuf* buf);
-
- static void BufferToFrame(OIIO::ImageBuf* buf, FramePtr frame);
-
- static PixelFormat::Format GetFormatFromOIIOBasetype(const OIIO::ImageSpec& spec);
-
- static rational GetPixelAspectRatioFromOIIO(const OIIO::ImageSpec& spec);
-
-};
-
-OLIVE_NAMESPACE_EXIT
-
-#endif // OIIOCOMMON_H
diff --git a/app/codec/oiio/oiiodecoder.cpp b/app/codec/oiio/oiiodecoder.cpp
index 1728c04d2..392951240 100644
--- a/app/codec/oiio/oiiodecoder.cpp
+++ b/app/codec/oiio/oiiodecoder.cpp
@@ -27,9 +27,9 @@
#include
#include "common/define.h"
+#include "common/oiioutils.h"
#include "config/config.h"
#include "core.h"
-#include "oiiocommon.h"
OLIVE_NAMESPACE_ENTER
@@ -81,8 +81,9 @@ FootagePtr OIIODecoder::Probe(const QString& filename, const QAtomicInt* cancell
image_stream->set_width(in->spec().width);
image_stream->set_height(in->spec().height);
- image_stream->set_format(OIIOCommon::GetFormatFromOIIOBasetype(in->spec()));
- image_stream->set_pixel_aspect_ratio(OIIOCommon::GetPixelAspectRatioFromOIIO(in->spec()));
+ image_stream->set_format(OIIOUtils::GetFormatFromOIIOBasetype(static_cast(in->spec().format.basetype)));
+ image_stream->set_channel_count(in->spec().nchannels);
+ image_stream->set_pixel_aspect_ratio(OIIOUtils::GetPixelAspectRatioFromOIIO(in->spec()));
image_stream->set_video_type(VideoStream::kVideoTypeStill);
// Images will always have just one stream
@@ -149,14 +150,15 @@ FramePtr OIIODecoder::RetrieveVideoInternal(const rational &timecode, const int&
frame->set_video_params(VideoParams(buffer_->spec().width,
buffer_->spec().height,
pix_fmt_,
- OIIOCommon::GetPixelAspectRatioFromOIIO(buffer_->spec()),
+ channel_count_,
+ OIIOUtils::GetPixelAspectRatioFromOIIO(buffer_->spec()),
VideoParams::kInterlaceNone, // FIXME: Does OIIO deinterlace for us?
divider));
frame->allocate();
if (divider == 1) {
- OIIOCommon::BufferToFrame(buffer_, frame);
+ OIIOUtils::BufferToFrame(buffer_, frame.get());
} else {
@@ -167,7 +169,7 @@ FramePtr OIIODecoder::RetrieveVideoInternal(const rational &timecode, const int&
qWarning() << "OIIO resize failed";
}
- OIIOCommon::BufferToFrame(&dst, frame);
+ OIIOUtils::BufferToFrame(&dst, frame.get());
}
@@ -215,18 +217,23 @@ bool OIIODecoder::OpenImageHandler(const QString &fn)
// Check if we can work with this pixel format
const OIIO::ImageSpec& spec = image_->spec();
- //is_rgba_ = (spec.nchannels == kRGBAChannels);
+ // Store channel count
+ channel_count_ = spec.nchannels;
// We use RGBA frames because that tends to be the native format of GPUs
- pix_fmt_ = OIIOCommon::GetFormatFromOIIOBasetype(spec);
+ pix_fmt_ = OIIOUtils::GetFormatFromOIIOBasetype(static_cast(spec.format.basetype));
- if (pix_fmt_ == PixelFormat::PIX_FMT_INVALID) {
+ if (pix_fmt_ == VideoParams::kFormatInvalid) {
qWarning() << "Failed to convert OIIO::ImageDesc to native pixel format";
return false;
}
- // FIXME: Many OIIO pixel formats are not handled here
- OIIO::TypeDesc type = PixelFormat::GetOIIOTypeDesc(pix_fmt_);
+ OIIO::TypeDesc::BASETYPE type = OIIOUtils::GetOIIOBaseTypeFromFormat(pix_fmt_);
+
+ if (type == OIIO::TypeDesc::UNKNOWN) {
+ qCritical() << "Failed to determine appropriate OIIO basetype from native format";
+ return false;
+ }
#if OIIO_VERSION < 20100
buffer_ = new OIIO::ImageBuf(OIIO::ImageSpec(spec.width, spec.height, spec.nchannels, type));
diff --git a/app/codec/oiio/oiiodecoder.h b/app/codec/oiio/oiiodecoder.h
index 820057d3e..f4b7e96d9 100644
--- a/app/codec/oiio/oiiodecoder.h
+++ b/app/codec/oiio/oiiodecoder.h
@@ -25,7 +25,6 @@
#include
#include "codec/decoder.h"
-#include "render/pixelformat.h"
OLIVE_NAMESPACE_ENTER
@@ -63,9 +62,9 @@ private:
int64_t last_sequence_index_;
- PixelFormat::Format pix_fmt_;
+ VideoParams::Format pix_fmt_;
- //bool is_rgba_;
+ int channel_count_;
OIIO::ImageBuf* buffer_;
diff --git a/app/codec/waveinput.cpp b/app/codec/waveinput.cpp
index 275bea1f2..06fd5f2b6 100644
--- a/app/codec/waveinput.cpp
+++ b/app/codec/waveinput.cpp
@@ -108,27 +108,27 @@ bool WaveInput::open()
uint16_t bits_per_sample;
data_stream >> bits_per_sample;
- SampleFormat::Format format;
+ AudioParams::Format format;
switch (bits_per_sample) {
case 8:
- format = SampleFormat::SAMPLE_FMT_U8;
+ format = AudioParams::kFormatUnsigned8;
break;
case 16:
- format = SampleFormat::SAMPLE_FMT_S16;
+ format = AudioParams::kFormatSigned16;
break;
case 32:
if (data_is_float) {
- format = SampleFormat::SAMPLE_FMT_FLT;
+ format = AudioParams::kFormatFloat32;
} else {
- format = SampleFormat::SAMPLE_FMT_S32;
+ format = AudioParams::kFormatSigned32;
}
break;
case 64:
if (data_is_float) {
- format = SampleFormat::SAMPLE_FMT_DBL;
+ format = AudioParams::kFormatFloat64;
} else {
- format = SampleFormat::SAMPLE_FMT_S64;
+ format = AudioParams::kFormatSigned64;
}
break;
default:
diff --git a/app/codec/waveoutput.cpp b/app/codec/waveoutput.cpp
index 844b3ad8f..648b8c4a8 100644
--- a/app/codec/waveoutput.cpp
+++ b/app/codec/waveoutput.cpp
@@ -20,6 +20,8 @@
#include "waveoutput.h"
+#include "render/audioparams.h"
+
OLIVE_NAMESPACE_ENTER
const int16_t kWAVIntegerFormat = 1;
@@ -60,18 +62,18 @@ bool WaveOutput::open()
// Type of format
switch (params_.format()) {
- case SampleFormat::SAMPLE_FMT_U8:
- case SampleFormat::SAMPLE_FMT_S16:
- case SampleFormat::SAMPLE_FMT_S32:
- case SampleFormat::SAMPLE_FMT_S64:
+ case AudioParams::kFormatUnsigned8:
+ case AudioParams::kFormatSigned16:
+ case AudioParams::kFormatSigned32:
+ case AudioParams::kFormatSigned64:
write_int(&file_, kWAVIntegerFormat);
break;
- case SampleFormat::SAMPLE_FMT_FLT:
- case SampleFormat::SAMPLE_FMT_DBL:
+ case AudioParams::kFormatFloat32:
+ case AudioParams::kFormatFloat64:
write_int(&file_, kWAVFloatFormat);
break;
- case SampleFormat::SAMPLE_FMT_INVALID:
- case SampleFormat::SAMPLE_FMT_COUNT:
+ case AudioParams::kFormatInvalid:
+ case AudioParams::kFormatCount:
qWarning() << "Invalid sample format for WAVE audio";
file_.close();
return false;
diff --git a/app/codec/waveoutput.h b/app/codec/waveoutput.h
index a42f103e0..450fe38bc 100644
--- a/app/codec/waveoutput.h
+++ b/app/codec/waveoutput.h
@@ -24,7 +24,6 @@
#include
#include
-#include "audio/sampleformat.h"
#include "render/audioparams.h"
OLIVE_NAMESPACE_ENTER
diff --git a/app/common/CMakeLists.txt b/app/common/CMakeLists.txt
index 553af7017..06963187b 100644
--- a/app/common/CMakeLists.txt
+++ b/app/common/CMakeLists.txt
@@ -16,44 +16,49 @@
set(OLIVE_SOURCES
${OLIVE_SOURCES}
- common/bezier.h
common/bezier.cpp
+ common/bezier.h
common/cancelableobject.h
common/channellayout.h
common/clamp.h
- common/commandlineparser.h
common/commandlineparser.cpp
- common/crashpadinterface.h
+ common/commandlineparser.h
common/crashpadinterface.cpp
+ common/crashpadinterface.h
common/crashpadutils.h
- common/debug.h
common/debug.cpp
+ common/debug.h
common/define.h
- common/filefunctions.h
+ common/ffmpegutils.cpp
+ common/ffmpegutils.h
common/filefunctions.cpp
- common/flipmodifiers.h
+ common/filefunctions.h
common/flipmodifiers.cpp
+ common/flipmodifiers.h
common/functiontimer.h
common/lerp.h
- common/memorypool.h
common/memorypool.cpp
+ common/memorypool.h
+ common/ocioutils.cpp
common/ocioutils.h
- common/qtutils.h
+ common/oiioutils.cpp
+ common/oiioutils.h
common/qtutils.cpp
+ common/qtutils.h
common/range.h
- common/ratiodialog.h
common/ratiodialog.cpp
+ common/ratiodialog.h
common/rational.h
common/rational.cpp
common/threadsafemap.h
- common/threadedobject.h
common/threadedobject.cpp
- common/timecodefunctions.h
+ common/threadedobject.h
common/timecodefunctions.cpp
- common/timerange.h
+ common/timecodefunctions.h
common/timerange.cpp
+ common/timerange.h
common/tohex.h
- common/xmlutils.h
common/xmlutils.cpp
+ common/xmlutils.h
PARENT_SCOPE
)
diff --git a/app/common/define.h b/app/common/define.h
index aa968fcf7..0a29394a0 100644
--- a/app/common/define.h
+++ b/app/common/define.h
@@ -29,10 +29,6 @@
OLIVE_NAMESPACE_ENTER
-const int kHSVChannels = 3;
-const int kRGBChannels = 3;
-const int kRGBAChannels = 4;
-
/// The minimum size an icon in ProjectExplorer can be
const int kProjectIconSizeMinimum = 16;
diff --git a/app/common/ffmpegutils.cpp b/app/common/ffmpegutils.cpp
new file mode 100644
index 000000000..9453bd851
--- /dev/null
+++ b/app/common/ffmpegutils.cpp
@@ -0,0 +1,141 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2019 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 .
+
+***/
+
+#include "common/ffmpegutils.h"
+
+OLIVE_NAMESPACE_ENTER
+
+AVPixelFormat FFmpegUtils::GetCompatiblePixelFormat(const AVPixelFormat &pix_fmt)
+{
+ AVPixelFormat possible_pix_fmts[] = {
+ AV_PIX_FMT_RGB24,
+ AV_PIX_FMT_RGBA,
+ AV_PIX_FMT_RGB48,
+ AV_PIX_FMT_RGBA64,
+ AV_PIX_FMT_NONE
+ };
+
+ return avcodec_find_best_pix_fmt_of_list(possible_pix_fmts,
+ pix_fmt,
+ 1,
+ nullptr);
+}
+
+AudioParams::Format FFmpegUtils::GetNativeSampleFormat(const AVSampleFormat &smp_fmt)
+{
+ switch (smp_fmt) {
+ case AV_SAMPLE_FMT_U8:
+ return AudioParams::kFormatUnsigned8;
+ case AV_SAMPLE_FMT_S16:
+ return AudioParams::kFormatSigned16;
+ case AV_SAMPLE_FMT_S32:
+ return AudioParams::kFormatSigned32;
+ case AV_SAMPLE_FMT_S64:
+ return AudioParams::kFormatSigned64;
+ case AV_SAMPLE_FMT_FLT:
+ return AudioParams::kFormatFloat32;
+ case AV_SAMPLE_FMT_DBL:
+ return AudioParams::kFormatFloat64;
+ case AV_SAMPLE_FMT_U8P :
+ case AV_SAMPLE_FMT_S16P:
+ case AV_SAMPLE_FMT_S32P:
+ case AV_SAMPLE_FMT_S64P:
+ case AV_SAMPLE_FMT_FLTP:
+ case AV_SAMPLE_FMT_DBLP:
+ case AV_SAMPLE_FMT_NONE:
+ case AV_SAMPLE_FMT_NB:
+ break;
+ }
+
+ return AudioParams::kFormatInvalid;
+}
+
+AVSampleFormat FFmpegUtils::GetFFmpegSampleFormat(const AudioParams::Format &smp_fmt)
+{
+ switch (smp_fmt) {
+ case AudioParams::kFormatUnsigned8:
+ return AV_SAMPLE_FMT_U8;
+ case AudioParams::kFormatSigned16:
+ return AV_SAMPLE_FMT_S16;
+ case AudioParams::kFormatSigned32:
+ return AV_SAMPLE_FMT_S32;
+ case AudioParams::kFormatSigned64:
+ return AV_SAMPLE_FMT_S64;
+ case AudioParams::kFormatFloat32:
+ return AV_SAMPLE_FMT_FLT;
+ case AudioParams::kFormatFloat64:
+ return AV_SAMPLE_FMT_DBL;
+ case AudioParams::kFormatInvalid:
+ case AudioParams::kFormatCount:
+ break;
+ }
+
+ return AV_SAMPLE_FMT_NONE;
+}
+
+AVPixelFormat FFmpegUtils::GetFFmpegPixelFormat(const VideoParams::Format &pix_fmt, int channel_layout)
+{
+ if (channel_layout == VideoParams::kRGBChannelCount) {
+ switch (pix_fmt) {
+ case VideoParams::kFormatUnsigned8:
+ return AV_PIX_FMT_RGB24;
+ case VideoParams::kFormatUnsigned16:
+ return AV_PIX_FMT_RGB48;
+ case VideoParams::kFormatFloat16:
+ case VideoParams::kFormatFloat32:
+ case VideoParams::kFormatInvalid:
+ case VideoParams::kFormatCount:
+ break;
+ }
+ } else if (channel_layout == VideoParams::kRGBAChannelCount) {
+ switch (pix_fmt) {
+ case VideoParams::kFormatUnsigned8:
+ return AV_PIX_FMT_RGBA;
+ case VideoParams::kFormatUnsigned16:
+ return AV_PIX_FMT_RGBA64;
+ case VideoParams::kFormatFloat16:
+ case VideoParams::kFormatFloat32:
+ case VideoParams::kFormatInvalid:
+ case VideoParams::kFormatCount:
+ break;
+ }
+ }
+
+ return AV_PIX_FMT_NONE;
+}
+
+VideoParams::Format FFmpegUtils::GetCompatiblePixelFormat(const VideoParams::Format &pix_fmt)
+{
+ switch (pix_fmt) {
+ case VideoParams::kFormatUnsigned8:
+ return VideoParams::kFormatUnsigned8;
+ case VideoParams::kFormatUnsigned16:
+ case VideoParams::kFormatFloat16:
+ case VideoParams::kFormatFloat32:
+ return VideoParams::kFormatUnsigned16;
+ case VideoParams::kFormatInvalid:
+ case VideoParams::kFormatCount:
+ break;
+ }
+
+ return VideoParams::kFormatInvalid;
+}
+
+OLIVE_NAMESPACE_EXIT
diff --git a/app/codec/ffmpeg/ffmpegcommon.h b/app/common/ffmpegutils.h
similarity index 77%
rename from app/codec/ffmpeg/ffmpegcommon.h
rename to app/common/ffmpegutils.h
index 106452fad..6e9fb002a 100644
--- a/app/codec/ffmpeg/ffmpegcommon.h
+++ b/app/common/ffmpegutils.h
@@ -25,12 +25,12 @@ extern "C" {
#include
}
-#include "audio/sampleformat.h"
-#include "render/pixelformat.h"
+#include "render/audioparams.h"
+#include "render/videoparams.h"
OLIVE_NAMESPACE_ENTER
-class FFmpegCommon {
+class FFmpegUtils {
public:
/**
* @brief Returns an AVPixelFormat that can be used to convert a frame to a data type Olive supports with minimal data loss
@@ -40,22 +40,22 @@ public:
/**
* @brief Returns a native pixel format that can be used to convert from a native frame to an AVFrame with minimal data loss
*/
- static PixelFormat::Format GetCompatiblePixelFormat(const PixelFormat::Format& pix_fmt);
+ static VideoParams::Format GetCompatiblePixelFormat(const VideoParams::Format& pix_fmt);
/**
* @brief Returns an FFmpeg pixel format for a given native pixel format
*/
- static AVPixelFormat GetFFmpegPixelFormat(const PixelFormat::Format& pix_fmt);
+ static AVPixelFormat GetFFmpegPixelFormat(const VideoParams::Format& pix_fmt, int channel_layout);
/**
* @brief Returns a native sample format type for a given AVSampleFormat
*/
- static SampleFormat::Format GetNativeSampleFormat(const AVSampleFormat& smp_fmt);
+ static AudioParams::Format GetNativeSampleFormat(const AVSampleFormat& smp_fmt);
/**
* @brief Returns an FFmpeg sample format type for a given native type
*/
- static AVSampleFormat GetFFmpegSampleFormat(const SampleFormat::Format &smp_fmt);
+ static AVSampleFormat GetFFmpegSampleFormat(const AudioParams::Format &smp_fmt);
};
OLIVE_NAMESPACE_EXIT
diff --git a/app/audio/sampleformat.h b/app/common/ocioutils.cpp
similarity index 57%
rename from app/audio/sampleformat.h
rename to app/common/ocioutils.cpp
index 1261d04a1..c5f182450 100644
--- a/app/audio/sampleformat.h
+++ b/app/common/ocioutils.cpp
@@ -18,39 +18,30 @@
***/
-#ifndef SAMPLEFORMAT_H
-#define SAMPLEFORMAT_H
-
-#include
-
-#include "common/define.h"
+#include "ocioutils.h"
OLIVE_NAMESPACE_ENTER
-class SampleFormat
+OCIO::BitDepth OCIOUtils::GetOCIOBitDepthFromPixelFormat(VideoParams::Format format)
{
-public:
- SampleFormat() = default;
+ switch (format) {
+ case VideoParams::kFormatUnsigned8:
+ return OCIO::BIT_DEPTH_UINT8;
+ case VideoParams::kFormatUnsigned16:
+ return OCIO::BIT_DEPTH_UINT16;
+ break;
+ case VideoParams::kFormatFloat16:
+ return OCIO::BIT_DEPTH_F16;
+ break;
+ case VideoParams::kFormatFloat32:
+ return OCIO::BIT_DEPTH_F32;
+ break;
+ case VideoParams::kFormatInvalid:
+ case VideoParams::kFormatCount:
+ break;
+ }
- enum Format {
- SAMPLE_FMT_INVALID = -1,
-
- SAMPLE_FMT_U8,
- SAMPLE_FMT_S16,
- SAMPLE_FMT_S32,
- SAMPLE_FMT_S64,
- SAMPLE_FMT_FLT,
- SAMPLE_FMT_DBL,
-
- SAMPLE_FMT_COUNT
- };
-
- static const Format kInternalFormat;
-
- static QString GetSampleFormatName(const Format& f);
-
-};
+ return OCIO::BIT_DEPTH_UNKNOWN;
+}
OLIVE_NAMESPACE_EXIT
-
-#endif // SAMPLEFORMAT_H
diff --git a/app/common/ocioutils.h b/app/common/ocioutils.h
index a290a1e50..edbaa9fef 100644
--- a/app/common/ocioutils.h
+++ b/app/common/ocioutils.h
@@ -24,4 +24,16 @@
#include
namespace OCIO = OpenColorIO_v2_0dev;
+#include "render/videoparams.h"
+
+OLIVE_NAMESPACE_ENTER
+
+class OCIOUtils
+{
+public:
+ static OCIO::BitDepth GetOCIOBitDepthFromPixelFormat(VideoParams::Format format);
+};
+
+OLIVE_NAMESPACE_EXIT
+
#endif // OCIOUTILS_H
diff --git a/app/codec/oiio/oiiocommon.cpp b/app/common/oiioutils.cpp
similarity index 68%
rename from app/codec/oiio/oiiocommon.cpp
rename to app/common/oiioutils.cpp
index f51f82aa2..8381ba904 100644
--- a/app/codec/oiio/oiiocommon.cpp
+++ b/app/common/oiioutils.cpp
@@ -18,11 +18,11 @@
***/
-#include "oiiocommon.h"
+#include "oiioutils.h"
OLIVE_NAMESPACE_ENTER
-void OIIOCommon::FrameToBuffer(FramePtr frame, OIIO::ImageBuf *buf)
+void OIIOUtils::FrameToBuffer(const Frame* frame, OIIO::ImageBuf *buf)
{
#if OIIO_VERSION < 20112
//
@@ -45,13 +45,13 @@ void OIIOCommon::FrameToBuffer(FramePtr frame, OIIO::ImageBuf *buf)
#else
buf->set_pixels(OIIO::ROI(),
buf->spec().format,
- frame->data(),
+ frame->const_data(),
OIIO::AutoStride,
frame->linesize_bytes());
#endif
}
-void OIIOCommon::BufferToFrame(OIIO::ImageBuf *buf, FramePtr frame)
+void OIIOUtils::BufferToFrame(OIIO::ImageBuf *buf, Frame* frame)
{
#if OIIO_VERSION < 20112
//
@@ -79,24 +79,42 @@ void OIIOCommon::BufferToFrame(OIIO::ImageBuf *buf, FramePtr frame)
#endif
}
-PixelFormat::Format OIIOCommon::GetFormatFromOIIOBasetype(const OIIO::ImageSpec& spec)
-{
- if (spec.format == OIIO::TypeDesc::UINT8) {
- return PixelFormat::PIX_FMT_RGBA8;
- } else if (spec.format == OIIO::TypeDesc::UINT16) {
- return PixelFormat::PIX_FMT_RGBA16U;
- } else if (spec.format == OIIO::TypeDesc::HALF) {
- return PixelFormat::PIX_FMT_RGBA16F;
- } else if (spec.format == OIIO::TypeDesc::FLOAT) {
- return PixelFormat::PIX_FMT_RGBA32F;
- } else {
- return PixelFormat::PIX_FMT_INVALID;
- }
-}
-
-rational OIIOCommon::GetPixelAspectRatioFromOIIO(const OIIO::ImageSpec &spec)
+rational OIIOUtils::GetPixelAspectRatioFromOIIO(const OIIO::ImageSpec &spec)
{
return rational::fromDouble(spec.get_float_attribute("PixelAspectRatio", 1));
}
+VideoParams::Format OIIOUtils::GetFormatFromOIIOBasetype(OIIO::TypeDesc::BASETYPE type)
+{
+ switch (type) {
+ case OIIO::TypeDesc::UNKNOWN:
+ case OIIO::TypeDesc::NONE:
+ break;
+
+ case OIIO::TypeDesc::INT8:
+ case OIIO::TypeDesc::INT16:
+ case OIIO::TypeDesc::INT32:
+ case OIIO::TypeDesc::UINT32:
+ case OIIO::TypeDesc::INT64:
+ case OIIO::TypeDesc::UINT64:
+ case OIIO::TypeDesc::STRING:
+ case OIIO::TypeDesc::PTR:
+ case OIIO::TypeDesc::LASTBASE:
+ case OIIO::TypeDesc::DOUBLE:
+ qDebug() << "Tried to use unknown OIIO base type";
+ break;
+
+ case OIIO::TypeDesc::UINT8:
+ return VideoParams::kFormatUnsigned8;
+ case OIIO::TypeDesc::UINT16:
+ return VideoParams::kFormatUnsigned16;
+ case OIIO::TypeDesc::HALF:
+ return VideoParams::kFormatFloat16;
+ case OIIO::TypeDesc::FLOAT:
+ return VideoParams::kFormatFloat32;
+ }
+
+ return VideoParams::kFormatInvalid;
+}
+
OLIVE_NAMESPACE_EXIT
diff --git a/app/common/oiioutils.h b/app/common/oiioutils.h
new file mode 100644
index 000000000..a9dca5baa
--- /dev/null
+++ b/app/common/oiioutils.h
@@ -0,0 +1,65 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2019 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 .
+
+***/
+
+#ifndef OIIOUTILS_H
+#define OIIOUTILS_H
+
+#include
+#include
+
+#include "codec/frame.h"
+#include "render/videoparams.h"
+
+OLIVE_NAMESPACE_ENTER
+
+class OIIOUtils {
+public:
+ static OIIO::TypeDesc::BASETYPE GetOIIOBaseTypeFromFormat(VideoParams::Format format)
+ {
+ switch (format) {
+ case VideoParams::kFormatUnsigned8:
+ return OIIO::TypeDesc::UINT8;
+ case VideoParams::kFormatUnsigned16:
+ return OIIO::TypeDesc::UINT16;
+ case VideoParams::kFormatFloat16:
+ return OIIO::TypeDesc::HALF;
+ case VideoParams::kFormatFloat32:
+ return OIIO::TypeDesc::FLOAT;
+ case VideoParams::kFormatInvalid:
+ case VideoParams::kFormatCount:
+ break;
+ }
+
+ return OIIO::TypeDesc::UNKNOWN;
+ }
+
+ static void FrameToBuffer(const Frame *frame, OIIO::ImageBuf* buf);
+
+ static void BufferToFrame(OIIO::ImageBuf* buf, Frame* frame);
+
+ static VideoParams::Format GetFormatFromOIIOBasetype(OIIO::TypeDesc::BASETYPE type);
+
+ static rational GetPixelAspectRatioFromOIIO(const OIIO::ImageSpec& spec);
+
+};
+
+OLIVE_NAMESPACE_EXIT
+
+#endif // OIIOUTILS_H
diff --git a/app/config/config.cpp b/app/config/config.cpp
index 2feb40578..3c818f084 100644
--- a/app/config/config.cpp
+++ b/app/config/config.cpp
@@ -116,11 +116,10 @@ void Config::SetDefaults()
SetEntryInternal(QStringLiteral("DefaultSequenceInterlacing"), NodeParam::kInt, VideoParams::kInterlaceNone);
SetEntryInternal(QStringLiteral("DefaultSequenceAudioFrequency"), NodeParam::kInt, 48000);
SetEntryInternal(QStringLiteral("DefaultSequenceAudioLayout"), NodeParam::kInt, QVariant::fromValue(static_cast(AV_CH_LAYOUT_STEREO)));
- SetEntryInternal(QStringLiteral("DefaultSequencePreviewFormat"), NodeParam::kInt, PixelFormat::PIX_FMT_RGBA16F);
// Online/offline settings
- SetEntryInternal(QStringLiteral("OnlinePixelFormat"), NodeParam::kInt, PixelFormat::PIX_FMT_RGBA32F);
- SetEntryInternal(QStringLiteral("OfflinePixelFormat"), NodeParam::kInt, PixelFormat::PIX_FMT_RGBA16F);
+ SetEntryInternal(QStringLiteral("OnlinePixelFormat"), NodeParam::kInt, VideoParams::kFormatFloat32);
+ SetEntryInternal(QStringLiteral("OfflinePixelFormat"), NodeParam::kInt, VideoParams::kFormatFloat16);
}
void Config::Load()
diff --git a/app/core.cpp b/app/core.cpp
index b60591b88..5a7f179bf 100644
--- a/app/core.cpp
+++ b/app/core.cpp
@@ -51,7 +51,6 @@
#include "panel/viewer/viewer.h"
#include "render/colormanager.h"
#include "render/diskmanager.h"
-#include "render/pixelformat.h"
#include "render/rendermanager.h"
#ifdef USE_OTIO
#include "task/project/loadotio/loadotio.h"
@@ -189,8 +188,6 @@ void Core::Stop()
DiskManager::DestroyInstance();
- PixelFormat::DestroyInstance();
-
NodeFactory::Destroy();
delete main_window_;
@@ -646,9 +643,6 @@ void Core::StartGUI(bool full_screen)
// Initialize disk service
DiskManager::CreateInstance();
- // Initialize pixel service
- PixelFormat::CreateInstance();
-
// Connect the PanelFocusManager to the application's focus change signal
connect(qApp,
&QApplication::focusChanged,
diff --git a/app/dialog/export/export.cpp b/app/dialog/export/export.cpp
index c14aff1f3..ccc3df207 100644
--- a/app/dialog/export/export.cpp
+++ b/app/dialog/export/export.cpp
@@ -34,7 +34,6 @@
#include "dialog/task/task.h"
#include "project/item/sequence/sequence.h"
#include "project/project.h"
-#include "render/pixelformat.h"
#include "ui/icons/icons.h"
OLIVE_NAMESPACE_ENTER
@@ -179,7 +178,7 @@ ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) :
video_tab_->height_slider()->SetDefaultValue(viewer_node_->video_params().height());
video_tab_->frame_rate_combobox()->SetFrameRate(viewer_node_->video_params().time_base().flipped());
video_tab_->pixel_aspect_combobox()->SetPixelAspectRatio(viewer_node_->video_params().pixel_aspect_ratio());
- video_tab_->pixel_format_field()->SetPixelFormat(PixelFormat::instance()->GetConfiguredFormatForMode(RenderMode::kOnline));
+ video_tab_->pixel_format_field()->SetPixelFormat(static_cast(Config::Current()["OnlinePixelFormat"].toInt()));
video_tab_->interlaced_combobox()->SetInterlaceMode(viewer_node_->video_params().interlacing());
audio_tab_->sample_rate_combobox()->SetSampleRate(viewer_node_->audio_params().sample_rate());
audio_tab_->channel_layout_combobox()->SetChannelLayout(viewer_node_->audio_params().channel_layout());
@@ -432,13 +431,14 @@ ExportParams ExportDialog::GenerateParams() const
static_cast(video_tab_->height_slider()->GetValue()),
video_tab_->frame_rate_combobox()->GetFrameRate().flipped(),
video_tab_->pixel_format_field()->GetPixelFormat(),
+ VideoParams::kInternalChannelCount,
video_tab_->pixel_aspect_combobox()->GetPixelAspectRatio(),
video_tab_->interlaced_combobox()->GetInterlaceMode(),
1);
AudioParams audio_render_params(audio_tab_->sample_rate_combobox()->currentData().toInt(),
audio_tab_->channel_layout_combobox()->GetChannelLayout(),
- SampleFormat::kInternalFormat);
+ AudioParams::kInternalFormat);
ExportParams params;
params.SetFilename(filename_edit_->text());
diff --git a/app/dialog/sequence/sequence.cpp b/app/dialog/sequence/sequence.cpp
index 3006c2b73..0df85621e 100644
--- a/app/dialog/sequence/sequence.cpp
+++ b/app/dialog/sequence/sequence.cpp
@@ -107,13 +107,14 @@ void SequenceDialog::accept()
parameter_tab_->GetSelectedVideoHeight(),
parameter_tab_->GetSelectedVideoFrameRate().flipped(),
parameter_tab_->GetSelectedPreviewFormat(),
+ VideoParams::kInternalChannelCount,
parameter_tab_->GetSelectedVideoPixelAspect(),
parameter_tab_->GetSelectedVideoInterlacingMode(),
parameter_tab_->GetSelectedPreviewResolution());
AudioParams audio_params = AudioParams(parameter_tab_->GetSelectedAudioSampleRate(),
parameter_tab_->GetSelectedAudioChannelLayout(),
- SampleFormat::kInternalFormat);
+ AudioParams::kInternalFormat);
if (make_undoable_) {
diff --git a/app/dialog/sequence/sequencedialogparametertab.cpp b/app/dialog/sequence/sequencedialogparametertab.cpp
index cd744eefc..326df8b11 100644
--- a/app/dialog/sequence/sequencedialogparametertab.cpp
+++ b/app/dialog/sequence/sequencedialogparametertab.cpp
@@ -133,7 +133,8 @@ void SequenceDialogParameterTab::UpdatePreviewResolutionLabel()
{
VideoParams test_param(video_width_field_->GetValue(),
video_height_field_->GetValue(),
- PixelFormat::PIX_FMT_INVALID,
+ VideoParams::kFormatInvalid,
+ VideoParams::kInternalChannelCount,
rational(1),
VideoParams::kInterlaceNone,
preview_resolution_field_->currentData().toInt());
diff --git a/app/dialog/sequence/sequencedialogparametertab.h b/app/dialog/sequence/sequencedialogparametertab.h
index 794abe505..d2dabdea1 100644
--- a/app/dialog/sequence/sequencedialogparametertab.h
+++ b/app/dialog/sequence/sequencedialogparametertab.h
@@ -58,7 +58,7 @@ public:
return preview_resolution_field_->GetDivider();
}
- PixelFormat::Format GetSelectedPreviewFormat() const
+ VideoParams::Format GetSelectedPreviewFormat() const
{
return preview_format_field_->GetPixelFormat();
}
diff --git a/app/dialog/sequence/sequencedialogpresettab.cpp b/app/dialog/sequence/sequencedialogpresettab.cpp
index 18c9419db..1f25a29fb 100644
--- a/app/dialog/sequence/sequencedialogpresettab.cpp
+++ b/app/dialog/sequence/sequencedialogpresettab.cpp
@@ -30,6 +30,7 @@
#include
#include "common/filefunctions.h"
+#include "config/config.h"
#include "node/input.h"
#include "render/videoparams.h"
#include "ui/icons/icons.h"
@@ -41,8 +42,6 @@ const int kDataIsPreset = Qt::UserRole;
const int kDataPresetIsCustomRole = Qt::UserRole + 1;
const int kDataPresetDataRole = Qt::UserRole + 2;
-const PixelFormat::Format kDefaultPreviewFormat = PixelFormat::PIX_FMT_RGBA16F;
-
SequenceDialogPresetTab::SequenceDialogPresetTab(QWidget* parent) :
QWidget(parent),
PresetManager(this, QStringLiteral("sequencepresets"))
@@ -100,6 +99,7 @@ QTreeWidgetItem* SequenceDialogPresetTab::CreateFolder(const QString &name)
QTreeWidgetItem *SequenceDialogPresetTab::CreateHDPresetFolder(const QString &name, int width, int height, int divider)
{
+ VideoParams::Format default_format = static_cast(Config::Current()["OfflinePixelFormat"].toInt());
QTreeWidgetItem* parent = CreateFolder(name);
AddStandardItem(parent, SequencePreset::Create(tr("%1 23.976 FPS").arg(name),
width,
@@ -110,7 +110,7 @@ QTreeWidgetItem *SequenceDialogPresetTab::CreateHDPresetFolder(const QString &na
48000,
AV_CH_LAYOUT_STEREO,
divider,
- kDefaultPreviewFormat));
+ default_format));
AddStandardItem(parent, SequencePreset::Create(tr("%1 25 FPS").arg(name),
width,
height,
@@ -120,7 +120,7 @@ QTreeWidgetItem *SequenceDialogPresetTab::CreateHDPresetFolder(const QString &na
48000,
AV_CH_LAYOUT_STEREO,
divider,
- kDefaultPreviewFormat));
+ default_format));
AddStandardItem(parent, SequencePreset::Create(tr("%1 29.97 FPS").arg(name),
width,
height,
@@ -130,7 +130,7 @@ QTreeWidgetItem *SequenceDialogPresetTab::CreateHDPresetFolder(const QString &na
48000,
AV_CH_LAYOUT_STEREO,
divider,
- kDefaultPreviewFormat));
+ default_format));
AddStandardItem(parent, SequencePreset::Create(tr("%1 50 FPS").arg(name),
width,
height,
@@ -140,7 +140,7 @@ QTreeWidgetItem *SequenceDialogPresetTab::CreateHDPresetFolder(const QString &na
48000,
AV_CH_LAYOUT_STEREO,
divider,
- kDefaultPreviewFormat));
+ default_format));
AddStandardItem(parent, SequencePreset::Create(tr("%1 59.94 FPS").arg(name),
width,
height,
@@ -150,12 +150,13 @@ QTreeWidgetItem *SequenceDialogPresetTab::CreateHDPresetFolder(const QString &na
48000,
AV_CH_LAYOUT_STEREO,
divider,
- kDefaultPreviewFormat));
+ default_format));
return parent;
}
QTreeWidgetItem *SequenceDialogPresetTab::CreateSDPresetFolder(const QString &name, int width, int height, const rational& frame_rate, const rational &standard_par, const rational &wide_par, int divider)
{
+ VideoParams::Format default_format = static_cast(Config::Current()["OfflinePixelFormat"].toInt());
QTreeWidgetItem* parent = CreateFolder(name);
preset_tree_->addTopLevelItem(parent);
AddStandardItem(parent, SequencePreset::Create(tr("%1 Standard").arg(name),
@@ -167,7 +168,7 @@ QTreeWidgetItem *SequenceDialogPresetTab::CreateSDPresetFolder(const QString &na
48000,
AV_CH_LAYOUT_STEREO,
divider,
- kDefaultPreviewFormat));
+ default_format));
AddStandardItem(parent, SequencePreset::Create(tr("%1 Widescreen").arg(name),
width,
height,
@@ -177,7 +178,7 @@ QTreeWidgetItem *SequenceDialogPresetTab::CreateSDPresetFolder(const QString &na
48000,
AV_CH_LAYOUT_STEREO,
divider,
- kDefaultPreviewFormat));
+ default_format));
return parent;
}
diff --git a/app/dialog/sequence/sequencepreset.h b/app/dialog/sequence/sequencepreset.h
index 6b134b8f1..59db546fd 100644
--- a/app/dialog/sequence/sequencepreset.h
+++ b/app/dialog/sequence/sequencepreset.h
@@ -26,7 +26,6 @@
#include "common/rational.h"
#include "common/xmlutils.h"
#include "dialog/sequence/presetmanager.h"
-#include "render/pixelformat.h"
#include "render/videoparams.h"
OLIVE_NAMESPACE_ENTER
@@ -44,7 +43,7 @@ public:
int sample_rate,
uint64_t channel_layout,
int preview_divider,
- PixelFormat::Format preview_format) :
+ VideoParams::Format preview_format) :
width_(width),
height_(height),
frame_rate_(frame_rate),
@@ -67,7 +66,7 @@ public:
int sample_rate,
uint64_t channel_layout,
int preview_divider,
- PixelFormat::Format preview_format)
+ VideoParams::Format preview_format)
{
return std::make_shared(name, width, height, frame_rate, pixel_aspect,
interlacing, sample_rate, channel_layout,
@@ -96,7 +95,7 @@ public:
} else if (reader->name() == QStringLiteral("divider")) {
preview_divider_ = reader->readElementText().toInt();
} else if (reader->name() == QStringLiteral("format")) {
- preview_format_ = static_cast(reader->readElementText().toInt());
+ preview_format_ = static_cast(reader->readElementText().toInt());
} else {
reader->skipCurrentElement();
}
@@ -157,7 +156,7 @@ public:
return preview_divider_;
}
- PixelFormat::Format preview_format() const
+ VideoParams::Format preview_format() const
{
return preview_format_;
}
@@ -171,7 +170,7 @@ private:
int sample_rate_;
uint64_t channel_layout_;
int preview_divider_;
- PixelFormat::Format preview_format_;
+ VideoParams::Format preview_format_;
};
diff --git a/app/node/input/media/video/video.cpp b/app/node/input/media/video/video.cpp
index c02aeaf39..5507bc12c 100644
--- a/app/node/input/media/video/video.cpp
+++ b/app/node/input/media/video/video.cpp
@@ -27,7 +27,6 @@
#include "codec/ffmpeg/ffmpegdecoder.h"
#include "core.h"
#include "project/item/footage/footage.h"
-#include "render/pixelformat.h"
OLIVE_NAMESPACE_ENTER
@@ -38,7 +37,7 @@ Node *VideoInput::copy() const
Stream::Type VideoInput::type() const
{
- return Stream::kVideo;
+ return Stream::kVideo;
}
QString VideoInput::Name() const
diff --git a/app/project/item/footage/videostream.cpp b/app/project/item/footage/videostream.cpp
index d96f319c7..9a0094e4f 100644
--- a/app/project/item/footage/videostream.cpp
+++ b/app/project/item/footage/videostream.cpp
@@ -104,7 +104,9 @@ void VideoStream::LoadCustomParameters(QXmlStreamReader *reader)
} else if (reader->name() == QStringLiteral("type")) {
set_video_type(static_cast(reader->readElementText().toInt()));
} else if (reader->name() == QStringLiteral("format")) {
- set_format(static_cast(reader->readElementText().toInt()));
+ set_format(static_cast(reader->readElementText().toInt()));
+ } else if (reader->name() == QStringLiteral("channels")) {
+ set_channel_count(reader->readElementText().toInt());
} else if (reader->name() == QStringLiteral("pixelaspect")) {
set_pixel_aspect_ratio(rational::fromString(reader->readElementText()));
} else if (reader->name() == QStringLiteral("framerate")) {
@@ -126,6 +128,7 @@ void VideoStream::SaveCustomParameters(QXmlStreamWriter *writer) const
writer->writeTextElement(QStringLiteral("interlacing"), QString::number(interlacing_));
writer->writeTextElement(QStringLiteral("type"), QString::number(video_type_));
writer->writeTextElement(QStringLiteral("format"), QString::number(format_));
+ writer->writeTextElement(QStringLiteral("channels"), QString::number(channel_count_));
writer->writeTextElement(QStringLiteral("pixelaspect"), pixel_aspect_ratio_.toString());
writer->writeTextElement(QStringLiteral("framerate"), frame_rate_.toString());
writer->writeTextElement(QStringLiteral("starttime"), QString::number(start_time_));
diff --git a/app/project/item/footage/videostream.h b/app/project/item/footage/videostream.h
index aa91707a2..59fb8956c 100644
--- a/app/project/item/footage/videostream.h
+++ b/app/project/item/footage/videostream.h
@@ -21,7 +21,6 @@
#ifndef VIDEOSTREAM_H
#define VIDEOSTREAM_H
-#include "render/pixelformat.h"
#include "render/videoparams.h"
#include "stream.h"
@@ -74,16 +73,26 @@ public:
height_ = height;
}
- const PixelFormat::Format& format() const
+ const VideoParams::Format& format() const
{
return format_;
}
- void set_format(const PixelFormat::Format& format)
+ void set_format(const VideoParams::Format& format)
{
format_ = format;
}
+ int channel_count() const
+ {
+ return channel_count_;
+ }
+
+ void set_channel_count(int c)
+ {
+ channel_count_ = c;
+ }
+
bool premultiplied_alpha() const;
void set_premultiplied_alpha(bool e);
@@ -153,7 +162,9 @@ private:
VideoType video_type_;
- PixelFormat::Format format_;
+ VideoParams::Format format_;
+
+ int channel_count_;
rational pixel_aspect_ratio_;
diff --git a/app/project/item/sequence/sequence.cpp b/app/project/item/sequence/sequence.cpp
index 91042e555..8b7c4d534 100644
--- a/app/project/item/sequence/sequence.cpp
+++ b/app/project/item/sequence/sequence.cpp
@@ -70,7 +70,7 @@ void Sequence::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, const
int video_width = 0, video_height = 0, preview_div = 1;
rational video_timebase, video_pixel_aspect;
VideoParams::Interlacing video_interlacing = VideoParams::kInterlaceNone;
- PixelFormat::Format preview_format = PixelFormat::PIX_FMT_INVALID;
+ VideoParams::Format preview_format = VideoParams::kFormatInvalid;
while (XMLReadNextStartElement(reader)) {
if (cancelled && *cancelled) {
@@ -86,7 +86,7 @@ void Sequence::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, const
} else if (reader->name() == QStringLiteral("divider")) {
preview_div = reader->readElementText().toInt();
} else if (reader->name() == QStringLiteral("format")) {
- preview_format = static_cast(reader->readElementText().toInt());
+ preview_format = static_cast(reader->readElementText().toInt());
} else if (reader->name() == QStringLiteral("pixelaspect")) {
video_pixel_aspect = rational::fromString(reader->readElementText());
} else if (reader->name() == QStringLiteral("interlacing")) {
@@ -97,11 +97,12 @@ void Sequence::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, const
}
set_video_params(VideoParams(video_width, video_height, video_timebase, preview_format,
- video_pixel_aspect, video_interlacing, preview_div));
+ VideoParams::kInternalChannelCount, video_pixel_aspect,
+ video_interlacing, preview_div));
} else if (reader->name() == QStringLiteral("audio")) {
int rate = 0;
uint64_t layout = 0;
- SampleFormat::Format format = SampleFormat::SAMPLE_FMT_INVALID;
+ AudioParams::Format format = AudioParams::kFormatInvalid;
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("rate")) {
@@ -109,7 +110,7 @@ void Sequence::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, const
} else if (reader->name() == QStringLiteral("layout")) {
layout = reader->readElementText().toULongLong();
} else if (reader->name() == QStringLiteral("format")) {
- format = static_cast(reader->readElementText().toInt());
+ format = static_cast(reader->readElementText().toInt());
} else {
reader->skipCurrentElement();
}
@@ -268,13 +269,14 @@ void Sequence::set_default_parameters()
set_video_params(VideoParams(width,
height,
Config::Current()["DefaultSequenceFrameRate"].value(),
- static_cast(Config::Current()["DefaultSequencePreviewFormat"].toInt()),
+ static_cast(Config::Current()["OfflinePixelFormat"].toInt()),
+ VideoParams::kInternalChannelCount,
Config::Current()["DefaultSequencePixelAspect"].value(),
Config::Current()["DefaultSequenceInterlacing"].value(),
VideoParams::generate_auto_divider(width, height)));
set_audio_params(AudioParams(Config::Current()["DefaultSequenceAudioFrequency"].toInt(),
Config::Current()["DefaultSequenceAudioLayout"].toULongLong(),
- SampleFormat::kInternalFormat));
+ AudioParams::kInternalFormat));
}
void Sequence::set_parameters_from_footage(const QList footage)
@@ -310,7 +312,8 @@ void Sequence::set_parameters_from_footage(const QList footage)
set_video_params(VideoParams(vs->width(),
vs->height(),
using_timebase,
- static_cast(Config::Current()["DefaultSequencePreviewFormat"].toInt()),
+ static_cast(Config::Current()["OfflinePixelFormat"].toInt()),
+ VideoParams::kInternalChannelCount,
vs->pixel_aspect_ratio(),
vs->interlacing(),
VideoParams::generate_auto_divider(vs->width(), vs->height())));
@@ -320,7 +323,7 @@ void Sequence::set_parameters_from_footage(const QList footage)
case Stream::kAudio:
if (!found_audio_params) {
AudioStream* as = static_cast(s.get());
- set_audio_params(AudioParams(as->sample_rate(), as->channel_layout(), SampleFormat::kInternalFormat));
+ set_audio_params(AudioParams(as->sample_rate(), as->channel_layout(), AudioParams::kInternalFormat));
found_audio_params = true;
}
break;
diff --git a/app/render/CMakeLists.txt b/app/render/CMakeLists.txt
index abb4bda59..7f0bae3c7 100644
--- a/app/render/CMakeLists.txt
+++ b/app/render/CMakeLists.txt
@@ -37,8 +37,6 @@ set(OLIVE_SOURCES
render/framehashcache.h
render/managedcolor.cpp
render/managedcolor.h
- render/pixelformat.cpp
- render/pixelformat.h
render/playbackcache.cpp
render/playbackcache.h
render/previewautocacher.cpp
diff --git a/app/render/audioparams.cpp b/app/render/audioparams.cpp
index 9fb1ec2e1..5ea10389e 100644
--- a/app/render/audioparams.cpp
+++ b/app/render/audioparams.cpp
@@ -49,6 +49,8 @@ const QVector AudioParams::kSupportedChannelLayouts = {
AV_CH_LAYOUT_7POINT1
};
+const AudioParams::Format AudioParams::kInternalFormat = AudioParams::kFormatFloat32;
+
qint64 AudioParams::time_to_bytes(const double &time) const
{
Q_ASSERT(is_valid());
@@ -68,6 +70,26 @@ bool AudioParams::operator!=(const AudioParams &other) const
return !(*this == other);
}
+QAudioFormat::SampleType AudioParams::GetQtSampleType(AudioParams::Format format)
+{
+ switch (format) {
+ case kFormatUnsigned8:
+ return QAudioFormat::UnSignedInt;
+ case kFormatSigned16:
+ case kFormatSigned32:
+ case kFormatSigned64:
+ return QAudioFormat::SignedInt;
+ case kFormatFloat32:
+ case kFormatFloat64:
+ return QAudioFormat::Float;
+ case kFormatInvalid:
+ case kFormatCount:
+ break;
+ }
+
+ return QAudioFormat::Unknown;
+}
+
qint64 AudioParams::time_to_bytes(const rational &time) const
{
return time_to_bytes(time.toDouble());
@@ -119,18 +141,18 @@ int AudioParams::channel_count() const
int AudioParams::bytes_per_sample_per_channel() const
{
switch (format_) {
- case SampleFormat::SAMPLE_FMT_U8:
+ case kFormatUnsigned8:
return 1;
- case SampleFormat::SAMPLE_FMT_S16:
+ case kFormatSigned16:
return 2;
- case SampleFormat::SAMPLE_FMT_S32:
- case SampleFormat::SAMPLE_FMT_FLT:
+ case kFormatSigned32:
+ case kFormatFloat32:
return 4;
- case SampleFormat::SAMPLE_FMT_DBL:
- case SampleFormat::SAMPLE_FMT_S64:
+ case kFormatSigned64:
+ case kFormatFloat64:
return 8;
- case SampleFormat::SAMPLE_FMT_INVALID:
- case SampleFormat::SAMPLE_FMT_COUNT:
+ case kFormatInvalid:
+ case kFormatCount:
break;
}
@@ -146,8 +168,8 @@ bool AudioParams::is_valid() const
{
return (sample_rate() > 0
&& channel_layout() > 0
- && format_ != SampleFormat::SAMPLE_FMT_INVALID
- && format_ != SampleFormat::SAMPLE_FMT_COUNT);
+ && format_ > kFormatInvalid
+ && format_ < kFormatCount);
}
QString AudioParams::SampleRateToString(const int &sample_rate)
diff --git a/app/render/audioparams.h b/app/render/audioparams.h
index 521218e0e..db9c0aa86 100644
--- a/app/render/audioparams.h
+++ b/app/render/audioparams.h
@@ -21,23 +21,51 @@
#ifndef AUDIOPARAMS_H
#define AUDIOPARAMS_H
+#include
#include
-#include "audio/sampleformat.h"
#include "common/rational.h"
OLIVE_NAMESPACE_ENTER
class AudioParams {
public:
+ enum Format {
+ /// Invalid
+ kFormatInvalid = -1,
+
+ /// 8-bit unsigned integer
+ kFormatUnsigned8,
+
+ /// 16-bit signed integer
+ kFormatSigned16,
+
+ /// 32-bit signed integer
+ kFormatSigned32,
+
+ /// 64-bit signed integer
+ kFormatSigned64,
+
+ /// 32-bit float
+ kFormatFloat32,
+
+ /// 64-bit float
+ kFormatFloat64,
+
+ /// Total format count
+ kFormatCount
+ };
+
+ static const Format kInternalFormat;
+
AudioParams() :
sample_rate_(0),
channel_layout_(0),
- format_(SampleFormat::SAMPLE_FMT_INVALID)
+ format_(kFormatInvalid)
{
}
- AudioParams(const int& sample_rate, const uint64_t& channel_layout, const SampleFormat::Format& format) :
+ AudioParams(const int& sample_rate, const uint64_t& channel_layout, const Format& format) :
sample_rate_(sample_rate),
channel_layout_(channel_layout),
format_(format)
@@ -59,7 +87,7 @@ public:
return rational(1, sample_rate());
}
- const SampleFormat::Format &format() const
+ const Format &format() const
{
return format_;
}
@@ -80,6 +108,8 @@ public:
bool operator==(const AudioParams& other) const;
bool operator!=(const AudioParams& other) const;
+ static QAudioFormat::SampleType GetQtSampleType(Format format);
+
static const QVector kSupportedChannelLayouts;
static const QVector kSupportedSampleRates;
@@ -98,7 +128,7 @@ private:
uint64_t channel_layout_;
- SampleFormat::Format format_;
+ Format format_;
};
diff --git a/app/render/color.cpp b/app/render/color.cpp
index 67151413e..55181d83f 100644
--- a/app/render/color.cpp
+++ b/app/render/color.cpp
@@ -20,7 +20,10 @@
#include "color.h"
+#include
+
#include "common/clamp.h"
+#include "common/oiioutils.h"
OLIVE_NAMESPACE_ENTER
@@ -65,9 +68,9 @@ Color Color::fromHsv(const double &h, const double &s, const double &v)
return Color(Rs + m, Gs + m, Bs + m);
}
-Color::Color(const char *data, const PixelFormat::Format &format)
+Color::Color(const char *data, const VideoParams::Format &format, int ch_layout)
{
- *this = fromData(data, format);
+ *this = fromData(data, format, ch_layout);
}
Color::Color(const QColor &c)
@@ -194,24 +197,24 @@ double Color::lightness() const
return l;
}
-void Color::toData(char *data, const PixelFormat::Format &format) const
+void Color::toData(char *data, const VideoParams::Format &format, int ch_layout) const
{
- OIIO::convert_types(OIIO::TypeDesc::DOUBLE,
- data_,
- PixelFormat::GetOIIOTypeDesc(format),
- data,
- kRGBAChannels);
+ OIIO::convert_pixel_values(OIIO::TypeDesc::DOUBLE,
+ data_,
+ OIIOUtils::GetOIIOBaseTypeFromFormat(format),
+ data,
+ ch_layout);
}
-Color Color::fromData(const char *data, const PixelFormat::Format &format)
+Color Color::fromData(const char *data, const VideoParams::Format &format, int ch_layout)
{
Color c;
- OIIO::convert_types(PixelFormat::GetOIIOTypeDesc(format),
- data,
- OIIO::TypeDesc::DOUBLE,
- c.data_,
- kRGBAChannels);
+ OIIO::convert_pixel_values(OIIOUtils::GetOIIOBaseTypeFromFormat(format),
+ data,
+ OIIO::TypeDesc::DOUBLE,
+ c.data_,
+ ch_layout);
return c;
}
@@ -236,7 +239,7 @@ double Color::GetRoughLuminance() const
const Color &Color::operator+=(const Color &rhs)
{
- for (int i=0;i
#include "common/define.h"
-#include "render/pixelformat.h"
+#include "render/videoparams.h"
OLIVE_NAMESPACE_ENTER
@@ -37,7 +37,7 @@ class Color
public:
Color()
{
- for (int i=0;iwidth() * f->height() * kRGBAChannels;
-
- switch (static_cast(f->format())) {
- case PixelFormat::PIX_FMT_INVALID:
- case PixelFormat::PIX_FMT_COUNT:
- qWarning() << "Alpha association functions received an invalid pixel format";
- break;
- case PixelFormat::PIX_FMT_RGBA8:
- case PixelFormat::PIX_FMT_RGBA16U:
- qWarning() << "Alpha association functions only works on float-based pixel formats at this time";
- break;
- case PixelFormat::PIX_FMT_RGBA16F:
- {
- AssociateAlphaInternal(action, reinterpret_cast(f->data()), pixel_count);
- break;
- }
- case PixelFormat::PIX_FMT_RGBA32F:
- {
- AssociateAlphaInternal(action, reinterpret_cast(f->data()), pixel_count);
- break;
- }
- }
-}
-
-template
-void ColorManager::AssociateAlphaInternal(ColorManager::AlphaAction action, T *data, int pix_count)
-{
- for (int i=0;i 0) {
- for (int j=0;j
- static void AssociateAlphaInternal(AlphaAction action, T* data, int pix_count);
-
QString config_filename_;
QString default_input_color_space_;
diff --git a/app/render/colorprocessor.cpp b/app/render/colorprocessor.cpp
index 6ea08ff41..cc249c977 100644
--- a/app/render/colorprocessor.cpp
+++ b/app/render/colorprocessor.cpp
@@ -21,6 +21,7 @@
#include "colorprocessor.h"
#include "common/define.h"
+#include "common/ocioutils.h"
#include "colormanager.h"
OLIVE_NAMESPACE_ENTER
@@ -77,7 +78,7 @@ ColorProcessor::ColorProcessor(ColorManager *config, const QString &input, const
void ColorProcessor::ConvertFrame(Frame *f)
{
- OCIO::BitDepth ocio_bit_depth = PixelFormat::GetOCIOBitDepthFromPixelFormat(f->format());
+ OCIO::BitDepth ocio_bit_depth = OCIOUtils::GetOCIOBitDepthFromPixelFormat(f->format());
if (ocio_bit_depth == OCIO::BIT_DEPTH_UNKNOWN) {
qCritical() << "Tried to color convert frame with no format";
@@ -87,7 +88,7 @@ void ColorProcessor::ConvertFrame(Frame *f)
OCIO::PackedImageDesc img(f->data(),
f->width(),
f->height(),
- kRGBAChannels,
+ VideoParams::kRGBAChannelCount,
ocio_bit_depth,
OCIO::AutoStride,
OCIO::AutoStride,
diff --git a/app/render/framehashcache.cpp b/app/render/framehashcache.cpp
index d555d2a38..d88e407f2 100644
--- a/app/render/framehashcache.cpp
+++ b/app/render/framehashcache.cpp
@@ -243,24 +243,27 @@ FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
int height = dw.max.y - dw.min.y + 1;
bool has_alpha = file.header().channels().findChannel("A");
- PixelFormat::Format image_format;
+ VideoParams::Format image_format;
if (pix_type == Imf::HALF) {
- image_format = PixelFormat::PIX_FMT_RGBA16F;
+ image_format = VideoParams::kFormatFloat16;
} else {
- image_format = PixelFormat::PIX_FMT_RGBA32F;
+ image_format = VideoParams::kFormatFloat32;
}
+ int channel_count = has_alpha ? VideoParams::kRGBAChannelCount : VideoParams::kRGBChannelCount;
+
frame = Frame::Create();
frame->set_video_params(VideoParams(width,
height,
image_format,
+ channel_count,
rational::fromDouble(file.header().pixelAspectRatio())));
frame->allocate();
- int bpc = PixelFormat::BytesPerChannel(image_format);
+ int bpc = VideoParams::GetBytesPerChannel(image_format);
- size_t xs = kRGBAChannels * bpc;
+ size_t xs = channel_count * bpc;
size_t ys = frame->linesize_bytes();
Imf::FrameBuffer framebuffer;
@@ -398,12 +401,15 @@ QString FrameHashCache::CachePathName(const QString &cache_path, const QByteArra
bool FrameHashCache::SaveCacheFrame(const QString &filename, char *data, const VideoParams &vparam, int linesize_bytes) const
{
- Q_ASSERT(PixelFormat::FormatIsFloat(vparam.format()));
+ if (!VideoParams::FormatIsFloat(vparam.format())) {
+ qCritical() << "Tried to cache frame with non-float pixel format";
+ return false;
+ }
// Floating point types are stored in EXR
Imf::PixelType pix_type;
- if (vparam.format() == PixelFormat::PIX_FMT_RGBA16F) {
+ if (vparam.format() == VideoParams::kFormatFloat16) {
pix_type = Imf::HALF;
} else {
pix_type = Imf::FLOAT;
@@ -414,7 +420,9 @@ bool FrameHashCache::SaveCacheFrame(const QString &filename, char *data, const V
header.channels().insert("R", Imf::Channel(pix_type));
header.channels().insert("G", Imf::Channel(pix_type));
header.channels().insert("B", Imf::Channel(pix_type));
- header.channels().insert("A", Imf::Channel(pix_type));
+ if (vparam.channel_count() == VideoParams::kRGBAChannelCount) {
+ header.channels().insert("A", Imf::Channel(pix_type));
+ }
header.compression() = Imf::DWAA_COMPRESSION;
header.insert("dwaCompressionLevel", Imf::FloatAttribute(200.0f));
@@ -422,16 +430,18 @@ bool FrameHashCache::SaveCacheFrame(const QString &filename, char *data, const V
Imf::OutputFile out(filename.toUtf8(), header, 0);
- int bpc = PixelFormat::BytesPerChannel(vparam.format());
+ int bpc = VideoParams::GetBytesPerChannel(vparam.format());
- size_t xs = kRGBAChannels * bpc;
+ size_t xs = vparam.channel_count() * bpc;
size_t ys = linesize_bytes;
Imf::FrameBuffer framebuffer;
framebuffer.insert("R", Imf::Slice(pix_type, data, xs, ys));
framebuffer.insert("G", Imf::Slice(pix_type, data + bpc, xs, ys));
framebuffer.insert("B", Imf::Slice(pix_type, data + 2*bpc, xs, ys));
- framebuffer.insert("A", Imf::Slice(pix_type, data + 3*bpc, xs, ys));
+ if (vparam.channel_count() == VideoParams::kRGBAChannelCount) {
+ framebuffer.insert("A", Imf::Slice(pix_type, data + 3*bpc, xs, ys));
+ }
out.setFrameBuffer(framebuffer);
out.writePixels(vparam.effective_height());
diff --git a/app/render/framehashcache.h b/app/render/framehashcache.h
index 1d8360043..17009dabf 100644
--- a/app/render/framehashcache.h
+++ b/app/render/framehashcache.h
@@ -25,7 +25,7 @@
#include "common/rational.h"
#include "common/timerange.h"
-#include "render/pixelformat.h"
+#include "codec/frame.h"
#include "render/playbackcache.h"
#include "render/videoparams.h"
diff --git a/app/render/managedcolor.cpp b/app/render/managedcolor.cpp
index f4d86e197..042478cf2 100644
--- a/app/render/managedcolor.cpp
+++ b/app/render/managedcolor.cpp
@@ -26,13 +26,13 @@ ManagedColor::ManagedColor()
{
}
-ManagedColor::ManagedColor(const float &r, const float &g, const float &b, const float &a) :
+ManagedColor::ManagedColor(const double &r, const double &g, const double &b, const double &a) :
Color(r, g, b, a)
{
}
-ManagedColor::ManagedColor(const char *data, const PixelFormat::Format &format) :
- Color(data, format)
+ManagedColor::ManagedColor(const char *data, const VideoParams::Format &format, int channel_layout) :
+ Color(data, format, channel_layout)
{
}
diff --git a/app/render/managedcolor.h b/app/render/managedcolor.h
index c214f57b4..707218903 100644
--- a/app/render/managedcolor.h
+++ b/app/render/managedcolor.h
@@ -30,8 +30,8 @@ class ManagedColor : public Color
{
public:
ManagedColor();
- ManagedColor(const float& r, const float& g, const float& b, const float& a = 1.0f);
- ManagedColor(const char *data, const PixelFormat::Format &format);
+ ManagedColor(const double& r, const double& g, const double& b, const double& a = 1.0);
+ ManagedColor(const char *data, const VideoParams::Format &format, int channel_layout);
ManagedColor(const Color& c);
const QString& color_input() const;
diff --git a/app/render/opengl/openglrenderer.cpp b/app/render/opengl/openglrenderer.cpp
index e6e304099..8020affe9 100644
--- a/app/render/opengl/openglrenderer.cpp
+++ b/app/render/opengl/openglrenderer.cpp
@@ -21,7 +21,7 @@
#include "openglrenderer.h"
#include
-#include
+#include
OLIVE_NAMESPACE_ENTER
@@ -128,7 +128,7 @@ void OpenGLRenderer::ClearDestination(double r, double g, double b, double a)
functions_->glClear(GL_COLOR_BUFFER_BIT);
}
-QVariant OpenGLRenderer::CreateNativeTexture2D(int width, int height, PixelFormat::Format format, Texture::ChannelFormat channel_format, const void *data, int linesize)
+QVariant OpenGLRenderer::CreateNativeTexture2D(int width, int height, VideoParams::Format format, int channel_count, const void *data, int linesize)
{
GLuint texture;
functions_->glGenTextures(1, &texture);
@@ -140,8 +140,8 @@ QVariant OpenGLRenderer::CreateNativeTexture2D(int width, int height, PixelForma
functions_->glBindTexture(GL_TEXTURE_2D, texture);
- functions_->glTexImage2D(GL_TEXTURE_2D, 0, GetInternalFormat(format, channel_format),
- width, height, 0, GetPixelFormat(channel_format),
+ functions_->glTexImage2D(GL_TEXTURE_2D, 0, GetInternalFormat(format, channel_count),
+ width, height, 0, GetPixelFormat(channel_count),
GetPixelType(format), data);
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
@@ -151,7 +151,7 @@ QVariant OpenGLRenderer::CreateNativeTexture2D(int width, int height, PixelForma
return texture;
}
-QVariant OpenGLRenderer::CreateNativeTexture3D(int width, int height, int depth, PixelFormat::Format format, Texture::ChannelFormat channel_format, const void *data, int linesize)
+QVariant OpenGLRenderer::CreateNativeTexture3D(int width, int height, int depth, VideoParams::Format format, int channel_count, const void *data, int linesize)
{
GLuint texture;
functions_->glGenTextures(1, &texture);
@@ -163,8 +163,8 @@ QVariant OpenGLRenderer::CreateNativeTexture3D(int width, int height, int depth,
functions_->glBindTexture(GL_TEXTURE_3D, texture);
- context_->extraFunctions()->glTexImage3D(GL_TEXTURE_3D, 0, GetInternalFormat(format, channel_format),
- width, height, depth, 0, GetPixelFormat(channel_format),
+ context_->extraFunctions()->glTexImage3D(GL_TEXTURE_3D, 0, GetInternalFormat(format, channel_count),
+ width, height, depth, 0, GetPixelFormat(channel_count),
GetPixelType(format), data);
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
@@ -241,7 +241,7 @@ void OpenGLRenderer::UploadToTexture(Texture *texture, const void *data, int lin
functions_->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
p.effective_width(), p.effective_height(),
- GL_RGBA, GetPixelType(p.format()),
+ GetPixelFormat(p.channel_count()), GetPixelType(p.format()),
data);
functions_->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
@@ -264,7 +264,7 @@ void OpenGLRenderer::DownloadFromTexture(Texture* texture, void *data, int lines
0,
p.width(),
p.height(),
- GL_RGBA,
+ GetPixelFormat(p.channel_count()),
GetPixelType(p.format()),
data);
@@ -360,7 +360,7 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video
GLuint tex_id = texture ? texture->id().value() : 0;
textures_to_bind.append({texture, job.GetInterpolation(it.key())});
- if (texture && texture->has_meaningful_alpha()) {
+ if (texture && texture->channel_count() == VideoParams::kRGBAChannelCount) {
input_textures_have_alpha = true;
}
@@ -440,6 +440,13 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video
destination_params.effective_width(),
destination_params.effective_height());
+ // Set whether our destination texture needs an alpha channel
+ if (input_textures_have_alpha || job.GetAlphaChannelRequired()) {
+ destination_params.set_channel_count(VideoParams::kRGBAChannelCount);
+ } else {
+ destination_params.set_channel_count(VideoParams::kRGBChannelCount);
+ }
+
// Bind vertex array object
QOpenGLVertexArrayObject vao_;
vao_.create();
@@ -533,9 +540,6 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video
if (destination) {
// Reset framebuffer to default if we were drawing to a texture
DetachTextureAsDestination();
-
- // Set metadata for whether this texture has a meaningful alpha channel
- destination->set_has_meaningful_alpha((input_textures_have_alpha || job.GetAlphaChannelRequired()));
}
// Release any textures we bound before
@@ -555,58 +559,97 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video
vao_.destroy();
}
-GLint OpenGLRenderer::GetInternalFormat(PixelFormat::Format format, bool with_alpha)
+GLint OpenGLRenderer::GetInternalFormat(VideoParams::Format format, int channel_layout)
{
switch (format) {
- case PixelFormat::PIX_FMT_RGBA8:
- return with_alpha ? GL_RGBA8 : GL_RGB8;
- case PixelFormat::PIX_FMT_RGBA16U:
- return with_alpha ? GL_RGBA16 : GL_RGB16;
- case PixelFormat::PIX_FMT_RGBA16F:
- return with_alpha ? GL_RGBA16F : GL_RGB16F;
- case PixelFormat::PIX_FMT_RGBA32F:
- return with_alpha ? GL_RGBA32F : GL_RGB32F;
-
- case PixelFormat::PIX_FMT_INVALID:
- case PixelFormat::PIX_FMT_COUNT:
+ case VideoParams::kFormatUnsigned8:
+ switch (channel_layout) {
+ case 1:
+ return GL_R8;
+ case 2:
+ return GL_RG8;
+ case 3:
+ return GL_RGB8;
+ case 4:
+ return GL_RGBA8;
+ }
+ break;
+ case VideoParams::kFormatUnsigned16:
+ switch (channel_layout) {
+ case 1:
+ return GL_R16;
+ case 2:
+ return GL_RG16;
+ case 3:
+ return GL_RGB16;
+ case 4:
+ return GL_RGBA16;
+ }
+ break;
+ case VideoParams::kFormatFloat16:
+ switch (channel_layout) {
+ case 1:
+ return GL_R16F;
+ case 2:
+ return GL_RG16F;
+ case 3:
+ return GL_RGB16F;
+ case 4:
+ return GL_RGBA16F;
+ }
+ break;
+ case VideoParams::kFormatFloat32:
+ switch (channel_layout) {
+ case 1:
+ return GL_R32F;
+ case 2:
+ return GL_RG32F;
+ case 3:
+ return GL_RGB32F;
+ case 4:
+ return GL_RGBA32F;
+ }
+ break;
+ case VideoParams::kFormatInvalid:
+ case VideoParams::kFormatCount:
break;
}
return GL_INVALID_VALUE;
}
-GLenum OpenGLRenderer::GetPixelType(PixelFormat::Format format)
+GLenum OpenGLRenderer::GetPixelType(VideoParams::Format format)
{
switch (format) {
- case PixelFormat::PIX_FMT_RGBA8:
+ case VideoParams::kFormatUnsigned8:
return GL_UNSIGNED_BYTE;
- case PixelFormat::PIX_FMT_RGBA16U:
+ case VideoParams::kFormatUnsigned16:
return GL_UNSIGNED_SHORT;
- case PixelFormat::PIX_FMT_RGBA16F:
+ case VideoParams::kFormatFloat16:
return GL_HALF_FLOAT;
- case PixelFormat::PIX_FMT_RGBA32F:
+ case VideoParams::kFormatFloat32:
return GL_FLOAT;
- case PixelFormat::PIX_FMT_INVALID:
- case PixelFormat::PIX_FMT_COUNT:
+ case VideoParams::kFormatInvalid:
+ case VideoParams::kFormatCount:
break;
}
return GL_INVALID_VALUE;
}
-GLenum OpenGLRenderer::GetPixelFormat(Texture::ChannelFormat format)
+GLenum OpenGLRenderer::GetPixelFormat(int channel_count)
{
- switch (format) {
- case Texture::kRGBA:
- return GL_RGBA;
- case Texture::kRGB:
- return GL_RGB;
- case Texture::kRedOnly:
+ switch (channel_count) {
+ case 1:
return GL_RED;
+ case 3:
+ return GL_RGB;
+ case 4:
+ return GL_RGBA;
+ default:
+ return GL_INVALID_VALUE;
}
-
- return GL_INVALID_ENUM;
}
void OpenGLRenderer::PrepareInputTexture(GLenum target, Texture::Interpolation interp)
diff --git a/app/render/opengl/openglrenderer.h b/app/render/opengl/openglrenderer.h
index ce1f5d795..d212a111a 100644
--- a/app/render/opengl/openglrenderer.h
+++ b/app/render/opengl/openglrenderer.h
@@ -51,8 +51,8 @@ public slots:
virtual void ClearDestination(double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) override;
- virtual QVariant CreateNativeTexture2D(int width, int height, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) override;
- virtual QVariant CreateNativeTexture3D(int width, int height, int depth, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) override;
+ virtual QVariant CreateNativeTexture2D(int width, int height, OLIVE_NAMESPACE::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) override;
+ virtual QVariant CreateNativeTexture3D(int width, int height, int depth, OLIVE_NAMESPACE::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) override;
virtual void DestroyNativeTexture(QVariant texture) override;
@@ -71,11 +71,11 @@ protected slots:
OLIVE_NAMESPACE::VideoParams destination_params) override;
private:
- static GLint GetInternalFormat(PixelFormat::Format format, bool with_alpha);
+ static GLint GetInternalFormat(VideoParams::Format format, int channel_layout);
- static GLenum GetPixelType(PixelFormat::Format format);
+ static GLenum GetPixelType(VideoParams::Format format);
- static GLenum GetPixelFormat(Texture::ChannelFormat format);
+ static GLenum GetPixelFormat(int channel_count);
void AttachTextureAsDestination(OLIVE_NAMESPACE::Texture* texture);
diff --git a/app/render/pixelformat.cpp b/app/render/pixelformat.cpp
deleted file mode 100644
index 92c0ebd46..000000000
--- a/app/render/pixelformat.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/***
-
- Olive - Non-Linear Video Editor
- Copyright (C) 2019 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 .
-
-***/
-
-#include "pixelformat.h"
-
-#include "OpenImageIO/imagebuf.h"
-#include
-#include
-#include
-
-#include "codec/oiio/oiiocommon.h"
-#include "common/define.h"
-#include "core.h"
-
-OLIVE_NAMESPACE_ENTER
-
-bool PixelFormat::FormatIsFloat(const PixelFormat::Format &format)
-{
- switch (format) {
- case PixelFormat::PIX_FMT_RGBA16F:
- case PixelFormat::PIX_FMT_RGBA32F:
- return true;
-
- case PixelFormat::PIX_FMT_RGBA8:
- case PixelFormat::PIX_FMT_RGBA16U:
- case PixelFormat::PIX_FMT_INVALID:
- case PixelFormat::PIX_FMT_COUNT:
- break;
- }
-
- return false;
-}
-
-OIIO::TypeDesc::BASETYPE PixelFormat::GetOIIOTypeDesc(const PixelFormat::Format &format)
-{
- switch (format) {
- case PixelFormat::PIX_FMT_RGBA8:
- return OIIO::TypeDesc::UINT8;
- case PixelFormat::PIX_FMT_RGBA16U:
- return OIIO::TypeDesc::UINT16;
- case PixelFormat::PIX_FMT_RGBA16F:
- return OIIO::TypeDesc::HALF;
- case PixelFormat::PIX_FMT_RGBA32F:
- return OIIO::TypeDesc::FLOAT;
- case PixelFormat::PIX_FMT_INVALID:
- case PixelFormat::PIX_FMT_COUNT:
- break;
- }
-
- return OIIO::TypeDesc::UNKNOWN;
-}
-
-QString PixelFormat::GetName(const PixelFormat::Format &format)
-{
- switch (format) {
- case PixelFormat::PIX_FMT_RGBA8:
- return tr("8-bit");
- case PixelFormat::PIX_FMT_RGBA16U:
- return tr("16-bit Integer");
- case PixelFormat::PIX_FMT_RGBA16F:
- return tr("Half-Float (16-bit)");
- case PixelFormat::PIX_FMT_RGBA32F:
- return tr("Full-Float (32-bit)");
- case PixelFormat::PIX_FMT_INVALID:
- case PixelFormat::PIX_FMT_COUNT:
- break;
- }
-
- return tr("Unknown (%1)").arg(format);
-}
-
-OCIO::BitDepth PixelFormat::GetOCIOBitDepthFromPixelFormat(PixelFormat::Format format)
-{
- switch (format) {
- case PixelFormat::PIX_FMT_RGBA8:
- return OCIO::BIT_DEPTH_UINT8;
- case PixelFormat::PIX_FMT_RGBA16U:
- return OCIO::BIT_DEPTH_UINT16;
- break;
- case PixelFormat::PIX_FMT_RGBA16F:
- return OCIO::BIT_DEPTH_F16;
- break;
- case PixelFormat::PIX_FMT_RGBA32F:
- return OCIO::BIT_DEPTH_F32;
- break;
- case PixelFormat::PIX_FMT_INVALID:
- case PixelFormat::PIX_FMT_COUNT:
- break;
- }
-
- return OCIO::BIT_DEPTH_UNKNOWN;
-}
-
-PixelFormat* PixelFormat::instance_ = nullptr;
-
-void PixelFormat::CreateInstance()
-{
- instance_ = new PixelFormat();
-}
-
-void PixelFormat::DestroyInstance()
-{
- delete instance_;
-}
-
-PixelFormat *PixelFormat::instance()
-{
- return instance_;
-}
-
-PixelFormat::Format PixelFormat::GetConfiguredFormatForMode(RenderMode::Mode mode)
-{
- return static_cast(
- Core::GetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat")).toInt());
-}
-
-void PixelFormat::SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format)
-{
- if (format != GetConfiguredFormatForMode(mode)) {
- Core::SetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat"), format);
-
- emit FormatChanged();
- }
-}
-
-PixelFormat::Format PixelFormat::OIIOFormatToOliveFormat(OIIO::TypeDesc desc)
-{
- if (desc == OIIO::TypeDesc::UINT8) {
- return PixelFormat::PIX_FMT_RGBA8;
- } else if (desc == OIIO::TypeDesc::UINT16) {
- return PixelFormat::PIX_FMT_RGBA16U;
- } else if (desc == OIIO::TypeDesc::HALF) {
- return PixelFormat::PIX_FMT_RGBA16F;
- } else if (desc == OIIO::TypeDesc::FLOAT) {
- return PixelFormat::PIX_FMT_RGBA32F;
- }
-
- return PixelFormat::PIX_FMT_INVALID;
-}
-
-int PixelFormat::GetBufferSize(const PixelFormat::Format &format, const int &width, const int &height)
-{
- return BytesPerPixel(format) * width * height;
-}
-
-int PixelFormat::BytesPerPixel(const PixelFormat::Format &format)
-{
- return BytesPerChannel(format) * kRGBAChannels;
-}
-
-int PixelFormat::BytesPerChannel(const PixelFormat::Format &format)
-{
- switch (format) {
- case PixelFormat::PIX_FMT_RGBA8:
- return 1;
- case PixelFormat::PIX_FMT_RGBA16U:
- case PixelFormat::PIX_FMT_RGBA16F:
- return 2;
- case PixelFormat::PIX_FMT_RGBA32F:
- return 4;
- case PixelFormat::PIX_FMT_INVALID:
- case PixelFormat::PIX_FMT_COUNT:
- break;
- }
-
- qFatal("Invalid pixel format requested");
-
- // qFatal will abort so we won't get here, but this suppresses compiler warnings
- return 0;
-}
-
-FramePtr PixelFormat::ConvertPixelFormat(FramePtr frame, const PixelFormat::Format &dest_format)
-{
- if (frame->format() == dest_format) {
- return frame;
- }
-
- // Create a destination frame with the same parameters
- FramePtr converted = Frame::Create();
- converted->set_video_params(VideoParams(frame->video_params().width(),
- frame->video_params().height(),
- dest_format));
- converted->set_timestamp(frame->timestamp());
- converted->allocate();
-
- // Do the conversion through OIIO - create a buffer for the source image
- OIIO::ImageBuf src(OIIO::ImageSpec(frame->width(),
- frame->height(),
- kRGBAChannels,
- GetOIIOTypeDesc(frame->format())));
-
- // Set the pixels (this is necessary as opposed to an OIIO buffer wrapper since Frame has
- // linesizes)
- OIIOCommon::FrameToBuffer(frame, &src);
-
- // Create a destination OIIO buffer with our destination format
- OIIO::ImageBuf dst(OIIO::ImageSpec(converted->width(),
- converted->height(),
- kRGBAChannels,
- GetOIIOTypeDesc(converted->format())));
-
- if (dst.copy_pixels(src)) {
-
- // Convert our buffer back to a frame
- OIIOCommon::BufferToFrame(&dst, converted);
-
- return converted;
- } else {
- return nullptr;
- }
-}
-
-OLIVE_NAMESPACE_EXIT
diff --git a/app/render/pixelformat.h b/app/render/pixelformat.h
deleted file mode 100644
index c60027c93..000000000
--- a/app/render/pixelformat.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/***
-
- Olive - Non-Linear Video Editor
- Copyright (C) 2019 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 .
-
-***/
-
-#ifndef BITDEPTHS_H
-#define BITDEPTHS_H
-
-#include
-#include
-#include
-#include
-
-#include "common/ocioutils.h"
-#include "render/rendermodes.h"
-
-OLIVE_NAMESPACE_ENTER
-
-class Frame;
-using FramePtr = std::shared_ptr;
-
-class PixelFormat : public QObject
-{
- Q_OBJECT
-public:
- /**
- * @brief Olive's internal supported pixel formats.
- */
- enum Format {
- PIX_FMT_INVALID = -1,
-
- PIX_FMT_RGBA8,
- PIX_FMT_RGBA16U,
- PIX_FMT_RGBA16F,
- PIX_FMT_RGBA32F,
-
- PIX_FMT_COUNT
- };
-
- static void CreateInstance();
- static void DestroyInstance();
- static PixelFormat* instance();
-
- /**
- * @brief Returns the configured pixel format for a given mode
- */
- Format GetConfiguredFormatForMode(RenderMode::Mode mode);
- void SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format);
-
- static Format OIIOFormatToOliveFormat(OIIO::TypeDesc desc);
-
- /**
- * @brief Returns the minimum buffer size (in bytes) necessary for a given format, width, and height.
- *
- * @param format
- *
- * The format of the data the buffer should contain. Must be a member of the olive::PixelFormat enum.
- *
- * @param width
- *
- * The width (in pixels) of the buffer.
- *
- * @param height
- *
- * The height (in pixels) of the buffer.
- */
- static int GetBufferSize(const Format &format, const int& width, const int& height);
-
- /**
- * @brief Returns the number of bytes per pixel for a certain format
- *
- * Different formats use different sizes of data for pixels. Use this function to determine how many bytes a pixel
- * requires for a certain format. The number of bytes will always be a multiple of 4 since all formats use RGBA and
- * are at least 1 bpc.
- */
- static int BytesPerPixel(const Format &format);
-
- /**
- * @brief Returns the number of bytes per channel for a certain format
- */
- static int BytesPerChannel(const Format& format);
-
- /**
- * @brief Convert a frame to a pixel format
- *
- * If the frame's pixel format == the destination format, this just returns `frame`.
- */
- static FramePtr ConvertPixelFormat(FramePtr frame, const Format &dest_format);
-
- /**
- * @brief Simple convenience function returning whether a pixel format is float-based or integer-based
- */
- static bool FormatIsFloat(const Format& format);
-
- /**
- * @brief Get corresponding OpenImageIO TypeDesc for a given pixel format
- */
- static OIIO::TypeDesc::BASETYPE GetOIIOTypeDesc(const Format& format);
-
- /**
- * @brief Get format name
- */
- static QString GetName(const Format& format);
-
- static OCIO::BitDepth GetOCIOBitDepthFromPixelFormat(PixelFormat::Format format);
-
-signals:
- void FormatChanged();
-
-private:
- PixelFormat() = default;
-
- static PixelFormat* instance_;
-
-};
-
-OLIVE_NAMESPACE_EXIT
-
-#endif // BITDEPTHS_H
diff --git a/app/render/renderer.cpp b/app/render/renderer.cpp
index 83107935b..e3aad5fd4 100644
--- a/app/render/renderer.cpp
+++ b/app/render/renderer.cpp
@@ -32,16 +32,16 @@ Renderer::Renderer(QObject *parent) :
}
-TexturePtr Renderer::CreateTexture(const VideoParams ¶ms, Texture::Type type, Texture::ChannelFormat channel_format, const void *data, int linesize)
+TexturePtr Renderer::CreateTexture(const VideoParams ¶ms, Texture::Type type, const void *data, int linesize)
{
QVariant v;
if (type == Texture::k3D) {
v = CreateNativeTexture3D(params.effective_width(), params.effective_height(),
- params.effective_depth(), params.format(), channel_format, data, linesize);
+ params.effective_depth(), params.format(), params.channel_count(), data, linesize);
} else {
v = CreateNativeTexture2D(params.effective_width(), params.effective_height(), params.format(),
- channel_format, data, linesize);
+ params.channel_count(), data, linesize);
}
if (v.isNull()) {
@@ -53,7 +53,7 @@ TexturePtr Renderer::CreateTexture(const VideoParams ¶ms, Texture::Type type
TexturePtr Renderer::CreateTexture(const VideoParams ¶ms, const void *data, int linesize)
{
- return CreateTexture(params, Texture::k2D, Texture::kRGBA, data, linesize);
+ return CreateTexture(params, Texture::k2D, data, linesize);
}
void Renderer::BlitColorManaged(ColorProcessorPtr color_processor, TexturePtr source, bool source_is_premultiplied, Texture *destination, const QMatrix4x4 &matrix)
@@ -104,6 +104,7 @@ bool Renderer::GetColorContext(ColorProcessorPtr color_processor, Renderer::Colo
"uniform int ove_maintex_alpha;\n"
"\n"
"// Macros defining `ove_maintex_alpha` state\n"
+ "// Matches `AlphaAssociated` C++ enum\n"
"#define ALPHA_NONE 0\n"
"#define ALPHA_UNASSOC 1\n"
"#define ALPHA_ASSOC 2\n"
@@ -185,8 +186,8 @@ bool Renderer::GetColorContext(ColorProcessorPtr color_processor, Renderer::Colo
}
// Allocate 3D LUT
- color_ctx.lut3d_textures[i].texture = CreateTexture(VideoParams(edge_len, edge_len, edge_len, PixelFormat::PIX_FMT_RGBA32F),
- Texture::k3D, Texture::kRGB, values);
+ color_ctx.lut3d_textures[i].texture = CreateTexture(VideoParams(edge_len, edge_len, edge_len, VideoParams::kFormatFloat32, VideoParams::kRGBChannelCount),
+ Texture::k3D, values);
color_ctx.lut3d_textures[i].name = sampler_name;
color_ctx.lut3d_textures[i].interpolation = (interpolation == OCIO::INTERP_NEAREST) ? Texture::kNearest : Texture::kLinear;
}
@@ -216,9 +217,8 @@ bool Renderer::GetColorContext(ColorProcessorPtr color_processor, Renderer::Colo
}
// Allocate 1D LUT
- color_ctx.lut1d_textures[i].texture = CreateTexture(VideoParams(width, height, PixelFormat::PIX_FMT_RGBA32F),
+ color_ctx.lut1d_textures[i].texture = CreateTexture(VideoParams(width, height, VideoParams::kFormatFloat32, (channel == OCIO::GpuShaderDesc::TEXTURE_RED_CHANNEL) ? 1 : VideoParams::kRGBChannelCount),
Texture::k2D,
- (channel == OCIO::GpuShaderDesc::TEXTURE_RED_CHANNEL) ? Texture::kRedOnly : Texture::kRGB,
values);
color_ctx.lut1d_textures[i].name = sampler_name;
color_ctx.lut1d_textures[i].interpolation = (interpolation == OCIO::INTERP_NEAREST) ? Texture::kNearest : Texture::kLinear;
@@ -244,6 +244,21 @@ void Renderer::BlitColorManagedInternal(ColorProcessorPtr color_processor, Textu
job.InsertValue(QStringLiteral("ove_maintex"), ShaderValue(QVariant::fromValue(source), NodeParam::kTexture));
job.InsertValue(QStringLiteral("ove_mvpmat"), ShaderValue(matrix, NodeParam::kMatrix));
+ AlphaAssociated associated;
+ if (source->channel_count() == VideoParams::kRGBAChannelCount) {
+ if (source_is_premultiplied) {
+ // De-assoc/re-assoc required for color management
+ associated = kAlphaAssociated;
+ } else {
+ // Just assoc at the end
+ associated = kAlphaUnassociated;
+ }
+ } else {
+ // No assoc/deassoc required
+ associated = kAlphaNone;
+ }
+ job.InsertValue(QStringLiteral("ove_maintex_alpha"), ShaderValue(associated, NodeParam::kInt));
+
foreach (const ColorContext::LUT& l, color_ctx.lut3d_textures) {
job.InsertValue(l.name, ShaderValue(QVariant::fromValue(l.texture), NodeParam::kTexture));
job.SetInterpolation(l.name, l.interpolation);
diff --git a/app/render/renderer.h b/app/render/renderer.h
index fdea3da57..99bcf6374 100644
--- a/app/render/renderer.h
+++ b/app/render/renderer.h
@@ -43,7 +43,7 @@ public:
virtual bool Init() = 0;
- TexturePtr CreateTexture(const VideoParams& params, Texture::Type type, Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0);
+ TexturePtr CreateTexture(const VideoParams& params, Texture::Type type, const void* data = nullptr, int linesize = 0);
TexturePtr CreateTexture(const VideoParams& params, const void *data = nullptr, int linesize = 0);
void BlitToTexture(QVariant shader,
@@ -72,8 +72,8 @@ public slots:
virtual void ClearDestination(double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) = 0;
- virtual QVariant CreateNativeTexture2D(int width, int height, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) = 0;
- virtual QVariant CreateNativeTexture3D(int width, int height, int depth, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) = 0;
+ virtual QVariant CreateNativeTexture2D(int width, int height, OLIVE_NAMESPACE::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) = 0;
+ virtual QVariant CreateNativeTexture3D(int width, int height, int depth, OLIVE_NAMESPACE::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) = 0;
virtual void DestroyNativeTexture(QVariant texture) = 0;
@@ -105,6 +105,12 @@ private:
};
+ enum AlphaAssociated {
+ kAlphaNone,
+ kAlphaUnassociated,
+ kAlphaAssociated
+ };
+
bool GetColorContext(ColorProcessorPtr color_processor, ColorContext* ctx);
void BlitColorManagedInternal(ColorProcessorPtr color_processor, TexturePtr source,
diff --git a/app/render/rendererthreadwrapper.cpp b/app/render/rendererthreadwrapper.cpp
index 2024fd377..483304575 100644
--- a/app/render/rendererthreadwrapper.cpp
+++ b/app/render/rendererthreadwrapper.cpp
@@ -76,7 +76,7 @@ void RendererThreadWrapper::ClearDestination(double r, double g, double b, doubl
Q_ARG(double, a));
}
-QVariant RendererThreadWrapper::CreateNativeTexture2D(int width, int height, PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void *data, int linesize)
+QVariant RendererThreadWrapper::CreateNativeTexture2D(int width, int height, VideoParams::Format format, int channel_count, const void *data, int linesize)
{
QVariant v;
@@ -84,15 +84,15 @@ QVariant RendererThreadWrapper::CreateNativeTexture2D(int width, int height, Pix
Q_RETURN_ARG(QVariant, v),
Q_ARG(int, width),
Q_ARG(int, height),
- OLIVE_NS_ARG(PixelFormat::Format, format),
- OLIVE_NS_ARG(Texture::ChannelFormat, channel_format),
+ OLIVE_NS_ARG(VideoParams::Format, format),
+ Q_ARG(int, channel_count),
Q_ARG(const void*, data),
Q_ARG(int, linesize));
return v;
}
-QVariant RendererThreadWrapper::CreateNativeTexture3D(int width, int height, int depth, PixelFormat::Format format, Texture::ChannelFormat channel_format, const void *data, int linesize)
+QVariant RendererThreadWrapper::CreateNativeTexture3D(int width, int height, int depth, VideoParams::Format format, int channel_count, const void *data, int linesize)
{
QVariant v;
@@ -101,8 +101,8 @@ QVariant RendererThreadWrapper::CreateNativeTexture3D(int width, int height, int
Q_ARG(int, width),
Q_ARG(int, height),
Q_ARG(int, depth),
- OLIVE_NS_ARG(PixelFormat::Format, format),
- OLIVE_NS_ARG(Texture::ChannelFormat, channel_format),
+ OLIVE_NS_ARG(VideoParams::Format, format),
+ Q_ARG(int, channel_count),
Q_ARG(const void*, data),
Q_ARG(int, linesize));
diff --git a/app/render/rendererthreadwrapper.h b/app/render/rendererthreadwrapper.h
index a3b9e5cda..1c682161a 100644
--- a/app/render/rendererthreadwrapper.h
+++ b/app/render/rendererthreadwrapper.h
@@ -47,8 +47,8 @@ public slots:
virtual void ClearDestination(double r = 0.0, double g = 0.0, double b = 0.0, double a = 0.0) override;
- virtual QVariant CreateNativeTexture2D(int width, int height, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) override;
- virtual QVariant CreateNativeTexture3D(int width, int height, int depth, OLIVE_NAMESPACE::PixelFormat::Format format, OLIVE_NAMESPACE::Texture::ChannelFormat channel_format, const void* data = nullptr, int linesize = 0) override;
+ virtual QVariant CreateNativeTexture2D(int width, int height, OLIVE_NAMESPACE::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) override;
+ virtual QVariant CreateNativeTexture3D(int width, int height, int depth, OLIVE_NAMESPACE::VideoParams::Format format, int channel_count, const void* data = nullptr, int linesize = 0) override;
virtual void DestroyNativeTexture(QVariant texture) override;
diff --git a/app/render/rendermanager.cpp b/app/render/rendermanager.cpp
index 2f6401a06..ba84737b0 100644
--- a/app/render/rendermanager.cpp
+++ b/app/render/rendermanager.cpp
@@ -86,11 +86,11 @@ QByteArray RenderManager::Hash(const Node *n, const VideoParams ¶ms, const r
// Embed video parameters into this hash
int width = params.effective_width();
int height = params.effective_height();
- PixelFormat::Format format = params.format();
+ VideoParams::Format format = params.format();
hasher.addData(reinterpret_cast(&width), sizeof(int));
hasher.addData(reinterpret_cast(&height), sizeof(int));
- hasher.addData(reinterpret_cast(&format), sizeof(PixelFormat::Format));
+ hasher.addData(reinterpret_cast(&format), sizeof(VideoParams::Format));
if (n) {
n->Hash(hasher, time);
@@ -111,7 +111,7 @@ RenderTicketPtr RenderManager::RenderFrame(ViewerOutput* viewer, ColorManager* c
viewer->audio_params(),
QSize(0, 0),
QMatrix4x4(),
- PixelFormat::PIX_FMT_INVALID,
+ VideoParams::kFormatInvalid,
nullptr,
cache,
prioritize);
@@ -121,7 +121,7 @@ RenderTicketPtr RenderManager::RenderFrame(ViewerOutput* viewer, ColorManager* c
const rational& time, RenderMode::Mode mode,
const VideoParams &video_params, const AudioParams &audio_params,
const QSize& force_size,
- const QMatrix4x4& force_matrix, PixelFormat::Format force_format,
+ const QMatrix4x4& force_matrix, VideoParams::Format force_format,
ColorProcessorPtr force_color_output,
FrameHashCache* cache, bool prioritize)
{
diff --git a/app/render/rendermanager.h b/app/render/rendermanager.h
index 702356023..06b23c59d 100644
--- a/app/render/rendermanager.h
+++ b/app/render/rendermanager.h
@@ -87,7 +87,7 @@ public:
const rational& time, RenderMode::Mode mode,
const VideoParams& video_params, const AudioParams& audio_params,
const QSize& force_size,
- const QMatrix4x4& force_matrix, PixelFormat::Format force_format,
+ const QMatrix4x4& force_matrix, VideoParams::Format force_format,
ColorProcessorPtr force_color_output,
FrameHashCache* cache = nullptr, bool prioritize = false);
diff --git a/app/render/renderprocessor.cpp b/app/render/renderprocessor.cpp
index a9bdca01a..d3c0480e8 100644
--- a/app/render/renderprocessor.cpp
+++ b/app/render/renderprocessor.cpp
@@ -67,11 +67,15 @@ void RenderProcessor::Run()
frame_params.set_height(frame_size.height());
}
- PixelFormat::Format frame_format = static_cast(ticket_->property("format").toInt());
- if (frame_format != PixelFormat::PIX_FMT_INVALID) {
+ VideoParams::Format frame_format = static_cast(ticket_->property("format").toInt());
+ if (frame_format != VideoParams::kFormatInvalid) {
frame_params.set_format(frame_format);
}
+ if (texture) {
+ frame_params.set_channel_count(texture->channel_count());
+ }
+
FramePtr frame = Frame::Create();
frame->set_timestamp(time);
frame->set_video_params(frame_params);
@@ -448,9 +452,14 @@ QVariant RenderProcessor::ProcessFrameGeneration(const Node *node, const Generat
{
FramePtr frame = Frame::Create();
- const VideoParams& video_params = ticket_->property("vparam").value();
+ VideoParams frame_params = ticket_->property("vparam").value();
+ if (job.GetAlphaChannelRequired()) {
+ frame_params.set_channel_count(VideoParams::kRGBAChannelCount);
+ } else {
+ frame_params.set_channel_count(VideoParams::kRGBChannelCount);
+ }
- frame->set_video_params(video_params);
+ frame->set_video_params(frame_params);
frame->allocate();
node->GenerateFrame(frame, job);
@@ -459,8 +468,6 @@ QVariant RenderProcessor::ProcessFrameGeneration(const Node *node, const Generat
frame->data(),
frame->linesize_pixels());
- texture->set_has_meaningful_alpha(job.GetAlphaChannelRequired());
-
return QVariant::fromValue(texture);
}
diff --git a/app/render/texture.h b/app/render/texture.h
index abf4e7e2e..4aaf01f62 100644
--- a/app/render/texture.h
+++ b/app/render/texture.h
@@ -41,19 +41,12 @@ public:
kMipmappedLinear
};
- enum ChannelFormat {
- kRGBA,
- kRGB,
- kRedOnly
- };
-
static const Interpolation kDefaultInterpolation;
Texture(Renderer* renderer, const QVariant& native, const VideoParams& param, Type type) :
renderer_(renderer),
params_(param),
id_(native),
- meaningful_alpha_(true),
type_(type)
{
}
@@ -82,11 +75,16 @@ public:
return params_.height();
}
- PixelFormat::Format format() const
+ VideoParams::Format format() const
{
return params_.format();
}
+ int channel_count() const
+ {
+ return params_.channel_count();
+ }
+
int divider() const
{
return params_.divider();
@@ -97,16 +95,6 @@ public:
return params_.pixel_aspect_ratio();
}
- bool has_meaningful_alpha() const
- {
- return meaningful_alpha_;
- }
-
- void set_has_meaningful_alpha(bool e)
- {
- meaningful_alpha_ = e;
- }
-
Type type() const
{
return type_;
@@ -119,8 +107,6 @@ private:
QVariant id_;
- bool meaningful_alpha_;
-
Type type_;
};
diff --git a/app/render/videoparams.cpp b/app/render/videoparams.cpp
index c9609701e..e7c500f6f 100644
--- a/app/render/videoparams.cpp
+++ b/app/render/videoparams.cpp
@@ -24,7 +24,9 @@
#include "core.h"
-OLIVE_NAMESPACE_ENTER
+OLIVE_NAMESPACE_ENTER;
+
+const int VideoParams::kInternalChannelCount = kRGBAChannelCount;
const rational VideoParams::kPixelAspectSquare(1);
const rational VideoParams::kPixelAspectNTSCStandard(8, 9);
@@ -63,16 +65,18 @@ VideoParams::VideoParams() :
width_(0),
height_(0),
depth_(0),
- format_(PixelFormat::PIX_FMT_INVALID),
+ format_(kFormatInvalid),
+ channel_count_(0),
interlacing_(Interlacing::kInterlaceNone)
{
}
-VideoParams::VideoParams(const int &width, const int &height, const PixelFormat::Format &format, const rational& pixel_aspect_ratio, const Interlacing &interlacing, const int& divider) :
+VideoParams::VideoParams(int width, int height, Format format, int nb_channels, const rational& pixel_aspect_ratio, Interlacing interlacing, int divider) :
width_(width),
height_(height),
depth_(0),
format_(format),
+ channel_count_(nb_channels),
pixel_aspect_ratio_(pixel_aspect_ratio),
interlacing_(interlacing),
divider_(divider)
@@ -81,11 +85,12 @@ VideoParams::VideoParams(const int &width, const int &height, const PixelFormat:
validate_pixel_aspect_ratio();
}
-VideoParams::VideoParams(const int &width, const int &height, const int &depth, const PixelFormat::Format &format, const rational &pixel_aspect_ratio, const VideoParams::Interlacing &interlacing, const int ÷r) :
+VideoParams::VideoParams(int width, int height, int depth, Format format, int nb_channels, const rational &pixel_aspect_ratio, VideoParams::Interlacing interlacing, int divider) :
width_(width),
height_(height),
depth_(depth),
format_(format),
+ channel_count_(nb_channels),
pixel_aspect_ratio_(pixel_aspect_ratio),
interlacing_(interlacing),
divider_(divider)
@@ -94,12 +99,13 @@ VideoParams::VideoParams(const int &width, const int &height, const int &depth,
validate_pixel_aspect_ratio();
}
-VideoParams::VideoParams(const int &width, const int &height, const rational &time_base, const PixelFormat::Format &format, const rational& pixel_aspect_ratio, const Interlacing &interlacing, const int ÷r) :
+VideoParams::VideoParams(int width, int height, const rational &time_base, Format format, int nb_channels, const rational& pixel_aspect_ratio, Interlacing interlacing, int divider) :
width_(width),
height_(height),
depth_(0),
time_base_(time_base),
format_(format),
+ channel_count_(nb_channels),
pixel_aspect_ratio_(pixel_aspect_ratio),
interlacing_(interlacing),
divider_(divider)
@@ -159,6 +165,64 @@ bool VideoParams::operator!=(const VideoParams &rhs) const
return !(*this == rhs);
}
+int VideoParams::GetBytesPerChannel(VideoParams::Format format)
+{
+ switch (format) {
+ case kFormatInvalid:
+ case kFormatCount:
+ break;
+ case kFormatUnsigned8:
+ return 1;
+ case kFormatUnsigned16:
+ case kFormatFloat16:
+ return 2;
+ case kFormatFloat32:
+ return 4;
+ }
+
+ return 0;
+}
+
+int VideoParams::GetBytesPerPixel(VideoParams::Format format, int channels)
+{
+ return GetBytesPerChannel(format) * channels;
+}
+
+bool VideoParams::FormatIsFloat(VideoParams::Format format)
+{
+ switch (format) {
+ case kFormatFloat16:
+ case kFormatFloat32:
+ return true;
+ case kFormatUnsigned8:
+ case kFormatUnsigned16:
+ case kFormatInvalid:
+ case kFormatCount:
+ break;
+ }
+
+ return false;
+}
+
+QString VideoParams::GetFormatName(VideoParams::Format format)
+{
+ switch (format) {
+ case kFormatUnsigned8:
+ return QCoreApplication::translate("VideoParams", "8-bit");
+ case kFormatUnsigned16:
+ return QCoreApplication::translate("VideoParams", "16-bit Integer");
+ case kFormatFloat16:
+ return QCoreApplication::translate("VideoParams", "Half-Float (16-bit)");
+ case kFormatFloat32:
+ return QCoreApplication::translate("VideoParams", "Full-Float (32-bit)");
+ case kFormatInvalid:
+ case kFormatCount:
+ break;
+ }
+
+ return QCoreApplication::translate("VideoParams", "Unknown (0x%1)").arg(format, 0, 16);
+}
+
void VideoParams::calculate_effective_size()
{
effective_width_ = GetScaledDimension(width(), divider_);
@@ -178,8 +242,8 @@ bool VideoParams::is_valid() const
return (width() > 0
&& height() > 0
&& !pixel_aspect_ratio_.isNull()
- && format_ != PixelFormat::PIX_FMT_INVALID
- && format_ != PixelFormat::PIX_FMT_COUNT);
+ && format_ > kFormatInvalid && format_ < kFormatCount
+ && channel_count_ > 0);
}
QString VideoParams::FrameRateToString(const rational &frame_rate)
diff --git a/app/render/videoparams.h b/app/render/videoparams.h
index 3d7102e9f..7cd4ef7c1 100644
--- a/app/render/videoparams.h
+++ b/app/render/videoparams.h
@@ -22,13 +22,35 @@
#define VIDEOPARAMS_H
#include "common/rational.h"
-#include "pixelformat.h"
#include "rendermodes.h"
OLIVE_NAMESPACE_ENTER
class VideoParams {
public:
+ enum Format {
+ /// Invalid or no format
+ kFormatInvalid = -1,
+
+ /// 8-bit unsigned integer
+ kFormatUnsigned8,
+
+ /// 16-bit unsigned integer
+ kFormatUnsigned16,
+
+ /// 16-bit half float
+ kFormatFloat16,
+
+ /// 32-bit full float
+ kFormatFloat32,
+
+ /// 64-bit double float - disabled since very, very few libs support 64-bit buffers
+ //kFormatFloat64,
+
+ /// Total format count
+ kFormatCount
+ };
+
enum Interlacing {
kInterlaceNone,
kInterlacedTopFirst,
@@ -36,16 +58,17 @@ public:
};
VideoParams();
- VideoParams(const int& width, const int& height, const PixelFormat::Format& format,
+ VideoParams(int width, int height, Format format, int nb_channels,
const rational& pixel_aspect_ratio = 1,
- const Interlacing& interlacing = kInterlaceNone, const int& divider = 1);
- VideoParams(const int& width, const int& height, const int& depth,
- const PixelFormat::Format& format,
+ Interlacing interlacing = kInterlaceNone, int divider = 1);
+ VideoParams(int width, int height, int depth,
+ Format format, int nb_channels,
const rational& pixel_aspect_ratio = 1,
- const Interlacing& interlacing = kInterlaceNone, const int& divider = 1);
- VideoParams(const int& width, const int& height, const rational& time_base,
- const PixelFormat::Format& format, const rational& pixel_aspect_ratio = 1,
- const Interlacing& interlacing = kInterlaceNone, const int& divider = 1);
+ Interlacing interlacing = kInterlaceNone, int divider = 1);
+ VideoParams(int width, int height, const rational& time_base,
+ Format format, int nb_channels,
+ const rational& pixel_aspect_ratio = 1,
+ Interlacing interlacing = kInterlaceNone, int divider = 1);
int width() const
{
@@ -116,16 +139,26 @@ public:
return effective_depth_;
}
- PixelFormat::Format format() const
+ Format format() const
{
return format_;
}
- void set_format(PixelFormat::Format f)
+ void set_format(Format f)
{
format_ = f;
}
+ int channel_count() const
+ {
+ return channel_count_;
+ }
+
+ void set_channel_count(int c)
+ {
+ channel_count_ = c;
+ }
+
const rational& pixel_aspect_ratio() const
{
return pixel_aspect_ratio_;
@@ -154,6 +187,33 @@ public:
bool operator==(const VideoParams& rhs) const;
bool operator!=(const VideoParams& rhs) const;
+ static int GetBytesPerChannel(Format format);
+ int GetBytesPerChannel() const
+ {
+ return GetBytesPerChannel(format_);
+ }
+
+ static int GetBytesPerPixel(Format format, int channels);
+ int GetBytesPerPixel() const
+ {
+ return GetBytesPerPixel(format_, channel_count_);
+ }
+
+ static int GetBufferSize(int width, int height, Format format, int channels)
+ {
+ return width * height * GetBytesPerPixel(format, channels);
+ }
+ int GetBufferSize() const
+ {
+ return GetBufferSize(width_, height_, format_, channel_count_);
+ }
+
+ static bool FormatIsFloat(Format format);
+
+ static QString GetFormatName(Format format);
+
+ static const int kInternalChannelCount;
+
static const rational kPixelAspectSquare;
static const rational kPixelAspectNTSCStandard;
static const rational kPixelAspectNTSCWidescreen;
@@ -165,6 +225,10 @@ public:
static const QVector kStandardPixelAspects;
static const QVector kSupportedDividers;
+ static const int kHSVChannelCount = 3;
+ static const int kRGBChannelCount = 3;
+ static const int kRGBAChannelCount = 4;
+
/**
* @brief Convert rational frame rate (i.e. flipped timebase) to a user-friendly string
*/
@@ -185,7 +249,9 @@ private:
int depth_;
rational time_base_;
- PixelFormat::Format format_;
+ Format format_;
+
+ int channel_count_;
rational pixel_aspect_ratio_;
diff --git a/app/task/export/export.cpp b/app/task/export/export.cpp
index e7e53b0a1..1f5d4df38 100644
--- a/app/task/export/export.cpp
+++ b/app/task/export/export.cpp
@@ -170,18 +170,6 @@ void ExportTask::FrameDownloaded(FramePtr f, const QByteArray &hash, const QVect
}
}
-void FrameColorConvert(ColorProcessorPtr processor, FramePtr frame)
-{
- // Color conversion must be done with unassociated alpha, and the pipeline is always associated
- ColorManager::DisassociateAlpha(frame);
-
- // Convert color space
- processor->ConvertFrame(frame);
-
- // Re-associate alpha
- ColorManager::ReassociateAlpha(frame);
-}
-
void ExportTask::AudioDownloaded(const TimeRange &range, SampleBufferPtr samples, qint64 job_time)
{
Q_UNUSED(job_time)
diff --git a/app/task/render/render.cpp b/app/task/render/render.cpp
index 6b90dd1e4..65821d777 100644
--- a/app/task/render/render.cpp
+++ b/app/task/render/render.cpp
@@ -42,7 +42,7 @@ bool RenderTask::Render(ColorManager* manager,
const TimeRangeList &audio_range,
RenderMode::Mode mode,
FrameHashCache* cache, const QSize &force_size,
- const QMatrix4x4 &force_matrix, PixelFormat::Format force_format,
+ const QMatrix4x4 &force_matrix, VideoParams::Format force_format,
ColorProcessorPtr force_color_output)
{
// Run watchers in another thread so they can accept signals even while this thread is blocked
diff --git a/app/task/render/render.h b/app/task/render/render.h
index 9f8c1ea17..428e4e243 100644
--- a/app/task/render/render.h
+++ b/app/task/render/render.h
@@ -44,7 +44,7 @@ protected:
const TimeRangeList &audio_range, RenderMode::Mode mode,
FrameHashCache *cache, const QSize& force_size = QSize(0, 0),
const QMatrix4x4& force_matrix = QMatrix4x4(),
- PixelFormat::Format force_format = PixelFormat::PIX_FMT_INVALID,
+ VideoParams::Format force_format = VideoParams::kFormatInvalid,
ColorProcessorPtr force_color_output = nullptr);
virtual void DownloadFrame(QThread* thread, FramePtr frame, const QByteArray &hash);
diff --git a/app/widget/manageddisplay/manageddisplay.h b/app/widget/manageddisplay/manageddisplay.h
index 86f82113a..dc10913dd 100644
--- a/app/widget/manageddisplay/manageddisplay.h
+++ b/app/widget/manageddisplay/manageddisplay.h
@@ -21,6 +21,7 @@
#ifndef MANAGEDDISPLAYOBJECT_H
#define MANAGEDDISPLAYOBJECT_H
+#include
#include
#include "render/colormanager.h"
diff --git a/app/widget/nodetableview/nodetabletraverser.cpp b/app/widget/nodetableview/nodetabletraverser.cpp
index 156409224..69df8e142 100644
--- a/app/widget/nodetableview/nodetabletraverser.cpp
+++ b/app/widget/nodetableview/nodetabletraverser.cpp
@@ -30,6 +30,7 @@ QVariant NodeTableTraverser::ProcessVideoFootage(StreamPtr stream, const rationa
video_stream->height(),
video_stream->timebase(),
video_stream->format(),
+ video_stream->channel_count(),
video_stream->pixel_aspect_ratio()));
}
@@ -39,7 +40,7 @@ QVariant NodeTableTraverser::ProcessAudioFootage(StreamPtr stream, const TimeRan
return QVariant::fromValue(AudioParams(audio_stream->sample_rate(),
audio_stream->channel_layout(),
- SampleFormat::kInternalFormat));
+ AudioParams::kInternalFormat));
}
OLIVE_NAMESPACE_EXIT
diff --git a/app/widget/nodetableview/nodetableview.cpp b/app/widget/nodetableview/nodetableview.cpp
index 722ff0a96..4f5116b7f 100644
--- a/app/widget/nodetableview/nodetableview.cpp
+++ b/app/widget/nodetableview/nodetableview.cpp
@@ -145,7 +145,7 @@ void NodeTableView::SetTime(const rational &time)
case NodeParam::kTexture:
{
// NodeTableTraverser puts video params in here
- for (int k=0;ksetItemWidget(sub_item, 2 + k, new QCheckBox());
}
break;
diff --git a/app/widget/scope/histogram/histogram.cpp b/app/widget/scope/histogram/histogram.cpp
index 87def5cc3..f292ccc29 100644
--- a/app/widget/scope/histogram/histogram.cpp
+++ b/app/widget/scope/histogram/histogram.cpp
@@ -80,7 +80,9 @@ void HistogramScope::DrawScope(TexturePtr managed_tex, QVariant pipeline)
if (!texture_row_sums_
|| texture_row_sums_->width() != this->width()
|| texture_row_sums_->height() != this->height()) {
- texture_row_sums_ = renderer()->CreateTexture(VideoParams(width(), height(), managed_tex->format()));
+ texture_row_sums_ = renderer()->CreateTexture(VideoParams(width(), height(),
+ managed_tex->format(),
+ managed_tex->channel_count()));
}
// Draw managed texture to a sums texture
diff --git a/app/widget/scope/scopebase/scopebase.cpp b/app/widget/scope/scopebase/scopebase.cpp
index 9cf864a24..ebeb1c7a7 100644
--- a/app/widget/scope/scopebase/scopebase.cpp
+++ b/app/widget/scope/scopebase/scopebase.cpp
@@ -20,6 +20,8 @@
#include "scopebase.h"
+#include "config/config.h"
+
OLIVE_NAMESPACE_ENTER
ScopeBase::ScopeBase(QWidget* parent) :
@@ -54,7 +56,9 @@ void ScopeBase::DrawScope(TexturePtr managed_tex, QVariant pipeline)
job.InsertValue(QStringLiteral("ove_maintex"), ShaderValue(QVariant::fromValue(managed_tex), NodeParam::kTexture));
- renderer()->Blit(pipeline, job, VideoParams(width(), height(), PixelFormat::PIX_FMT_RGBA16F));
+ renderer()->Blit(pipeline, job, VideoParams(width(), height(),
+ static_cast(Config::Current()["OfflinePixelFormat"].toInt()),
+ VideoParams::kInternalChannelCount));
}
void ScopeBase::UploadTextureFromBuffer()
diff --git a/app/widget/scope/waveform/waveform.cpp b/app/widget/scope/waveform/waveform.cpp
index 9abd47458..ac4964624 100644
--- a/app/widget/scope/waveform/waveform.cpp
+++ b/app/widget/scope/waveform/waveform.cpp
@@ -28,6 +28,7 @@
#include
#include "common/qtutils.h"
+#include "config/config.h"
#include "node/node.h"
OLIVE_NAMESPACE_ENTER
@@ -74,7 +75,9 @@ void WaveformScope::DrawScope(TexturePtr managed_tex, QVariant pipeline)
job.InsertValue(QStringLiteral("ove_maintex"),
ShaderValue(QVariant::fromValue(managed_tex), NodeParam::kTexture));
- renderer()->Blit(pipeline, job, VideoParams(width(), height(), PixelFormat::PIX_FMT_RGBA16F));
+ renderer()->Blit(pipeline, job, VideoParams(width(), height(),
+ static_cast(Config::Current()["OfflinePixelFormat"].toInt()),
+ VideoParams::kInternalChannelCount));
float waveform_dim_x = ceil((width() - 1.0) * waveform_scale);
float waveform_dim_y = ceil((height() - 1.0) * waveform_scale);
diff --git a/app/widget/standardcombos/pixelformatcombobox.h b/app/widget/standardcombos/pixelformatcombobox.h
index 88ad74f29..7fc29dc94 100644
--- a/app/widget/standardcombos/pixelformatcombobox.h
+++ b/app/widget/standardcombos/pixelformatcombobox.h
@@ -23,7 +23,7 @@
#include
-#include "render/pixelformat.h"
+#include "render/videoparams.h"
OLIVE_NAMESPACE_ENTER
@@ -35,21 +35,21 @@ public:
QComboBox(parent)
{
// Set up preview formats
- for (int i=0;i(i);
+ for (int i=0;i(i);
- if (!float_only || PixelFormat::FormatIsFloat(pix_fmt)) {
- this->addItem(PixelFormat::GetName(pix_fmt), pix_fmt);
+ if (!float_only || VideoParams::FormatIsFloat(pix_fmt)) {
+ this->addItem(VideoParams::GetFormatName(pix_fmt), pix_fmt);
}
}
}
- PixelFormat::Format GetPixelFormat() const
+ VideoParams::Format GetPixelFormat() const
{
- return static_cast(this->currentData().toInt());
+ return static_cast(this->currentData().toInt());
}
- void SetPixelFormat(PixelFormat::Format fmt)
+ void SetPixelFormat(VideoParams::Format fmt)
{
for (int i=0; icount(); i++) {
if (this->itemData(i).toInt() == fmt) {
diff --git a/app/widget/timelinewidget/tool/import.cpp b/app/widget/timelinewidget/tool/import.cpp
index a2c77b7d4..a1552839e 100644
--- a/app/widget/timelinewidget/tool/import.cpp
+++ b/app/widget/timelinewidget/tool/import.cpp
@@ -397,8 +397,8 @@ void ImportTool::DropGhosts(bool insert)
QVector block_items(parent()->GetGhostItems().size());
- // Check if we're inserting
- if (insert) {
+ // Check if we're inserting (only valid if we're not creating this sequence ourselves)
+ if (insert && !open_sequence) {
InsertGapsAtGhostDestination(command);
}
diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp
index ed83de293..d2b584722 100644
--- a/app/widget/viewer/viewer.cpp
+++ b/app/widget/viewer/viewer.cpp
@@ -37,7 +37,6 @@
#include "config/config.h"
#include "project/item/sequence/sequence.h"
#include "project/project.h"
-#include "render/pixelformat.h"
#include "render/rendermanager.h"
#include "task/taskmanager.h"
#include "widget/menu/menu.h"
@@ -113,9 +112,6 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
connect(waveform_view_, &AudioWaveformView::TimeChanged, this, &ViewerWidget::TimeChangedFromWaveform);
connect(waveform_view_, &AudioWaveformView::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
- // Ensures renderer is updated if the global pixel format is changed
- connect(PixelFormat::instance(), &PixelFormat::FormatChanged, this, &ViewerWidget::UpdateRendererVideoParameters);
-
connect(&playback_backup_timer_, &QTimer::timeout, this, &ViewerWidget::PlaybackTimerUpdate);
SetAutoMaxScrollBar(true);
@@ -616,11 +612,6 @@ void ViewerWidget::RequestNextFrameForQueue()
watcher->SetTicket(GetFrame(next_time, false));
}
-PixelFormat::Format ViewerWidget::GetCurrentPixelFormat() const
-{
- return PixelFormat::instance()->GetConfiguredFormatForMode(RenderMode::kOffline);
-}
-
RenderTicketPtr ViewerWidget::GetFrame(const rational &t, bool clear_render_queue)
{
QByteArray cached_hash = GetConnectedNode()->video_frame_cache()->GetHash(t);
diff --git a/app/widget/viewer/viewer.h b/app/widget/viewer/viewer.h
index 887f92b06..838dc4f4f 100644
--- a/app/widget/viewer/viewer.h
+++ b/app/widget/viewer/viewer.h
@@ -191,8 +191,6 @@ private:
void RequestNextFrameForQueue();
- PixelFormat::Format GetCurrentPixelFormat() const;
-
RenderTicketPtr GetFrame(const rational& t, bool clear_render_queue);
void FinishPlayPreprocess();
diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp
index 84e9487bf..68fe1d505 100644
--- a/app/widget/viewer/viewerdisplay.cpp
+++ b/app/widget/viewer/viewerdisplay.cpp
@@ -31,9 +31,9 @@
#include "common/define.h"
#include "common/functiontimer.h"
-#include "gizmotraverser.h"
-#include "render/pixelformat.h"
+#include "config/config.h"
#include "core.h"
+#include "gizmotraverser.h"
OLIVE_NAMESPACE_ENTER
@@ -105,7 +105,8 @@ void ViewerDisplayWidget::SetImage(FramePtr in_buffer)
if (!texture_
|| texture_->width() != in_buffer->width()
|| texture_->height() != in_buffer->height()
- || texture_->format() != in_buffer->format()) {
+ || texture_->format() != in_buffer->format()
+ || texture_->channel_count() != in_buffer->channel_count()) {
texture_ = renderer()->CreateTexture(in_buffer->video_params(), in_buffer->data(), in_buffer->linesize_pixels());
} else {
texture_->Upload(in_buffer->data(), in_buffer->linesize_pixels());
@@ -299,7 +300,7 @@ void ViewerDisplayWidget::OnPaint()
// Draw texture through color transform
renderer()->BlitColorManaged(color_service(), texture_, true,
- VideoParams(width(), height(), PixelFormat::PIX_FMT_RGBA16F),
+ VideoParams(width(), height(), static_cast(Config::Current()["OfflinePixelFormat"].toInt()), VideoParams::kInternalChannelCount),
GetCompleteMatrixFlippedYTranslation());
}