Skip to content

Commit

Permalink
Large refactor of Timeline, TimelineBase, ClipBase, and Clip, to allo…
Browse files Browse the repository at this point in the history
…w a Clip access to the parent timeline instance (if available), and thus, certain properties (preview size, timeline FPS, etc...). This allows for a simpler rendering of Clip keyframes (during the Clip::GetFrame method), and a simpler Timeline class, that can change the preview window size dynamically and no longer requires a Singleton Settings class.

 - Also removed "crop" from Clip class, as it was never implmeneted correctly, and we have a fully functional "crop" effect when needed
 - Added caching to Clip class, to optimize previewing of cached frames (much faster than previous)
  • Loading branch information
jonoomph committed Oct 4, 2020
1 parent 453d55f commit f9a717e
Show file tree
Hide file tree
Showing 35 changed files with 519 additions and 347 deletions.
45 changes: 18 additions & 27 deletions include/Clip.h
Expand Up @@ -42,6 +42,7 @@
#include "Effects.h"
#include "EffectInfo.h"
#include "Fraction.h"
#include "Frame.h"
#include "KeyFrame.h"
#include "ReaderBase.h"
#include "JuceHeader.h"
Expand Down Expand Up @@ -146,9 +147,6 @@ 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
Expand All @@ -169,9 +167,8 @@ namespace openshot {
/// Destructor
virtual ~Clip();


/// Get the cache object used by this reader (always returns NULL for this object)
CacheMemory* GetCache() override { return &final_cache; };
/// Get the cache object used by this clip
CacheMemory* GetCache() { return &cache; };

/// Determine if reader is open or closed
bool IsOpen() override { return is_open; };
Expand All @@ -191,23 +188,24 @@ namespace openshot {
/// Return the list of effects on the timeline
std::list<openshot::EffectBase*> Effects() { return effects; };

/// @brief Get an openshot::Frame object for a specific frame number of this timeline. The image size and number
/// of samples match the source reader.
/// @brief This method is required for all derived classes of ClipBase, and returns a
/// new openshot::Frame object. All Clip keyframes and effects are resolved into
/// pixels.
///
/// @returns The requested frame (containing the image)
/// @param requested_frame The frame number that is requested
std::shared_ptr<openshot::Frame> GetFrame(int64_t requested_frame);
/// @returns A new openshot::Frame object
/// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline.
std::shared_ptr<openshot::Frame> GetFrame(int64_t frame_number);

/// @brief Get an openshot::Frame object for a specific frame number of this timeline. The image size and number
/// of samples can be customized to match the Timeline, or any custom output. Extra samples will be moved to the
/// next Frame. Missing samples will be moved from the next Frame.
/// @brief This method is required for all derived classes of ClipBase, and returns a
/// modified openshot::Frame object
///
/// @returns The requested frame (containing the image)
/// @param requested_frame The frame number that is requested
/// @param width The width of the image requested
/// @param height The height of the image requested
/// @param samples The number of samples requested
std::shared_ptr<openshot::Frame> GetFrame(int64_t requested_frame, int width, int height, int samples);
/// A new openshot::Frame objects is returned, based on a copy from the source image, with all keyframes and clip effects
/// rendered.
///
/// @returns The modified openshot::Frame object
/// @param frame This is ignored on Clip, due to caching optimizations. This frame instance is clobbered with the source frame.
/// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline.
std::shared_ptr<openshot::Frame> GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number);

/// Open the internal reader
void Open();
Expand Down Expand Up @@ -262,13 +260,6 @@ namespace openshot {
/// Curve representing the color of the audio wave form
openshot::Color wave_color;

// Crop settings and curves
openshot::GravityType crop_gravity; ///< Cropping needs to have a gravity to determine what side we are cropping
openshot::Keyframe crop_width; ///< Curve representing width in percent (0.0=0%, 1.0=100%)
openshot::Keyframe crop_height; ///< Curve representing height in percent (0.0=0%, 1.0=100%)
openshot::Keyframe crop_x; ///< Curve representing X offset in percent (-1.0=-100%, 0.0=0%, 1.0=100%)
openshot::Keyframe crop_y; ///< Curve representing Y offset in percent (-1.0=-100%, 0.0=0%, 1.0=100%)

// Perspective curves
openshot::Keyframe perspective_c1_x; ///< Curves representing X for coordinate 1
openshot::Keyframe perspective_c1_y; ///< Curves representing Y for coordinate 1
Expand Down
26 changes: 26 additions & 0 deletions include/ClipBase.h
Expand Up @@ -33,10 +33,13 @@

#include <memory>
#include <sstream>
#include "CacheMemory.h"
#include "Exceptions.h"
#include "Frame.h"
#include "Point.h"
#include "KeyFrame.h"
#include "Json.h"
#include "TimelineBase.h"

namespace openshot {

Expand All @@ -54,6 +57,7 @@ namespace openshot {
float start; ///< The position in seconds to start playing (used to trim the beginning of a clip)
float end; ///< The position in seconds to end playing (used to trim the ending of a clip)
std::string previous_properties; ///< This string contains the previous JSON properties
openshot::TimelineBase* timeline; ///< Pointer to the parent timeline instance (if any)

/// Generate JSON for a property
Json::Value add_property_json(std::string name, float value, std::string type, std::string memo, const Keyframe* keyframe, float min_value, float max_value, bool readonly, int64_t requested_frame) const;
Expand All @@ -62,6 +66,7 @@ namespace openshot {
Json::Value add_property_choice_json(std::string name, int value, int selected_value) const;

public:
CacheMemory cache;

/// Constructor for the base clip
ClipBase() { };
Expand All @@ -72,20 +77,41 @@ namespace openshot {
bool operator> ( ClipBase& a) { return (Position() > a.Position()); }
bool operator>= ( ClipBase& a) { return (Position() >= a.Position()); }

/// @brief This method is required for all derived classes of ClipBase, and returns a
/// new openshot::Frame object. All Clip keyframes and effects are resolved into
/// pixels.
///
/// @returns A new openshot::Frame object
/// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline.
virtual std::shared_ptr<openshot::Frame> GetFrame(int64_t frame_number) = 0;

/// @brief This method is required for all derived classes of ClipBase, and returns a
/// modified openshot::Frame object
///
/// The frame object is passed into this method and used as a starting point (pixels and audio).
/// All Clip keyframes and effects are resolved into pixels.
///
/// @returns The modified openshot::Frame object
/// @param frame The frame object that needs the clip or effect applied to it
/// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline.
virtual std::shared_ptr<openshot::Frame> GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number) = 0;

/// Get basic properties
std::string Id() const { return id; } ///< Get the Id of this clip object
float Position() const { return position; } ///< Get position on timeline (in seconds)
int Layer() const { return layer; } ///< Get layer of clip on timeline (lower number is covered by higher numbers)
float Start() const { return start; } ///< Get start position (in seconds) of clip (trim start of video)
float End() const { return end; } ///< Get end position (in seconds) of clip (trim end of video)
float Duration() const { return end - start; } ///< Get the length of this clip (in seconds)
openshot::TimelineBase* ParentTimeline() { return timeline; } ///< Get the associated Timeline pointer (if any)

/// Set basic properties
void Id(std::string value) { id = value; } ///> Set the Id of this clip object
void Position(float value) { position = value; } ///< Set position on timeline (in seconds)
void Layer(int value) { layer = value; } ///< Set layer of clip on timeline (lower number is covered by higher numbers)
void Start(float value) { start = value; } ///< Set start position (in seconds) of clip (trim start of video)
void End(float value) { end = value; } ///< Set end position (in seconds) of clip (trim end of video)
void ParentTimeline(openshot::TimelineBase* new_timeline) { timeline = new_timeline; } ///< Set associated Timeline pointer

/// Get and Set JSON methods
virtual std::string Json() const = 0; ///< Generate JSON string of this object
Expand Down
21 changes: 10 additions & 11 deletions include/EffectBase.h
Expand Up @@ -67,6 +67,10 @@ namespace openshot
{
private:
int order; ///< The order to evaluate this effect. Effects are processed in this order (when more than one overlap).

protected:
openshot::ClipBase* clip; ///< Pointer to the parent clip instance (if any)

public:

/// Information about the current effect
Expand All @@ -78,21 +82,16 @@ namespace openshot
/// Constrain a color value from 0 to 255
int constrain(int color_value);

/// @brief This method is required for all derived classes of EffectBase, and returns a
/// modified openshot::Frame object
///
/// The frame object is passed into this method, and a frame_number is passed in which
/// tells the effect which settings to use from its keyframes (starting at 1).
///
/// @returns The modified openshot::Frame object
/// @param frame The frame object that needs the effect applied to it
/// @param frame_number The frame number (starting at 1) of the effect on the timeline.
virtual std::shared_ptr<openshot::Frame> GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number) = 0;

/// Initialize the values of the EffectInfo struct. It is important for derived classes to call
/// this method, or the EffectInfo struct values will not be initialized.
void InitEffectInfo();

/// Parent clip object of this effect (which can be unparented and NULL)
openshot::ClipBase* ParentClip();

/// Set parent clip object of this effect
void ParentClip(openshot::ClipBase* new_clip);

/// Get and Set JSON methods
virtual std::string Json() const = 0; ///< Generate JSON string of this object
virtual void SetJson(const std::string value) = 0; ///< Load JSON string into this object
Expand Down
1 change: 1 addition & 0 deletions include/OpenShot.h
Expand Up @@ -138,6 +138,7 @@
#include "QtHtmlReader.h"
#include "QtImageReader.h"
#include "QtTextReader.h"
#include "TimelineBase.h"
#include "Timeline.h"
#include "Settings.h"

Expand Down
10 changes: 5 additions & 5 deletions include/ReaderBase.h
Expand Up @@ -98,9 +98,9 @@ namespace openshot
{
protected:
/// Section lock for multiple threads
juce::CriticalSection getFrameCriticalSection;
juce::CriticalSection processingCriticalSection;
openshot::ClipBase* parent;
juce::CriticalSection getFrameCriticalSection;
juce::CriticalSection processingCriticalSection;
openshot::ClipBase* clip; ///< Pointer to the parent clip instance (if any)

public:

Expand All @@ -111,10 +111,10 @@ namespace openshot
openshot::ReaderInfo info;

/// Parent clip object of this reader (which can be unparented and NULL)
openshot::ClipBase* GetClip();
openshot::ClipBase* ParentClip();

/// Set parent clip object of this reader
void SetClip(openshot::ClipBase* clip);
void ParentClip(openshot::ClipBase* new_clip);

/// Close the reader (and any resources it was consuming)
virtual void Close() = 0;
Expand Down
4 changes: 3 additions & 1 deletion include/Timeline.h
Expand Up @@ -54,6 +54,8 @@
#include "OpenMPUtilities.h"
#include "ReaderBase.h"
#include "Settings.h"
#include "TimelineBase.h"


namespace openshot {

Expand Down Expand Up @@ -146,7 +148,7 @@ namespace openshot {
* t.Close();
* @endcode
*/
class Timeline : public ReaderBase {
class Timeline : public TimelineBase, public ReaderBase {
private:
bool is_open; ///<Is Timeline Open?
bool auto_map_clips; ///< Auto map framerates and sample rates to all clips
Expand Down
47 changes: 47 additions & 0 deletions include/TimelineBase.h
@@ -0,0 +1,47 @@
/**
* @file
* @brief Header file for Timeline class
* @author Jonathan Thomas <jonathan@openshot.org>
*
* @ref License
*/

/* LICENSE
*
* Copyright (c) 2008-2019 OpenShot Studios, LLC
* <http://www.openshotstudios.com/>. This file is part of
* OpenShot Library (libopenshot), an open-source project dedicated to
* delivering high quality video editing and animation solutions to the
* world. For more information visit <http://www.openshot.org/>.
*
* OpenShot Library (libopenshot) is free software: you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* OpenShot Library (libopenshot) 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef OPENSHOT_TIMELINE_BASE_H
#define OPENSHOT_TIMELINE_BASE_H


namespace openshot {
/**
* @brief This class represents a timeline (used for building generic timeline implementations)
*/
class TimelineBase {

public:
int preview_width; ///< Optional preview width of timeline image. If your preview window is smaller than the timeline, it's recommended to set this.
int preview_height; ///< Optional preview width of timeline image. If your preview window is smaller than the timeline, it's recommended to set this.
};
}

#endif
20 changes: 14 additions & 6 deletions include/effects/Bars.h
Expand Up @@ -77,16 +77,24 @@ namespace openshot
/// @param bottom The curve to adjust the bottom bar size (between 0 and 1)
Bars(Color color, Keyframe left, Keyframe top, Keyframe right, Keyframe bottom);

/// @brief This method is required for all derived classes of EffectBase, and returns a
/// @brief This method is required for all derived classes of ClipBase, and returns a
/// new openshot::Frame object. All Clip keyframes and effects are resolved into
/// pixels.
///
/// @returns A new openshot::Frame object
/// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline.
std::shared_ptr<openshot::Frame> GetFrame(int64_t frame_number) override { return GetFrame(std::shared_ptr<Frame> (new Frame()), frame_number); }

/// @brief This method is required for all derived classes of ClipBase, and returns a
/// modified openshot::Frame object
///
/// The frame object is passed into this method, and a frame_number is passed in which
/// tells the effect which settings to use from its keyframes (starting at 1).
/// The frame object is passed into this method and used as a starting point (pixels and audio).
/// All Clip keyframes and effects are resolved into pixels.
///
/// @returns The modified openshot::Frame object
/// @param frame The frame object that needs the effect applied to it
/// @param frame_number The frame number (starting at 1) of the effect on the timeline.
std::shared_ptr<Frame> GetFrame(std::shared_ptr<Frame> frame, int64_t frame_number) override;
/// @param frame The frame object that needs the clip or effect applied to it
/// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline.
std::shared_ptr<openshot::Frame> GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number) override;

/// Get and Set JSON methods
std::string Json() const override; ///< Generate JSON string of this object
Expand Down
20 changes: 14 additions & 6 deletions include/effects/Blur.h
Expand Up @@ -89,16 +89,24 @@ namespace openshot
/// @param new_iterations The curve to adjust the # of iterations (between 1 and 100)
Blur(Keyframe new_horizontal_radius, Keyframe new_vertical_radius, Keyframe new_sigma, Keyframe new_iterations);

/// @brief This method is required for all derived classes of EffectBase, and returns a
/// @brief This method is required for all derived classes of ClipBase, and returns a
/// new openshot::Frame object. All Clip keyframes and effects are resolved into
/// pixels.
///
/// @returns A new openshot::Frame object
/// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline.
std::shared_ptr<openshot::Frame> GetFrame(int64_t frame_number) override { return GetFrame(std::shared_ptr<Frame> (new Frame()), frame_number); }

/// @brief This method is required for all derived classes of ClipBase, and returns a
/// modified openshot::Frame object
///
/// The frame object is passed into this method, and a frame_number is passed in which
/// tells the effect which settings to use from its keyframes (starting at 1).
/// The frame object is passed into this method and used as a starting point (pixels and audio).
/// All Clip keyframes and effects are resolved into pixels.
///
/// @returns The modified openshot::Frame object
/// @param frame The frame object that needs the effect applied to it
/// @param frame_number The frame number (starting at 1) of the effect on the timeline.
std::shared_ptr<Frame> GetFrame(std::shared_ptr<Frame> frame, int64_t frame_number) override;
/// @param frame The frame object that needs the clip or effect applied to it
/// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline.
std::shared_ptr<openshot::Frame> GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number) override;

/// Get and Set JSON methods
std::string Json() const override; ///< Generate JSON string of this object
Expand Down
20 changes: 14 additions & 6 deletions include/effects/Brightness.h
Expand Up @@ -77,16 +77,24 @@ namespace openshot
/// @param new_contrast The curve to adjust the contrast (3 is typical, 20 is a lot, 100 is max. 0 is invalid)
Brightness(Keyframe new_brightness, Keyframe new_contrast);

/// @brief This method is required for all derived classes of EffectBase, and returns a
/// @brief This method is required for all derived classes of ClipBase, and returns a
/// new openshot::Frame object. All Clip keyframes and effects are resolved into
/// pixels.
///
/// @returns A new openshot::Frame object
/// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline.
std::shared_ptr<openshot::Frame> GetFrame(int64_t frame_number) override { return GetFrame(std::shared_ptr<Frame> (new Frame()), frame_number); }

/// @brief This method is required for all derived classes of ClipBase, and returns a
/// modified openshot::Frame object
///
/// The frame object is passed into this method, and a frame_number is passed in which
/// tells the effect which settings to use from its keyframes (starting at 1).
/// The frame object is passed into this method and used as a starting point (pixels and audio).
/// All Clip keyframes and effects are resolved into pixels.
///
/// @returns The modified openshot::Frame object
/// @param frame The frame object that needs the effect applied to it
/// @param frame_number The frame number (starting at 1) of the effect on the timeline.
std::shared_ptr<Frame> GetFrame(std::shared_ptr<Frame> frame, int64_t frame_number) override;
/// @param frame The frame object that needs the clip or effect applied to it
/// @param frame_number The frame number (starting at 1) of the clip or effect on the timeline.
std::shared_ptr<openshot::Frame> GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number) override;

/// Get and Set JSON methods
std::string Json() const override; ///< Generate JSON string of this object
Expand Down

0 comments on commit f9a717e

Please sign in to comment.