1 /***
2 
3     Olive - Non-Linear Video Editor
4     Copyright (C) 2019  Olive Team
5 
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 
19 ***/
20 
21 #ifndef EFFECT_H
22 #define EFFECT_H
23 
24 #include <memory>
25 #include <QObject>
26 #include <QString>
27 #include <QVector>
28 #include <QColor>
29 #include <QOpenGLFunctions>
30 #include <QOpenGLShaderProgram>
31 #include <QOpenGLTexture>
32 #include <QMutex>
33 #include <QThread>
34 #include <QLabel>
35 #include <QWidget>
36 #include <QGridLayout>
37 #include <QPushButton>
38 #include <QMouseEvent>
39 #include <QXmlStreamReader>
40 #include <QXmlStreamWriter>
41 #include <random>
42 
43 #include "ui/collapsiblewidget.h"
44 #include "effectrow.h"
45 #include "effectgizmo.h"
46 
47 class Clip;
48 
49 class Effect;
50 using EffectPtr = std::shared_ptr<Effect>;
51 
52 struct EffectMeta {
53   QString name;
54   QString category;
55   QString filename;
56   QString path;
57   QString tooltip;
58   int internal;
59   int type;
60   int subtype;
61 };
62 extern QVector<EffectMeta> effects;
63 
64 double log_volume(double linear);
65 
66 enum EffectType {
67   EFFECT_TYPE_INVALID,
68   EFFECT_TYPE_VIDEO,
69   EFFECT_TYPE_AUDIO,
70   EFFECT_TYPE_EFFECT,
71   EFFECT_TYPE_TRANSITION
72 };
73 
74 enum EffectKeyframeType {
75   EFFECT_KEYFRAME_LINEAR,
76   EFFECT_KEYFRAME_BEZIER,
77   EFFECT_KEYFRAME_HOLD
78 };
79 
80 enum EffectInternal {
81   EFFECT_INTERNAL_TRANSFORM,
82   EFFECT_INTERNAL_TEXT,
83   EFFECT_INTERNAL_SOLID,
84   EFFECT_INTERNAL_NOISE,
85   EFFECT_INTERNAL_VOLUME,
86   EFFECT_INTERNAL_PAN,
87   EFFECT_INTERNAL_TONE,
88   EFFECT_INTERNAL_SHAKE,
89   EFFECT_INTERNAL_TIMECODE,
90   EFFECT_INTERNAL_MASK,
91   EFFECT_INTERNAL_FILLLEFTRIGHT,
92   EFFECT_INTERNAL_VST,
93   EFFECT_INTERNAL_CORNERPIN,
94   EFFECT_INTERNAL_FREI0R,
95   EFFECT_INTERNAL_RICHTEXT,
96   EFFECT_INTERNAL_COUNT
97 };
98 
99 struct GLTextureCoords {
100   int grid_size;
101 
102   int vertexTopLeftX;
103   int vertexTopLeftY;
104   int vertexTopLeftZ;
105   int vertexTopRightX;
106   int vertexTopRightY;
107   int vertexTopRightZ;
108   int vertexBottomLeftX;
109   int vertexBottomLeftY;
110   int vertexBottomLeftZ;
111   int vertexBottomRightX;
112   int vertexBottomRightY;
113   int vertexBottomRightZ;
114 
115   float textureTopLeftX;
116   float textureTopLeftY;
117   float textureTopLeftQ;
118   float textureTopRightX;
119   float textureTopRightY;
120   float textureTopRightQ;
121   float textureBottomRightX;
122   float textureBottomRightY;
123   float textureBottomRightQ;
124   float textureBottomLeftX;
125   float textureBottomLeftY;
126   float textureBottomLeftQ;
127 
128   int blendmode;
129   float opacity;
130 };
131 
132 const EffectMeta* get_meta_from_name(const QString& input);
133 
134 qint16 mix_audio_sample(qint16 a, qint16 b);
135 
136 class Effect : public QObject {
137   Q_OBJECT
138 public:
139   Effect(Clip *c, const EffectMeta* em);
140   ~Effect();
141 
142   Clip* parent_clip;
143   const EffectMeta* meta;
144   int id;
145   QString name;
146 
147   void AddRow(EffectRow* row);
148 
149   EffectRow* row(int i);
150   int row_count();
151 
152   EffectGizmo* add_gizmo(int type);
153   EffectGizmo* gizmo(int i);
154   int gizmo_count();
155 
156   bool IsEnabled();
157   bool IsExpanded();
158 
159   virtual void refresh();
160 
161   virtual EffectPtr copy(Clip* c);
162   void copy_field_keyframes(EffectPtr e);
163 
164   virtual void load(QXmlStreamReader& stream);
165   virtual void custom_load(QXmlStreamReader& stream);
166   virtual void save(QXmlStreamWriter& stream);
167 
168   void load_from_string(const QByteArray &s);
169   QByteArray save_to_string();
170 
171   // glsl handling
172   bool is_open();
173   void open();
174   void close();
175   bool is_glsl_linked();
176   virtual void startEffect();
177   virtual void endEffect();
178 
179   enum VideoEffectFlags {
180     ShaderFlag        = 0x1,
181     CoordsFlag        = 0x2,
182     SuperimposeFlag   = 0x4,
183     ImageFlag         = 0x8
184   };
185   int Flags();
186   void SetFlags(int flags);
187 
188   int getIterations();
189   void setIterations(int i);
190 
191   const char* ffmpeg_filter;
192 
193   virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size);
194   virtual void process_shader(double timecode, GLTextureCoords&, int iteration);
195   virtual void process_coords(double timecode, GLTextureCoords& coords, int data);
196   virtual GLuint process_superimpose(double timecode);
197   virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count);
198 
199   virtual void gizmo_draw(double timecode, GLTextureCoords& coords);
200   void gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode, bool done);
201   void gizmo_world_to_screen();
202   bool are_gizmos_enabled();
203 
204   template <typename T>
randomNumber()205   T randomNumber()
206   {
207     static std::random_device device;
208     static std::mt19937 generator(device());
209     static std::uniform_int_distribution<> distribution(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
210     return distribution(generator);
211   }
212 
213   static EffectPtr Create(Clip *c, const EffectMeta *em);
214   static const EffectMeta* GetInternalMeta(int internal_id, int type);
215 public slots:
216   void FieldChanged();
217   void SetEnabled(bool b);
218   void SetExpanded(bool e);
219 signals:
220   void EnabledChanged(bool);
221 private slots:
222   void delete_self();
223   void move_up();
224   void move_down();
225   void save_to_file();
226   void load_from_file();
227 protected:
228   // glsl effect
229   QOpenGLShaderProgram* glslProgram;
230   QString vertPath;
231   QString fragPath;
232 
233   // superimpose effect
234   QImage img;
235   QOpenGLTexture* texture;
236 
237   // enable effect to update constantly
238   virtual bool AlwaysUpdate();
239 
240 private:
241   bool isOpen;
242   QVector<EffectRow*> rows;
243   QVector<EffectGizmo*> gizmos;
244   bool bound;
245   int iterations;
246 
247   bool enabled_;
248   bool expanded_;
249 
250   int flags_;
251 
252   QVector<KeyframeDataChange*> gizmo_dragging_actions_;
253 
254   // superimpose functions
255   virtual void redraw(double timecode);
256   bool valueHasChanged(double timecode);
257   QVector<QVariant> cachedValues;
258   void delete_texture();
259   void validate_meta_path();
260 };
261 
262 #endif // EFFECT_H
263