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:
itsmattkc
2020-02-27 13:54:38 +11:00
parent 0624184b18
commit 02ce48d0c6
27 changed files with 491 additions and 564 deletions
+14
View File
@@ -3,7 +3,9 @@
AVPixelFormat FFmpegCommon::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
};
@@ -73,8 +75,14 @@ AVPixelFormat FFmpegCommon::GetFFmpegPixelFormat(const PixelFormat::Format &pix_
return AV_PIX_FMT_RGBA;
case PixelFormat::PIX_FMT_RGBA16U:
return AV_PIX_FMT_RGBA64;
case PixelFormat::PIX_FMT_RGB8:
return AV_PIX_FMT_RGB24;
case PixelFormat::PIX_FMT_RGB16U:
return AV_PIX_FMT_RGB48;
case PixelFormat::PIX_FMT_RGBA16F:
case PixelFormat::PIX_FMT_RGBA32F:
case PixelFormat::PIX_FMT_RGB16F:
case PixelFormat::PIX_FMT_RGB32F:
case PixelFormat::PIX_FMT_INVALID:
case PixelFormat::PIX_FMT_COUNT:
break;
@@ -86,8 +94,14 @@ AVPixelFormat FFmpegCommon::GetFFmpegPixelFormat(const PixelFormat::Format &pix_
PixelFormat::Format FFmpegCommon::GetCompatiblePixelFormat(const PixelFormat::Format &pix_fmt)
{
switch (pix_fmt) {
case PixelFormat::PIX_FMT_RGB8:
return PixelFormat::PIX_FMT_RGB8;
case PixelFormat::PIX_FMT_RGBA8:
return PixelFormat::PIX_FMT_RGBA8;
case PixelFormat::PIX_FMT_RGB16U:
case PixelFormat::PIX_FMT_RGB16F:
case PixelFormat::PIX_FMT_RGB32F:
return PixelFormat::PIX_FMT_RGB16U;
case PixelFormat::PIX_FMT_RGBA16U:
case PixelFormat::PIX_FMT_RGBA16F:
case PixelFormat::PIX_FMT_RGBA32F:
+14 -5
View File
@@ -40,7 +40,7 @@ extern "C" {
#include "common/timecodefunctions.h"
#include "ffmpegcommon.h"
#include "render/diskmanager.h"
#include "render/pixelservice.h"
#include "render/pixelformat.h"
FFmpegDecoder::FFmpegDecoder() :
fmt_ctx_(nullptr),
@@ -154,11 +154,20 @@ bool FFmpegDecoder::Open()
// Determine which Olive native pixel format we retrieved
// Note that FFmpeg doesn't support float formats
if (ideal_pix_fmt_ == AV_PIX_FMT_RGBA) {
switch (ideal_pix_fmt_) {
case AV_PIX_FMT_RGB24:
native_pix_fmt_ = PixelFormat::PIX_FMT_RGB8;
break;
case AV_PIX_FMT_RGBA:
native_pix_fmt_ = PixelFormat::PIX_FMT_RGBA8;
} else if (ideal_pix_fmt_ == AV_PIX_FMT_RGBA64) {
break;
case AV_PIX_FMT_RGB48:
native_pix_fmt_ = PixelFormat::PIX_FMT_RGB16U;
break;
case AV_PIX_FMT_RGBA64:
native_pix_fmt_ = PixelFormat::PIX_FMT_RGBA16U;
} else {
break;
default:
// We should never get here, but just in case...
qFatal("Invalid output format");
}
@@ -378,7 +387,7 @@ FramePtr FFmpegDecoder::RetrieveVideo(const rational &timecode)
// Convert frame to RGBA for the rest of the pipeline
uint8_t* output_data = reinterpret_cast<uint8_t*>(working_frame_converted->data());
int output_linesize = working_frame_converted->width() * kRGBAChannels * PixelService::BytesPerChannel(native_pix_fmt_);
int output_linesize = working_frame_converted->width() * PixelFormat::ChannelCount(native_pix_fmt_) * PixelFormat::BytesPerChannel(native_pix_fmt_);
sws_scale(scale_ctx_,
working_frame->data,
+3 -3
View File
@@ -3,7 +3,7 @@
#include <QFile>
#include "ffmpegcommon.h"
#include "render/pixelservice.h"
#include "render/pixelformat.h"
FFmpegEncoder::FFmpegEncoder(const EncodingParams &params) :
Encoder(params),
@@ -188,12 +188,12 @@ void FFmpegEncoder::WriteInternal(FramePtr frame)
// We may need to convert this frame to a frame that swscale will understand
if (frame->format() != video_conversion_fmt_) {
frame = PixelService::ConvertPixelFormat(frame, video_conversion_fmt_);
frame = PixelFormat::ConvertPixelFormat(frame, video_conversion_fmt_);
}
// Use swscale context to convert formats/linesizes
input_data = frame->const_data();
input_linesize = frame->width() * PixelService::BytesPerPixel(video_conversion_fmt_);
input_linesize = frame->width() * PixelFormat::BytesPerPixel(video_conversion_fmt_);
error_code = sws_scale(video_scale_ctx_,
reinterpret_cast<const uint8_t**>(&input_data),
&input_linesize,
+1 -3
View File
@@ -23,8 +23,6 @@
#include <QDebug>
#include <QtGlobal>
#include "render/pixelservice.h"
Frame::Frame() :
width_(0),
height_(0),
@@ -139,7 +137,7 @@ void Frame::allocate()
{
// Assume this frame is intended to be a video frame
if (width_ > 0 && height_ > 0) {
data_.resize(PixelService::GetBufferSize(static_cast<PixelFormat::Format>(format_), width_, height_));
data_.resize(PixelFormat::GetBufferSize(static_cast<PixelFormat::Format>(format_), width_, height_));
} else if (sample_count_ > 0) {
data_.resize(audio_params_.samples_to_bytes(sample_count_));
}
+8 -14
View File
@@ -115,25 +115,24 @@ bool OIIODecoder::Open()
width_ = spec.width;
height_ = spec.height;
is_rgba_ = (spec.nchannels == kRGBAChannels);
// Weirdly, switch statement doesn't work correctly here
if (spec.format == OIIO::TypeDesc::UINT8) {
pix_fmt_ = PixelFormat::PIX_FMT_RGBA8;
pix_fmt_ = is_rgba_ ? PixelFormat::PIX_FMT_RGBA8 : PixelFormat::PIX_FMT_RGB8;
} else if (spec.format == OIIO::TypeDesc::UINT16) {
pix_fmt_ = PixelFormat::PIX_FMT_RGBA16U;
pix_fmt_ = is_rgba_ ? PixelFormat::PIX_FMT_RGBA16U : PixelFormat::PIX_FMT_RGB16U;
} else if (spec.format == OIIO::TypeDesc::HALF) {
pix_fmt_ = PixelFormat::PIX_FMT_RGBA16F;
pix_fmt_ = is_rgba_ ? PixelFormat::PIX_FMT_RGBA16F : PixelFormat::PIX_FMT_RGB16F;
} else if (spec.format == OIIO::TypeDesc::FLOAT) {
pix_fmt_ = PixelFormat::PIX_FMT_RGBA32F;
pix_fmt_ = is_rgba_ ? PixelFormat::PIX_FMT_RGBA32F : PixelFormat::PIX_FMT_RGB32F;
} else {
qWarning() << "Failed to convert OIIO::ImageDesc to native pixel format";
return false;
}
// FIXME: Many OIIO pixel formats are not handled here
is_rgba_ = (spec.nchannels == kRGBAChannels);
pix_fmt_info_ = PixelService::GetPixelFormatInfo(static_cast<PixelFormat::Format>(pix_fmt_));
type_ = PixelFormat::GetOIIOTypeDesc(pix_fmt_);
open_ = true;
@@ -170,12 +169,7 @@ FramePtr OIIODecoder::RetrieveVideo(const rational &timecode)
frame_->allocate();
// Use the native format to determine what format OIIO should return
// FIXME: Behavior of RGB images as opposed to RGBA?
image_->read_image(pix_fmt_info_.oiio_desc, frame_->data());
if (!is_rgba_) {
PixelService::ConvertRGBtoRGBA(frame_);
}
image_->read_image(type_, frame_->data());
}
return frame_;
+2 -2
View File
@@ -24,7 +24,7 @@
#include <OpenImageIO/imageio.h>
#include "codec/decoder.h"
#include "render/pixelservice.h"
#include "render/pixelformat.h"
class OIIODecoder : public Decoder
{
@@ -57,7 +57,7 @@ private:
PixelFormat::Format pix_fmt_;
PixelFormat::Info pix_fmt_info_;
OIIO::TypeDesc type_;
bool is_rgba_;