diff --git a/app/codec/oiio/oiiodecoder.cpp b/app/codec/oiio/oiiodecoder.cpp index 9f755216f..1d98bae6c 100644 --- a/app/codec/oiio/oiiodecoder.cpp +++ b/app/codec/oiio/oiiodecoder.cpp @@ -20,7 +20,6 @@ #include "oiiodecoder.h" -#include #include #include #include @@ -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(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(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(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(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; } } diff --git a/app/codec/oiio/oiiodecoder.h b/app/codec/oiio/oiiodecoder.h index b5360e042..3d863da4e 100644 --- a/app/codec/oiio/oiiodecoder.h +++ b/app/codec/oiio/oiiodecoder.h @@ -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_; diff --git a/app/render/renderprocessor.cpp b/app/render/renderprocessor.cpp index 0eb5d294e..064279753 100644 --- a/app/render/renderprocessor.cpp +++ b/app/render/renderprocessor.cpp @@ -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) {