OpenShot Library | libopenshot  0.1.3
Clip.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Source file for Clip class
4  * @author Jonathan Thomas <jonathan@openshot.org>
5  *
6  * @section LICENSE
7  *
8  * Copyright (c) 2008-2014 OpenShot Studios, LLC
9  * <http://www.openshotstudios.com/>. This file is part of
10  * OpenShot Library (libopenshot), an open-source project dedicated to
11  * delivering high quality video editing and animation solutions to the
12  * world. For more information visit <http://www.openshot.org/>.
13  *
14  * OpenShot Library (libopenshot) is free software: you can redistribute it
15  * and/or modify it under the terms of the GNU Lesser General Public License
16  * as published by the Free Software Foundation, either version 3 of the
17  * License, or (at your option) any later version.
18  *
19  * OpenShot Library (libopenshot) is distributed in the hope that it will be
20  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 #include "../include/Clip.h"
29 
30 using namespace openshot;
31 
32 // Init default settings for a clip
33 void Clip::init_settings()
34 {
35  // Init clip settings
36  Position(0.0);
37  Layer(0);
38  Start(0.0);
39  End(0.0);
41  scale = SCALE_FIT;
44  waveform = false;
46 
47  // Init scale curves
48  scale_x = Keyframe(1.0);
49  scale_y = Keyframe(1.0);
50 
51  // Init location curves
52  location_x = Keyframe(0.0);
53  location_y = Keyframe(0.0);
54 
55  // Init alpha & rotation
56  alpha = Keyframe(1.0);
57  rotation = Keyframe(0.0);
58 
59  // Init time & volume
60  time = Keyframe(0.0);
61  volume = Keyframe(1.0);
62 
63  // Init audio waveform color
64  wave_color = Color((unsigned char)0, (unsigned char)123, (unsigned char)255, (unsigned char)255);
65 
66  // Init crop settings
68  crop_width = Keyframe(-1.0);
69  crop_height = Keyframe(-1.0);
70  crop_x = Keyframe(0.0);
71  crop_y = Keyframe(0.0);
72 
73  // Init shear and perspective curves
74  shear_x = Keyframe(0.0);
75  shear_y = Keyframe(0.0);
76  perspective_c1_x = Keyframe(-1.0);
77  perspective_c1_y = Keyframe(-1.0);
78  perspective_c2_x = Keyframe(-1.0);
79  perspective_c2_y = Keyframe(-1.0);
80  perspective_c3_x = Keyframe(-1.0);
81  perspective_c3_y = Keyframe(-1.0);
82  perspective_c4_x = Keyframe(-1.0);
83  perspective_c4_y = Keyframe(-1.0);
84 
85  // Init audio channel filter and mappings
86  channel_filter = Keyframe(-1.0);
87  channel_mapping = Keyframe(-1.0);
88 
89  // Init audio and video overrides
90  has_audio = Keyframe(-1.0);
91  has_video = Keyframe(-1.0);
92 
93  // Default pointers
94  reader = NULL;
95  resampler = NULL;
96  audio_cache = NULL;
97  manage_reader = false;
98 }
99 
100 // Default Constructor for a clip
102 {
103  // Init all default settings
104  init_settings();
105 }
106 
107 // Constructor with reader
108 Clip::Clip(ReaderBase* new_reader)
109 {
110  // Init all default settings
111  init_settings();
112 
113  // Set the reader
114  reader = new_reader;
115 
116  // Open and Close the reader (to set the duration of the clip)
117  Open();
118  Close();
119 
120  // Update duration
121  End(reader->info.duration);
122 }
123 
124 // Constructor with filepath
125 Clip::Clip(string path)
126 {
127  // Init all default settings
128  init_settings();
129 
130  // Get file extension (and convert to lower case)
131  string ext = get_file_extension(path);
132  transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
133 
134  // Determine if common video formats
135  if (ext=="avi" || ext=="mov" || ext=="mkv" || ext=="mpg" || ext=="mpeg" || ext=="mp3" || ext=="mp4" || ext=="mts" ||
136  ext=="ogg" || ext=="wav" || ext=="wmv" || ext=="webm" || ext=="vob")
137  {
138  try
139  {
140  // Open common video format
141  reader = new FFmpegReader(path);
142 
143  } catch(...) { }
144  }
145 
146  // If no video found, try each reader
147  if (!reader)
148  {
149  try
150  {
151  // Try an image reader
152  reader = new QtImageReader(path);
153 
154  } catch(...) {
155  try
156  {
157  // Try a video reader
158  reader = new FFmpegReader(path);
159 
160  } catch(...) { }
161  }
162  }
163 
164  // Update duration
165  if (reader) {
166  End(reader->info.duration);
167  manage_reader = true;
168  }
169 }
170 
171 // Destructor
173 {
174  // Delete the reader if clip created it
175  if (manage_reader && reader) {
176  delete reader;
177  reader = NULL;
178  }
179 
180  // Close the resampler
181  if (resampler) {
182  delete resampler;
183  resampler = NULL;
184  }
185 }
186 
187 /// Set the current reader
188 void Clip::Reader(ReaderBase* new_reader)
189 {
190  // set reader pointer
191  reader = new_reader;
192 }
193 
194 /// Get the current reader
196 {
197  if (reader)
198  return reader;
199  else
200  // Throw error if reader not initialized
201  throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", "");
202 }
203 
204 // Open the internal reader
206 {
207  if (reader)
208  {
209  // Open the reader
210  reader->Open();
211 
212  // Set some clip properties from the file reader
213  if (end == 0.0)
214  End(reader->info.duration);
215  }
216  else
217  // Throw error if reader not initialized
218  throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", "");
219 }
220 
221 // Close the internal reader
223 {
224  if (reader) {
225  ZmqLogger::Instance()->AppendDebugMethod("Clip::Close", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
226 
227  // Close the reader
228  reader->Close();
229  }
230  else
231  // Throw error if reader not initialized
232  throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", "");
233 }
234 
235 // Get end position of clip (trim end of video), which can be affected by the time curve.
236 float Clip::End() throw(ReaderClosed)
237 {
238  // if a time curve is present, use it's length
239  if (time.Points.size() > 1)
240  {
241  // Determine the FPS fo this clip
242  float fps = 24.0;
243  if (reader)
244  // file reader
245  fps = reader->info.fps.ToFloat();
246  else
247  // Throw error if reader not initialized
248  throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", "");
249 
250  return float(time.GetLength()) / fps;
251  }
252  else
253  // just use the duration (as detected by the reader)
254  return end;
255 }
256 
257 // Get an openshot::Frame object for a specific frame number of this reader.
258 tr1::shared_ptr<Frame> Clip::GetFrame(long int requested_frame) throw(ReaderClosed)
259 {
260  if (reader)
261  {
262  // Adjust out of bounds frame number
263  requested_frame = adjust_frame_number_minimum(requested_frame);
264 
265  // Adjust has_video and has_audio overrides
266  int enabled_audio = has_audio.GetInt(requested_frame);
267  if (enabled_audio == -1 && reader && reader->info.has_audio)
268  enabled_audio = 1;
269  else if (enabled_audio == -1 && reader && !reader->info.has_audio)
270  enabled_audio = 0;
271  int enabled_video = has_video.GetInt(requested_frame);
272  if (enabled_video == -1 && reader && reader->info.has_video)
273  enabled_video = 1;
274  else if (enabled_video == -1 && reader && !reader->info.has_audio)
275  enabled_video = 0;
276 
277  // Adjust parent reader with same settings (for performance gains)
278  if (reader) {
279  // Override parent reader
280  reader->info.has_audio = enabled_audio;
281  reader->info.has_video = enabled_video;
282  }
283 
284  // Is a time map detected
285  long int new_frame_number = requested_frame;
286  if (time.Values.size() > 1)
287  new_frame_number = time.GetLong(requested_frame);
288 
289 
290  // Now that we have re-mapped what frame number is needed, go and get the frame pointer
291  tr1::shared_ptr<Frame> original_frame = GetOrCreateFrame(new_frame_number);
292 
293  // Create a new frame
294  tr1::shared_ptr<Frame> frame(new Frame(new_frame_number, 1, 1, "#000000", original_frame->GetAudioSamplesCount(), original_frame->GetAudioChannelsCount()));
295  frame->SampleRate(original_frame->SampleRate());
296  frame->ChannelsLayout(original_frame->ChannelsLayout());
297 
298  // Copy the image from the odd field
299  if (enabled_video)
300  frame->AddImage(tr1::shared_ptr<QImage>(new QImage(*original_frame->GetImage())));
301 
302  // Loop through each channel, add audio
303  if (enabled_audio && reader->info.has_audio)
304  for (int channel = 0; channel < original_frame->GetAudioChannelsCount(); channel++)
305  frame->AddAudio(true, channel, 0, original_frame->GetAudioSamples(channel), original_frame->GetAudioSamplesCount(), 1.0);
306 
307  // Get time mapped frame number (used to increase speed, change direction, etc...)
308  tr1::shared_ptr<Frame> new_frame = get_time_mapped_frame(frame, requested_frame);
309 
310  // Apply effects to the frame (if any)
311  apply_effects(new_frame);
312 
313  // Return processed 'frame'
314  return new_frame;
315  }
316  else
317  // Throw error if reader not initialized
318  throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", "");
319 }
320 
321 // Get file extension
322 string Clip::get_file_extension(string path)
323 {
324  // return last part of path
325  return path.substr(path.find_last_of(".") + 1);
326 }
327 
328 // Reverse an audio buffer
329 void Clip::reverse_buffer(juce::AudioSampleBuffer* buffer)
330 {
331  int number_of_samples = buffer->getNumSamples();
332  int channels = buffer->getNumChannels();
333 
334  // Reverse array (create new buffer to hold the reversed version)
335  AudioSampleBuffer *reversed = new juce::AudioSampleBuffer(channels, number_of_samples);
336  reversed->clear();
337 
338  for (int channel = 0; channel < channels; channel++)
339  {
340  int n=0;
341  for (int s = number_of_samples - 1; s >= 0; s--, n++)
342  reversed->getWritePointer(channel)[n] = buffer->getWritePointer(channel)[s];
343  }
344 
345  // Copy the samples back to the original array
346  buffer->clear();
347  // Loop through channels, and get audio samples
348  for (int channel = 0; channel < channels; channel++)
349  // Get the audio samples for this channel
350  buffer->addFrom(channel, 0, reversed->getReadPointer(channel), number_of_samples, 1.0f);
351 
352  delete reversed;
353  reversed = NULL;
354 }
355 
356 // Adjust the audio and image of a time mapped frame
357 tr1::shared_ptr<Frame> Clip::get_time_mapped_frame(tr1::shared_ptr<Frame> frame, long int frame_number) throw(ReaderClosed)
358 {
359  // Check for valid reader
360  if (!reader)
361  // Throw error if reader not initialized
362  throw ReaderClosed("No Reader has been initialized for this Clip. Call Reader(*reader) before calling this method.", "");
363 
364  // Check for a valid time map curve
365  if (time.Values.size() > 1)
366  {
367  tr1::shared_ptr<Frame> new_frame;
368 
369  // create buffer and resampler
370  juce::AudioSampleBuffer *samples = NULL;
371  if (!resampler)
372  resampler = new AudioResampler();
373 
374  // Get new frame number
375  int new_frame_number = round(time.GetValue(frame_number));
376 
377  // Create a new frame
378  int samples_in_frame = Frame::GetSamplesPerFrame(new_frame_number, reader->info.fps, reader->info.sample_rate, frame->GetAudioChannelsCount());
379  new_frame = tr1::shared_ptr<Frame>(new Frame(new_frame_number, 1, 1, "#000000", samples_in_frame, frame->GetAudioChannelsCount()));
380 
381  // Copy the image from the new frame
382  new_frame->AddImage(GetOrCreateFrame(new_frame_number)->GetImage());
383 
384 
385  // Get delta (difference in previous Y value)
386  int delta = int(round(time.GetDelta(frame_number)));
387 
388  // Init audio vars
389  int sample_rate = reader->info.sample_rate;
390  int channels = reader->info.channels;
391  int number_of_samples = GetOrCreateFrame(new_frame_number)->GetAudioSamplesCount();
392 
393  // Only resample audio if needed
394  if (reader->info.has_audio) {
395  // Determine if we are speeding up or slowing down
396  if (time.GetRepeatFraction(frame_number).den > 1) {
397  // SLOWING DOWN AUDIO
398  // Resample data, and return new buffer pointer
399  AudioSampleBuffer *resampled_buffer = NULL;
400  int resampled_buffer_size = 0;
401 
402  // SLOW DOWN audio (split audio)
403  samples = new juce::AudioSampleBuffer(channels, number_of_samples);
404  samples->clear();
405 
406  // Loop through channels, and get audio samples
407  for (int channel = 0; channel < channels; channel++)
408  // Get the audio samples for this channel
409  samples->addFrom(channel, 0, GetOrCreateFrame(new_frame_number)->GetAudioSamples(channel),
410  number_of_samples, 1.0f);
411 
412  // Reverse the samples (if needed)
413  if (!time.IsIncreasing(frame_number))
414  reverse_buffer(samples);
415 
416  // Resample audio to be X times slower (where X is the denominator of the repeat fraction)
417  resampler->SetBuffer(samples, 1.0 / time.GetRepeatFraction(frame_number).den);
418 
419  // Resample the data (since it's the 1st slice)
420  resampled_buffer = resampler->GetResampledBuffer();
421 
422  // Get the length of the resampled buffer (if one exists)
423  resampled_buffer_size = resampled_buffer->getNumSamples();
424 
425  // Just take the samples we need for the requested frame
426  int start = (number_of_samples * (time.GetRepeatFraction(frame_number).num - 1));
427  if (start > 0)
428  start -= 1;
429  for (int channel = 0; channel < channels; channel++)
430  // Add new (slower) samples, to the frame object
431  new_frame->AddAudio(true, channel, 0, resampled_buffer->getReadPointer(channel, start),
432  number_of_samples, 1.0f);
433 
434  // Clean up
435  resampled_buffer = NULL;
436 
437  }
438  else if (abs(delta) > 1 && abs(delta) < 100) {
439  int start = 0;
440  if (delta > 0) {
441  // SPEED UP (multiple frames of audio), as long as it's not more than X frames
442  int total_delta_samples = 0;
443  for (int delta_frame = new_frame_number - (delta - 1);
444  delta_frame <= new_frame_number; delta_frame++)
445  total_delta_samples += Frame::GetSamplesPerFrame(delta_frame, reader->info.fps,
446  reader->info.sample_rate,
447  reader->info.channels);
448 
449  // Allocate a new sample buffer for these delta frames
450  samples = new juce::AudioSampleBuffer(channels, total_delta_samples);
451  samples->clear();
452 
453  // Loop through each frame in this delta
454  for (int delta_frame = new_frame_number - (delta - 1);
455  delta_frame <= new_frame_number; delta_frame++) {
456  // buffer to hold detal samples
457  int number_of_delta_samples = GetOrCreateFrame(delta_frame)->GetAudioSamplesCount();
458  AudioSampleBuffer *delta_samples = new juce::AudioSampleBuffer(channels,
459  number_of_delta_samples);
460  delta_samples->clear();
461 
462  for (int channel = 0; channel < channels; channel++)
463  delta_samples->addFrom(channel, 0, GetOrCreateFrame(delta_frame)->GetAudioSamples(channel),
464  number_of_delta_samples, 1.0f);
465 
466  // Reverse the samples (if needed)
467  if (!time.IsIncreasing(frame_number))
468  reverse_buffer(delta_samples);
469 
470  // Copy the samples to
471  for (int channel = 0; channel < channels; channel++)
472  // Get the audio samples for this channel
473  samples->addFrom(channel, start, delta_samples->getReadPointer(channel),
474  number_of_delta_samples, 1.0f);
475 
476  // Clean up
477  delete delta_samples;
478  delta_samples = NULL;
479 
480  // Increment start position
481  start += number_of_delta_samples;
482  }
483  }
484  else {
485  // SPEED UP (multiple frames of audio), as long as it's not more than X frames
486  int total_delta_samples = 0;
487  for (int delta_frame = new_frame_number - (delta + 1);
488  delta_frame >= new_frame_number; delta_frame--)
489  total_delta_samples += Frame::GetSamplesPerFrame(delta_frame, reader->info.fps,
490  reader->info.sample_rate,
491  reader->info.channels);
492 
493  // Allocate a new sample buffer for these delta frames
494  samples = new juce::AudioSampleBuffer(channels, total_delta_samples);
495  samples->clear();
496 
497  // Loop through each frame in this delta
498  for (int delta_frame = new_frame_number - (delta + 1);
499  delta_frame >= new_frame_number; delta_frame--) {
500  // buffer to hold delta samples
501  int number_of_delta_samples = GetOrCreateFrame(delta_frame)->GetAudioSamplesCount();
502  AudioSampleBuffer *delta_samples = new juce::AudioSampleBuffer(channels,
503  number_of_delta_samples);
504  delta_samples->clear();
505 
506  for (int channel = 0; channel < channels; channel++)
507  delta_samples->addFrom(channel, 0, GetOrCreateFrame(delta_frame)->GetAudioSamples(channel),
508  number_of_delta_samples, 1.0f);
509 
510  // Reverse the samples (if needed)
511  if (!time.IsIncreasing(frame_number))
512  reverse_buffer(delta_samples);
513 
514  // Copy the samples to
515  for (int channel = 0; channel < channels; channel++)
516  // Get the audio samples for this channel
517  samples->addFrom(channel, start, delta_samples->getReadPointer(channel),
518  number_of_delta_samples, 1.0f);
519 
520  // Clean up
521  delete delta_samples;
522  delta_samples = NULL;
523 
524  // Increment start position
525  start += number_of_delta_samples;
526  }
527  }
528 
529  // Resample audio to be X times faster (where X is the delta of the repeat fraction)
530  resampler->SetBuffer(samples, float(start) / float(number_of_samples));
531 
532  // Resample data, and return new buffer pointer
533  AudioSampleBuffer *buffer = resampler->GetResampledBuffer();
534  int resampled_buffer_size = buffer->getNumSamples();
535 
536  // Add the newly resized audio samples to the current frame
537  for (int channel = 0; channel < channels; channel++)
538  // Add new (slower) samples, to the frame object
539  new_frame->AddAudio(true, channel, 0, buffer->getReadPointer(channel), number_of_samples, 1.0f);
540 
541  // Clean up
542  buffer = NULL;
543  }
544  else {
545  // Use the samples on this frame (but maybe reverse them if needed)
546  samples = new juce::AudioSampleBuffer(channels, number_of_samples);
547  samples->clear();
548 
549  // Loop through channels, and get audio samples
550  for (int channel = 0; channel < channels; channel++)
551  // Get the audio samples for this channel
552  samples->addFrom(channel, 0, frame->GetAudioSamples(channel), number_of_samples, 1.0f);
553 
554  // reverse the samples
555  if (!time.IsIncreasing(frame_number))
556  reverse_buffer(samples);
557 
558  // Add reversed samples to the frame object
559  for (int channel = 0; channel < channels; channel++)
560  new_frame->AddAudio(true, channel, 0, samples->getReadPointer(channel), number_of_samples, 1.0f);
561 
562 
563  }
564 
565  delete samples;
566  samples = NULL;
567  }
568 
569  // Return new time mapped frame
570  return new_frame;
571 
572  } else
573  // Use original frame
574  return frame;
575 }
576 
577 // Adjust frame number minimum value
578 long int Clip::adjust_frame_number_minimum(long int frame_number)
579 {
580  // Never return a frame number 0 or below
581  if (frame_number < 1)
582  return 1;
583  else
584  return frame_number;
585 
586 }
587 
588 // Get or generate a blank frame
589 tr1::shared_ptr<Frame> Clip::GetOrCreateFrame(long int number)
590 {
591  tr1::shared_ptr<Frame> new_frame;
592 
593  // Init some basic properties about this frame
594  int samples_in_frame = Frame::GetSamplesPerFrame(number, reader->info.fps, reader->info.sample_rate, reader->info.channels);
595 
596  try {
597  // Debug output
598  ZmqLogger::Instance()->AppendDebugMethod("Clip::GetOrCreateFrame (from reader)", "number", number, "samples_in_frame", samples_in_frame, "", -1, "", -1, "", -1, "", -1);
599 
600  // Determine the max size of this clips source image (based on the timeline's size, the scaling mode,
601  // and the scaling keyframes). This is a performance improvement, to keep the images as small as possible,
602  // without loosing quality.
603  if (scale == SCALE_FIT || scale == SCALE_STRETCH) {
604  // Best fit or Stretch scaling (based on max timeline size * scaling keyframes)
605  float max_scale_x = scale_x.GetMaxPoint().co.Y;
606  float max_scale_y = scale_y.GetMaxPoint().co.Y;
607  reader->SetMaxSize(max_width * max_scale_x, max_height * max_scale_y);
608 
609  } else if (scale == SCALE_CROP) {
610  // Cropping scale mode (based on max timeline size * cropped size * scaling keyframes)
611  float max_scale_x = scale_x.GetMaxPoint().co.Y;
612  float max_scale_y = scale_y.GetMaxPoint().co.Y;
613  QSize width_size(max_width * max_scale_x, round(max_width / (float(reader->info.width) / float(reader->info.height))));
614  QSize height_size(round(max_height / (float(reader->info.height) / float(reader->info.width))), max_height * max_scale_y);
615 
616  // respect aspect ratio
617  if (width_size.width() >= max_width && width_size.height() >= max_height)
618  reader->SetMaxSize(width_size.width(), width_size.height());
619  else
620  reader->SetMaxSize(height_size.width(), height_size.height());
621 
622  } else {
623  // No scaling, use original image size (slower)
624  reader->SetMaxSize(0, 0);
625  }
626 
627  // Attempt to get a frame (but this could fail if a reader has just been closed)
628  new_frame = reader->GetFrame(number);
629 
630  // Return real frame
631  if (new_frame)
632  return new_frame;
633 
634  } catch (const ReaderClosed & e) {
635  // ...
636  } catch (const TooManySeeks & e) {
637  // ...
638  } catch (const OutOfBoundsFrame & e) {
639  // ...
640  }
641 
642  // Debug output
643  ZmqLogger::Instance()->AppendDebugMethod("Clip::GetOrCreateFrame (create blank)", "number", number, "samples_in_frame", samples_in_frame, "", -1, "", -1, "", -1, "", -1);
644 
645  // Create blank frame
646  new_frame = tr1::shared_ptr<Frame>(new Frame(number, reader->info.width, reader->info.height, "#000000", samples_in_frame, reader->info.channels));
647  new_frame->SampleRate(reader->info.sample_rate);
648  new_frame->ChannelsLayout(reader->info.channel_layout);
649  return new_frame;
650 }
651 
652 // Generate JSON string of this object
653 string Clip::Json() {
654 
655  // Return formatted string
656  return JsonValue().toStyledString();
657 }
658 
659 // Get all properties for a specific frame
660 string Clip::PropertiesJSON(long int requested_frame) {
661 
662  // Generate JSON properties list
663  Json::Value root;
664  root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame);
665  root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 30 * 60 * 60 * 48, false, requested_frame);
666  root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame);
667  root["start"] = add_property_json("Start", Start(), "float", "", NULL, 0, 30 * 60 * 60 * 48, false, requested_frame);
668  root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 30 * 60 * 60 * 48, false, requested_frame);
669  root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 30 * 60 * 60 * 48, true, requested_frame);
670  root["gravity"] = add_property_json("Gravity", gravity, "int", "", NULL, 0, 8, false, requested_frame);
671  root["scale"] = add_property_json("Scale", scale, "int", "", NULL, 0, 3, false, requested_frame);
672  root["anchor"] = add_property_json("Anchor", anchor, "int", "", NULL, 0, 1, false, requested_frame);
673  root["handles"] = add_property_json("Handles", handles, "int", "", NULL, 0, 1, false, requested_frame);
674  root["waveform"] = add_property_json("Waveform", waveform, "int", "", NULL, 0, 1, false, requested_frame);
675 
676  // Add gravity choices (dropdown style)
677  root["gravity"]["choices"].append(add_property_choice_json("Top Left", GRAVITY_TOP_LEFT, gravity));
678  root["gravity"]["choices"].append(add_property_choice_json("Top Center", GRAVITY_TOP, gravity));
679  root["gravity"]["choices"].append(add_property_choice_json("Top Right", GRAVITY_TOP_RIGHT, gravity));
680  root["gravity"]["choices"].append(add_property_choice_json("Left", GRAVITY_LEFT, gravity));
681  root["gravity"]["choices"].append(add_property_choice_json("Center", GRAVITY_CENTER, gravity));
682  root["gravity"]["choices"].append(add_property_choice_json("Right", GRAVITY_RIGHT, gravity));
683  root["gravity"]["choices"].append(add_property_choice_json("Bottom Left", GRAVITY_BOTTOM_LEFT, gravity));
684  root["gravity"]["choices"].append(add_property_choice_json("Bottom Center", GRAVITY_BOTTOM, gravity));
685  root["gravity"]["choices"].append(add_property_choice_json("Bottom Right", GRAVITY_BOTTOM_RIGHT, gravity));
686 
687  // Add scale choices (dropdown style)
688  root["scale"]["choices"].append(add_property_choice_json("Crop", SCALE_CROP, scale));
689  root["scale"]["choices"].append(add_property_choice_json("Best Fit", SCALE_FIT, scale));
690  root["scale"]["choices"].append(add_property_choice_json("Stretch", SCALE_STRETCH, scale));
691  root["scale"]["choices"].append(add_property_choice_json("None", SCALE_NONE, scale));
692 
693  // Add anchor choices (dropdown style)
694  root["anchor"]["choices"].append(add_property_choice_json("Canvas", ANCHOR_CANVAS, anchor));
695  root["anchor"]["choices"].append(add_property_choice_json("Viewport", ANCHOR_VIEWPORT, anchor));
696 
697  // Add transform handles choices (dropdown style)
698  root["handles"]["choices"].append(add_property_choice_json("None", TRANSFORM_HANDLE_NONE, handles));
699  root["handles"]["choices"].append(add_property_choice_json("Selection", TRANSFORM_HANDLE_SELECTION, handles));
700 
701  // Add waveform choices (dropdown style)
702  root["waveform"]["choices"].append(add_property_choice_json("Yes", true, waveform));
703  root["waveform"]["choices"].append(add_property_choice_json("No", false, waveform));
704 
705  // Keyframes
706  root["location_x"] = add_property_json("Location X", location_x.GetValue(requested_frame), "float", "", &location_x, -1.0, 1.0, false, requested_frame);
707  root["location_y"] = add_property_json("Location Y", location_y.GetValue(requested_frame), "float", "", &location_y, -1.0, 1.0, false, requested_frame);
708  root["scale_x"] = add_property_json("Scale X", scale_x.GetValue(requested_frame), "float", "", &scale_x, 0.0, 1.0, false, requested_frame);
709  root["scale_y"] = add_property_json("Scale Y", scale_y.GetValue(requested_frame), "float", "", &scale_y, 0.0, 1.0, false, requested_frame);
710  root["alpha"] = add_property_json("Alpha", alpha.GetValue(requested_frame), "float", "", &alpha, 0.0, 1.0, false, requested_frame);
711  root["shear_x"] = add_property_json("Shear X", shear_x.GetValue(requested_frame), "float", "", &shear_x, -1.0, 1.0, false, requested_frame);
712  root["shear_y"] = add_property_json("Shear Y", shear_y.GetValue(requested_frame), "float", "", &shear_y, -1.0, 1.0, false, requested_frame);
713  root["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", &rotation, -360, 360, false, requested_frame);
714  root["volume"] = add_property_json("Volume", volume.GetValue(requested_frame), "float", "", &volume, 0.0, 1.0, false, requested_frame);
715  root["time"] = add_property_json("Time", time.GetValue(requested_frame), "float", "", &time, 0.0, 30 * 60 * 60 * 48, false, requested_frame);
716  root["channel_filter"] = add_property_json("Channel Filter", channel_filter.GetValue(requested_frame), "int", "", &channel_filter, -1, 10, false, requested_frame);
717  root["channel_mapping"] = add_property_json("Channel Mapping", channel_mapping.GetValue(requested_frame), "int", "", &channel_mapping, -1, 10, false, requested_frame);
718  root["has_audio"] = add_property_json("Enable Audio", has_audio.GetValue(requested_frame), "int", "", &has_audio, -1, 1.0, false, requested_frame);
719  root["has_video"] = add_property_json("Enable Video", has_video.GetValue(requested_frame), "int", "", &has_video, -1, 1.0, false, requested_frame);
720 
721  root["wave_color"] = add_property_json("Wave Color", 0.0, "color", "", &wave_color.red, 0, 255, false, requested_frame);
722  root["wave_color"]["red"] = add_property_json("Red", wave_color.red.GetValue(requested_frame), "float", "", &wave_color.red, 0, 255, false, requested_frame);
723  root["wave_color"]["blue"] = add_property_json("Blue", wave_color.blue.GetValue(requested_frame), "float", "", &wave_color.blue, 0, 255, false, requested_frame);
724  root["wave_color"]["green"] = add_property_json("Green", wave_color.green.GetValue(requested_frame), "float", "", &wave_color.green, 0, 255, false, requested_frame);
725 
726 
727  // Return formatted string
728  return root.toStyledString();
729 }
730 
731 // Generate Json::JsonValue for this object
732 Json::Value Clip::JsonValue() {
733 
734  // Create root json object
735  Json::Value root = ClipBase::JsonValue(); // get parent properties
736  root["gravity"] = gravity;
737  root["scale"] = scale;
738  root["anchor"] = anchor;
739  root["handles"] = handles;
740  root["waveform"] = waveform;
741  root["scale_x"] = scale_x.JsonValue();
742  root["scale_y"] = scale_y.JsonValue();
743  root["location_x"] = location_x.JsonValue();
744  root["location_y"] = location_y.JsonValue();
745  root["alpha"] = alpha.JsonValue();
746  root["rotation"] = rotation.JsonValue();
747  root["time"] = time.JsonValue();
748  root["volume"] = volume.JsonValue();
749  root["wave_color"] = wave_color.JsonValue();
750  root["crop_width"] = crop_width.JsonValue();
751  root["crop_height"] = crop_height.JsonValue();
752  root["crop_x"] = crop_x.JsonValue();
753  root["crop_y"] = crop_y.JsonValue();
754  root["shear_x"] = shear_x.JsonValue();
755  root["shear_y"] = shear_y.JsonValue();
756  root["channel_filter"] = channel_filter.JsonValue();
757  root["channel_mapping"] = channel_mapping.JsonValue();
758  root["has_audio"] = has_audio.JsonValue();
759  root["has_video"] = has_video.JsonValue();
760  root["perspective_c1_x"] = perspective_c1_x.JsonValue();
761  root["perspective_c1_y"] = perspective_c1_y.JsonValue();
762  root["perspective_c2_x"] = perspective_c2_x.JsonValue();
763  root["perspective_c2_y"] = perspective_c2_y.JsonValue();
764  root["perspective_c3_x"] = perspective_c3_x.JsonValue();
765  root["perspective_c3_y"] = perspective_c3_y.JsonValue();
766  root["perspective_c4_x"] = perspective_c4_x.JsonValue();
767  root["perspective_c4_y"] = perspective_c4_y.JsonValue();
768 
769  // Add array of effects
770  root["effects"] = Json::Value(Json::arrayValue);
771 
772  // loop through effects
773  list<EffectBase*>::iterator effect_itr;
774  for (effect_itr=effects.begin(); effect_itr != effects.end(); ++effect_itr)
775  {
776  // Get clip object from the iterator
777  EffectBase *existing_effect = (*effect_itr);
778  root["effects"].append(existing_effect->JsonValue());
779  }
780 
781  if (reader)
782  root["reader"] = reader->JsonValue();
783 
784  // return JsonValue
785  return root;
786 }
787 
788 // Load JSON string into this object
789 void Clip::SetJson(string value) throw(InvalidJSON) {
790 
791  // Parse JSON string into JSON objects
792  Json::Value root;
793  Json::Reader reader;
794  bool success = reader.parse( value, root );
795  if (!success)
796  // Raise exception
797  throw InvalidJSON("JSON could not be parsed (or is invalid)", "");
798 
799  try
800  {
801  // Set all values that match
802  SetJsonValue(root);
803  }
804  catch (exception e)
805  {
806  // Error parsing JSON (or missing keys)
807  throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", "");
808  }
809 }
810 
811 // Load Json::JsonValue into this object
812 void Clip::SetJsonValue(Json::Value root) {
813 
814  // Set parent data
816 
817  // Set data from Json (if key is found)
818  if (!root["gravity"].isNull())
819  gravity = (GravityType) root["gravity"].asInt();
820  if (!root["scale"].isNull())
821  scale = (ScaleType) root["scale"].asInt();
822  if (!root["anchor"].isNull())
823  anchor = (AnchorType) root["anchor"].asInt();
824  if (!root["handles"].isNull())
825  handles = (TransformHandleType) root["handles"].asInt();
826  if (!root["waveform"].isNull())
827  waveform = root["waveform"].asBool();
828  if (!root["scale_x"].isNull())
829  scale_x.SetJsonValue(root["scale_x"]);
830  if (!root["scale_y"].isNull())
831  scale_y.SetJsonValue(root["scale_y"]);
832  if (!root["location_x"].isNull())
833  location_x.SetJsonValue(root["location_x"]);
834  if (!root["location_y"].isNull())
835  location_y.SetJsonValue(root["location_y"]);
836  if (!root["alpha"].isNull())
837  alpha.SetJsonValue(root["alpha"]);
838  if (!root["rotation"].isNull())
839  rotation.SetJsonValue(root["rotation"]);
840  if (!root["time"].isNull())
841  time.SetJsonValue(root["time"]);
842  if (!root["volume"].isNull())
843  volume.SetJsonValue(root["volume"]);
844  if (!root["wave_color"].isNull())
845  wave_color.SetJsonValue(root["wave_color"]);
846  if (!root["crop_width"].isNull())
847  crop_width.SetJsonValue(root["crop_width"]);
848  if (!root["crop_height"].isNull())
849  crop_height.SetJsonValue(root["crop_height"]);
850  if (!root["crop_x"].isNull())
851  crop_x.SetJsonValue(root["crop_x"]);
852  if (!root["crop_y"].isNull())
853  crop_y.SetJsonValue(root["crop_y"]);
854  if (!root["shear_x"].isNull())
855  shear_x.SetJsonValue(root["shear_x"]);
856  if (!root["shear_y"].isNull())
857  shear_y.SetJsonValue(root["shear_y"]);
858  if (!root["channel_filter"].isNull())
859  channel_filter.SetJsonValue(root["channel_filter"]);
860  if (!root["channel_mapping"].isNull())
861  channel_mapping.SetJsonValue(root["channel_mapping"]);
862  if (!root["has_audio"].isNull())
863  has_audio.SetJsonValue(root["has_audio"]);
864  if (!root["has_video"].isNull())
865  has_video.SetJsonValue(root["has_video"]);
866  if (!root["perspective_c1_x"].isNull())
867  perspective_c1_x.SetJsonValue(root["perspective_c1_x"]);
868  if (!root["perspective_c1_y"].isNull())
869  perspective_c1_y.SetJsonValue(root["perspective_c1_y"]);
870  if (!root["perspective_c2_x"].isNull())
871  perspective_c2_x.SetJsonValue(root["perspective_c2_x"]);
872  if (!root["perspective_c2_y"].isNull())
873  perspective_c2_y.SetJsonValue(root["perspective_c2_y"]);
874  if (!root["perspective_c3_x"].isNull())
875  perspective_c3_x.SetJsonValue(root["perspective_c3_x"]);
876  if (!root["perspective_c3_y"].isNull())
877  perspective_c3_y.SetJsonValue(root["perspective_c3_y"]);
878  if (!root["perspective_c4_x"].isNull())
879  perspective_c4_x.SetJsonValue(root["perspective_c4_x"]);
880  if (!root["perspective_c4_y"].isNull())
881  perspective_c4_y.SetJsonValue(root["perspective_c4_y"]);
882  if (!root["effects"].isNull()) {
883 
884  // Clear existing effects
885  effects.clear();
886 
887  // loop through effects
888  for (int x = 0; x < root["effects"].size(); x++) {
889  // Get each effect
890  Json::Value existing_effect = root["effects"][x];
891 
892  // Create Effect
893  EffectBase *e = NULL;
894 
895  if (!existing_effect["type"].isNull()) {
896  // Create instance of effect
897  e = EffectInfo().CreateEffect(existing_effect["type"].asString());
898 
899  // Load Json into Effect
900  e->SetJsonValue(existing_effect);
901 
902  // Add Effect to Timeline
903  AddEffect(e);
904  }
905  }
906  }
907  if (!root["reader"].isNull()) // does Json contain a reader?
908  {
909  if (!root["reader"]["type"].isNull()) // does the reader Json contain a 'type'?
910  {
911  // Close previous reader (if any)
912  bool already_open = false;
913  if (reader)
914  {
915  // Track if reader was open
916  already_open = reader->IsOpen();
917 
918  // Close and delete existing reader (if any)
919  reader->Close();
920  delete reader;
921  reader = NULL;
922  }
923 
924  // Create new reader (and load properties)
925  string type = root["reader"]["type"].asString();
926 
927  if (type == "FFmpegReader") {
928 
929  // Create new reader
930  reader = new FFmpegReader(root["reader"]["path"].asString(), false);
931  reader->SetJsonValue(root["reader"]);
932 
933  } else if (type == "QtImageReader") {
934 
935  // Create new reader
936  reader = new QtImageReader(root["reader"]["path"].asString(), false);
937  reader->SetJsonValue(root["reader"]);
938 
939 #ifdef USE_IMAGEMAGICK
940  } else if (type == "ImageReader") {
941 
942  // Create new reader
943  reader = new ImageReader(root["reader"]["path"].asString(), false);
944  reader->SetJsonValue(root["reader"]);
945 
946  } else if (type == "TextReader") {
947 
948  // Create new reader
949  reader = new TextReader();
950  reader->SetJsonValue(root["reader"]);
951 #endif
952 
953  } else if (type == "ChunkReader") {
954 
955  // Create new reader
956  reader = new ChunkReader(root["reader"]["path"].asString(), (ChunkVersion) root["reader"]["chunk_version"].asInt());
957  reader->SetJsonValue(root["reader"]);
958 
959  } else if (type == "DummyReader") {
960 
961  // Create new reader
962  reader = new DummyReader();
963  reader->SetJsonValue(root["reader"]);
964  }
965 
966  // mark as managed reader
967  if (reader)
968  manage_reader = true;
969 
970  // Re-Open reader (if needed)
971  if (already_open)
972  reader->Open();
973 
974  }
975  }
976 }
977 
978 // Sort effects by order
979 void Clip::sort_effects()
980 {
981  // sort clips
982  effects.sort(CompareClipEffects());
983 }
984 
985 // Add an effect to the clip
987 {
988  // Add effect to list
989  effects.push_back(effect);
990 
991  // Sort effects
992  sort_effects();
993 }
994 
995 // Remove an effect from the clip
997 {
998  effects.remove(effect);
999 }
1000 
1001 // Apply effects to the source frame (if any)
1002 tr1::shared_ptr<Frame> Clip::apply_effects(tr1::shared_ptr<Frame> frame)
1003 {
1004  // Find Effects at this position and layer
1005  list<EffectBase*>::iterator effect_itr;
1006  for (effect_itr=effects.begin(); effect_itr != effects.end(); ++effect_itr)
1007  {
1008  // Get clip object from the iterator
1009  EffectBase *effect = (*effect_itr);
1010 
1011  // Apply the effect to this frame
1012  frame = effect->GetFrame(frame, frame->number);
1013 
1014  } // end effect loop
1015 
1016  // Return modified frame
1017  return frame;
1018 }
vector< Coordinate > Values
Vector of all Values (i.e. the processed coordinates from the curve)
Definition: KeyFrame.h:93
int max_height
The maximium image height needed by this clip (used for optimizations)
Definition: ClipBase.h:62
This class reads a special chunk-formatted file, which can be easily shared in a distributed environm...
Definition: ChunkReader.h:104
Keyframe perspective_c3_x
Curves representing X for coordinate 3.
Definition: Clip.h:249
Point GetMaxPoint()
Get max point (by Y coordinate)
Definition: KeyFrame.cpp:207
void SetBuffer(AudioSampleBuffer *new_buffer, double sample_rate, double new_sample_rate)
Sets the audio buffer and key settings.
void Close()
Close the internal reader.
Definition: Clip.cpp:222
Json::Value JsonValue()
Generate Json::JsonValue for this object.
Definition: Color.cpp:92
int num
Numerator for the fraction.
Definition: Fraction.h:44
Keyframe scale_y
Curve representing the vertical scaling in percent (0 to 1)
Definition: Clip.h:220
Keyframe perspective_c4_x
Curves representing X for coordinate 4.
Definition: Clip.h:251
This abstract class is the base class, used by all effects in libopenshot.
Definition: EffectBase.h:66
EffectBase * CreateEffect(string effect_type)
Definition: EffectInfo.cpp:42
Align clip to the right of its parent (middle aligned)
Definition: Enums.h:42
float GetDelta(long int index)
Get the change in Y value (from the previous Y value)
Definition: KeyFrame.cpp:410
Keyframe perspective_c1_x
Curves representing X for coordinate 1.
Definition: Clip.h:245
Keyframe green
Curve representing the green value (0 - 255)
Definition: Color.h:46
Keyframe perspective_c2_x
Curves representing X for coordinate 2.
Definition: Clip.h:247
Keyframe crop_x
Curve representing X offset in percent (-1.0=-100%, 0.0=0%, 1.0=100%)
Definition: Clip.h:239
string previous_properties
This string contains the previous JSON properties.
Definition: ClipBase.h:60
string PropertiesJSON(long int requested_frame)
Definition: Clip.cpp:660
float End()
Override End() method.
Definition: Clip.cpp:236
Json::Value add_property_json(string name, float value, string type, string memo, Keyframe *keyframe, float min_value, float max_value, bool readonly, long int requested_frame)
Generate JSON for a property.
Definition: ClipBase.cpp:65
Keyframe perspective_c3_y
Curves representing Y for coordinate 3.
Definition: Clip.h:250
tr1::shared_ptr< Frame > GetFrame(long int requested_frame)
Get an openshot::Frame object for a specific frame number of this timeline.
Definition: Clip.cpp:258
Align clip to the bottom right of its parent.
Definition: Enums.h:45
Json::Value JsonValue()
Generate Json::JsonValue for this object.
Definition: KeyFrame.cpp:321
ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
Definition: ReaderBase.h:83
GravityType gravity
The gravity of a clip determines where it snaps to it&#39;s parent.
Definition: Clip.h:151
int width
The width of the video (in pixesl)
Definition: ReaderBase.h:67
Keyframe volume
Curve representing the volume (0 to 1)
Definition: Clip.h:230
int max_width
The maximum image width needed by this clip (used for optimizations)
Definition: ClipBase.h:61
Do not scale the clip.
Definition: Enums.h:54
This class represents a single frame of video (i.e. image & audio data)
Definition: Frame.h:115
This class is used as a simple, dummy reader, which always returns a blank frame. ...
Definition: DummyReader.h:53
float ToFloat()
Return this fraction as a float (i.e. 1/2 = 0.5)
Definition: Fraction.cpp:41
Keyframe red
Curve representing the red value (0 - 255)
Definition: Color.h:45
float duration
Length of time (in seconds)
Definition: ReaderBase.h:64
Scale the clip until both height and width fill the canvas (cropping the overlap) ...
Definition: Enums.h:51
Keyframe time
Curve representing the frames over time to play (used for speed and direction of video) ...
Definition: Clip.h:229
ScaleType
This enumeration determines how clips are scaled to fit their parent container.
Definition: Enums.h:49
void AddEffect(EffectBase *effect)
Add an effect to the clip.
Definition: Clip.cpp:986
virtual void Close()=0
Close the reader (and any resources it was consuming)
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:95
int Layer()
Get layer of clip on timeline (lower number is covered by higher numbers)
Definition: ClipBase.h:84
Keyframe has_audio
Override has_video and has_audio properties of clip (and their readers)
Definition: Clip.h:259
Exception when a reader is closed, and a frame is requested.
Definition: Exceptions.h:234
bool has_video
Determines if this file has a video stream.
Definition: ReaderBase.h:61
~Clip()
Destructor.
Definition: Clip.cpp:172
Keyframe has_video
An optional override to determine if this clip has video (-1=undefined, 0=no, 1=yes) ...
Definition: Clip.h:260
virtual tr1::shared_ptr< Frame > GetFrame(tr1::shared_ptr< Frame > frame, long int frame_number)=0
This method is required for all derived classes of EffectBase, and returns a modified openshot::Frame...
Color wave_color
Curve representing the color of the audio wave form.
Definition: Clip.h:233
Align clip to the top right of its parent.
Definition: Enums.h:39
virtual Json::Value JsonValue()=0
Generate Json::JsonValue for this object.
Definition: EffectBase.cpp:69
Align clip to the bottom left of its parent.
Definition: Enums.h:43
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
Definition: Clip.cpp:812
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
Definition: KeyFrame.cpp:362
Keyframe crop_width
Curve representing width in percent (0.0=0%, 1.0=100%)
Definition: Clip.h:237
This class uses the ImageMagick++ libraries, to open image files, and return openshot::Frame objects ...
Definition: ImageReader.h:67
Keyframe location_x
Curve representing the relative X position in percent based on the gravity (-1 to 1) ...
Definition: Clip.h:221
float GetValue(long int index)
Get the value at a specific index.
Definition: KeyFrame.cpp:226
Keyframe location_y
Curve representing the relative Y position in percent based on the gravity (-1 to 1) ...
Definition: Clip.h:222
void SetMaxSize(int width, int height)
Set Max Image Size (used for performance optimization)
Definition: ReaderBase.h:143
bool has_audio
Determines if this file has an audio stream.
Definition: ReaderBase.h:62
This class uses the FFmpeg libraries, to open video files and audio files, and return openshot::Frame...
Definition: FFmpegReader.h:92
TransformHandleType
This enumeration determines what parent a clip should be aligned to.
Definition: Enums.h:65
virtual void SetJsonValue(Json::Value root)=0
Load Json::JsonValue into this object.
Definition: ClipBase.cpp:49
Keyframe perspective_c1_y
Curves representing Y for coordinate 1.
Definition: Clip.h:246
Keyframe blue
Curve representing the red value (0 - 255)
Definition: Color.h:47
Keyframe crop_y
Curve representing Y offset in percent (-1.0=-100%, 0.0=0%, 1.0=100%)
Definition: Clip.h:240
Keyframe shear_x
Curve representing X shear angle in degrees (-45.0=left, 45.0=right)
Definition: Clip.h:243
ScaleType scale
The scale determines how a clip should be resized to fit it&#39;s parent.
Definition: Clip.h:152
int height
The height of the video (in pixels)
Definition: ReaderBase.h:66
Align clip to the bottom center of its parent.
Definition: Enums.h:44
Align clip to the top left of its parent.
Definition: Enums.h:37
Json::Value add_property_choice_json(string name, int value, int selected_value)
Generate JSON choice for a property (dropdown properties)
Definition: ClipBase.cpp:101
Exception for files that can not be found or opened.
Definition: Exceptions.h:132
string Id()
Get basic properties.
Definition: ClipBase.h:82
Keyframe channel_filter
Audio channel filter and mappings.
Definition: Clip.h:255
TransformHandleType handles
The transform handle determines if selection handles are added to clip (to display the clips edges) ...
Definition: Clip.h:154
Add selection handles to clip (useful for editors to display edges of clip)
Definition: Enums.h:68
float Position()
Get position on timeline (in seconds)
Definition: ClipBase.h:83
bool IsIncreasing(int index)
Get the direction of the curve at a specific index (increasing or decreasing)
Definition: KeyFrame.cpp:292
void AppendDebugMethod(string method_name, string arg1_name, float arg1_value, string arg2_name, float arg2_value, string arg3_name, float arg3_value, string arg4_name, float arg4_value, string arg5_name, float arg5_value, string arg6_name, float arg6_value)
Append debug information.
Definition: ZmqLogger.cpp:162
void SetJson(string value)
Load JSON string into this object.
Definition: Clip.cpp:789
Keyframe channel_mapping
A number representing an audio channel to output (only works when filtering a channel) ...
Definition: Clip.h:256
float start
The position in seconds to start playing (used to trim the beginning of a clip)
Definition: ClipBase.h:58
Align clip to the left of its parent (middle aligned)
Definition: Enums.h:40
virtual Json::Value JsonValue()=0
Generate Json::JsonValue for this object.
Definition: ReaderBase.cpp:106
virtual void SetJsonValue(Json::Value root)=0
Load Json::JsonValue into this object.
Definition: EffectBase.cpp:109
ChunkVersion
This enumeration allows the user to choose which version of the chunk they would like (low...
Definition: ChunkReader.h:75
Keyframe rotation
Curve representing the rotation (0 to 360)
Definition: Clip.h:226
virtual void SetJsonValue(Json::Value root)=0
Load Json::JsonValue into this object.
Definition: ReaderBase.cpp:155
Scale the clip until both height and width fill the canvas (distort to fit)
Definition: Enums.h:53
vector< Point > Points
Vector of all Points.
Definition: KeyFrame.h:92
ReaderInfo info
Information about the current media file.
Definition: ReaderBase.h:111
Keyframe shear_y
Curve representing Y shear angle in degrees (-45.0=down, 45.0=up)
Definition: Clip.h:244
Clip()
Default Constructor.
Definition: Clip.cpp:101
Anchor the clip to the viewport (which can be moved / animated around the canvas) ...
Definition: Enums.h:61
Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
Definition: ReaderBase.h:69
AnchorType
This enumeration determines what parent a clip should be aligned to.
Definition: Enums.h:58
float end
The position in seconds to end playing (used to trim the ending of a clip)
Definition: ClipBase.h:59
Exception for frames that are out of bounds.
Definition: Exceptions.h:202
void Open()
Open the internal reader.
Definition: Clip.cpp:205
static ZmqLogger * Instance()
Create or get an instance of this logger singleton (invoke the class with this method) ...
Definition: ZmqLogger.cpp:38
This class represents a color (used on the timeline and clips)
Definition: Color.h:42
int GetInt(long int index)
Get the rounded INT value at a specific index.
Definition: KeyFrame.cpp:248
Align clip to the center of its parent (middle aligned)
Definition: Enums.h:41
GravityType crop_gravity
Cropping needs to have a gravity to determine what side we are cropping.
Definition: Clip.h:236
void RemoveEffect(EffectBase *effect)
Remove an effect from the clip.
Definition: Clip.cpp:996
This namespace is the default namespace for all code in the openshot library.
virtual tr1::shared_ptr< Frame > GetFrame(long int number)=0
Coordinate co
This is the primary coordinate.
Definition: Point.h:83
AnchorType anchor
The anchor determines what parent a clip should snap to.
Definition: Clip.h:153
Exception for invalid JSON.
Definition: Exceptions.h:152
Keyframe alpha
Curve representing the alpha (1 to 0)
Definition: Clip.h:225
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
Definition: Color.cpp:129
Do not add any transform handles to clip.
Definition: Enums.h:67
Keyframe scale_x
Curve representing the horizontal scaling in percent (0 to 1)
Definition: Clip.h:219
Keyframe perspective_c2_y
Curves representing Y for coordinate 2.
Definition: Clip.h:248
AudioSampleBuffer * GetResampledBuffer()
Get the resampled audio buffer.
virtual Json::Value JsonValue()=0
Generate Json::JsonValue for this object.
Definition: ClipBase.cpp:33
This class uses the ImageMagick++ libraries, to create frames with "Text", and return openshot::Frame...
Definition: TextReader.h:81
This class uses the Qt library, to open image files, and return openshot::Frame objects containing th...
Definition: QtImageReader.h:69
This class returns a listing of all effects supported by libopenshot.
Definition: EffectInfo.h:45
Align clip to the top center of its parent.
Definition: Enums.h:38
int den
Denominator for the fraction.
Definition: Fraction.h:45
int channels
The number of audio channels used in the audio stream.
Definition: ReaderBase.h:82
A Keyframe is a collection of Point instances, which is used to vary a number or property over time...
Definition: KeyFrame.h:64
Scale the clip until either height or width fills the canvas (with no cropping)
Definition: Enums.h:52
float Y
The Y value of the coordinate (usually representing the value of the property being animated) ...
Definition: Coordinate.h:62
Keyframe perspective_c4_y
Curves representing Y for coordinate 4.
Definition: Clip.h:252
int GetSamplesPerFrame(Fraction fps, int sample_rate, int channels)
Calculate the # of samples per video frame (for the current frame number)
Definition: Frame.cpp:497
Json::Value JsonValue()
Generate Json::JsonValue for this object.
Definition: Clip.cpp:732
long int GetLong(long int index)
Get the rounded LONG value at a specific index.
Definition: KeyFrame.cpp:270
float Duration()
Get the length of this clip (in seconds)
Definition: ClipBase.h:87
long int GetLength()
Definition: KeyFrame.cpp:442
GravityType
This enumeration determines how clips are aligned to their parent container.
Definition: Enums.h:35
Anchor the clip to the canvas.
Definition: Enums.h:60
string Json()
Get and Set JSON methods.
Definition: Clip.cpp:653
float Start()
Get start position (in seconds) of clip (trim start of video)
Definition: ClipBase.h:85
virtual void Open()=0
Open the reader (and start consuming resources, such as images or video files)
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition: ReaderBase.h:81
Exception when too many seek attempts happen.
Definition: Exceptions.h:254
Fraction GetRepeatFraction(long int index)
Get the fraction that represents how many times this value is repeated in the curve.
Definition: KeyFrame.cpp:388
ReaderBase * Reader()
Get the current reader.
Definition: Clip.cpp:195
virtual bool IsOpen()=0
Determine if reader is open or closed.
This class is used to resample audio data for many sequential frames.
Keyframe crop_height
Curve representing height in percent (0.0=0%, 1.0=100%)
Definition: Clip.h:238