diff --git a/app/codec/frame.cpp b/app/codec/frame.cpp index 75b4a9205..cb97725cc 100644 --- a/app/codec/frame.cpp +++ b/app/codec/frame.cpp @@ -26,14 +26,22 @@ #include #include "common/oiioutils.h" +#include "render/framemanager.h" namespace olive { Frame::Frame() : + data_(nullptr), + data_size_(0), timestamp_(0) { } +Frame::~Frame() +{ + destroy(); +} + FramePtr Frame::Create() { return std::make_shared(); @@ -66,7 +74,7 @@ Color Frame::get_pixel(int x, int y) const int byte_offset = y * linesize_bytes() + x * video_params().GetBytesPerPixel(); - return Color(data_.data() + byte_offset, video_params().format(), video_params().channel_count()); + return Color(reinterpret_cast(data_ + byte_offset), video_params().format(), video_params().channel_count()); } bool Frame::contains_pixel(int x, int y) const @@ -82,7 +90,7 @@ void Frame::set_pixel(int x, int y, const Color &c) int byte_offset = y * linesize_bytes() + x * video_params().GetBytesPerPixel(); - c.toData(data_.data() + byte_offset, video_params().format(), video_params().channel_count()); + c.toData(reinterpret_cast(data_ + byte_offset), video_params().format(), video_params().channel_count()); } bool Frame::allocate() @@ -93,11 +101,27 @@ bool Frame::allocate() return false; } - data_.resize(VideoParams::GetBufferSize(linesize_, height(), params_.format(), params_.channel_count())); + if (is_allocated()) { + // Already allocated + return true; + } + + data_size_ = VideoParams::GetBufferSize(linesize_, height(), params_.format(), params_.channel_count()); + data_ = FrameManager::Allocate(data_size_); return true; } +void Frame::destroy() +{ + if (is_allocated()) { + FrameManager::Deallocate(data_size_, data_); + + data_size_ = 0; + data_ = nullptr; + } +} + FramePtr Frame::convert(VideoParams::Format format) const { // Create new params with destination format diff --git a/app/codec/frame.h b/app/codec/frame.h index df3bef2d8..1859332bc 100644 --- a/app/codec/frame.h +++ b/app/codec/frame.h @@ -24,6 +24,7 @@ #include #include +#include "common/define.h" #include "common/rational.h" #include "render/color.h" #include "render/videoparams.h" @@ -41,6 +42,10 @@ class Frame public: Frame(); + ~Frame(); + + DISABLE_COPY_MOVE(Frame) + static FramePtr Create(); const VideoParams& video_params() const; @@ -102,7 +107,7 @@ public: */ char* data() { - return data_.data(); + return data_; } /** @@ -110,7 +115,7 @@ public: */ const char* const_data() const { - return data_.constData(); + return data_; } /** @@ -127,16 +132,13 @@ public: */ bool is_allocated() const { - return !data_.isEmpty(); + return data_; } /** * @brief Destroy a memory buffer allocated with allocate() */ - void destroy() - { - data_.clear(); - } + void destroy(); /** * @brief Returns the size of the array returned in data() in bytes @@ -145,7 +147,7 @@ public: */ int allocated_size() const { - return data_.size(); + return data_size_; } FramePtr convert(VideoParams::Format format) const; @@ -153,7 +155,8 @@ public: private: VideoParams params_; - QByteArray data_; + char* data_; + int data_size_; rational timestamp_; diff --git a/app/core.cpp b/app/core.cpp index 2379a2bc0..ad864b41f 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -51,6 +51,7 @@ #include "panel/project/project.h" #include "panel/viewer/viewer.h" #include "render/diskmanager.h" +#include "render/framemanager.h" #include "render/rendermanager.h" #ifdef USE_OTIO #include "task/project/loadotio/loadotio.h" @@ -140,6 +141,9 @@ void Core::Start() // Initialize RenderManager RenderManager::CreateInstance(); + // Initialize FrameManager + FrameManager::CreateInstance(); + // // Start application // @@ -184,6 +188,8 @@ void Core::Stop() } } + FrameManager::DestroyInstance(); + RenderManager::DestroyInstance(); MenuShared::DestroyInstance(); diff --git a/app/render/CMakeLists.txt b/app/render/CMakeLists.txt index 25f89e6d8..4d71d23cf 100644 --- a/app/render/CMakeLists.txt +++ b/app/render/CMakeLists.txt @@ -33,6 +33,8 @@ set(OLIVE_SOURCES render/diskmanager.h render/framehashcache.cpp render/framehashcache.h + render/framemanager.cpp + render/framemanager.h render/managedcolor.cpp render/managedcolor.h render/playbackcache.cpp diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index 8b539f518..8e105ccdd 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -455,7 +455,6 @@ void ViewerWidget::UpdateTextureFromNode() // Check playback queue for a frame if (IsPlaying()) { - // We still run the playback queue even when FrameExistsAtTime returns false because we might be // playing backwards and about to start showing frames, so the queue should be prepared for // that. diff --git a/app/widget/viewer/viewerplaybacktimer.cpp b/app/widget/viewer/viewerplaybacktimer.cpp index f94657592..03452c3b8 100644 --- a/app/widget/viewer/viewerplaybacktimer.cpp +++ b/app/widget/viewer/viewerplaybacktimer.cpp @@ -21,6 +21,7 @@ #include "viewerplaybacktimer.h" #include +#include namespace olive { @@ -29,14 +30,14 @@ void ViewerPlaybackTimer::Start(const int64_t &start_timestamp, const int &playb start_msec_ = QDateTime::currentMSecsSinceEpoch(); start_timestamp_ = start_timestamp; playback_speed_ = playback_speed; - timebase_ = timebase; + timebase_ = timebase * 1000; } int64_t ViewerPlaybackTimer::GetTimestampNow() const { int64_t real_time = QDateTime::currentMSecsSinceEpoch() - start_msec_; - int64_t frames_since_start = qRound(static_cast(real_time) / (timebase_ * 1000)); + int64_t frames_since_start = qFloor(static_cast(real_time) / (timebase_)); return start_timestamp_ + frames_since_start * playback_speed_; }