oiiodecoder: improved code

This commit is contained in:
itsmattkc
2022-05-24 18:49:29 -07:00
parent 6371fe0bc0
commit c2570b23c3
3 changed files with 61 additions and 53 deletions
+46 -42
View File
@@ -20,7 +20,6 @@
#include "oiiodecoder.h"
#include <OpenImageIO/imagebufalgo.h>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
@@ -36,8 +35,7 @@ namespace olive {
QStringList OIIODecoder::supported_formats_;
OIIODecoder::OIIODecoder() :
image_(nullptr),
buffer_(nullptr)
image_(nullptr)
{
}
@@ -75,17 +73,11 @@ FootageDescription OIIODecoder::Probe(const QString &filename, const QAtomicInt*
bool stream_enabled = true;
for (int i=0; in->seek_subimage(i, 0); i++) {
VideoParams video_params;
OIIO::ImageSpec spec = in->spec();
VideoParams video_params = GetVideoParamsFromImageSpec(spec);
video_params.set_stream_index(i);
video_params.set_width(spec.width);
video_params.set_height(spec.height);
video_params.set_format(OIIOUtils::GetFormatFromOIIOBasetype(static_cast<OIIO::TypeDesc::BASETYPE>(spec.format.basetype)));
video_params.set_channel_count(spec.nchannels);
video_params.set_pixel_aspect_ratio(OIIOUtils::GetPixelAspectRatioFromOIIO(spec));
video_params.set_video_type(VideoParams::kVideoTypeStill);
if (i > 1) {
// This is a multilayer image and this image might have an offset
@@ -128,31 +120,40 @@ bool OIIODecoder::RetrieveVideoInternal(TexturePtr destination, const rational &
Q_UNUSED(timecode)
Q_UNUSED(cancelled)
VideoParams vp(buffer_->spec().width,
buffer_->spec().height,
pix_fmt_,
channel_count_,
OIIOUtils::GetPixelAspectRatioFromOIIO(buffer_->spec()),
VideoParams::kInterlaceNone, // FIXME: Does OIIO deinterlace for us?
params.divider);
VideoParams vp = GetVideoParamsFromImageSpec(image_->spec());
vp.set_divider(params.divider);
if (params.divider == 1) {
if (!buffer_.is_allocated() || last_params_ != params) {
last_params_ = params;
destination->Upload(buffer_->localpixels(), buffer_->scanline_stride() / vp.GetBytesPerPixel());
buffer_.destroy();
buffer_.set_video_params(vp);
buffer_.allocate();
} else {
if (params.divider == 1) {
// Just upload straight to the buffer
image_->read_image(oiio_pix_fmt_, buffer_.data(), OIIO::AutoStride, buffer_.linesize_bytes());
} else {
OIIO::ImageBuf buf(image_->spec());
image_->read_image(image_->spec().format, buf.localpixels(), buf.pixel_stride(), buf.scanline_stride(), buf.z_stride());
// Will need to resize the image
OIIO::ImageBuf dst(OIIO::ImageSpec(vp.effective_width(), vp.effective_height(), buffer_->spec().nchannels, buffer_->spec().format));
// Roughly downsample image for divider (for some reason OIIO::ImageBufAlgo::resample failed here)
int px_sz = vp.GetBytesPerPixel();
for (int dst_y=0; dst_y<buffer_.height(); dst_y++) {
int src_y = dst_y * buf.spec().height / buffer_.height();
if (!OIIO::ImageBufAlgo::resample(dst, *buffer_)) {
qWarning() << "OIIO resize failed";
for (int dst_x=0; dst_x<buffer_.width(); dst_x++) {
int src_x = dst_x * buf.spec().width / buffer_.width();
memcpy(buffer_.data() + buffer_.linesize_bytes() * dst_y + px_sz * dst_x,
static_cast<uint8_t*>(buf.localpixels()) + buf.scanline_stride() * src_y + px_sz * src_x,
px_sz);
}
}
}
destination->Upload(dst.localpixels(), dst.scanline_stride() / vp.GetBytesPerPixel());
}
destination->Upload(buffer_.data(), buffer_.linesize_pixels());
return true;
}
@@ -201,9 +202,6 @@ bool OIIODecoder::OpenImageHandler(const QString &fn, int subimage)
// Check if we can work with this pixel format
const OIIO::ImageSpec& spec = image_->spec();
// Store channel count
channel_count_ = spec.nchannels;
// We use RGBA frames because that tends to be the native format of GPUs
pix_fmt_ = OIIOUtils::GetFormatFromOIIOBasetype(static_cast<OIIO::TypeDesc::BASETYPE>(spec.format.basetype));
@@ -212,18 +210,13 @@ bool OIIODecoder::OpenImageHandler(const QString &fn, int subimage)
return false;
}
OIIO::TypeDesc::BASETYPE type = OIIOUtils::GetOIIOBaseTypeFromFormat(pix_fmt_);
oiio_pix_fmt_ = OIIOUtils::GetOIIOBaseTypeFromFormat(pix_fmt_);
if (type == OIIO::TypeDesc::UNKNOWN) {
if (oiio_pix_fmt_ == OIIO::TypeDesc::UNKNOWN) {
qCritical() << "Failed to determine appropriate OIIO basetype from native format";
return false;
}
buffer_ = new OIIO::ImageBuf(OIIO::ImageSpec(spec.width, spec.height, spec.nchannels, type),
OIIO::InitializePixels::No);
image_->read_image(type, buffer_->localpixels());
return true;
}
@@ -234,10 +227,21 @@ void OIIODecoder::CloseImageHandle()
image_ = nullptr;
}
if (buffer_) {
delete buffer_;
buffer_ = nullptr;
}
buffer_.destroy();
}
VideoParams OIIODecoder::GetVideoParamsFromImageSpec(const OIIO::ImageSpec &spec)
{
VideoParams video_params;
video_params.set_width(spec.width);
video_params.set_height(spec.height);
video_params.set_format(OIIOUtils::GetFormatFromOIIOBasetype(static_cast<OIIO::TypeDesc::BASETYPE>(spec.format.basetype)));
video_params.set_channel_count(spec.nchannels);
video_params.set_pixel_aspect_ratio(OIIOUtils::GetPixelAspectRatioFromOIIO(spec));
video_params.set_video_type(VideoParams::kVideoTypeStill);
return video_params;
}
}
+5 -3
View File
@@ -56,11 +56,13 @@ private:
void CloseImageHandle();
static VideoParams GetVideoParamsFromImageSpec(const OIIO::ImageSpec &spec);
VideoParams::Format pix_fmt_;
OIIO::TypeDesc::BASETYPE oiio_pix_fmt_;
int channel_count_;
OIIO::ImageBuf* buffer_;
Frame buffer_;
RetrieveVideoParams last_params_;
static QStringList supported_formats_;
+10 -8
View File
@@ -424,23 +424,25 @@ void RenderProcessor::ProcessVideoFootage(TexturePtr destination, const FootageJ
DecoderPtr decoder = nullptr;
if (stream_data.video_type() == VideoParams::kVideoTypeVideo) {
switch (stream_data.video_type()) {
case VideoParams::kVideoTypeVideo:
case VideoParams::kVideoTypeStill:
decoder = ResolveDecoderFromInput(decoder_id, default_codec_stream);
} else {
break;
case VideoParams::kVideoTypeImageSequence:
{
// Since image sequences involve multiple files, we don't engage the decoder cache
decoder = Decoder::CreateFromID(decoder_id);
QString frame_filename;
if (stream_data.video_type() == VideoParams::kVideoTypeImageSequence) {
int64_t frame_number = stream_data.get_time_in_timebase_units(input_time);
frame_filename = Decoder::TransformImageSequenceFileName(stream.filename(), frame_number);
} else {
frame_filename = stream.filename();
}
int64_t frame_number = stream_data.get_time_in_timebase_units(input_time);
frame_filename = Decoder::TransformImageSequenceFileName(stream.filename(), frame_number);
// Decoder will close automatically since it's a stream_ptr
decoder->Open(Decoder::CodecStream(frame_filename, stream_data.stream_index()));
break;
}
}
if (decoder) {