OpenShot Library | libopenshot  0.5.0
EffectBase.cpp
Go to the documentation of this file.
1 
9 // Copyright (c) 2008-2019 OpenShot Studios, LLC
10 //
11 // SPDX-License-Identifier: LGPL-3.0-or-later
12 
13 #include <iostream>
14 #include <iomanip>
15 #include <algorithm>
16 #include <cmath>
17 
18 #include "EffectBase.h"
19 
20 #include "Exceptions.h"
21 #include "Clip.h"
22 #include "Timeline.h"
23 #include "ReaderBase.h"
24 #include "ChunkReader.h"
25 #include "FFmpegReader.h"
26 #include "QtImageReader.h"
27 #include "ZmqLogger.h"
28 #include <omp.h>
29 
30 #ifdef USE_IMAGEMAGICK
31  #include "ImageReader.h"
32 #endif
33 
34 using namespace openshot;
35 
36 // Initialize the values of the EffectInfo struct
38 {
39  // Init clip settings
40  Position(0.0);
41  Layer(0);
42  Start(0.0);
43  End(0.0);
44  Order(0);
45  ParentClip(NULL);
46  parentEffect = NULL;
47  mask_invert = false;
48  mask_reader = NULL;
51 
52  info.has_video = false;
53  info.has_audio = false;
54  info.has_tracked_object = false;
55  info.name = "";
56  info.description = "";
58  info.apply_before_clip = true;
59 }
60 
61 // Display file information
62 void EffectBase::DisplayInfo(std::ostream* out) {
63  *out << std::fixed << std::setprecision(2) << std::boolalpha;
64  *out << "----------------------------" << std::endl;
65  *out << "----- Effect Information -----" << std::endl;
66  *out << "----------------------------" << std::endl;
67  *out << "--> Name: " << info.name << std::endl;
68  *out << "--> Description: " << info.description << std::endl;
69  *out << "--> Has Video: " << info.has_video << std::endl;
70  *out << "--> Has Audio: " << info.has_audio << std::endl;
71  *out << "--> Apply Before Clip Keyframes: " << info.apply_before_clip << std::endl;
72  *out << "--> Order: " << order << std::endl;
73  *out << "----------------------------" << std::endl;
74 }
75 
76 // Constrain a color value from 0 to 255
77 int EffectBase::constrain(int color_value)
78 {
79  // Constrain new color from 0 to 255
80  if (color_value < 0)
81  color_value = 0;
82  else if (color_value > 255)
83  color_value = 255;
84 
85  return color_value;
86 }
87 
88 // Generate JSON string of this object
89 std::string EffectBase::Json() const {
90 
91  // Return formatted string
92  return JsonValue().toStyledString();
93 }
94 
95 // Generate Json::Value for this object
96 Json::Value EffectBase::JsonValue() const {
97 
98  // Create root json object
99  Json::Value root = ClipBase::JsonValue(); // get parent properties
100  root["name"] = info.name;
101  root["class_name"] = info.class_name;
102  root["description"] = info.description;
103  root["parent_effect_id"] = info.parent_effect_id;
104  root["has_video"] = info.has_video;
105  root["has_audio"] = info.has_audio;
106  root["has_tracked_object"] = info.has_tracked_object;
107  root["apply_before_clip"] = info.apply_before_clip;
108  root["order"] = Order();
109  root["mask_invert"] = mask_invert;
110  root["mask_time_mode"] = mask_time_mode;
111  root["mask_loop_mode"] = mask_loop_mode;
112  if (mask_reader)
113  root["mask_reader"] = mask_reader->JsonValue();
114  else
115  root["mask_reader"] = Json::objectValue;
116 
117  // return JsonValue
118  return root;
119 }
120 
121 // Load JSON string into this object
122 void EffectBase::SetJson(const std::string value) {
123 
124  // Parse JSON string into JSON objects
125  try
126  {
127  Json::Value root = openshot::stringToJson(value);
128  // Set all values that match
129  SetJsonValue(root);
130  }
131  catch (const std::exception& e)
132  {
133  // Error parsing JSON (or missing keys)
134  throw InvalidJSON("JSON is invalid (missing keys or invalid data types)");
135  }
136 }
137 
138 // Load Json::Value into this object
139 void EffectBase::SetJsonValue(const Json::Value root) {
140 
141  if (ParentTimeline()){
142  // Get parent timeline
143  Timeline* parentTimeline = static_cast<Timeline *>(ParentTimeline());
144 
145  // Get the list of effects on the timeline
146  std::list<EffectBase*> effects = parentTimeline->ClipEffects();
147 
148  // TODO: Fix recursive call for Object Detection
149 
150  // // Loop through the effects and check if we have a child effect linked to this effect
151  for (auto const& effect : effects){
152  // Set the properties of all effects which parentEffect points to this
153  if ((effect->info.parent_effect_id == this->Id()) && (effect->Id() != this->Id()))
154  effect->SetJsonValue(root);
155  }
156  }
157 
158  // Set this effect properties with the parent effect properties (except the id and parent_effect_id)
159  Json::Value my_root;
160  if (parentEffect){
161  my_root = parentEffect->JsonValue();
162  my_root["id"] = this->Id();
163  my_root["parent_effect_id"] = this->info.parent_effect_id;
164  } else {
165  my_root = root;
166  }
167 
168  // Legacy compatibility: older shared-mask JSON stored source trim
169  // separately from the effect trim. Canonical trim now uses ClipBase.
170  if (my_root["start"].isNull() && !my_root["mask_start"].isNull())
171  my_root["start"] = my_root["mask_start"];
172  if (my_root["end"].isNull() && !my_root["mask_end"].isNull())
173  my_root["end"] = my_root["mask_end"];
174 
175  // Set parent data
176  ClipBase::SetJsonValue(my_root);
177 
178  // Set data from Json (if key is found)
179  if (!my_root["order"].isNull())
180  Order(my_root["order"].asInt());
181 
182  if (!my_root["apply_before_clip"].isNull())
183  info.apply_before_clip = my_root["apply_before_clip"].asBool();
184 
185  if (!my_root["mask_invert"].isNull())
186  mask_invert = my_root["mask_invert"].asBool();
187  if (!my_root["mask_time_mode"].isNull()) {
188  const int time_mode = my_root["mask_time_mode"].asInt();
189  mask_time_mode = (time_mode == MASK_TIME_TIMELINE || time_mode == MASK_TIME_SOURCE_FPS)
190  ? time_mode : MASK_TIME_SOURCE_FPS;
191  }
192  if (!my_root["mask_loop_mode"].isNull()) {
193  const int loop_mode = my_root["mask_loop_mode"].asInt();
194  if (loop_mode >= MASK_LOOP_PLAY_ONCE && loop_mode <= MASK_LOOP_PING_PONG)
195  mask_loop_mode = loop_mode;
196  else
198  }
199 
200  const Json::Value mask_reader_json =
201  !my_root["mask_reader"].isNull() ? my_root["mask_reader"] : my_root["reader"];
202 
203  if (!mask_reader_json.isNull()) {
204  if (!mask_reader_json["type"].isNull()) {
205  MaskReader(CreateReaderFromJson(mask_reader_json));
206  } else if (mask_reader_json.isObject() && mask_reader_json.empty()) {
207  MaskReader(NULL);
208  }
209  }
210 
211  if (!my_root["parent_effect_id"].isNull()){
212  info.parent_effect_id = my_root["parent_effect_id"].asString();
213  if (info.parent_effect_id.size() > 0 && info.parent_effect_id != "" && parentEffect == NULL)
215  else
216  parentEffect = NULL;
217  }
218 }
219 
220 // Generate Json::Value for this object
221 Json::Value EffectBase::JsonInfo() const {
222 
223  // Create root json object
224  Json::Value root;
225  root["name"] = info.name;
226  root["class_name"] = info.class_name;
227  root["description"] = info.description;
228  root["has_video"] = info.has_video;
229  root["has_audio"] = info.has_audio;
230 
231  // return JsonValue
232  return root;
233 }
234 
235 // Get all properties for a specific frame
236 Json::Value EffectBase::BasePropertiesJSON(int64_t requested_frame) const {
237  // Generate JSON properties list
238  Json::Value root;
239  root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame);
240  root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 30 * 60 * 60 * 48, false, requested_frame);
241  root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame);
242  root["start"] = add_property_json("Start", Start(), "float", "", NULL, 0, 30 * 60 * 60 * 48, false, requested_frame);
243  root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 30 * 60 * 60 * 48, false, requested_frame);
244  root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 30 * 60 * 60 * 48, true, requested_frame);
245 
246  // Add replace_image choices (dropdown style)
247  root["apply_before_clip"] = add_property_json("Apply Before Clip Keyframes", info.apply_before_clip, "int", "", NULL, 0, 1, false, requested_frame);
248  root["apply_before_clip"]["choices"].append(add_property_choice_json("Yes", true, info.apply_before_clip));
249  root["apply_before_clip"]["choices"].append(add_property_choice_json("No", false, info.apply_before_clip));
250 
251  // Set the parent effect which properties this effect will inherit
252  root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame);
253 
254  if (info.has_video) {
255  root["mask_invert"] = add_property_json("Mask: Invert", mask_invert, "int", "", NULL, 0, 1, false, requested_frame);
256  root["mask_invert"]["choices"].append(add_property_choice_json("Yes", true, mask_invert));
257  root["mask_invert"]["choices"].append(add_property_choice_json("No", false, mask_invert));
258 
259  root["mask_time_mode"] = add_property_json("Mask: Time Mode", mask_time_mode, "int", "", NULL, 0, 1, false, requested_frame);
260  root["mask_time_mode"]["choices"].append(add_property_choice_json("Timeline", MASK_TIME_TIMELINE, mask_time_mode));
261  root["mask_time_mode"]["choices"].append(add_property_choice_json("Source FPS", MASK_TIME_SOURCE_FPS, mask_time_mode));
262 
263  root["mask_loop_mode"] = add_property_json("Mask: Loop", mask_loop_mode, "int", "", NULL, 0, 2, false, requested_frame);
264  root["mask_loop_mode"]["choices"].append(add_property_choice_json("Play Once", MASK_LOOP_PLAY_ONCE, mask_loop_mode));
265  root["mask_loop_mode"]["choices"].append(add_property_choice_json("Repeat", MASK_LOOP_REPEAT, mask_loop_mode));
266  root["mask_loop_mode"]["choices"].append(add_property_choice_json("Ping-Pong", MASK_LOOP_PING_PONG, mask_loop_mode));
267 
268  if (mask_reader)
269  root["mask_reader"] = add_property_json("Mask: Source", 0.0, "reader", mask_reader->Json(), NULL, 0, 1, false, requested_frame);
270  else
271  root["mask_reader"] = add_property_json("Mask: Source", 0.0, "reader", "{}", NULL, 0, 1, false, requested_frame);
272  }
273 
274  return root;
275 }
276 
277 ReaderBase* EffectBase::CreateReaderFromJson(const Json::Value& reader_json) const {
278  if (reader_json["type"].isNull())
279  return NULL;
280 
281  ReaderBase* reader = NULL;
282  const std::string type = reader_json["type"].asString();
283 
284  if (type == "FFmpegReader") {
285  reader = new FFmpegReader(reader_json["path"].asString());
286  reader->SetJsonValue(reader_json);
287  // Mask readers are video-only sources. Disabling audio avoids FFmpeg
288  // A/V readiness fallbacks that can repeat stale video frames.
289  reader->info.has_audio = false;
290  reader->info.audio_stream_index = -1;
291  } else if (type == "QtImageReader") {
292  reader = new QtImageReader(reader_json["path"].asString());
293  reader->SetJsonValue(reader_json);
294  } else if (type == "ChunkReader") {
295  reader = new ChunkReader(reader_json["path"].asString(),
296  static_cast<ChunkVersion>(reader_json["chunk_version"].asInt()));
297  reader->SetJsonValue(reader_json);
298 #ifdef USE_IMAGEMAGICK
299  } else if (type == "ImageReader") {
300  reader = new ImageReader(reader_json["path"].asString());
301  reader->SetJsonValue(reader_json);
302 #endif
303  }
304 
305  return reader;
306 }
307 
309  if (mask_reader == new_reader)
310  return;
311 
312  if (mask_reader) {
313  mask_reader->Close();
314  delete mask_reader;
315  }
316 
317  mask_reader = new_reader;
318  cached_single_mask_image.reset();
319  cached_single_mask_width = 0;
320  cached_single_mask_height = 0;
321  if (mask_reader)
322  mask_reader->ParentClip(clip);
323 }
324 
326  if (clip) {
327  Clip* parent_clip = dynamic_cast<Clip*>(clip);
328  if (parent_clip && parent_clip->info.fps.num > 0 && parent_clip->info.fps.den > 0)
329  return parent_clip->info.fps.ToDouble();
330  }
331 
332  Timeline* parent_timeline = dynamic_cast<Timeline*>(ParentTimeline());
333  if (parent_timeline && parent_timeline->info.fps.num > 0 && parent_timeline->info.fps.den > 0)
334  return parent_timeline->info.fps.ToDouble();
335 
336  if (mask_reader && mask_reader->info.fps.num > 0 && mask_reader->info.fps.den > 0)
337  return mask_reader->info.fps.ToDouble();
338 
339  return 30.0;
340 }
341 
343  if (!mask_reader)
344  return 0.0;
345 
346  if (mask_reader->info.duration > 0.0f)
347  return static_cast<double>(mask_reader->info.duration);
348 
349  if (mask_reader->info.video_length > 0 &&
350  mask_reader->info.fps.num > 0 && mask_reader->info.fps.den > 0) {
351  return static_cast<double>(mask_reader->info.video_length) / mask_reader->info.fps.ToDouble();
352  }
353 
354  return 0.0;
355 }
356 
357 int64_t EffectBase::MapMaskFrameNumber(int64_t frame_number) {
358  if (!mask_reader)
359  return frame_number;
360 
361  int64_t requested_index = std::max(int64_t(0), frame_number - 1);
362  if (!clip && ParentTimeline()) {
363  const double host_fps = ResolveMaskHostFps();
364  if (host_fps > 0.0) {
365  const int64_t start_offset = static_cast<int64_t>(std::llround(std::max(0.0f, Start()) * host_fps));
366  requested_index = std::max(int64_t(0), requested_index - start_offset);
367  }
368  }
369  int64_t mapped_index = requested_index;
370 
372  mask_reader->info.fps.num > 0 && mask_reader->info.fps.den > 0) {
373  const double host_fps = ResolveMaskHostFps();
374  const double source_fps = mask_reader->info.fps.ToDouble();
375  if (host_fps > 0.0 && source_fps > 0.0) {
376  const double seconds = static_cast<double>(requested_index) / host_fps;
377  mapped_index = static_cast<int64_t>(std::llround(seconds * source_fps));
378  }
379  }
380 
381  const int64_t source_len = mask_reader->info.video_length;
382  const double source_fps = (mask_reader->info.fps.num > 0 && mask_reader->info.fps.den > 0)
383  ? mask_reader->info.fps.ToDouble() : 30.0;
384  const double source_duration = ResolveMaskSourceDuration();
385  const double start_sec = std::min<double>(std::max(0.0f, Start()), source_duration);
386  const double end_sec = std::min<double>(std::max(0.0f, End()), source_duration);
387 
388  const int64_t range_start = std::max(int64_t(1), static_cast<int64_t>(std::llround(start_sec * source_fps)) + 1);
389  int64_t range_end = (end_sec > 0.0)
390  ? static_cast<int64_t>(std::llround(end_sec * source_fps)) + 1
391  : source_len;
392  if (source_len > 0)
393  range_end = std::min(range_end, source_len);
394  if (range_end < range_start)
395  range_end = range_start;
396 
397  const int64_t range_len = std::max(int64_t(1), range_end - range_start + 1);
398  int64_t range_index = mapped_index;
399 
400  switch (mask_loop_mode) {
401  case MASK_LOOP_REPEAT:
402  range_index = mapped_index % range_len;
403  break;
404  case MASK_LOOP_PING_PONG:
405  if (range_len > 1) {
406  const int64_t cycle_len = (range_len * 2) - 2;
407  int64_t phase = mapped_index % cycle_len;
408  if (phase >= range_len)
409  phase = cycle_len - phase;
410  range_index = phase;
411  } else {
412  range_index = 0;
413  }
414  break;
415  case MASK_LOOP_PLAY_ONCE:
416  default:
417  if (mapped_index < 0)
418  range_index = 0;
419  else if (mapped_index >= range_len)
420  range_index = range_len - 1;
421  else
422  range_index = mapped_index;
423  break;
424  }
425 
426  int64_t mapped_frame = range_start + range_index;
427  if (source_len > 0)
428  mapped_frame = std::min(std::max(int64_t(1), mapped_frame), source_len);
429  return std::max(int64_t(1), mapped_frame);
430 }
431 
432 std::shared_ptr<QImage> EffectBase::GetMaskImage(std::shared_ptr<QImage> target_image, int64_t frame_number) {
433  if (!mask_reader || !target_image || target_image->isNull())
434  return {};
435 
436  std::shared_ptr<QImage> source_mask;
437  bool used_cached_scaled = false;
438  #pragma omp critical (open_effect_mask_reader)
439  {
440  try {
441  if (!mask_reader->IsOpen())
442  mask_reader->Open();
443 
444  if (mask_reader->info.has_single_image &&
445  cached_single_mask_image &&
446  cached_single_mask_width == target_image->width() &&
447  cached_single_mask_height == target_image->height()) {
448  source_mask = cached_single_mask_image;
449  used_cached_scaled = true;
450  }
451  else {
452  const int64_t mapped_frame = MapMaskFrameNumber(frame_number);
453  auto source_frame = mask_reader->GetFrame(mapped_frame);
454  if (source_frame && source_frame->GetImage() && !source_frame->GetImage()->isNull())
455  source_mask = std::make_shared<QImage>(*source_frame->GetImage());
456  }
457  } catch (const std::exception& e) {
459  std::string("EffectBase::GetMaskImage unable to read mask frame: ") + e.what());
460  source_mask.reset();
461  }
462  }
463 
464  if (!source_mask || source_mask->isNull())
465  return {};
466 
467  if (used_cached_scaled)
468  return source_mask;
469 
470  auto scaled_mask = std::make_shared<QImage>(
471  source_mask->scaled(
472  target_image->width(), target_image->height(),
473  Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
474  if (mask_reader->info.has_single_image) {
475  cached_single_mask_image = scaled_mask;
476  cached_single_mask_width = target_image->width();
477  cached_single_mask_height = target_image->height();
478  }
479  return scaled_mask;
480 }
481 
482 void EffectBase::BlendWithMask(std::shared_ptr<QImage> original_image, std::shared_ptr<QImage> effected_image,
483  std::shared_ptr<QImage> mask_image) const {
484  if (!original_image || !effected_image || !mask_image)
485  return;
486  if (original_image->size() != effected_image->size() || effected_image->size() != mask_image->size())
487  return;
488 
489  unsigned char* original_pixels = reinterpret_cast<unsigned char*>(original_image->bits());
490  unsigned char* effected_pixels = reinterpret_cast<unsigned char*>(effected_image->bits());
491  unsigned char* mask_pixels = reinterpret_cast<unsigned char*>(mask_image->bits());
492  const int pixel_count = effected_image->width() * effected_image->height();
493 
494  #pragma omp parallel for schedule(static)
495  for (int i = 0; i < pixel_count; ++i) {
496  const int idx = i * 4;
497  int gray = qGray(mask_pixels[idx], mask_pixels[idx + 1], mask_pixels[idx + 2]);
498  if (mask_invert)
499  gray = 255 - gray;
500  const float factor = static_cast<float>(gray) / 255.0f;
501  const float inverse = 1.0f - factor;
502 
503  effected_pixels[idx] = static_cast<unsigned char>(
504  (original_pixels[idx] * inverse) + (effected_pixels[idx] * factor));
505  effected_pixels[idx + 1] = static_cast<unsigned char>(
506  (original_pixels[idx + 1] * inverse) + (effected_pixels[idx + 1] * factor));
507  effected_pixels[idx + 2] = static_cast<unsigned char>(
508  (original_pixels[idx + 2] * inverse) + (effected_pixels[idx + 2] * factor));
509  effected_pixels[idx + 3] = static_cast<unsigned char>(
510  (original_pixels[idx + 3] * inverse) + (effected_pixels[idx + 3] * factor));
511  }
512 }
513 
514 std::shared_ptr<openshot::Frame> EffectBase::ProcessFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number) {
515  // Audio-only effects skip common mask handling.
516  if (!info.has_video || !mask_reader)
517  return GetFrame(frame, frame_number);
518 
519  // Effects that already apply masks inside GetFrame() should bypass common blend handling.
520  if (HandlesMaskInternally())
521  return GetFrame(frame, frame_number);
522 
523  auto pre_image = frame->GetImage();
524  if (!pre_image || pre_image->isNull())
525  return GetFrame(frame, frame_number);
526 
527  const auto original_image = std::make_shared<QImage>(pre_image->copy());
528  auto output_frame = GetFrame(frame, frame_number);
529  if (!output_frame)
530  return output_frame;
531  auto effected_image = output_frame->GetImage();
532  if (!effected_image || effected_image->isNull() ||
533  effected_image->size() != original_image->size())
534  return output_frame;
535 
536  auto mask_image = GetMaskImage(effected_image, frame_number);
537  if (!mask_image || mask_image->isNull())
538  return output_frame;
539 
540  if (UseCustomMaskBlend(frame_number))
541  ApplyCustomMaskBlend(original_image, effected_image, mask_image, frame_number);
542  else
543  BlendWithMask(original_image, effected_image, mask_image);
544 
545  return output_frame;
546 }
547 
550  return clip;
551 }
552 
555  clip = new_clip;
556  if (mask_reader)
557  mask_reader->ParentClip(new_clip);
558 }
559 
560 // Set the parent effect from which this properties will be set to
561 void EffectBase::SetParentEffect(std::string parentEffect_id) {
562 
563  // Get parent Timeline
564  Timeline* parentTimeline = static_cast<Timeline *>(ParentTimeline());
565 
566  if (parentTimeline){
567 
568  // Get a pointer to the parentEffect
569  EffectBase* parentEffectPtr = parentTimeline->GetClipEffect(parentEffect_id);
570 
571  if (parentEffectPtr){
572  // Set the parent Effect
573  parentEffect = parentEffectPtr;
574 
575  // Set the properties of this effect with the parent effect's properties
576  Json::Value EffectJSON = parentEffect->JsonValue();
577  EffectJSON["id"] = this->Id();
578  EffectJSON["parent_effect_id"] = this->info.parent_effect_id;
579  this->SetJsonValue(EffectJSON);
580  }
581  }
582  return;
583 }
584 
585 // Return the ID of this effect's parent clip
586 std::string EffectBase::ParentClipId() const{
587  if(clip)
588  return clip->Id();
589  else
590  return "";
591 }
592 
594  MaskReader(NULL);
595 }
openshot::ClipBase::add_property_json
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
Generate JSON for a property.
Definition: ClipBase.cpp:96
openshot::stringToJson
const Json::Value stringToJson(const std::string value)
Definition: Json.cpp:16
openshot::EffectBase::~EffectBase
virtual ~EffectBase()
Definition: EffectBase.cpp:593
openshot::EffectBase
This abstract class is the base class, used by all effects in libopenshot.
Definition: EffectBase.h:56
openshot::EffectBase::info
EffectInfoStruct info
Information about the current effect.
Definition: EffectBase.h:110
openshot::ReaderBase::JsonValue
virtual Json::Value JsonValue() const =0
Generate Json::Value for this object.
Definition: ReaderBase.cpp:106
openshot::EffectBase::JsonInfo
Json::Value JsonInfo() const
Generate JSON object of meta data / info.
Definition: EffectBase.cpp:221
Clip.h
Header file for Clip class.
openshot::ChunkReader
This class reads a special chunk-formatted file, which can be easily shared in a distributed environm...
Definition: ChunkReader.h:78
openshot::ReaderBase::GetFrame
virtual std::shared_ptr< openshot::Frame > GetFrame(int64_t number)=0
openshot::EffectInfoStruct::apply_before_clip
bool apply_before_clip
Apply effect before we evaluate the clip's keyframes.
Definition: EffectBase.h:46
openshot::ReaderBase::SetJsonValue
virtual void SetJsonValue(const Json::Value root)=0
Load Json::Value into this object.
Definition: ReaderBase.cpp:157
openshot::ReaderBase::Json
virtual std::string Json() const =0
Generate JSON string of this object.
openshot::ClipBase::End
virtual void End(float value)
Set end position (in seconds) of clip (trim end of video)
Definition: ClipBase.cpp:53
openshot::EffectBase::mask_invert
bool mask_invert
Invert grayscale mask values before blending.
Definition: EffectBase.h:111
openshot
This namespace is the default namespace for all code in the openshot library.
Definition: Compressor.h:28
openshot::EffectBase::ParentClip
openshot::ClipBase * ParentClip()
Parent clip object of this effect (which can be unparented and NULL)
Definition: EffectBase.cpp:549
openshot::ClipBase::add_property_choice_json
Json::Value add_property_choice_json(std::string name, int value, int selected_value) const
Generate JSON choice for a property (dropdown properties)
Definition: ClipBase.cpp:132
openshot::ZmqLogger::Log
void Log(std::string message)
Log message to all subscribers of this logger (if any)
Definition: ZmqLogger.cpp:103
openshot::Clip
This class represents a clip (used to arrange readers on the timeline)
Definition: Clip.h:89
openshot::EffectBase::JsonValue
virtual Json::Value JsonValue() const
Generate Json::Value for this object.
Definition: EffectBase.cpp:96
openshot::EffectBase::mask_time_mode
int mask_time_mode
How effect frames map to mask source frames.
Definition: EffectBase.h:124
openshot::ReaderBase::info
openshot::ReaderInfo info
Information about the current media file.
Definition: ReaderBase.h:88
Timeline.h
Header file for Timeline class.
openshot::EffectBase::DisplayInfo
void DisplayInfo(std::ostream *out=&std::cout)
Display effect information in the standard output stream (stdout)
Definition: EffectBase.cpp:62
openshot::EffectBase::CreateReaderFromJson
ReaderBase * CreateReaderFromJson(const Json::Value &reader_json) const
Create a reader instance from reader JSON.
Definition: EffectBase.cpp:277
openshot::ReaderInfo::duration
float duration
Length of time (in seconds)
Definition: ReaderBase.h:43
EffectBase.h
Header file for EffectBase class.
openshot::ClipBase::Position
void Position(float value)
Set the Id of this clip object
Definition: ClipBase.cpp:19
openshot::EffectBase::Json
virtual std::string Json() const
Generate JSON string of this object.
Definition: EffectBase.cpp:89
openshot::EffectBase::UseCustomMaskBlend
virtual bool UseCustomMaskBlend(int64_t frame_number) const
Optional override for effects that need custom mask behavior.
Definition: EffectBase.h:93
openshot::Fraction::ToDouble
double ToDouble() const
Return this fraction as a double (i.e. 1/2 = 0.5)
Definition: Fraction.cpp:40
openshot::EffectBase::SetParentEffect
void SetParentEffect(std::string parentEffect_id)
Set the parent effect from which this properties will be set to.
Definition: EffectBase.cpp:561
openshot::ClipBase::SetJsonValue
virtual void SetJsonValue(const Json::Value root)=0
Load Json::Value into this object.
Definition: ClipBase.cpp:80
openshot::QtImageReader
This class uses the Qt library, to open image files, and return openshot::Frame objects containing th...
Definition: QtImageReader.h:74
openshot::EffectBase::MASK_TIME_TIMELINE
@ MASK_TIME_TIMELINE
Definition: EffectBase.h:114
openshot::ClipBase::JsonValue
virtual Json::Value JsonValue() const =0
Generate Json::Value for this object.
Definition: ClipBase.cpp:64
openshot::EffectBase::ProcessFrame
std::shared_ptr< openshot::Frame > ProcessFrame(std::shared_ptr< openshot::Frame > frame, int64_t frame_number)
Apply effect processing with common mask support (if enabled).
Definition: EffectBase.cpp:514
openshot::ReaderInfo::video_length
int64_t video_length
The number of frames in the video stream.
Definition: ReaderBase.h:53
openshot::EffectBase::BasePropertiesJSON
Json::Value BasePropertiesJSON(int64_t requested_frame) const
Generate JSON object of base properties (recommended to be used by all effects)
Definition: EffectBase.cpp:236
openshot::Fraction::num
int num
Numerator for the fraction.
Definition: Fraction.h:32
ZmqLogger.h
Header file for ZeroMQ-based Logger class.
openshot::Fraction::den
int den
Denominator for the fraction.
Definition: Fraction.h:33
openshot::EffectBase::MASK_LOOP_PLAY_ONCE
@ MASK_LOOP_PLAY_ONCE
Definition: EffectBase.h:119
openshot::ReaderBase::Open
virtual void Open()=0
Open the reader (and start consuming resources, such as images or video files)
openshot::ReaderInfo::has_audio
bool has_audio
Determines if this file has an audio stream.
Definition: ReaderBase.h:41
openshot::EffectBase::parentEffect
EffectBase * parentEffect
Parent effect (which properties will set this effect properties)
Definition: EffectBase.h:104
openshot::ReaderBase::IsOpen
virtual bool IsOpen()=0
Determine if reader is open or closed.
openshot::InvalidJSON
Exception for invalid JSON.
Definition: Exceptions.h:223
openshot::Timeline
This class represents a timeline.
Definition: Timeline.h:152
openshot::ImageReader
This class uses the ImageMagick++ libraries, to open image files, and return openshot::Frame objects ...
Definition: ImageReader.h:55
openshot::Timeline::ClipEffects
std::list< openshot::EffectBase * > ClipEffects() const
Return the list of effects on all clips.
Definition: Timeline.cpp:453
openshot::EffectBase::InitEffectInfo
void InitEffectInfo()
Definition: EffectBase.cpp:37
openshot::EffectInfoStruct::has_audio
bool has_audio
Determines if this effect manipulates the audio of a frame.
Definition: EffectBase.h:44
openshot::ReaderInfo::has_single_image
bool has_single_image
Determines if this file only contains a single image.
Definition: ReaderBase.h:42
openshot::EffectInfoStruct::has_tracked_object
bool has_tracked_object
Determines if this effect track objects through the clip.
Definition: EffectBase.h:45
openshot::EffectBase::ResolveMaskSourceDuration
double ResolveMaskSourceDuration() const
Determine mask source duration in seconds.
Definition: EffectBase.cpp:342
openshot::ClipBase::Start
void Start(float value)
Set start position (in seconds) of clip (trim start of video)
Definition: ClipBase.cpp:42
openshot::FFmpegReader
This class uses the FFmpeg libraries, to open video files and audio files, and return openshot::Frame...
Definition: FFmpegReader.h:103
openshot::EffectBase::MaskReader
ReaderBase * MaskReader()
Get the common mask reader.
Definition: EffectBase.h:175
ChunkReader.h
Header file for ChunkReader class.
openshot::EffectBase::ParentClipId
std::string ParentClipId() const
Return the ID of this effect's parent clip.
Definition: EffectBase.cpp:586
openshot::ReaderInfo::audio_stream_index
int audio_stream_index
The index of the audio stream.
Definition: ReaderBase.h:63
openshot::ZmqLogger::Instance
static ZmqLogger * Instance()
Create or get an instance of this logger singleton (invoke the class with this method)
Definition: ZmqLogger.cpp:35
openshot::EffectBase::ResolveMaskHostFps
double ResolveMaskHostFps()
Determine host FPS used to convert timeline frames to mask source FPS.
Definition: EffectBase.cpp:325
openshot::EffectBase::Order
int Order() const
Get the order that this effect should be executed.
Definition: EffectBase.h:182
openshot::EffectInfoStruct::class_name
std::string class_name
The class name of the effect.
Definition: EffectBase.h:39
ReaderBase.h
Header file for ReaderBase class.
openshot::EffectInfoStruct::description
std::string description
The description of this effect and what it does.
Definition: EffectBase.h:41
openshot::EffectInfoStruct::has_video
bool has_video
Determines if this effect manipulates the image of a frame.
Definition: EffectBase.h:43
openshot::EffectBase::MASK_LOOP_REPEAT
@ MASK_LOOP_REPEAT
Definition: EffectBase.h:120
openshot::ClipBase::Id
void Id(std::string value)
Definition: ClipBase.h:94
openshot::EffectBase::MASK_LOOP_PING_PONG
@ MASK_LOOP_PING_PONG
Definition: EffectBase.h:121
openshot::EffectBase::constrain
int constrain(int color_value)
Constrain a color value from 0 to 255.
Definition: EffectBase.cpp:77
openshot::ReaderInfo::fps
openshot::Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
Definition: ReaderBase.h:48
openshot::EffectInfoStruct::parent_effect_id
std::string parent_effect_id
Id of the parent effect (if there is one)
Definition: EffectBase.h:42
openshot::ReaderBase
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:75
openshot::EffectBase::mask_loop_mode
int mask_loop_mode
Behavior when mask range reaches the end.
Definition: EffectBase.h:125
openshot::EffectInfoStruct::name
std::string name
The name of the effect.
Definition: EffectBase.h:40
openshot::ClipBase::GetFrame
virtual std::shared_ptr< openshot::Frame > GetFrame(int64_t frame_number)=0
This method is required for all derived classes of ClipBase, and returns a new openshot::Frame object...
openshot::ReaderBase::Close
virtual void Close()=0
Close the reader (and any resources it was consuming)
openshot::EffectBase::MASK_TIME_SOURCE_FPS
@ MASK_TIME_SOURCE_FPS
Definition: EffectBase.h:115
QtImageReader.h
Header file for QtImageReader class.
openshot::EffectBase::HandlesMaskInternally
virtual bool HandlesMaskInternally() const
Optional override for effects that apply mask processing inside GetFrame().
Definition: EffectBase.h:100
openshot::Timeline::GetClipEffect
openshot::EffectBase * GetClipEffect(const std::string &id)
Look up a clip effect by ID.
Definition: Timeline.cpp:440
openshot::EffectBase::MapMaskFrameNumber
int64_t MapMaskFrameNumber(int64_t frame_number)
Convert an effect frame number to a mask source frame number.
Definition: EffectBase.cpp:357
ImageReader.h
Header file for ImageReader class.
openshot::ClipBase
This abstract class is the base class, used by all clips in libopenshot.
Definition: ClipBase.h:32
openshot::EffectBase::SetJson
virtual void SetJson(const std::string value)
Load JSON string into this object.
Definition: EffectBase.cpp:122
openshot::ChunkVersion
ChunkVersion
This enumeration allows the user to choose which version of the chunk they would like (low,...
Definition: ChunkReader.h:49
openshot::ClipBase::Layer
void Layer(int value)
Set layer of clip on timeline (lower number is covered by higher numbers)
Definition: ClipBase.cpp:31
openshot::EffectBase::ApplyCustomMaskBlend
virtual void ApplyCustomMaskBlend(std::shared_ptr< QImage > original_image, std::shared_ptr< QImage > effected_image, std::shared_ptr< QImage > mask_image, int64_t frame_number) const
Optional override for effects with custom mask implementation.
Definition: EffectBase.h:96
Exceptions.h
Header file for all Exception classes.
FFmpegReader.h
Header file for FFmpegReader class.
openshot::EffectBase::SetJsonValue
virtual void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
Definition: EffectBase.cpp:139
openshot::ReaderBase::ParentClip
openshot::ClipBase * ParentClip()
Parent clip object of this reader (which can be unparented and NULL)
Definition: ReaderBase.cpp:240
openshot::EffectBase::clip
openshot::ClipBase * clip
Pointer to the parent clip instance (if any)
Definition: EffectBase.h:73