4 #include "batchrender.h"
5 #include "bcprogressbox.h"
8 #include "compresspopup.h"
10 #include "confirmsave.h"
11 #include "cwindowgui.h"
16 #include "edlsession.h"
19 #include "filesystem.h"
21 #include "formatcheck.h"
22 #include "formatpopup.h"
23 #include "formattools.h"
27 #include "localsession.h"
28 #include "mainprogress.h"
29 #include "mainsession.h"
33 #include "mwindowgui.h"
35 #include "packagedispatcher.h"
36 #include "packagerenderer.h"
38 #include "playabletracks.h"
39 #include "preferences.h"
40 #include "quicktime.h"
41 #include "renderfarm.h"
43 #include "statusbar.h"
47 #include "transportque.h"
50 #include "videoconfig.h"
58 RenderItem::RenderItem(MWindow *mwindow)
59 : BC_MenuItem(_("Render..."), "Shift+R", 'R')
61 this->mwindow = mwindow;
65 int RenderItem::handle_event()
67 mwindow->render->start_interactive();
80 RenderProgress::RenderProgress(MWindow *mwindow, Render *render)
83 this->mwindow = mwindow;
84 this->render = render;
86 Thread::set_synchronous(1);
89 RenderProgress::~RenderProgress()
96 void RenderProgress::run()
98 Thread::disable_cancel();
101 if(render->total_rendered != last_value)
103 render->progress->update(render->total_rendered);
104 last_value = render->total_rendered;
107 Thread::enable_cancel();
109 Thread::disable_cancel();
122 MainPackageRenderer::MainPackageRenderer(Render *render)
125 this->render = render;
130 MainPackageRenderer::~MainPackageRenderer()
135 int MainPackageRenderer::get_master()
140 int MainPackageRenderer::get_result()
142 return render->result;
145 void MainPackageRenderer::set_result(int value)
148 render->result = value;
151 void MainPackageRenderer::set_progress(int64_t value)
153 render->counter_lock->lock("MainPackageRenderer::set_progress");
154 render->total_rendered += value;
156 // If non interactive, print progress out
157 if(!render->progress)
159 int64_t current_eta = render->progress_timer->get_scaled_difference(1000);
160 if(current_eta - render->last_eta > 1000)
165 if(render->total_rendered)
169 render->progress_max /
170 render->total_rendered -
175 char string[BCTEXTLEN];
176 Units::totext(string,
180 printf("\r%d%% ETA: %s ", (int)(100 *
181 (float)render->total_rendered /
182 render->progress_max),
185 render->last_eta = current_eta;
189 render->counter_lock->unlock();
192 int MainPackageRenderer::progress_cancelled()
194 return (render->progress && render->progress->is_cancelled()) ||
195 render->batch_cancelled;
209 Render::Render(MWindow *mwindow)
212 this->mwindow = mwindow;
213 if(mwindow) plugindb = mwindow->plugindb;
218 package_lock = new Mutex("Render::package_lock");
219 counter_lock = new Mutex("Render::counter_lock");
220 completion = new Condition(0, "Render::completion");
221 progress_timer = new Timer;
229 if(preferences) delete preferences;
230 delete progress_timer;
233 void Render::start_interactive()
235 if(!Thread::running())
237 mode = Render::INTERACTIVE;
245 // raise the window if rendering hasn't started yet
246 if (render_window && ! in_progress) {
247 render_window->raise_window();
250 ErrorBox error_box(PROGRAM_NAME ": Error",
251 mwindow->gui->get_abs_cursor_x(1),
252 mwindow->gui->get_abs_cursor_y(1));
253 error_box.create_objects("Already rendering");
254 error_box.raise_window();
255 error_box.run_window();
260 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs)
263 if(!Thread::running())
265 mode = Render::BATCH;
272 ErrorBox error_box(PROGRAM_NAME ": Error",
273 mwindow->gui->get_abs_cursor_x(1),
274 mwindow->gui->get_abs_cursor_y(1));
275 error_box.create_objects("Already rendering");
276 error_box.raise_window();
277 error_box.run_window();
281 void Render::start_batches(ArrayList<BatchRenderJob*> *jobs,
282 BC_Hash *boot_defaults,
283 Preferences *preferences,
284 ArrayList<PluginServer*> *plugindb)
286 mode = Render::BATCH;
289 this->preferences = preferences;
290 this->plugindb = plugindb;
294 this->preferences = 0;
297 void Render::stop_operation()
299 if(Thread::running())
302 // Wait for completion
303 completion->lock("Render::stop_operation");
316 if(mode == Render::INTERACTIVE)
318 // Fix the asset for rendering
319 printf("Render::run 1\n");
320 Asset *asset = new Asset;
321 load_defaults(asset);
322 printf("Render::run 2\n");
323 check_asset(mwindow->edl, *asset);
324 printf("Render::run 3\n");
326 // Get format from user
329 printf("Render::run 4\n");
336 printf("Render::run 5\n");
337 RenderWindow window(mwindow, this, asset);
338 printf("Render::run 6\n");
339 window.create_objects();
340 printf("Render::run 7\n");
341 result = window.run_window();
342 printf("Render::run 8\n");
344 // add to recentlist only on OK
345 window.format_tools->path_recent->add_item(FILE_FORMAT_PREFIX(asset->format), asset->path);
351 printf("Render::run 8.1\n");
352 // Check the asset format for errors.
353 FormatCheck format_check(asset);
354 printf("Render::run 8.2\n");
355 format_error = format_check.check_format();
356 printf("Render::run 8.3\n");
358 }while(format_error && !result);
360 printf("Render::run 9\n");
362 save_defaults(asset);
363 mwindow->save_defaults();
364 printf("Render::run 10\n");
366 if(!result) render(1, asset, mwindow->edl, strategy);
367 printf("Render::run 11\n");
369 Garbage::delete_object(asset);
370 printf("Render::run 12\n");
373 if(mode == Render::BATCH)
375 for(int i = 0; i < jobs->total && !result; i++)
377 BatchRenderJob *job = jobs->values[i];
382 mwindow->batch_render->update_active(i);
386 printf("Render::run: %s\n", job->edl_path);
390 FileXML *file = new FileXML;
392 edl->create_objects();
393 file->read_from_file(job->edl_path);
394 if(!plugindb && mwindow)
395 plugindb = mwindow->plugindb;
396 edl->load_xml(plugindb, file, LOAD_ALL);
398 check_asset(edl, *job->asset);
399 render(0, job->asset, edl, job->strategy);
406 mwindow->batch_render->update_done(i, 1, elapsed_time);
409 char string[BCTEXTLEN];
411 (double)progress_timer->get_scaled_difference(1);
412 Units::totext(string,
415 printf("Render::run: done in %s\n", string);
421 mwindow->batch_render->update_active(-1);
423 printf("Render::run: failed\n");
430 mwindow->batch_render->update_active(-1);
431 mwindow->batch_render->update_done(-1, 0, 0);
434 printf("Render::run 100\n");
439 int Render::check_asset(EDL *edl, Asset &asset)
441 if(asset.video_data &&
442 edl->tracks->playable_video_tracks() &&
443 File::supports_video(asset.format))
445 asset.video_data = 1;
447 asset.width = edl->session->output_w;
448 asset.height = edl->session->output_h;
449 asset.interlace_mode = edl->session->interlace_mode;
450 asset.tcstart = (int64_t) (edl->session->get_frame_offset() +
451 edl->local_session->get_selectionstart() *
452 edl->session->frame_rate);
453 asset.tcend = (int64_t) (edl->session->get_frame_offset() +
454 edl->local_session->get_selectionend() *
455 edl->session->frame_rate);
459 asset.video_data = 0;
465 if(asset.audio_data &&
466 edl->tracks->playable_audio_tracks() &&
467 File::supports_audio(asset.format))
469 asset.audio_data = 1;
470 asset.channels = edl->session->audio_channels;
471 if(asset.format == FILE_MOV) asset.byte_order = 0;
472 asset.tcstart = (int64_t) (edl->session->get_frame_offset() +
473 edl->local_session->get_selectionstart() *
474 edl->session->sample_rate);
475 asset.tcend = (int64_t) (edl->session->get_frame_offset() +
476 edl->local_session->get_selectionend() *
477 edl->session->sample_rate);
481 asset.audio_data = 0;
487 if(!asset.audio_data &&
495 int Render::fix_strategy(int strategy, int use_renderfarm)
499 if(strategy == FILE_PER_LABEL)
500 strategy = FILE_PER_LABEL_FARM;
502 if(strategy == SINGLE_PASS)
503 strategy = SINGLE_PASS_FARM;
507 if(strategy == FILE_PER_LABEL_FARM)
508 strategy = FILE_PER_LABEL;
510 if(strategy == SINGLE_PASS_FARM)
511 strategy = SINGLE_PASS;
516 void Render::start_progress()
518 char filename[BCTEXTLEN];
519 char string[BCTEXTLEN];
522 progress_max = packages->get_progress_max();
524 progress_timer->update();
528 // Generate the progress box
529 fs.extract_name(filename, default_asset->path);
530 sprintf(string, _("Rendering %s..."), filename);
532 // Don't bother with the filename since renderfarm defeats the meaning
533 progress = mwindow->mainprogress->start_progress(_("Rendering..."),
535 render_progress = new RenderProgress(mwindow, this);
536 render_progress->start();
540 void Render::stop_progress()
544 char string[BCTEXTLEN], string2[BCTEXTLEN];
545 delete render_progress;
546 progress->get_time(string);
547 elapsed_time = progress->get_time();
548 progress->stop_progress();
551 sprintf(string2, _("Rendering took %s"), string);
552 mwindow->gui->lock_window("");
553 mwindow->gui->show_message(string2);
554 mwindow->gui->stop_hourglass();
555 mwindow->gui->unlock_window();
562 int Render::render(int test_overwrite,
567 char string[BCTEXTLEN];
568 // Total length in seconds
570 int last_audio_buffer;
571 RenderFarmServer *farm_server = 0;
573 int total_digits; // Total number of digits including padding the user specified.
574 int number_start; // Character in the filename path at which the number begins
575 int current_number; // The number the being injected into the filename.
577 // (VFrame*)(VFrame array [])(Channel [])
578 VFrame ***video_output;
579 // Pointer to output buffers
580 VFrame *video_output_ptr[MAX_CHANNELS];
581 double *audio_output_ptr[MAX_CHANNELS];
586 this->default_asset = asset;
593 preferences = new Preferences;
595 preferences->copy_from(mwindow->preferences);
599 // Create rendering command
600 command = new TransportCommand;
601 command->command = NORMAL_FWD;
602 command->get_edl()->copy_all(edl);
603 command->change_type = CHANGE_ALL;
604 // Get highlighted playback range
605 command->set_playback_range();
606 // Adjust playback range with in/out points
607 command->adjust_playback_range();
608 packages = new PackageDispatcher;
611 // Configure preview monitor
612 VideoOutConfig vconfig;
613 PlaybackConfig *playback_config = new PlaybackConfig;
616 audio_cache = new CICache(preferences, plugindb);
617 video_cache = new CICache(preferences, plugindb);
619 default_asset->frame_rate = command->get_edl()->session->frame_rate;
620 default_asset->sample_rate = command->get_edl()->session->sample_rate;
622 // Conform asset to EDL. Find out if any tracks are playable.
623 result = check_asset(command->get_edl(), *default_asset);
627 // Get total range to render
628 total_start = command->start_position;
629 total_end = command->end_position;
630 total_length = total_end - total_start;
633 if(EQUIV(total_length, 0))
648 // Stop background rendering
649 if(mwindow) mwindow->stop_brender();
651 fs.complete_path(default_asset->path);
652 strategy = Render::fix_strategy(strategy, preferences->use_renderfarm);
654 result = packages->create_packages(mwindow,
675 frames_per_second = 0;
679 // Start dispatching external jobs
682 mwindow->gui->lock_window("Render::render 1");
683 mwindow->gui->show_message(_("Starting render farm"));
684 mwindow->gui->start_hourglass();
685 mwindow->gui->unlock_window();
689 printf("Render::render: starting render farm\n");
692 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
694 farm_server = new RenderFarmServer(plugindb,
704 result = farm_server->start_clients();
710 mwindow->gui->lock_window("Render::render 2");
711 mwindow->gui->show_message(_("Failed to start render farm"),
712 mwindow->theme->message_error);
713 mwindow->gui->stop_hourglass();
714 mwindow->gui->unlock_window();
718 printf("Render::render: Failed to start render farm\n");
727 // Perform local rendering
737 MainPackageRenderer package_renderer(this);
738 result = package_renderer.initialize(mwindow,
739 command->get_edl(), // Copy of master EDL
752 // Get unfinished job
753 RenderPackage *package;
755 if(strategy == SINGLE_PASS_FARM)
757 package = packages->get_package(frames_per_second, -1, 1);
761 package = packages->get_package(0, -1, 1);
776 if(package_renderer.render_package(package))
779 // Result is also set directly by the RenderFarm.
781 frames_per_second = (double)(package->video_end - package->video_start) /
782 (double)(timer.get_difference() / 1000);
789 printf("Render::run: Session finished.\n");
795 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
797 farm_server->wait_clients();
798 result |= packages->packages_are_done();
801 printf("Render::render 90\n");
805 (!progress || !progress->is_cancelled()) &&
810 ErrorBox error_box(PROGRAM_NAME ": Error",
811 mwindow->gui->get_abs_cursor_x(1),
812 mwindow->gui->get_abs_cursor_y(1));
813 error_box.create_objects(_("Error rendering data."));
814 error_box.raise_window();
815 error_box.run_window();
819 printf("Render::render: Error rendering data\n");
823 // Delete the progress box
826 //printf("Render::render 100\n");
834 // Paste all packages into timeline if desired
837 load_mode != LOAD_NOTHING &&
839 mode != Render::BATCH)
841 mwindow->gui->lock_window("Render::render 3");
846 ArrayList<Asset*> *assets = packages->get_asset_list();
847 if(load_mode == LOAD_PASTE)
849 mwindow->load_assets(assets,
854 mwindow->edl->session->labels_follow_edits,
855 mwindow->edl->session->plugins_follow_edits,
860 mwindow->save_backup();
861 mwindow->undo->update_undo(_("render"), LOAD_ALL);
862 mwindow->update_plugin_guis();
863 mwindow->gui->update(1,
870 mwindow->sync_parameters(CHANGE_ALL);
871 mwindow->gui->unlock_window();
878 mwindow->gui->lock_window("Render::render 3");
879 mwindow->gui->stop_hourglass();
880 mwindow->gui->unlock_window();
883 //printf("Render::render 110\n");
884 // Need to restart because brender always stops before render.
886 mwindow->restart_brender();
887 if(farm_server) delete farm_server;
889 delete playback_config;
892 // Must delete packages after server
895 completion->unlock();
896 //printf("Render::render 120\n");
902 void Render::create_filename(char *path,
909 int len = strlen(default_path);
910 char printf_string[BCTEXTLEN];
911 int found_number = 0;
913 for(i = 0, j = 0; i < number_start; i++, j++)
915 printf_string[j] = default_path[i];
919 sprintf(&printf_string[j], "%%0%dd", total_digits);
920 j = strlen(printf_string);
923 // Copy remainder of string
924 for( ; i < len; i++, j++)
926 printf_string[j] = default_path[i];
928 printf_string[j] = 0;
929 // Print the printf argument to the path
930 sprintf(path, printf_string, current_number);
933 void Render::get_starting_number(char *path,
940 int len = strlen(path);
941 char number_text[BCTEXTLEN];
949 ptr2 = strrchr(path, '/');
951 // Search for first 0 after last /.
953 ptr = strchr(ptr2, '0');
955 if(ptr && isdigit(*ptr))
957 number_start = ptr - path;
959 // Store the first number
960 char *ptr2 = number_text;
964 current_number = atol(number_text);
965 total_digits = strlen(number_text);
969 // No number found or number not long enough
970 if(total_digits < min_digits)
974 total_digits = min_digits;
984 int Render::load_defaults(Asset *asset)
986 strategy = mwindow->defaults->get("RENDER_STRATEGY", SINGLE_PASS);
987 load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOAD_NEW_TRACKS);
990 asset->load_defaults(mwindow->defaults,
1002 int Render::save_defaults(Asset *asset)
1004 mwindow->defaults->update("RENDER_STRATEGY", strategy);
1005 mwindow->defaults->update("RENDER_LOADMODE", load_mode);
1010 asset->save_defaults(mwindow->defaults,
1028 RenderWindow::RenderWindow(MWindow *mwindow, Render *render, Asset *asset)
1029 : BC_Window(PROGRAM_NAME ": Render",
1030 mwindow->gui->get_root_w(0, 1) / 2 - WIDTH / 2,
1031 mwindow->gui->get_root_h(1) / 2 - HEIGHT / 2,
1040 this->mwindow = mwindow;
1041 this->render = render;
1042 this->asset = asset;
1045 RenderWindow::~RenderWindow()
1047 delete format_tools;
1053 int RenderWindow::create_objects()
1056 add_subwindow(new BC_Title(x,
1058 (char*)((render->strategy == FILE_PER_LABEL ||
1059 render->strategy == FILE_PER_LABEL_FARM) ?
1060 _("Select the first file to render to:") :
1061 _("Select a file to render to:"))));
1064 format_tools = new FormatTools(mwindow,
1067 format_tools->create_objects(x,
1080 loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
1081 loadmode->create_objects();
1083 add_subwindow(new BC_OKButton(this));
1084 add_subwindow(new BC_CancelButton(this));