no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / vtrack.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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 2 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "asset.h"
23 #include "autoconf.h"
24 #include "cache.h"
25 #include "clip.h"
26 #include "datatype.h"
27 #include "edit.h"
28 #include "edits.h"
29 #include "edl.h"
30 #include "edlsession.h"
31 #include "filexml.h"
32 #include "floatauto.h"
33 #include "floatautos.h"
34 #include "language.h"
35 #include "localsession.h"
36 #include "patch.h"
37 #include "mainsession.h"
38 #include "theme.h"
39 #include "trackcanvas.h"
40 #include "tracks.h"
41 #include "transportque.inc"
42 #include "units.h"
43 #include "vautomation.h"
44 #include "vedit.h"
45 #include "vedits.h"
46 #include "vframe.h"
47 #include "vmodule.h"
48 #include "vpluginset.h"
49 #include "vtrack.h"
50
51 VTrack::VTrack(EDL *edl, Tracks *tracks)
52  : Track(edl, tracks)
53 {
54         data_type = TRACK_VIDEO;
55         data_h = edl->local_session->zoom_vtrack;
56         draw = 1;
57 }
58
59 VTrack::~VTrack()
60 {
61 }
62
63 void VTrack::create_objects()
64 {
65         Track::create_objects();
66         automation = new VAutomation(edl, this);
67         automation->create_objects();
68         edits = new VEdits(edl, this);
69 }
70
71 // Used by PlaybackEngine
72 void VTrack::synchronize_params(Track *track)
73 {
74         Track::synchronize_params(track);
75         //VTrack *vtrack = (VTrack*)track;
76 }
77
78 // Used by EDL::operator=
79 int VTrack::copy_settings(Track *track)
80 {
81         Track::copy_settings(track);
82         //VTrack *vtrack = (VTrack*)track;
83         return 0;
84 }
85
86 int VTrack::vertical_span(Theme *theme)
87 {
88         int track_h = Track::vertical_span(theme);
89         int patch_h = theme->title_h;
90         if( expand_view )
91                 patch_h += theme->play_h + theme->fade_h + theme->mode_h;
92         return MAX(track_h, patch_h);
93 }
94
95
96 PluginSet* VTrack::new_plugins()
97 {
98         return new VPluginSet(edl, this);
99 }
100
101 int VTrack::load_defaults(BC_Hash *defaults)
102 {
103         Track::load_defaults(defaults);
104         return 0;
105 }
106
107 void VTrack::set_default_title()
108 {
109         Track *current = ListItem<Track>::list->first;
110         int i;
111         for(i = 0; current; current = NEXT)
112         {
113                 if(current->data_type == TRACK_VIDEO) i++;
114         }
115         sprintf(title, _("Video %d"), i);
116         BC_Resources::encode_to_utf8(title, BCTEXTLEN);
117 }
118
119 int64_t VTrack::to_units(double position, int round)
120 {
121         return round ? Units::round(position * edl->session->frame_rate) :
122                 Units::to_int64(position * edl->session->frame_rate + 1e-6);
123 }
124
125 double VTrack::to_doubleunits(double position)
126 {
127         return position * edl->session->frame_rate;
128 }
129
130
131 double VTrack::from_units(int64_t position)
132 {
133         return (double)position / edl->session->frame_rate;
134 }
135
136
137
138
139 int VTrack::identical(int64_t sample1, int64_t sample2)
140 {
141 // Units of frames
142         if(labs(sample1 - sample2) <= 1) return 1; else return 0;
143 }
144
145 int VTrack::save_header(FileXML *file)
146 {
147         file->tag.set_property("TYPE", "VIDEO");
148         return 0;
149 }
150
151 int VTrack::save_derived(FileXML *file)
152 {
153         return 0;
154 }
155
156 int VTrack::load_header(FileXML *file, uint32_t load_flags)
157 {
158         return 0;
159 }
160
161 int VTrack::load_derived(FileXML *file, uint32_t load_flags)
162 {
163         return 0;
164 }
165
166
167 int VTrack::direct_copy_possible(int64_t start, int direction, int use_nudge)
168 {
169         if(use_nudge) start += nudge;
170
171 // Track size must equal output size
172         if(track_w != edl->session->output_w || track_h != edl->session->output_h)
173                 return 0;
174
175         if(has_speed()) return 0;
176
177 // No automation must be present in the track
178         if(!automation->direct_copy_possible(start, direction))
179                 return 0;
180
181 // No plugin must be present
182         if(plugin_used(start, direction))
183                 return 0;
184
185 // No transition
186         if(get_current_transition(start, direction, 0, 0))
187                 return 0;
188
189         return 1;
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208 int VTrack::create_derived_objs(int flash)
209 {
210         edits = new VEdits(edl, this);
211         return 0;
212 }
213
214
215 // int VTrack::get_dimensions(double &view_start,
216 //      double &view_units,
217 //      double &zoom_units)
218 // {
219 //      view_start = edl->local_session->view_start * edl->session->frame_rate;
220 //      view_units = 0;
221 //      zoom_units = edl->local_session->zoom_sample / edl->session->sample_rate * edl->session->frame_rate;
222 //      return 0;
223 // }
224
225 int VTrack::copy_derived(int64_t start, int64_t end, FileXML *xml)
226 {
227 // automation is copied in the Track::copy
228         return 0;
229 }
230
231 int VTrack::copy_automation_derived(AutoConf *auto_conf, int64_t start, int64_t end, FileXML *file)
232 {
233         return 0;
234 }
235
236 int VTrack::paste_derived(int64_t start, int64_t end, int64_t total_length, FileXML *xml, int &current_channel)
237 {
238         return 0;
239 }
240
241 int VTrack::paste_output(int64_t startproject, int64_t endproject, int64_t startsource, int64_t endsource, int layer, Asset *asset)
242 {
243         return 0;
244 }
245
246 int VTrack::clear_derived(int64_t start, int64_t end)
247 {
248         return 0;
249 }
250
251 int VTrack::paste_automation_derived(int64_t start, int64_t end, int64_t total_length, FileXML *xml, int shift_autos, int &current_pan)
252 {
253         return 0;
254 }
255
256 int VTrack::clear_automation_derived(AutoConf *auto_conf, int64_t start, int64_t end, int shift_autos)
257 {
258         return 0;
259 }
260
261 int VTrack::draw_autos_derived(float view_start, float zoom_units, AutoConf *auto_conf)
262 {
263         return 0;
264 }
265
266
267 int VTrack::select_auto_derived(float zoom_units, float view_start, AutoConf *auto_conf, int cursor_x, int cursor_y)
268 {
269         return 0;
270 }
271
272
273 int VTrack::move_auto_derived(float zoom_units, float view_start, AutoConf *auto_conf, int cursor_x, int cursor_y, int shift_down)
274 {
275         return 0;
276 }
277
278 int VTrack::draw_floating_autos_derived(float view_start, float zoom_units, AutoConf *auto_conf, int flash)
279 {
280         return 0;
281 }
282
283 int VTrack::is_playable(int64_t position, int direction)
284 {
285         int result = 0;
286         float in_x, in_y, in_w, in_h;
287         float out_x, out_y, out_w, out_h;
288
289         calculate_output_transfer(position,
290                 direction,
291                 in_x, in_y, in_w, in_h,
292                 out_x, out_y, out_w, out_h);
293
294 //printf("VTrack::is_playable %0.0f %0.0f %0.0f %0.0f %0.0f %0.0f %0.0f %0.0f\n",
295 //in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h);
296         if(out_w > 0 && out_h > 0)
297                 result = 1;
298         return result;
299 }
300
301 void VTrack::calculate_input_transfer(int asset_w, int asset_h,
302         int64_t position, int direction,
303         float &in_x, float &in_y, float &in_w, float &in_h,
304         float &out_x, float &out_y, float &out_w, float &out_h)
305 {
306         float auto_x, auto_y, auto_z;
307         float camera_z = 1.;
308         float camera_x = asset_w / 2.;
309         float camera_y = asset_h / 2.;
310 // camera and output coords
311         float x[6], y[6];
312
313 //printf("VTrack::calculate_input_transfer %jd\n", position);
314
315 // get camera center in asset
316         automation->get_camera(&auto_x, &auto_y, &auto_z,
317                 position, direction);
318
319         camera_z *= auto_z;
320         camera_x += auto_x;
321         camera_y += auto_y;
322
323 // get camera coords on asset
324         x[0] = camera_x - (float)track_w / 2 / camera_z;
325         y[0] = camera_y - (float)track_h / 2 / camera_z;
326         x[1] = x[0] + (float)track_w / camera_z;
327         y[1] = y[0] + (float)track_h / camera_z;
328
329 // get asset coords on camera
330         x[2] = 0;
331         y[2] = 0;
332         x[3] = track_w;
333         y[3] = track_h;
334
335 // crop asset coords on camera
336         if(x[0] < 0)
337         {
338                 x[2] -= x[0] * camera_z;
339                 x[0] = 0;
340         }
341         if(y[0] < 0)
342         {
343                 y[2] -= y[0] * camera_z;
344                 y[0] = 0;
345         }
346         if(x[1] > asset_w)
347         {
348                 x[3] -= (x[1] - asset_w) * camera_z;
349                 x[1] = asset_w;
350         }
351         if(y[1] > asset_h)
352         {
353                 y[3] -= (y[1] - asset_h) * camera_z;
354                 y[1] = asset_h;
355         }
356
357 // get output bounding box
358         out_x = x[2];
359         out_y = y[2];
360         out_w = x[3] - x[2];
361         out_h = y[3] - y[2];
362
363         in_x = x[0];
364         in_y = y[0];
365         in_w = x[1] - x[0];
366         in_h = y[1] - y[0];
367 // printf("VTrack::calculate_input_transfer %f %f %f %f -> %f %f %f %f\n",
368 // in_x, in_y, in_w, in_h,
369 // out_x, out_y, out_w, out_h);
370 }
371
372 void VTrack::calculate_output_transfer(int64_t position, int direction,
373         float &in_x, float &in_y, float &in_w, float &in_h,
374         float &out_x, float &out_y, float &out_w, float &out_h)
375 {
376         float center_x, center_y, center_z;
377         float x[4], y[4];
378
379         x[0] = 0;
380         y[0] = 0;
381         x[1] = track_w;
382         y[1] = track_h;
383
384         automation->get_projector(&center_x,
385                 &center_y,
386                 &center_z,
387                 position,
388                 direction);
389
390         center_x += edl->session->output_w / 2;
391         center_y += edl->session->output_h / 2;
392
393         x[2] = center_x - (track_w / 2) * center_z;
394         y[2] = center_y - (track_h / 2) * center_z;
395         x[3] = x[2] + track_w * center_z;
396         y[3] = y[2] + track_h * center_z;
397
398 // Clip to boundaries of output
399         if(x[2] < 0)
400         {
401                 x[0] -= (x[2] - 0) / center_z;
402                 x[2] = 0;
403         }
404         if(y[2] < 0)
405         {
406                 y[0] -= (y[2] - 0) / center_z;
407                 y[2] = 0;
408         }
409         if(x[3] > edl->session->output_w)
410         {
411                 x[1] -= (x[3] - edl->session->output_w) / center_z;
412                 x[3] = edl->session->output_w;
413         }
414         if(y[3] > edl->session->output_h)
415         {
416                 y[1] -= (y[3] - edl->session->output_h) / center_z;
417                 y[3] = edl->session->output_h;
418         }
419
420         in_x = x[0];
421         in_y = y[0];
422         in_w = x[1] - x[0];
423         in_h = y[1] - y[0];
424         out_x = x[2];
425         out_y = y[2];
426         out_w = x[3] - x[2];
427         out_h = y[3] - y[2];
428 // printf("VTrack::calculate_output_transfer %f %f %f %f -> %f %f %f %f\n",
429 // in_x, in_y, in_w, in_h,
430 // out_x, out_y, out_w, out_h);
431 }
432
433
434
435 int VTrack::get_projection(float &in_x1, float &in_y1, float &in_x2, float &in_y2,
436         float &out_x1, float &out_y1, float &out_x2, float &out_y2,
437         int frame_w, int frame_h, int64_t real_position, int direction)
438 {
439         float center_x, center_y, center_z;
440         float x[4], y[4];
441
442         automation->get_projector(&center_x,
443                 &center_y,
444                 &center_z,
445                 real_position,
446                 direction);
447
448         x[0] = y[0] = 0;
449         x[1] = frame_w;
450         y[1] = frame_h;
451
452         center_x += edl->session->output_w / 2;
453         center_y += edl->session->output_h / 2;
454
455         x[2] = center_x - (frame_w / 2) * center_z;
456         y[2] = center_y - (frame_h / 2) * center_z;
457         x[3] = x[2] + frame_w * center_z;
458         y[3] = y[2] + frame_h * center_z;
459
460         if(x[2] < 0)
461         {
462                 x[0] -= x[2] / center_z;
463                 x[2] = 0;
464         }
465         if(y[2] < 0)
466         {
467                 y[0] -= y[2] / center_z;
468                 y[2] = 0;
469         }
470         if(x[3] > edl->session->output_w)
471         {
472                 x[1] -= (x[3] - edl->session->output_w) / center_z;
473                 x[3] = edl->session->output_w;
474         }
475         if(y[3] > edl->session->output_h)
476         {
477                 y[1] -= (y[3] - edl->session->output_h) / center_z;
478                 y[3] = edl->session->output_h;
479         }
480
481         in_x1 = x[0];  in_y1 = y[0];  in_x2 = x[1];  in_y2 = y[1];
482         out_x1 = x[2]; out_y1 = y[2]; out_x2 = x[3]; out_y2 = y[3];
483         return 0;
484 }
485
486
487
488 static inline void addto_value(FloatAuto *fauto, float offset)
489 {
490         fauto->set_value(fauto->get_value() + offset);
491 }
492
493 static inline void multiply_value(FloatAuto *fauto, float scale)
494 {
495         fauto->set_value(fauto->get_value() * scale);
496 }
497
498
499 void VTrack::set_fauto_xy(int fauto, float x, float y)
500 {
501 // set default keyframe
502         FloatAuto *xdft = (FloatAuto *)automation->autos[fauto+0]->default_auto;
503         FloatAuto *ydft = (FloatAuto *)automation->autos[fauto+1]->default_auto;
504         xdft->set_value(x);
505         ydft->set_value(y);
506 // set everyone else
507         FloatAuto *xauto = (FloatAuto *)automation->autos[fauto+0]->first;
508         FloatAuto *yauto = (FloatAuto *)automation->autos[fauto+1]->first;
509         for( ; xauto; xauto=(FloatAuto *)xauto->next ) xauto->set_value(x);
510         for( ; yauto; yauto=(FloatAuto *)yauto->next ) yauto->set_value(y);
511 }
512
513 void VTrack::translate(int fauto, float dx, float dy, int all)
514 {
515         if( all ) {
516                 addto_value((FloatAuto*)automation->autos[fauto+0]->default_auto, dx);
517                 addto_value((FloatAuto*)automation->autos[fauto+1]->default_auto, dy);
518                 FloatAutos **fautos = (FloatAutos **)&automation->autos;
519                 FloatAuto *xauto = (FloatAuto *)fautos[fauto+0]->first;
520                 FloatAuto *yauto = (FloatAuto *)fautos[fauto+1]->first;
521                 for( ; xauto; xauto=(FloatAuto *)xauto->next ) addto_value(xauto, dx);
522                 for( ; yauto; yauto=(FloatAuto *)yauto->next ) addto_value(yauto, dy);
523         }
524         else {
525                 FloatAutos **fautos = (FloatAutos **)&automation->autos;
526                 FloatAuto *xauto = (FloatAuto *)fautos[fauto+0]->get_auto_for_editing(-1, 1);
527                 FloatAuto *yauto = (FloatAuto *)fautos[fauto+1]->get_auto_for_editing(-1, 1);
528                 addto_value(xauto, dx);
529                 addto_value(yauto, dy);
530         }
531 }
532