oiiodecoder: improved code
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user