various: pixel optimizations
Several things are accomplished in this commit, including: - Use OIIO instead of our own functions for pixel format conversions (cleaner code/less for us to maintain) - Fold all PixelService functions into the PixelFormat class (cleaner code) - Moved OpenGL pixel definitions to OpenGL classes and out of the global classes. - Add support for RGB buffers as well as RGBA (optimization)
This commit is contained in:
@@ -28,8 +28,6 @@ set(OLIVE_SOURCES
|
||||
render/diskmanager.cpp
|
||||
render/pixelformat.h
|
||||
render/pixelformat.cpp
|
||||
render/pixelservice.h
|
||||
render/pixelservice.cpp
|
||||
render/rendermodes.h
|
||||
render/videoparams.h
|
||||
render/videoparams.cpp
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "render/backend/audio/audiobackend.h"
|
||||
#include "render/backend/opengl/openglbackend.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
Exporter::Exporter(ViewerOutput* viewer,
|
||||
Encoder *encoder,
|
||||
@@ -121,7 +121,7 @@ void Exporter::EncodeFrame()
|
||||
|
||||
// OCIO conversion requires a frame in 32F format
|
||||
if (frame->format() != PixelFormat::PIX_FMT_RGBA32F) {
|
||||
frame = PixelService::ConvertPixelFormat(frame, PixelFormat::PIX_FMT_RGBA32F);
|
||||
frame = PixelFormat::ConvertPixelFormat(frame, PixelFormat::PIX_FMT_RGBA32F);
|
||||
}
|
||||
|
||||
// Color conversion must be done with unassociated alpha, and the pipeline is always associated
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "openglcolorprocessor.h"
|
||||
#include "openglrenderfunctions.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
OpenGLProxy::OpenGLProxy(QObject *parent) :
|
||||
QObject(parent),
|
||||
@@ -90,7 +90,7 @@ void OpenGLProxy::FrameToValue(DecoderPtr decoder, StreamPtr stream, const TimeR
|
||||
}
|
||||
|
||||
// Convert frame to float for OCIO
|
||||
frame = PixelService::ConvertPixelFormat(frame, PixelFormat::PIX_FMT_RGBA32F);
|
||||
frame = PixelFormat::ConvertPixelFormat(frame, PixelFormat::PIX_FMT_RGBA32F);
|
||||
|
||||
// Perform color transform
|
||||
color_processor->ConvertFrame(frame);
|
||||
@@ -384,8 +384,6 @@ void OpenGLProxy::TextureToBuffer(const QVariant &tex_in, void *buffer)
|
||||
{
|
||||
OpenGLTextureCache::ReferencePtr texture = tex_in.value<OpenGLTextureCache::ReferencePtr>();
|
||||
|
||||
PixelFormat::Info format_info = PixelService::GetPixelFormatInfo(video_params_.format());
|
||||
|
||||
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
|
||||
buffer_.Attach(texture->texture());
|
||||
buffer_.Bind();
|
||||
@@ -394,8 +392,8 @@ void OpenGLProxy::TextureToBuffer(const QVariant &tex_in, void *buffer)
|
||||
0,
|
||||
video_params_.effective_width(),
|
||||
video_params_.effective_height(),
|
||||
format_info.pixel_format,
|
||||
format_info.gl_pixel_type,
|
||||
OpenGLRenderFunctions::GetPixelFormat(video_params_.format()),
|
||||
OpenGLRenderFunctions::GetPixelType(video_params_.format()),
|
||||
buffer);
|
||||
|
||||
buffer_.Release();
|
||||
|
||||
@@ -71,6 +71,67 @@ void OpenGLRenderFunctions::PrepareToDraw(QOpenGLFunctions* f) {
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
GLint OpenGLRenderFunctions::GetInternalFormat(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
return GL_RGB8;
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return GL_RGBA8;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
return GL_RGB16;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return GL_RGBA16;
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
return GL_RGB16F;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return GL_RGBA16F;
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
return GL_RGB32F;
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return GL_RGBA32F;
|
||||
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
GLenum OpenGLRenderFunctions::GetPixelFormat(const PixelFormat::Format &format)
|
||||
{
|
||||
if (PixelFormat::FormatHasAlphaChannel(format)) {
|
||||
return GL_RGBA;
|
||||
} else {
|
||||
return GL_RGB;
|
||||
}
|
||||
}
|
||||
|
||||
GLenum OpenGLRenderFunctions::GetPixelType(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return GL_HALF_FLOAT;
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return GL_FLOAT;
|
||||
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
void OpenGLRenderFunctions::Blit(OpenGLShaderPtr pipeline, bool flipped, QMatrix4x4 matrix) {
|
||||
// FIXME: is currentContext() reliable here?
|
||||
QOpenGLFunctions* func = QOpenGLContext::currentContext()->functions();
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <QOpenGLFunctions>
|
||||
|
||||
#include "openglshader.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
class OpenGLRenderFunctions {
|
||||
public:
|
||||
@@ -50,6 +51,12 @@ public:
|
||||
|
||||
static void PrepareToDraw(QOpenGLFunctions* f);
|
||||
|
||||
static GLint GetInternalFormat(const PixelFormat::Format& format);
|
||||
|
||||
static GLenum GetPixelFormat(const PixelFormat::Format& format);
|
||||
|
||||
static GLenum GetPixelType(const PixelFormat::Format& format);
|
||||
|
||||
};
|
||||
|
||||
#endif // OPENGLFUNCTIONS_H
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
||||
#include "render/pixelservice.h"
|
||||
#include "openglrenderfunctions.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
OpenGLTexture::OpenGLTexture() :
|
||||
created_ctx_(nullptr),
|
||||
@@ -120,16 +121,14 @@ void OpenGLTexture::Upload(const void *data)
|
||||
|
||||
Bind();
|
||||
|
||||
PixelFormat::Info info = PixelService::GetPixelFormatInfo(format_);
|
||||
|
||||
created_ctx_->functions()->glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
width_,
|
||||
height_,
|
||||
info.pixel_format,
|
||||
info.gl_pixel_type,
|
||||
OpenGLRenderFunctions::GetPixelFormat(format_),
|
||||
OpenGLRenderFunctions::GetPixelType(format_),
|
||||
data);
|
||||
|
||||
Release();
|
||||
@@ -152,16 +151,14 @@ void OpenGLTexture::CreateInternal(QOpenGLContext* create_ctx, GLuint* tex, cons
|
||||
f->glBindTexture(GL_TEXTURE_2D, *tex);
|
||||
|
||||
// Allocate storage for texture
|
||||
const PixelFormat::Info& bit_depth = PixelService::GetPixelFormatInfo(format_);
|
||||
|
||||
f->glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
bit_depth.internal_format,
|
||||
OpenGLRenderFunctions::GetInternalFormat(format_),
|
||||
width_,
|
||||
height_,
|
||||
0,
|
||||
bit_depth.pixel_format,
|
||||
bit_depth.gl_pixel_type,
|
||||
OpenGLRenderFunctions::GetPixelFormat(format_),
|
||||
OpenGLRenderFunctions::GetPixelType(format_),
|
||||
data);
|
||||
|
||||
// Set texture filtering to bilinear
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "openglcolorprocessor.h"
|
||||
#include "openglrenderfunctions.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
OpenGLWorker::OpenGLWorker(VideoRenderFrameCache *frame_cache, DecoderCache* decoder_cache, QObject *parent) :
|
||||
VideoRenderWorker(frame_cache, decoder_cache, parent)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "config/config.h"
|
||||
#include "render/diskmanager.h"
|
||||
#include "render/diskmanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "videorenderworker.h"
|
||||
|
||||
VideoRenderBackend::VideoRenderBackend(QObject *parent) :
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
#include "videorenderworker.h"
|
||||
|
||||
#include "common/define.h"
|
||||
#include "common/functiontimer.h"
|
||||
#include "node/block/transition/transition.h"
|
||||
#include "node/node.h"
|
||||
#include "project/project.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
VideoRenderWorker::VideoRenderWorker(VideoRenderFrameCache *frame_cache, DecoderCache* decoder_cache, QObject *parent) :
|
||||
RenderWorker(decoder_cache, parent),
|
||||
frame_cache_(frame_cache),
|
||||
operating_mode_(kHashRenderCache)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const VideoRenderingParams &VideoRenderWorker::video_params()
|
||||
@@ -225,10 +225,11 @@ void VideoRenderWorker::CloseInternal()
|
||||
|
||||
void VideoRenderWorker::Download(const rational& time, QVariant texture, QString filename)
|
||||
{
|
||||
PixelFormat::Info format_info = PixelService::GetPixelFormatInfo(video_params().format());
|
||||
|
||||
// Set up OIIO::ImageSpec for compressing cached images on disk
|
||||
OIIO::ImageSpec spec(video_params().effective_width(), video_params().effective_height(), kRGBAChannels, format_info.oiio_desc);
|
||||
OIIO::ImageSpec spec(video_params().effective_width(),
|
||||
video_params().effective_height(),
|
||||
PixelFormat::ChannelCount(video_params().format()),
|
||||
PixelFormat::GetOIIOTypeDesc(video_params().format()));
|
||||
|
||||
if (video_params_.format() != PixelFormat::PIX_FMT_RGBA8
|
||||
&& video_params_.format() != PixelFormat::PIX_FMT_RGBA16U) {
|
||||
@@ -249,7 +250,7 @@ void VideoRenderWorker::Download(const rational& time, QVariant texture, QString
|
||||
|
||||
if (out) {
|
||||
out->open(working_fn_std, spec);
|
||||
out->write_image(format_info.oiio_desc, download_buffer_.data());
|
||||
out->write_image(PixelFormat::GetOIIOTypeDesc(video_params().format()), download_buffer_.data());
|
||||
out->close();
|
||||
|
||||
#if OIIO_VERSION < 10903
|
||||
@@ -276,7 +277,7 @@ void VideoRenderWorker::Download(const rational& time, QVariant texture, QString
|
||||
|
||||
void VideoRenderWorker::ResizeDownloadBuffer()
|
||||
{
|
||||
download_buffer_.resize(PixelService::GetBufferSize(video_params_.format(), video_params_.effective_width(), video_params_.effective_height()));
|
||||
download_buffer_.resize(PixelFormat::GetBufferSize(video_params_.format(), video_params_.effective_width(), video_params_.effective_height()));
|
||||
}
|
||||
|
||||
NodeValueTable VideoRenderWorker::RenderBlock(const TrackOutput *track, const TimeRange &range)
|
||||
|
||||
@@ -123,6 +123,11 @@ void ColorManager::SetOCIOMethodForMode(RenderMode::Mode mode, ColorManager::OCI
|
||||
|
||||
void ColorManager::AssociateAlphaPixFmtFilter(ColorManager::AlphaAction action, FramePtr f)
|
||||
{
|
||||
if (!PixelFormat::FormatHasAlphaChannel(f->format())) {
|
||||
// This frame has no alpha channel, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
int pixel_count = f->width() * f->height() * kRGBAChannels;
|
||||
|
||||
switch (static_cast<PixelFormat::Format>(f->format())) {
|
||||
@@ -130,15 +135,19 @@ void ColorManager::AssociateAlphaPixFmtFilter(ColorManager::AlphaAction action,
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
qWarning() << "Alpha association functions received an invalid pixel format";
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
qWarning() << "Alpha association functions only works on float-based pixel formats at this time";
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
{
|
||||
AssociateAlphaInternal<qfloat16>(action, reinterpret_cast<qfloat16*>(f->data()), pixel_count);
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
{
|
||||
AssociateAlphaInternal<float>(action, reinterpret_cast<float*>(f->data()), pixel_count);
|
||||
|
||||
@@ -38,7 +38,7 @@ ColorProcessor::ColorProcessor(OCIO::ConstConfigRcPtr config,
|
||||
|
||||
void ColorProcessor::ConvertFrame(FramePtr f)
|
||||
{
|
||||
OCIO::PackedImageDesc img(reinterpret_cast<float*>(f->data()), f->width(), f->height(), kRGBAChannels);
|
||||
OCIO::PackedImageDesc img(reinterpret_cast<float*>(f->data()), f->width(), f->height(), PixelFormat::ChannelCount(f->format()));
|
||||
|
||||
processor->apply(img);
|
||||
}
|
||||
|
||||
@@ -19,3 +19,237 @@
|
||||
***/
|
||||
|
||||
#include "pixelformat.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFloat16>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "core.h"
|
||||
|
||||
bool PixelFormat::FormatHasAlphaChannel(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return true;
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
OIIO::TypeDesc PixelFormat::GetOIIOTypeDesc(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return OIIO::TypeDesc::UINT8;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return OIIO::TypeDesc::UINT16;
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return OIIO::TypeDesc::HALF;
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
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_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return tr("8-bit");
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return tr("16-bit Integer");
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return tr("Half-Float (16-bit)");
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
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);
|
||||
}
|
||||
|
||||
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<PixelFormat::Format>(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, bool has_alpha)
|
||||
{
|
||||
if (desc == OIIO::TypeDesc::UINT8) {
|
||||
return has_alpha ? PixelFormat::PIX_FMT_RGBA8 : PixelFormat::PIX_FMT_RGB8;
|
||||
} else if (desc == OIIO::TypeDesc::UINT16) {
|
||||
return has_alpha ? PixelFormat::PIX_FMT_RGBA16U : PixelFormat::PIX_FMT_RGB16U;
|
||||
} else if (desc == OIIO::TypeDesc::HALF) {
|
||||
return has_alpha ? PixelFormat::PIX_FMT_RGBA16F : PixelFormat::PIX_FMT_RGB16F;
|
||||
} else if (desc == OIIO::TypeDesc::FLOAT) {
|
||||
return has_alpha ? PixelFormat::PIX_FMT_RGBA32F : PixelFormat::PIX_FMT_RGB32F;
|
||||
}
|
||||
|
||||
return PixelFormat::PIX_FMT_INVALID;
|
||||
}
|
||||
|
||||
/*PixelFormat::Info PixelFormat::GetPixelFormatInfo(const PixelFormat::Format &format)
|
||||
{
|
||||
PixelFormat::Info info;
|
||||
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
info.name = tr("8-bit");
|
||||
info.internal_format = (format == PixelFormat::PIX_FMT_RGB8) ? GL_RGB8 : GL_RGBA8;
|
||||
info.gl_pixel_type = GL_UNSIGNED_BYTE;
|
||||
info.oiio_desc = OIIO::TypeDesc::UINT8;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
info.name = tr("16-bit Integer");
|
||||
info.internal_format = (format == PixelFormat::PIX_FMT_RGB16U) ? GL_RGB8 : GL_RGBA16;
|
||||
info.gl_pixel_type = GL_UNSIGNED_SHORT;
|
||||
info.oiio_desc = OIIO::TypeDesc::UINT16;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
info.name = tr("Half-Float (16-bit)");
|
||||
info.internal_format = (format == PixelFormat::PIX_FMT_RGB8) ? GL_RGB8 : GL_RGBA16F;
|
||||
info.gl_pixel_type = GL_HALF_FLOAT;
|
||||
info.oiio_desc = OIIO::TypeDesc::HALF;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
info.name = tr("Full-Float (32-bit)");
|
||||
info.internal_format = (format == PixelFormat::PIX_FMT_RGB8) ? GL_RGB8 : GL_RGBA32F;
|
||||
info.gl_pixel_type = GL_FLOAT;
|
||||
info.oiio_desc = OIIO::TypeDesc::FLOAT;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
qFatal("Invalid pixel format requested");
|
||||
}
|
||||
|
||||
info.pixel_format = GL_RGBA;
|
||||
info.bytes_per_pixel = BytesPerPixel(format);
|
||||
|
||||
return info;
|
||||
}*/
|
||||
|
||||
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) * ChannelCount(format);
|
||||
}
|
||||
|
||||
int PixelFormat::BytesPerChannel(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return 1;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return 2;
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
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;
|
||||
}
|
||||
|
||||
int PixelFormat::ChannelCount(const PixelFormat::Format &format)
|
||||
{
|
||||
if (PixelFormat::FormatHasAlphaChannel(format)) {
|
||||
return kRGBAChannels;
|
||||
} else {
|
||||
return kRGBChannels;
|
||||
}
|
||||
}
|
||||
|
||||
FramePtr PixelFormat::ConvertPixelFormat(FramePtr frame, const PixelFormat::Format &dest_format)
|
||||
{
|
||||
if (frame->format() == dest_format) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
FramePtr converted = Frame::Create();
|
||||
|
||||
// Copy parameters
|
||||
converted->set_width(frame->width());
|
||||
converted->set_height(frame->height());
|
||||
converted->set_timestamp(frame->timestamp());
|
||||
converted->set_format(dest_format);
|
||||
converted->allocate();
|
||||
|
||||
OIIO::TypeDesc src_type = GetOIIOTypeDesc(frame->format());
|
||||
OIIO::TypeDesc dst_type = GetOIIOTypeDesc(dest_format);
|
||||
|
||||
if (OIIO::convert_type(src_type, frame->data(), dst_type, converted->data())) {
|
||||
return converted;
|
||||
} else {
|
||||
qDebug() << "Failed to convert type:" << OIIO::geterror().c_str();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+89
-17
@@ -25,7 +25,14 @@
|
||||
#include <QOpenGLExtraFunctions>
|
||||
#include <QString>
|
||||
|
||||
class PixelFormat {
|
||||
#include "render/rendermodes.h"
|
||||
|
||||
class Frame;
|
||||
using FramePtr = std::shared_ptr<Frame>;
|
||||
|
||||
class PixelFormat : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief Olive's internal supported pixel formats.
|
||||
@@ -38,27 +45,92 @@ public:
|
||||
PIX_FMT_RGBA16F,
|
||||
PIX_FMT_RGBA32F,
|
||||
|
||||
PIX_FMT_RGB8,
|
||||
PIX_FMT_RGB16U,
|
||||
PIX_FMT_RGB16F,
|
||||
PIX_FMT_RGB32F,
|
||||
|
||||
PIX_FMT_COUNT
|
||||
};
|
||||
|
||||
static void CreateInstance();
|
||||
static void DestroyInstance();
|
||||
static PixelFormat* instance();
|
||||
|
||||
/**
|
||||
* @brief A struct of information pertaining to each enum PixelFormat.
|
||||
*
|
||||
* Primarily this is a means of retrieving OpenGL texture information for different pixel formats/bit depths. Both
|
||||
* RAM and VRAM buffers will need a PixelFormat. To keep consistency between the OpenGL code and CPU code when using
|
||||
* a given PixelFormat, the PixelFormatInfo struct contains all necessary variables that you'll need to plug into
|
||||
* OpenGL.
|
||||
*
|
||||
* Use the static function PixelService::GetPixelFormatInfo to generate a PixelFormatInfo object.
|
||||
* @brief Returns the configured pixel format for a given mode
|
||||
*/
|
||||
struct Info {
|
||||
QString name;
|
||||
GLint internal_format;
|
||||
GLenum pixel_format;
|
||||
GLenum gl_pixel_type;
|
||||
int bytes_per_pixel;
|
||||
OIIO::TypeDesc oiio_desc;
|
||||
};
|
||||
Format GetConfiguredFormatForMode(RenderMode::Mode mode);
|
||||
void SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format);
|
||||
|
||||
static Format OIIOFormatToOliveFormat(OIIO::TypeDesc desc, bool has_alpha);
|
||||
|
||||
/**
|
||||
* @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 Return the number of channels in this format
|
||||
*/
|
||||
static int ChannelCount(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 has an alpha channel or not
|
||||
*/
|
||||
static bool FormatHasAlphaChannel(const Format& format);
|
||||
|
||||
/**
|
||||
* @brief Get corresponding OpenImageIO TypeDesc for a given pixel format
|
||||
*/
|
||||
static OIIO::TypeDesc GetOIIOTypeDesc(const Format& format);
|
||||
|
||||
/**
|
||||
* @brief Get format name
|
||||
*/
|
||||
static QString GetName(const Format& format);
|
||||
|
||||
signals:
|
||||
void FormatChanged();
|
||||
|
||||
private:
|
||||
PixelFormat() = default;
|
||||
|
||||
static PixelFormat* instance_;
|
||||
|
||||
};
|
||||
|
||||
#endif // BITDEPTHS_H
|
||||
|
||||
@@ -1,366 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "pixelservice.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFloat16>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "core.h"
|
||||
|
||||
PixelService* PixelService::instance_ = nullptr;
|
||||
|
||||
void PixelService::CreateInstance()
|
||||
{
|
||||
instance_ = new PixelService();
|
||||
}
|
||||
|
||||
void PixelService::DestroyInstance()
|
||||
{
|
||||
delete instance_;
|
||||
}
|
||||
|
||||
PixelService *PixelService::instance()
|
||||
{
|
||||
return instance_;
|
||||
}
|
||||
|
||||
PixelFormat::Format PixelService::GetConfiguredFormatForMode(RenderMode::Mode mode)
|
||||
{
|
||||
return static_cast<PixelFormat::Format>(Core::GetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat")).toInt());
|
||||
}
|
||||
|
||||
void PixelService::SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format)
|
||||
{
|
||||
if (format != GetConfiguredFormatForMode(mode)) {
|
||||
Core::SetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat"), format);
|
||||
|
||||
emit FormatChanged();
|
||||
}
|
||||
}
|
||||
|
||||
PixelFormat::Format PixelService::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;
|
||||
}
|
||||
|
||||
PixelFormat::Info PixelService::GetPixelFormatInfo(const PixelFormat::Format &format)
|
||||
{
|
||||
PixelFormat::Info info;
|
||||
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
info.name = tr("8-bit");
|
||||
info.internal_format = GL_RGBA8;
|
||||
info.gl_pixel_type = GL_UNSIGNED_BYTE;
|
||||
info.oiio_desc = OIIO::TypeDesc::UINT8;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
info.name = tr("16-bit Integer");
|
||||
info.internal_format = GL_RGBA16;
|
||||
info.gl_pixel_type = GL_UNSIGNED_SHORT;
|
||||
info.oiio_desc = OIIO::TypeDesc::UINT16;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
info.name = tr("Half-Float (16-bit)");
|
||||
info.internal_format = GL_RGBA16F;
|
||||
info.gl_pixel_type = GL_HALF_FLOAT;
|
||||
info.oiio_desc = OIIO::TypeDesc::HALF;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
info.name = tr("Full-Float (32-bit)");
|
||||
info.internal_format = GL_RGBA32F;
|
||||
info.gl_pixel_type = GL_FLOAT;
|
||||
info.oiio_desc = OIIO::TypeDesc::FLOAT;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
qFatal("Invalid pixel format requested");
|
||||
}
|
||||
|
||||
info.pixel_format = GL_RGBA;
|
||||
info.bytes_per_pixel = BytesPerPixel(format);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
int PixelService::GetBufferSize(const PixelFormat::Format &format, const int &width, const int &height)
|
||||
{
|
||||
return BytesPerPixel(format) * width * height;
|
||||
}
|
||||
|
||||
int PixelService::BytesPerPixel(const PixelFormat::Format &format)
|
||||
{
|
||||
return BytesPerChannel(format) * kRGBAChannels;
|
||||
}
|
||||
|
||||
int PixelService::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 PixelService::ConvertPixelFormat(FramePtr frame, const PixelFormat::Format &dest_format)
|
||||
{
|
||||
if (frame->format() == dest_format) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
// FIXME: It'd be nice if this was multithreaded soon
|
||||
|
||||
FramePtr converted = Frame::Create();
|
||||
|
||||
// Copy parameters
|
||||
converted->set_width(frame->width());
|
||||
converted->set_height(frame->height());
|
||||
converted->set_timestamp(frame->timestamp());
|
||||
converted->set_format(dest_format);
|
||||
converted->allocate();
|
||||
|
||||
int pix_count = frame->width() * frame->height() * kRGBAChannels;
|
||||
|
||||
bool valid = true;
|
||||
|
||||
switch (static_cast<PixelFormat::Format>(frame->format())) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
{
|
||||
uint8_t* source = reinterpret_cast<uint8_t*>(frame->data());
|
||||
|
||||
switch (dest_format) {
|
||||
case PixelFormat::PIX_FMT_RGBA16U: // 8-bit Integer -> 16-bit Integer
|
||||
{
|
||||
uint16_t* destination = reinterpret_cast<uint16_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint16_t>(source[i] * 257);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16F: // 8-bit Integer -> 16-bit Float
|
||||
{
|
||||
qfloat16* destination = reinterpret_cast<qfloat16*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i] / 255.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA32F: // 8-bit Integer -> 32-bit Float
|
||||
{
|
||||
float* destination = reinterpret_cast<float*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i] / 255.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
{
|
||||
uint16_t* source = reinterpret_cast<uint16_t*>(frame->data());
|
||||
|
||||
switch (dest_format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8: // 16-bit Integer -> 8-bit Integer
|
||||
{
|
||||
uint8_t* destination = reinterpret_cast<uint8_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint8_t>(source[i] / 257);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16F: // 16-bit Integer -> 16-bit Float
|
||||
{
|
||||
qfloat16* destination = reinterpret_cast<qfloat16*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i] / 65535.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA32F: // 16-bit Integer -> 32-bit Float
|
||||
{
|
||||
float* destination = reinterpret_cast<float*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i] / 65535.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
{
|
||||
qfloat16* source = reinterpret_cast<qfloat16*>(frame->data());
|
||||
|
||||
switch (dest_format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8: // 16-bit Float -> 8-bit Integer
|
||||
{
|
||||
uint8_t* destination = reinterpret_cast<uint8_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint8_t>(source[i] * 255.0f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16U: // 16-bit Float -> 16-bit Integer
|
||||
{
|
||||
uint16_t* destination = reinterpret_cast<uint16_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint16_t>(source[i] * 65535.0f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA32F: // 16-bit Float -> 32-bit Float
|
||||
{
|
||||
float* destination = reinterpret_cast<float*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
{
|
||||
float* source = reinterpret_cast<float*>(frame->data());
|
||||
|
||||
switch (dest_format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8: // 32-bit Float -> 8-bit Integer
|
||||
{
|
||||
uint8_t* destination = reinterpret_cast<uint8_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint8_t>(source[i] * 255.0f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16U: // 32-bit Float -> 16-bit Integer
|
||||
{
|
||||
uint16_t* destination = reinterpret_cast<uint16_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint16_t>(source[i] * 65535.0f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16F: // 32-bit Float -> 16-bit Float
|
||||
{
|
||||
qfloat16* destination = reinterpret_cast<qfloat16*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
return converted;
|
||||
}
|
||||
|
||||
qWarning() << "Invalid parameters called for pixel format conversion";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PixelService::ConvertRGBtoRGBA(FramePtr frame)
|
||||
{
|
||||
PixelFormat::Format dest_format = static_cast<PixelFormat::Format>(frame->format());
|
||||
|
||||
int rgb_pixel_size = BytesPerChannel(dest_format) * kRGBChannels;
|
||||
int rgb_frame_size = frame->width() * frame->height() * rgb_pixel_size;
|
||||
int rgb_iter = rgb_frame_size - rgb_pixel_size;
|
||||
|
||||
int rgba_pixel_size = BytesPerChannel(dest_format) * kRGBAChannels;
|
||||
int rgba_frame_size = frame->width() * frame->height() * rgba_pixel_size;
|
||||
int rgba_iter = rgba_frame_size - rgba_pixel_size;
|
||||
|
||||
// Work backwards to save time
|
||||
while (rgb_iter >= 0) {
|
||||
memcpy(&frame->data()[rgba_iter], &frame->data()[rgb_iter], static_cast<size_t>(rgb_pixel_size));
|
||||
|
||||
uint8_t* alpha_ptr = reinterpret_cast<uint8_t*>(frame->data()) + rgba_iter + rgb_pixel_size;
|
||||
|
||||
// Write a full alpha value according to the format
|
||||
switch (dest_format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
*alpha_ptr = UINT8_MAX;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
*reinterpret_cast<uint16_t*>(alpha_ptr) = UINT16_MAX;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
*reinterpret_cast<qfloat16*>(alpha_ptr) = 1.0f;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
*reinterpret_cast<float*>(alpha_ptr) = 1.0f;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
qFatal("Invalid pixel format requested");
|
||||
}
|
||||
|
||||
rgb_iter -= rgb_pixel_size;
|
||||
rgba_iter -= rgba_pixel_size;
|
||||
}
|
||||
}
|
||||
@@ -1,106 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef PIXELSERVICE_H
|
||||
#define PIXELSERVICE_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "codec/frame.h"
|
||||
#include "pixelformat.h"
|
||||
#include "render/rendermodes.h"
|
||||
|
||||
class PixelService : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static void CreateInstance();
|
||||
static void DestroyInstance();
|
||||
static PixelService* instance();
|
||||
|
||||
/**
|
||||
* @brief Returns the configured pixel format for a given mode
|
||||
*/
|
||||
PixelFormat::Format GetConfiguredFormatForMode(RenderMode::Mode mode);
|
||||
void SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format);
|
||||
|
||||
static PixelFormat::Format OIIOFormatToOliveFormat(OIIO::TypeDesc desc);
|
||||
|
||||
/**
|
||||
* @brief Return a PixelFormatInfo containing information for a certain format
|
||||
*
|
||||
* \see PixelFormatInfo
|
||||
*/
|
||||
static PixelFormat::Info GetPixelFormatInfo(const PixelFormat::Format& format);
|
||||
|
||||
/**
|
||||
* @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 PixelFormat::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 PixelFormat::Format &format);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of bytes per channel for a certain format
|
||||
*/
|
||||
static int BytesPerChannel(const PixelFormat::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 PixelFormat::Format &dest_format);
|
||||
|
||||
/**
|
||||
* @brief Convert an RGB image to an RGBA image
|
||||
*/
|
||||
static void ConvertRGBtoRGBA(FramePtr frame);
|
||||
|
||||
signals:
|
||||
void FormatChanged();
|
||||
|
||||
private:
|
||||
PixelService() = default;
|
||||
|
||||
static PixelService* instance_;
|
||||
|
||||
};
|
||||
|
||||
#endif // PIXELSERVICE_H
|
||||
Reference in New Issue
Block a user