From 453d55f41a36f6e1db74771d1cc017b0e477c3df Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Wed, 26 Aug 2020 22:47:31 -0500 Subject: [PATCH] Fixed a bug with cropping logic on Clip (disabled it temporarily). I need to replace the Crop functionality with a more robust cropping tool. Also, updated Timeline to use the MaxWidth/MaxHeight settings when calling the clip (since those are set when the screen is resized). --- include/Clip.h | 9 ++++++--- src/Clip.cpp | 39 +++++++++++++++++++++++++++++---------- src/Timeline.cpp | 4 ++-- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/include/Clip.h b/include/Clip.h index 71ab83c37..51f9a859e 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -116,10 +116,10 @@ namespace openshot { int64_t adjust_frame_number_minimum(int64_t frame_number); /// Apply effects to the source frame (if any) - std::shared_ptr apply_effects(std::shared_ptr frame); + void apply_effects(std::shared_ptr frame); /// Apply keyframes to the source frame (if any) - std::shared_ptr apply_keyframes(std::shared_ptr frame, int width, int height); + void apply_keyframes(std::shared_ptr frame, int width, int height); /// Get file extension std::string get_file_extension(std::string path); @@ -146,6 +146,9 @@ namespace openshot { void reverse_buffer(juce::AudioSampleBuffer* buffer); public: + /// Final cache object used to hold final frames + CacheMemory final_cache; + openshot::GravityType gravity; ///< The gravity of a clip determines where it snaps to its parent openshot::ScaleType scale; ///< The scale determines how a clip should be resized to fit its parent openshot::AnchorType anchor; ///< The anchor determines what parent a clip should snap to @@ -168,7 +171,7 @@ namespace openshot { /// Get the cache object used by this reader (always returns NULL for this object) - CacheMemory* GetCache() override { return NULL; }; + CacheMemory* GetCache() override { return &final_cache; }; /// Determine if reader is open or closed bool IsOpen() override { return is_open; }; diff --git a/src/Clip.cpp b/src/Clip.cpp index 0c664ebe0..7a504cc9d 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -107,6 +107,9 @@ void Clip::init_settings() // Init audio and video overrides has_audio = Keyframe(-1.0); has_video = Keyframe(-1.0); + + // Initialize Clip cache + final_cache.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * 2, info.width, info.height, info.sample_rate, info.channels); } // Init reader's rotation (if any) @@ -352,6 +355,16 @@ std::shared_ptr Clip::GetFrame(int64_t requested_frame, int width, int he // Adjust out of bounds frame number requested_frame = adjust_frame_number_minimum(requested_frame); + // Check the cache for this frame + std::shared_ptr cached_frame = final_cache.GetFrame(requested_frame); + if (cached_frame) { + // Debug output + ZmqLogger::Instance()->AppendDebugMethod("Clip::GetFrame", "returned cached frame", requested_frame); + + // Return the cached frame + return cached_frame; + } + // Adjust has_video and has_audio overrides int enabled_audio = has_audio.GetInt(requested_frame); if (enabled_audio == -1 && reader && reader->info.has_audio) @@ -403,6 +416,9 @@ std::shared_ptr Clip::GetFrame(int64_t requested_frame, int width, int he // Apply keyframe / transforms apply_keyframes(frame, width, height); + // Cache frame + final_cache.Add(frame); + // Return processed 'frame' return frame; } @@ -874,6 +890,9 @@ void Clip::SetJsonValue(const Json::Value root) { // Set parent data ClipBase::SetJsonValue(root); + // Clear cache + final_cache.Clear(); + // Set data from Json (if key is found) if (!root["gravity"].isNull()) gravity = (GravityType) root["gravity"].asInt(); @@ -1062,16 +1081,22 @@ void Clip::AddEffect(EffectBase* effect) // Sort effects sort_effects(); + + // Clear cache + final_cache.Clear(); } // Remove an effect from the clip void Clip::RemoveEffect(EffectBase* effect) { effects.remove(effect); + + // Clear cache + final_cache.Clear(); } // Apply effects to the source frame (if any) -std::shared_ptr Clip::apply_effects(std::shared_ptr frame) +void Clip::apply_effects(std::shared_ptr frame) { // Find Effects at this position and layer for (auto effect : effects) @@ -1080,9 +1105,6 @@ std::shared_ptr Clip::apply_effects(std::shared_ptr frame) frame = effect->GetFrame(frame, frame->number); } // end effect loop - - // Return modified frame - return frame; } // Compare 2 floating point numbers for equality @@ -1093,7 +1115,7 @@ bool Clip::isEqual(double a, double b) // Apply keyframes to the source frame (if any) -std::shared_ptr Clip::apply_keyframes(std::shared_ptr frame, int width, int height) +void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) { // Get actual frame image data std::shared_ptr source_image = frame->GetImage(); @@ -1315,7 +1337,7 @@ std::shared_ptr Clip::apply_keyframes(std::shared_ptr frame, int w /* COMPOSITE SOURCE IMAGE (LAYER) ONTO FINAL IMAGE */ std::shared_ptr new_image; - new_image = std::shared_ptr(new QImage(*source_image)); + new_image = std::shared_ptr(new QImage(QSize(width, height), source_image->format())); new_image->fill(QColor(QString::fromStdString("#00000000"))); // Load timeline's new frame image into a QPainter @@ -1328,7 +1350,7 @@ std::shared_ptr Clip::apply_keyframes(std::shared_ptr frame, int w // Composite a new layer onto the image painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - painter.drawImage(0, 0, *source_image, crop_x_value * source_image->width(), crop_y_value * source_image->height(), crop_w_value * source_image->width(), crop_h_value * source_image->height()); + painter.drawImage(0, 0, *source_image); // Draw frame #'s on top of image (if needed) if (display != FRAME_DISPLAY_NONE) { @@ -1361,7 +1383,4 @@ std::shared_ptr Clip::apply_keyframes(std::shared_ptr frame, int w // Add new QImage to frame frame->AddImage(new_image); - - // Return modified frame - return frame; } diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 7f068d1a6..d9b23ca5f 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -368,7 +368,7 @@ std::shared_ptr Timeline::GetOrCreateFrame(Clip* clip, int64_t number) // Attempt to get a frame (but this could fail if a reader has just been closed) #pragma omp critical (T_GetOtCreateFrame) - new_frame = std::shared_ptr(clip->GetFrame(number, info.width, info.height, samples_in_frame)); + new_frame = std::shared_ptr(clip->GetFrame(number, Settings::Instance()->MAX_WIDTH, Settings::Instance()->MAX_HEIGHT, samples_in_frame)); // Return real frame return new_frame; @@ -671,7 +671,7 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) int samples_in_frame = Frame::GetSamplesPerFrame(frame_number, info.fps, info.sample_rate, info.channels); // Cache clip object - clip->GetFrame(clip_frame_number, info.width, info.height, samples_in_frame); + clip->GetFrame(clip_frame_number, Settings::Instance()->MAX_WIDTH, Settings::Instance()->MAX_HEIGHT, samples_in_frame); } } }