From 1127a0f3ba085ba610a7475a17813388a802ca69 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Tue, 1 Oct 2013 15:22:25 -0500 Subject: [PATCH] Refactored Clips into a base class called ClipBase. Effects and Clips use this base class, which allows them to be positioned and layered on the timeline. Also fixed a regression in Coordinate, which was not properly setting instance variables. --- include/Clip.h | 29 ++++------------ include/ClipBase.h | 81 ++++++++++++++++++++++++++++++++++++++++++++ include/Coordinate.h | 7 ++-- include/EffectBase.h | 3 +- include/Timeline.h | 2 +- src/EffectBase.cpp | 6 ++++ src/KeyFrame.cpp | 3 +- src/Main.cpp | 27 +++++++++++++++ src/Timeline.cpp | 2 ++ src/openshot.i | 2 ++ tests/Clip_Tests.cpp | 2 +- 11 files changed, 135 insertions(+), 29 deletions(-) create mode 100644 include/ClipBase.h diff --git a/include/Clip.h b/include/Clip.h index da875e87..e736edc4 100644 --- a/include/Clip.h +++ b/include/Clip.h @@ -34,6 +34,7 @@ #endif #include +#include "ClipBase.h" #include "Color.h" #include "FFmpegReader.h" #include "FrameRate.h" @@ -111,13 +112,10 @@ namespace openshot { * c2.alpha.AddPoint(384, 1.0); // Animate the alpha to visible (between frame #360 and frame #384) * @endcode */ - class Clip { + class Clip : public ClipBase { private: - float position; ///< The position on the timeline where this clip should start playing - int layer; ///< The layer this clip is on. Lower clips are covered up by higher clips. - 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) bool waveform; ///< Should a waveform be used instead of the clip's image + float end; ///< The position in seconds to end playing (used to trim the ending of a clip) // Audio resampler (if time mapping) AudioResampler *resampler; @@ -149,12 +147,6 @@ namespace openshot { ScaleType scale; ///< The scale determines how a clip should be resized to fit it's parent AnchorType anchor; ///< The anchor determines what parent a clip should snap to - // Compare a clip using the Position() property - bool operator< ( Clip& a) { return (Position() < a.Position()); } - bool operator<= ( Clip& a) { return (Position() <= a.Position()); } - bool operator> ( Clip& a) { return (Position() > a.Position()); } - bool operator>= ( Clip& a) { return (Position() >= a.Position()); } - /// Default Constructor Clip(); @@ -185,19 +177,12 @@ namespace openshot { /// Get the current reader ReaderBase* Reader() throw(ReaderClosed); - /// Get basic properties - float Position() { return position; } ///< Get position on timeline (in seconds) - int Layer() { return layer; } ///< Get layer of clip on timeline (lower number is covered by higher numbers) - float Start() { return start; } ///< Get start position (in seconds) of clip (trim start of video) + /// Override End() method float End() throw(ReaderClosed); ///< Get end position (in seconds) of clip (trim end of video), which can be affected by the time curve. - float Duration() { return End() - Start(); } ///< Get the length of this clip (in seconds) - bool Waveform() { return waveform; } ///< Get the waveform property of this clip - - /// Set basic properties - 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) + + /// Waveform property + bool Waveform() { return waveform; } ///< Get the waveform property of this clip void Waveform(bool value) { waveform = value; } ///< Set the waveform property of this clip // Scale and Location curves diff --git a/include/ClipBase.h b/include/ClipBase.h new file mode 100644 index 00000000..46ba21fa --- /dev/null +++ b/include/ClipBase.h @@ -0,0 +1,81 @@ +/** + * @file + * @brief Header file for ClipBase class + * @author Jonathan Thomas + * + * @section LICENSE + * + * Copyright (c) 2008-2013 OpenShot Studios, LLC + * (http://www.openshotstudios.com). This file is part of + * OpenShot Library (http://www.openshot.org), an open-source project + * dedicated to delivering high quality video editing and animation solutions + * to the world. + * + * OpenShot Library 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. + * + * OpenShot Library 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 OpenShot Library. If not, see . + */ + +#ifndef OPENSHOT_CLIPBASE_H +#define OPENSHOT_CLIPBASE_H + +/// Do not include the juce unittest headers, because it collides with unittest++ +#ifndef __JUCE_UNITTEST_JUCEHEADER__ + #define __JUCE_UNITTEST_JUCEHEADER__ +#endif + +#include + +using namespace std; + +namespace openshot { + + /** + * @brief This abstract class is the base class, used by all clips in libopenshot. + * + * Clips are objects that attach to the timeline and can be layered and positioned + * together. There are 2 primary types of clips: Effects and Video/Audio Clips. + */ + class ClipBase { + private: + float position; ///< The position on the timeline where this clip should start playing + int layer; ///< The layer this clip is on. Lower clips are covered up by higher clips. + 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) + + public: + + // Compare a clip using the Position() property + bool operator< ( ClipBase& a) { return (Position() < a.Position()); } + bool operator<= ( ClipBase& a) { return (Position() <= a.Position()); } + bool operator> ( ClipBase& a) { return (Position() > a.Position()); } + bool operator>= ( ClipBase& a) { return (Position() >= a.Position()); } + + /// Get basic properties + float Position() { return position; } ///< Get position on timeline (in seconds) + int Layer() { return layer; } ///< Get layer of clip on timeline (lower number is covered by higher numbers) + float Start() { return start; } ///< Get start position (in seconds) of clip (trim start of video) + float End() { return end; } ///< Get end position (in seconds) of clip (trim end of video) + float Duration() { return End() - Start(); } ///< Get the length of this clip (in seconds) + + /// Set basic properties + 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) + + }; + + +} + +#endif diff --git a/include/Coordinate.h b/include/Coordinate.h index bcbd57cd..98393fca 100644 --- a/include/Coordinate.h +++ b/include/Coordinate.h @@ -28,6 +28,7 @@ #ifndef OPENSHOT_COORDINATE_H #define OPENSHOT_COORDINATE_H +#include #include "../include/Fraction.h" namespace openshot { @@ -66,21 +67,21 @@ namespace openshot { /// @brief Set the repeating Fraction (used internally on the timeline, to track changes to coordinates) /// @param repeated The fraction representing how many times this coordinate Y value repeats (only used on the timeline) - void Repeat(Fraction repeated) { repeated=repeated; } + void Repeat(Fraction is_repeated) { repeated=is_repeated; } /// Get the repeating Fraction (used internally on the timeline, to track changes to coordinates) Fraction Repeat() { return repeated; } /// @brief Set the increasing flag (used internally on the timeline, to track changes to coordinates) /// @param increasing Indicates if this coorindate Y value is increasing (when compared to the previous coordinate) - void IsIncreasing(bool increasing) { increasing=increasing; } + void IsIncreasing(bool is_increasing) { increasing = is_increasing; } /// Get the increasing flag (used internally on the timeline, to track changes to coordinates) bool IsIncreasing() { return increasing; } /// @brief Set the delta / difference between previous coordinate value (used internally on the timeline, to track changes to coordinates) /// @param delta Indicates how much this Y value differs from the previous Y value - void Delta(float delta) { delta=delta; } + void Delta(float new_delta) { delta=new_delta; } /// Get the delta / difference between previous coordinate value (used internally on the timeline, to track changes to coordinates) float Delta() { return delta; } diff --git a/include/EffectBase.h b/include/EffectBase.h index cc5b3b04..edba03d8 100644 --- a/include/EffectBase.h +++ b/include/EffectBase.h @@ -31,6 +31,7 @@ #include #include #include +#include "ClipBase.h" #include "Frame.h" using namespace std; @@ -59,7 +60,7 @@ namespace openshot * The only requirements for an 'effect', is to derive from this base class, implement the Apply() * method, and call the InitEffectInfo() method. */ - class EffectBase + class EffectBase : ClipBase { public: /// Information about the current effect diff --git a/include/Timeline.h b/include/Timeline.h index a983b6d7..c3741d8e 100644 --- a/include/Timeline.h +++ b/include/Timeline.h @@ -57,7 +57,7 @@ namespace openshot { /// Comparison method for sorting clip pointers (by Position and Layer) struct CompareClips{ - bool operator()( Clip* lhs, Clip* rhs){ + bool operator()( ClipBase* lhs, ClipBase* rhs){ return lhs->Position() <= rhs->Position() && lhs->Layer() < rhs->Layer(); }}; diff --git a/src/EffectBase.cpp b/src/EffectBase.cpp index 4f78d718..7906a88f 100644 --- a/src/EffectBase.cpp +++ b/src/EffectBase.cpp @@ -32,6 +32,12 @@ using namespace openshot; // Initialize the values of the FileInfo struct void EffectBase::InitEffectInfo() { + // Init clip settings + Position(0.0); + Layer(0); + Start(0.0); + End(0.0); + info.has_video = false; info.has_audio = false; info.name = ""; diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index 126db122..6f6561d9 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -233,7 +233,7 @@ bool Keyframe::IsIncreasing(int index) // return the maximum value return int(round(Values[Values.size() - 1].IsIncreasing())); else - // return a blank coordinate (0,0) + // return the default direction of most curves (i.e. increasing is true) return true; } @@ -430,6 +430,7 @@ void Keyframe::Process() { // Loop forward and look for the next unique value (to determine direction) for (vector::iterator direction_it = it + 1; direction_it != Values.end(); direction_it++) { int next = int(round((*direction_it).Y)); + // Detect direction if (current_value < next) { diff --git a/src/Main.cpp b/src/Main.cpp index ab453aa6..c153b5dd 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -45,6 +45,33 @@ using namespace tr1; int main(int argc, char* argv[]) { + // Create a empty clip + Clip c1a; + //c1a.Open(); + +// // Check basic settings +// CHECK_EQUAL(ANCHOR_CANVAS, c1a.anchor); +// CHECK_EQUAL(GRAVITY_CENTER, c1a.gravity); +// CHECK_EQUAL(SCALE_FIT, c1a.scale); +// CHECK_EQUAL(0, c1a.Layer()); +// CHECK_CLOSE(0.0f, c1a.Position(), 0.00001); +// CHECK_CLOSE(0.0f, c1a.Start(), 0.00001); +// CHECK_CLOSE(0.0f, c1a.End(), 0.00001); + + // Change some properties + c1a.Layer(1); + c1a.Position(5.0); + c1a.Start(3.5); + c1a.End(10.5); + + cout << c1a.Layer() << endl; + cout << c1a.Position() << endl; + cout << c1a.Start() << endl; + cout << c1a.End() << endl; + + return 0; + + // Create a chunkwriter // FFmpegReader *r3 = new FFmpegReader("/home/jonathan/Videos/sintel_trailer-720p.mp4"); // r3->DisplayInfo(); diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 3c6a5e0a..a538c8a6 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -155,6 +155,8 @@ void Timeline::add_layer(tr1::shared_ptr new_frame, Clip* source_clip, in int source_width = source_image->columns(); int source_height = source_image->rows(); + /* APPLY EFFECTS */ + /* ALPHA & OPACITY */ if (source_clip->alpha.GetValue(clip_frame_number) != 0) { diff --git a/src/openshot.i b/src/openshot.i index 7bab01a7..98abbe62 100644 --- a/src/openshot.i +++ b/src/openshot.i @@ -50,6 +50,7 @@ #include "../include/ReaderBase.h" #include "../include/WriterBase.h" #include "../include/Cache.h" +#include "../include/ClipBase.h" #include "../include/Clip.h" #include "../include/ChunkReader.h" #include "../include/ChunkWriter.h" @@ -86,6 +87,7 @@ %include "../include/Cache.h" %include "../include/ChunkReader.h" %include "../include/ChunkWriter.h" +%include "../include/ClipBase.h" %include "../include/Clip.h" %include "../include/Coordinate.h" %include "../include/Color.h" diff --git a/tests/Clip_Tests.cpp b/tests/Clip_Tests.cpp index 2c21750e..02f34450 100644 --- a/tests/Clip_Tests.cpp +++ b/tests/Clip_Tests.cpp @@ -66,9 +66,9 @@ TEST(Clip_Basic_Gettings_and_Setters) { // Create a empty clip Clip c1; - c1.Open(); // Check basic settings + CHECK_THROW(c1.Open(), ReaderClosed); CHECK_EQUAL(ANCHOR_CANVAS, c1.anchor); CHECK_EQUAL(GRAVITY_CENTER, c1.gravity); CHECK_EQUAL(SCALE_FIT, c1.scale);