From 695adea56269932c6095453b2893ff5faaf120b4 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 5 Sep 2019 00:03:26 +1000 Subject: [PATCH] added OIIO decoder --- app/decoder/CMakeLists.txt | 1 + app/decoder/decoder.cpp | 2 + app/decoder/ffmpeg/ffmpegdecoder.cpp | 7 +- app/decoder/frame.cpp | 5 + app/decoder/frame.h | 7 +- app/decoder/oiio/CMakeLists.txt | 22 ++++ app/decoder/oiio/oiiodecoder.cpp | 126 +++++++++++++++++++++++ app/decoder/oiio/oiiodecoder.h | 59 +++++++++++ app/project/item/footage/CMakeLists.txt | 2 + app/project/item/footage/footage.cpp | 16 ++- app/project/item/footage/footage.h | 1 + app/project/item/footage/imagestream.cpp | 46 +++++++++ app/project/item/footage/imagestream.h | 47 +++++++++ app/project/item/footage/stream.h | 3 +- app/project/item/footage/videostream.cpp | 20 ---- app/project/item/footage/videostream.h | 18 +--- app/render/pixelservice.cpp | 2 +- 17 files changed, 337 insertions(+), 47 deletions(-) create mode 100644 app/decoder/oiio/CMakeLists.txt create mode 100644 app/decoder/oiio/oiiodecoder.cpp create mode 100644 app/decoder/oiio/oiiodecoder.h create mode 100644 app/project/item/footage/imagestream.cpp create mode 100644 app/project/item/footage/imagestream.h diff --git a/app/decoder/CMakeLists.txt b/app/decoder/CMakeLists.txt index 22ab4ae4b..272ef91bb 100644 --- a/app/decoder/CMakeLists.txt +++ b/app/decoder/CMakeLists.txt @@ -15,6 +15,7 @@ # along with this program. If not, see . add_subdirectory(ffmpeg) +add_subdirectory(oiio) set(OLIVE_SOURCES ${OLIVE_SOURCES} diff --git a/app/decoder/decoder.cpp b/app/decoder/decoder.cpp index 96ee1f257..583a057c2 100644 --- a/app/decoder/decoder.cpp +++ b/app/decoder/decoder.cpp @@ -25,6 +25,7 @@ #include #include "decoder/ffmpeg/ffmpegdecoder.h" +#include "decoder/oiio/oiiodecoder.h" Decoder::Decoder() : open_(false), @@ -61,6 +62,7 @@ void Decoder::set_stream(StreamPtr fs) QVector ReceiveListOfAllDecoders() { QVector decoders; + decoders.append(std::make_shared()); decoders.append(std::make_shared()); return decoders; diff --git a/app/decoder/ffmpeg/ffmpegdecoder.cpp b/app/decoder/ffmpeg/ffmpegdecoder.cpp index e3f6e3368..fc62a44df 100644 --- a/app/decoder/ffmpeg/ffmpegdecoder.cpp +++ b/app/decoder/ffmpeg/ffmpegdecoder.cpp @@ -246,10 +246,10 @@ FramePtr FFmpegDecoder::Retrieve(const rational &timecode, const rational &lengt } // Frame was valid, now we create an Olive frame to place the data into - FramePtr frame_container = std::make_shared(); + FramePtr frame_container = Frame::Create(); frame_container->set_width(frame_->width); frame_container->set_height(frame_->height); - frame_container->set_format(output_fmt_); // FIXME: Hardcoded value + frame_container->set_format(output_fmt_); frame_container->set_timestamp(rational(frame_->pts * avstream_->time_base.num, avstream_->time_base.den)); frame_container->allocate(); @@ -266,10 +266,9 @@ FramePtr FFmpegDecoder::Retrieve(const rational &timecode, const rational &lengt &dst_data, &dst_linesize); + // Audio decoding will use a length value eventually Q_UNUSED(length) -// Close(); - return frame_container; } diff --git a/app/decoder/frame.cpp b/app/decoder/frame.cpp index 8211be699..fafa082b7 100644 --- a/app/decoder/frame.cpp +++ b/app/decoder/frame.cpp @@ -31,6 +31,11 @@ Frame::Frame() : { } +FramePtr Frame::Create() +{ + return std::make_shared(); +} + const int &Frame::width() { return width_; diff --git a/app/decoder/frame.h b/app/decoder/frame.h index 6151e4533..3a27b6b9f 100644 --- a/app/decoder/frame.h +++ b/app/decoder/frame.h @@ -27,6 +27,9 @@ #include "common/rational.h" #include "render/pixelformat.h" +class Frame; +using FramePtr = std::shared_ptr; + /** * @brief Video frame data or audio sample data from a Decoder * @@ -40,6 +43,8 @@ public: /// Normal constructor Frame(); + static FramePtr Create(); + /** * @brief Get frame's width in pixels */ @@ -107,6 +112,4 @@ private: }; -using FramePtr = std::shared_ptr; - #endif // FRAME_H diff --git a/app/decoder/oiio/CMakeLists.txt b/app/decoder/oiio/CMakeLists.txt new file mode 100644 index 000000000..5a20b7719 --- /dev/null +++ b/app/decoder/oiio/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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 . + +set(OLIVE_SOURCES + ${OLIVE_SOURCES} + decoder/oiio/oiiodecoder.h + decoder/oiio/oiiodecoder.cpp + PARENT_SCOPE +) diff --git a/app/decoder/oiio/oiiodecoder.cpp b/app/decoder/oiio/oiiodecoder.cpp new file mode 100644 index 000000000..df674f755 --- /dev/null +++ b/app/decoder/oiio/oiiodecoder.cpp @@ -0,0 +1,126 @@ +/*** + + 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 . + +***/ + +#include "oiiodecoder.h" + +#include + +OIIODecoder::OIIODecoder() +{ +} + +QString OIIODecoder::id() +{ + return "oiio"; +} + +bool OIIODecoder::Probe(Footage *f) +{ + auto in = OIIO::ImageInput::open(f->filename().toStdString()); + + if (!in) { + return false; + } + + // Get stats for this image and dump them into the Footage file + const OIIO::ImageSpec& spec = in->spec(); + + ImageStreamPtr image_stream = std::make_shared(); + image_stream->set_width(spec.width); + image_stream->set_height(spec.height); + f->add_stream(image_stream); + + // If we're here, we have a successful image open + in->close(); + + return true; +} + +bool OIIODecoder::Open() +{ + image_ = OIIO::ImageInput::open(stream()->footage()->filename().toStdString()); + + if (!image_) { + return false; + } + + // Check if we can work with this pixel format + const OIIO::ImageSpec& spec = image_->spec(); + + width_ = spec.width; + height_ = spec.height; + + // Weirdly, compiler complains this is a boolean value without casting to int + switch (static_cast(spec.format)) { + case OIIO::TypeDesc::UINT8: + pix_fmt_ = olive::PIX_FMT_RGBA8; + break; + case OIIO::TypeDesc::UINT16: + pix_fmt_ = olive::PIX_FMT_RGBA16; + break; + case OIIO::TypeDesc::HALF: + pix_fmt_ = olive::PIX_FMT_RGBA16F; + break; + case OIIO::TypeDesc::FLOAT: + pix_fmt_ = olive::PIX_FMT_RGBA32F; + break; + default: + qWarning() << "Failed to convert OIIO::ImageDesc to native pixel format"; + return false; + } + + pix_fmt_info_ = PixelService::GetPixelFormatInfo(static_cast(pix_fmt_)); + + return true; +} + +FramePtr OIIODecoder::Retrieve(const rational &timecode, const rational &length) +{ + Q_UNUSED(timecode) + Q_UNUSED(length) + + FramePtr f = Frame::Create(); + + f->set_width(width_); + f->set_height(height_); + f->set_format(pix_fmt_); + f->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, f->data()); + + return f; +} + +void OIIODecoder::Close() +{ + image_->close(); + image_ = nullptr; +} + +int64_t OIIODecoder::GetTimestampFromTime(const rational &time) +{ + Q_UNUSED(time) + + // A still image will always return the same frame + + return 0; +} diff --git a/app/decoder/oiio/oiiodecoder.h b/app/decoder/oiio/oiiodecoder.h new file mode 100644 index 000000000..d062e7563 --- /dev/null +++ b/app/decoder/oiio/oiiodecoder.h @@ -0,0 +1,59 @@ +/*** + + 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 . + +***/ + +#ifndef OIIODECODER_H +#define OIIODECODER_H + +#include + +#include "decoder/decoder.h" +#include "render/pixelservice.h" + +class OIIODecoder : public Decoder +{ +public: + OIIODecoder(); + + virtual QString id() override; + + virtual bool Probe(Footage *f) override; + + virtual bool Open() override; + + virtual FramePtr Retrieve(const rational &timecode, const rational &length = 0) override; + + virtual void Close() override; + + virtual int64_t GetTimestampFromTime(const rational &time) override; + +private: + std::unique_ptr image_; + + int width_; + + int height_; + + olive::PixelFormat pix_fmt_; + + PixelFormatInfo pix_fmt_info_; + +}; + +#endif // OIIODECODER_H diff --git a/app/project/item/footage/CMakeLists.txt b/app/project/item/footage/CMakeLists.txt index 5482cce07..b533f5530 100644 --- a/app/project/item/footage/CMakeLists.txt +++ b/app/project/item/footage/CMakeLists.txt @@ -21,6 +21,8 @@ set(OLIVE_SOURCES project/item/footage/audiostream.cpp project/item/footage/footage.h project/item/footage/footage.cpp + project/item/footage/imagestream.h + project/item/footage/imagestream.cpp project/item/footage/stream.h project/item/footage/stream.cpp project/item/footage/videostream.h diff --git a/app/project/item/footage/footage.cpp b/app/project/item/footage/footage.cpp index dd90fb6d3..706f79ede 100644 --- a/app/project/item/footage/footage.cpp +++ b/app/project/item/footage/footage.cpp @@ -188,8 +188,11 @@ void Footage::UpdateTooltip() StreamPtr s = streams_.at(i); - if (s->type() == Stream::kVideo) { - VideoStreamPtr vs = std::static_pointer_cast(s); + switch (s->type()) { + case Stream::kVideo: + case Stream::kImage: + { + ImageStreamPtr vs = std::static_pointer_cast(s); tip.append( QCoreApplication::translate("Footage", @@ -197,7 +200,10 @@ void Footage::UpdateTooltip() QString::number(vs->width()), QString::number(vs->height())) ); - } else if (streams_.at(i)->type() == Stream::kAudio) { + break; + } + case Stream::kAudio: + { AudioStreamPtr as = std::static_pointer_cast(s); tip.append( @@ -206,6 +212,10 @@ void Footage::UpdateTooltip() QString::number(as->channels()), QString::number(as->sample_rate())) ); + break; + } + default: + break; } } } diff --git a/app/project/item/footage/footage.h b/app/project/item/footage/footage.h index 73697def7..4f00df0d9 100644 --- a/app/project/item/footage/footage.h +++ b/app/project/item/footage/footage.h @@ -27,6 +27,7 @@ #include "common/rational.h" #include "project/item/item.h" #include "project/item/footage/audiostream.h" +#include "project/item/footage/imagestream.h" #include "project/item/footage/videostream.h" /** diff --git a/app/project/item/footage/imagestream.cpp b/app/project/item/footage/imagestream.cpp new file mode 100644 index 000000000..c704838bf --- /dev/null +++ b/app/project/item/footage/imagestream.cpp @@ -0,0 +1,46 @@ +/*** + + 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 . + +***/ + +#include "imagestream.h" + +ImageStream::ImageStream() +{ + set_type(kImage); +} + +const int &ImageStream::width() +{ + return width_; +} + +void ImageStream::set_width(const int &width) +{ + width_ = width; +} + +const int &ImageStream::height() +{ + return height_; +} + +void ImageStream::set_height(const int &height) +{ + height_ = height; +} diff --git a/app/project/item/footage/imagestream.h b/app/project/item/footage/imagestream.h new file mode 100644 index 000000000..f905adc3f --- /dev/null +++ b/app/project/item/footage/imagestream.h @@ -0,0 +1,47 @@ +/*** + + 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 . + +***/ + +#ifndef IMAGESTREAM_H +#define IMAGESTREAM_H + +#include "stream.h" + +/** + * @brief A Stream derivative containing video-specific information + */ +class ImageStream : public Stream +{ +public: + ImageStream(); + + const int& width(); + void set_width(const int& width); + + const int& height(); + void set_height(const int& height); + +private: + int width_; + int height_; +}; + +using ImageStreamPtr = std::shared_ptr; + +#endif // IMAGESTREAM_H diff --git a/app/project/item/footage/stream.h b/app/project/item/footage/stream.h index b99071dc6..a4339844c 100644 --- a/app/project/item/footage/stream.h +++ b/app/project/item/footage/stream.h @@ -45,7 +45,8 @@ public: kAudio, kData, kSubtitle, - kAttachment + kAttachment, + kImage = 100 }; /** diff --git a/app/project/item/footage/videostream.cpp b/app/project/item/footage/videostream.cpp index 8377b0f88..f8e1ac2be 100644 --- a/app/project/item/footage/videostream.cpp +++ b/app/project/item/footage/videostream.cpp @@ -24,23 +24,3 @@ VideoStream::VideoStream() { set_type(kVideo); } - -const int &VideoStream::width() -{ - return width_; -} - -void VideoStream::set_width(const int &width) -{ - width_ = width; -} - -const int &VideoStream::height() -{ - return height_; -} - -void VideoStream::set_height(const int &height) -{ - height_ = height; -} diff --git a/app/project/item/footage/videostream.h b/app/project/item/footage/videostream.h index a64f0db0d..2e59240c3 100644 --- a/app/project/item/footage/videostream.h +++ b/app/project/item/footage/videostream.h @@ -21,26 +21,12 @@ #ifndef VIDEOSTREAM_H #define VIDEOSTREAM_H -#include "common/rational.h" -#include "stream.h" +#include "imagestream.h" -/** - * @brief A Stream derivative containing video-specific information - */ -class VideoStream : public Stream +class VideoStream : public ImageStream { public: VideoStream(); - - const int& width(); - void set_width(const int& width); - - const int& height(); - void set_height(const int& height); - -private: - int width_; - int height_; }; using VideoStreamPtr = std::shared_ptr; diff --git a/app/render/pixelservice.cpp b/app/render/pixelservice.cpp index babaf293f..b648cb9b9 100644 --- a/app/render/pixelservice.cpp +++ b/app/render/pixelservice.cpp @@ -102,7 +102,7 @@ FramePtr PixelService::ConvertPixelFormat(FramePtr frame, const olive::PixelForm // FIXME: It'd be nice if this was multithreaded soon - FramePtr converted = std::make_shared(); + FramePtr converted = Frame::Create(); // Copy parameters converted->set_width(frame->width());