r1014: Enable horizontal scrolling with the mouse wheel by pressing Ctrl.
[cinelerra_cv/ct.git] / cinelerra / packagedispatcher.C
blob31d6c2aa4ee05ffca30543d5bc44c1534d1fc971
1 #include "asset.h"
2 #include "clip.h"
3 #include "confirmsave.h"
4 #include "edl.h"
5 #include "edlsession.h"
6 #include "labels.h"
7 #include "mutex.h"
8 #include "mwindow.h"
9 #include "packagedispatcher.h"
10 #include "packagerenderer.h"
11 #include "preferences.h"
12 #include "render.h"
13 #include "file.h"
17 PackageDispatcher::PackageDispatcher()
19         packages = 0;
20         package_lock = new Mutex("PackageDispatcher::package_lock");
21         packaging_engine = 0;
24 PackageDispatcher::~PackageDispatcher()
26         if(packages)
27         {
28                 for(int i = 0; i < total_packages; i++)
29                         delete packages[i];
30                 delete [] packages;
31         }
32         if (packaging_engine)
33                 delete packaging_engine;
34         delete package_lock;
37 int PackageDispatcher::create_packages(MWindow *mwindow,
38         EDL *edl,
39         Preferences *preferences,
40         int strategy, 
41         Asset *default_asset, 
42         double total_start, 
43         double total_end,
44         int test_overwrite)
46         int result = 0;
48         this->mwindow = mwindow;
49         this->edl = edl;
50         this->preferences = preferences;
51         this->strategy = strategy;
52         this->default_asset = default_asset;
53         this->total_start = total_start;
54         this->total_end = total_end;
56         nodes = preferences->get_enabled_nodes();
57         audio_position = Units::to_int64(total_start * default_asset->sample_rate);
58         video_position = Units::to_int64(total_start * default_asset->frame_rate);
59         audio_end = Units::to_int64(total_end * default_asset->sample_rate);
60         video_end = Units::to_int64(total_end * default_asset->frame_rate);
61         current_package = 0;
63 // sleep(1);
64 // printf("PackageDispatcher::create_packages 1 %d %f %f\n", 
65 // video_end, 
66 // total_end, 
67 // default_asset->frame_rate);
71         if(strategy == SINGLE_PASS)
72         {
73                 total_len = this->total_end - this->total_start;
74                 package_len = total_len;
75                 min_package_len = total_len;
76                 total_packages = 1;
77                 total_allocated = 1;
78                 packages = new RenderPackage*[total_allocated];
79                 packages[0] = new RenderPackage;
80                 packages[0]->audio_start = audio_position;
81                 packages[0]->audio_end = audio_end;
82                 packages[0]->video_start = video_position;
83                 packages[0]->video_end = video_end;
84                 packages[0]->audio_do = default_asset->audio_data;
85                 packages[0]->video_do = default_asset->video_data;
86                 strcpy(packages[0]->path, default_asset->path);
87         }
88         else
89         if(strategy == SINGLE_PASS_FARM)
90         {
91                 packaging_engine = File::new_packaging_engine(default_asset);
92                 packaging_engine->create_packages_single_farm(
93                                         edl,
94                                         preferences,
95                                         default_asset, 
96                                         total_start, 
97                                         total_end);
98         }
99         else
100         if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
101         {
102                 Label *label = edl->labels->first;
103                 total_packages = 0;
104                 packages = new RenderPackage*[edl->labels->total() + 2];
106                 Render::get_starting_number(default_asset->path, 
107                         current_number,
108                         number_start, 
109                         total_digits,
110                         2);
112                 while(audio_position < audio_end)
113                 {
114                         RenderPackage *package = 
115                                 packages[total_packages] = 
116                                 new RenderPackage;
117                         package->audio_start = audio_position;
118                         package->video_start = video_position;
119                         package->audio_do = default_asset->audio_data;
120                         package->video_do = default_asset->video_data;
123                         while(label && 
124                                 (label->position < (double)audio_position / default_asset->sample_rate ||
125                                 EQUIV(label->position, (double)audio_position / default_asset->sample_rate)))
126                         {
127                                 label = label->next;
128                         }
130                         if(!label)
131                         {
132                                 package->audio_end = Units::to_int64(total_end * default_asset->sample_rate);
133                                 package->video_end = Units::to_int64(total_end * default_asset->frame_rate);
134                         }
135                         else
136                         {
137                                 package->audio_end = Units::to_int64(label->position * default_asset->sample_rate);
138                                 package->video_end = Units::to_int64(label->position * default_asset->frame_rate);
139                         }
141                         if(package->audio_end > audio_end)
142                         {
143                                 package->audio_end = audio_end;
144                         }
146                         if(package->video_end > video_end)
147                         {
148                                 package->video_end = video_end;
149                         }
151                         audio_position = package->audio_end;
152                         video_position = package->video_end;
153 // Create file number differently if image file sequence
154                         Render::create_filename(package->path, 
155                                 default_asset->path, 
156                                 current_number,
157                                 total_digits,
158                                 number_start);
159                         current_number++;
161                         total_packages++;
162                 }
163                 
164                 total_allocated = total_packages;
165         }
166         else
167         if(strategy == BRENDER_FARM)
168         {
169                 total_len = this->total_end - this->total_start;
171 // Create packages as they're requested.
172                 total_packages = 0;
173                 total_allocated = 0;
174                 packages = 0;
176                 Render::get_starting_number(default_asset->path, 
177                         current_number,
178                         number_start, 
179                         total_digits,
180                         6);
182 // Master node only
183                 if(preferences->renderfarm_nodes.total == 1)
184                 {
185                         package_len = total_len;
186                         min_package_len = total_len;
187                 }
188                 else
189                 {
190                         package_len = preferences->brender_fragment / 
191                                 edl->session->frame_rate;
192                         min_package_len = 1.0 / edl->session->frame_rate;
193                 }
194         }
196 // Test existence of every output file.
197 // Only if this isn't a background render or non interactive.
198         if(strategy != BRENDER_FARM && 
199                 test_overwrite &&
200                 mwindow)
201         {
202                 ArrayList<char*> paths;
203                 get_package_paths(&paths);
204                 result = ConfirmSave::test_files(mwindow, &paths);
205                 paths.remove_all_objects();
206         }
207         
208         return result;
211 void PackageDispatcher::get_package_paths(ArrayList<char*> *path_list)
213                 if (strategy == SINGLE_PASS_FARM)
214                         packaging_engine->get_package_paths(path_list);
215                 else
216                 {
217                         for(int i = 0; i < total_allocated; i++)
218                                 path_list->append(strdup(packages[i]->path));
219                         path_list->set_free();
220                 }
224 RenderPackage* PackageDispatcher::get_package(double frames_per_second, 
225         int client_number,
226         int use_local_rate)
228         package_lock->lock("PackageDispatcher::get_package");
229 // printf("PackageDispatcher::get_package 1 %f\n", 
230 // frames_per_second);
232         preferences->set_rate(frames_per_second, client_number);
233         if(mwindow) mwindow->preferences->copy_rates_from(preferences);
234         float avg_frames_per_second = preferences->get_avg_rate(use_local_rate);
236         RenderPackage *result = 0;
237 //printf("PackageDispatcher::get_package 1 %d\n", strategy);
238         if(strategy == SINGLE_PASS || 
239                 strategy == FILE_PER_LABEL || 
240                 strategy == FILE_PER_LABEL_FARM)
241         {
242                 if(current_package < total_packages)
243                 {
244                         result = packages[current_package];
245                         current_package++;
246                 }
247         }
248         else
249         if(strategy == SINGLE_PASS_FARM)
250         {
251                 result = packaging_engine->get_package_single_farm(frames_per_second, 
252                                                 client_number,
253                                                 use_local_rate);
254         }
255         else
256         if(strategy == BRENDER_FARM)
257         {
258 //printf("Dispatcher::get_package 1 %d %d\n", video_position, video_end);
259                 if(video_position < video_end)
260                 {
261 // Allocate new packages
262                         if(total_packages == 0)
263                         {
264                                 total_allocated = 256;
265                                 packages = new RenderPackage*[total_allocated];
266                         }
267                         else
268                         if(total_packages >= total_allocated)
269                         {
270                                 RenderPackage **old_packages = packages;
271                                 total_allocated *= 2;
272                                 packages = new RenderPackage*[total_allocated];
273                                 memcpy(packages, 
274                                         old_packages, 
275                                         total_packages * sizeof(RenderPackage*));
276                                 delete [] old_packages;
277                         }
279 // Calculate package.
280                         result = packages[total_packages] = new RenderPackage;
281                         double scaled_len;
283 // No load balancing data exists
284                         if(EQUIV(frames_per_second, 0) || 
285                                 EQUIV(avg_frames_per_second, 0))
286                         {
287                                 scaled_len = package_len;
288                         }
289                         else
290 // Load balancing data exists
291                         {
292                                 scaled_len = package_len * 
293                                         frames_per_second / 
294                                         avg_frames_per_second;
295                         }
297                         scaled_len = MAX(scaled_len, min_package_len);
299 // Always an image file sequence
300                         result->audio_start = audio_position;
301                         result->video_start = video_position;
302                         result->audio_end = result->audio_start + 
303                                 Units::to_int64(scaled_len * default_asset->sample_rate);
304                         result->video_end = result->video_start + 
305                                 Units::to_int64(scaled_len * default_asset->frame_rate);
306                         if(result->video_end == result->video_start) result->video_end++;
307                         audio_position = result->audio_end;
308                         video_position = result->video_end;
309                         result->audio_do = default_asset->audio_data;
310                         result->video_do = default_asset->video_data;
313 // The frame numbers are read from the vframe objects themselves.
314                         Render::create_filename(result->path,
315                                 default_asset->path,
316                                 0,
317                                 total_digits,
318                                 number_start);
319 //printf("PackageDispatcher::get_package 2 %s\n", result->path);
321                         current_number++;
322                         total_packages++;
323                         current_package++;
324                 }
325         }
327         package_lock->unlock();
329 //printf("PackageDispatcher::get_package %p\n", result);
330         return result;
334 ArrayList<Asset*>* PackageDispatcher::get_asset_list()
336         ArrayList<Asset*> *assets = new ArrayList<Asset*>;
338         for(int i = 0; i < current_package; i++)
339         {
340                 Asset *asset = new Asset;
341                 *asset = *default_asset;
342                 strcpy(asset->path, packages[i]->path);
343                 asset->video_length = packages[i]->video_end - packages[i]->video_start;
344                 asset->audio_length = packages[i]->audio_end - packages[i]->audio_start;
345                 assets->append(asset);
346         }
348         return assets;
351 int64_t PackageDispatcher::get_progress_max()
353         if (strategy == SINGLE_PASS_FARM)
354                 return packaging_engine->get_progress_max();
355         else
356                 return Units::to_int64(default_asset->sample_rate * 
357                                 (total_end - total_start)) +
358                         Units::to_int64(preferences->render_preroll * 
359                                 total_allocated * 
360                                 default_asset->sample_rate);
363 int PackageDispatcher::get_total_packages()
365         return total_allocated;
368 int PackageDispatcher::packages_are_done()
370         if (packaging_engine)
371                 return packaging_engine->packages_are_done();
372         return 0;