4 #include "bcprogressbox.h"
7 #include "compresspopup.h"
9 #include "cwindowgui.h"
13 #include "edlsession.h"
16 #include "filesystem.h"
17 #include "formatcheck.h"
18 #include "formatpopup.h"
19 #include "formattools.h"
22 #include "localsession.h"
23 #include "mainprogress.h"
24 #include "mainsession.h"
27 #include "mwindowgui.h"
30 #include "neworappend.h"
31 #include "packagedispatcher.h"
32 #include "packagerenderer.h"
34 #include "playabletracks.h"
35 #include "preferences.h"
36 #include "statusbar.h"
39 #include "transportque.h"
40 #include "quicktime.h"
43 #include "renderfarm.h"
46 #include "videoconfig.h"
52 #define _(String) gettext(String)
53 #define gettext_noop(String) String
54 #define N_(String) gettext_noop (String)
58 RenderItem::RenderItem(MWindow *mwindow)
59 : BC_MenuItem(_("Render..."), "Shift+R", 'R')
61 this->mwindow = mwindow;
65 int RenderItem::handle_event()
67 mwindow->render_single();
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_result()
137 return render->result;
140 void MainPackageRenderer::set_result(int value)
143 render->result = value;
146 void MainPackageRenderer::set_progress(int64_t value)
148 render->counter_lock->lock();
149 render->total_rendered += audio_read_length;
150 render->counter_lock->unlock();
153 int MainPackageRenderer::progress_cancelled()
155 return render->progress->is_cancelled();
164 Render::Render(MWindow *mwindow)
167 this->mwindow = mwindow;
169 package_lock = new Mutex;
170 counter_lock = new Mutex;
180 int Render::check_asset(EDL *edl, Asset &asset)
182 if(asset.video_data &&
183 edl->tracks->playable_video_tracks() &&
184 File::supports_video(asset.format))
186 asset.video_data = 1;
188 asset.width = edl->session->output_w;
189 asset.height = edl->session->output_h;
193 asset.video_data = 0;
197 if(asset.audio_data &&
198 edl->tracks->playable_audio_tracks() &&
199 File::supports_audio(asset.format))
201 asset.audio_data = 1;
202 asset.channels = edl->session->audio_channels;
203 if(asset.format == FILE_MOV) asset.byte_order = 0;
207 asset.audio_data = 0;
210 //printf("Render::check_asset 3\n");
214 void Render::start_progress()
216 char filename[BCTEXTLEN];
217 char string[BCTEXTLEN];
219 // Generate the progress box
220 fs.extract_name(filename, default_asset->path);
221 sprintf(string, _("Rendering %s..."), filename);
223 // Don't bother with the filename since renderfarm defeats the meaning
224 progress = mwindow->mainprogress->start_progress(_("Rendering..."),
225 Units::to_int64(default_asset->sample_rate *
226 (total_end - total_start)) +
227 Units::to_int64(preferences->render_preroll *
228 packages->total_allocated *
229 default_asset->sample_rate));
230 render_progress = new RenderProgress(mwindow, this);
231 render_progress->start();
234 void Render::stop_progress()
238 char string[BCTEXTLEN], string2[BCTEXTLEN];
239 delete render_progress;
240 progress->get_time(string);
241 progress->stop_progress();
244 sprintf(string2, _("Rendering took %s"), string);
245 mwindow->gui->lock_window();
246 mwindow->gui->show_message(string2, BLACK);
247 mwindow->gui->unlock_window();
256 char string[BCTEXTLEN];
257 // Total length in seconds
259 int last_audio_buffer;
260 RenderFarmServer *farm_server = 0;
262 int total_digits; // Total number of digits including padding the user specified.
263 int number_start; // Character in the filename path at which the number begins
264 int current_number; // The number the being injected into the filename.
266 // (VFrame*)(VFrame array [])(Channel [])
267 VFrame ***video_output;
268 // Pointer to output buffers
269 VFrame *video_output_ptr[MAX_CHANNELS];
270 double *audio_output_ptr[MAX_CHANNELS];
277 // Fix the EDL for rendering
278 default_asset = new Asset;
279 preferences = new Preferences;
280 *preferences = *mwindow->preferences;
281 command = new TransportCommand;
282 command->command = NORMAL_FWD;
283 *command->get_edl() = *mwindow->edl;
284 command->change_type = CHANGE_ALL;
285 command->set_playback_range(mwindow->edl);
289 // Adjust playback range with in/out points
290 if(mwindow->edl->local_session->in_point >= 0 ||
291 mwindow->edl->local_session->out_point >= 0)
293 if(mwindow->edl->local_session->in_point >= 0)
294 command->start_position = mwindow->edl->local_session->in_point;
296 command->start_position = 0;
298 if(mwindow->edl->local_session->out_point >= 0)
299 command->end_position = mwindow->edl->local_session->out_point;
301 command->end_position = mwindow->edl->tracks->total_playable_length();
305 packages = new PackageDispatcher;
308 // Configure preview monitor
309 VideoOutConfig vconfig(PLAYBACK_LOCALHOST, 0);
310 PlaybackConfig *playback_config = new PlaybackConfig(PLAYBACK_LOCALHOST, 0);
311 for(int i = 0; i < MAX_CHANNELS; i++)
313 vconfig.do_channel[i] = (i < command->get_edl()->session->video_channels);
314 playback_config->vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
315 playback_config->aconfig->do_channel[i] = (i < command->get_edl()->session->audio_channels);
319 audio_cache = new CICache(command->get_edl(), preferences, mwindow->plugindb);
320 video_cache = new CICache(command->get_edl(), preferences, mwindow->plugindb);
322 load_defaults(default_asset);
326 default_asset->frame_rate = command->get_edl()->session->frame_rate;
327 default_asset->sample_rate = command->get_edl()->session->sample_rate;
328 check_asset(command->get_edl(), *default_asset);
339 // Get format from user
346 RenderWindow window(mwindow, this, default_asset);
347 window.create_objects();
348 result = window.run_window();
353 // Check the asset format for errors.
354 FormatCheck format_check(default_asset);
355 format_error = format_check.check_format();
357 }while(format_error && !result);
359 check_asset(command->get_edl(), *default_asset);
360 //printf("%d %d\n", default_asset->video_data, default_asset->audio_data);
361 save_defaults(default_asset);
362 mwindow->save_defaults();
364 //printf("Render 2\n");
365 //default_asset->dump();
368 // Get total range to render
369 total_start = command->start_position;
370 total_end = command->end_position;
371 total_length = total_end - total_start;
374 if(EQUIV(total_length, 0))
384 //printf("Render 3\n");
393 // Stop background rendering
394 mwindow->stop_brender();
396 fs.complete_path(default_asset->path);
397 if(preferences->use_renderfarm)
399 if(strategy == SINGLE_PASS)
400 strategy = SINGLE_PASS_FARM;
402 if(strategy == FILE_PER_LABEL)
403 strategy = FILE_PER_LABEL_FARM;
407 if(strategy == SINGLE_PASS_FARM)
408 strategy = SINGLE_PASS;
410 if(strategy == FILE_PER_LABEL_FARM)
411 strategy = FILE_PER_LABEL;
414 result = packages->create_packages(mwindow,
425 //printf("Render 4\n");
435 frames_per_second = 0;
439 // Start dispatching external jobs
440 mwindow->gui->lock_window();
441 mwindow->gui->show_message(_("Starting render farm"), BLACK);
442 mwindow->gui->unlock_window();
443 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
445 farm_server = new RenderFarmServer(mwindow,
455 result = farm_server->start_clients();
459 mwindow->gui->lock_window();
460 mwindow->gui->show_message(_("Failed to start render farm"), BLACK);
461 mwindow->gui->unlock_window();
467 //printf("Render 5\n");
470 // Perform local rendering
480 //printf("Render 6\n");
481 MainPackageRenderer package_renderer(this);
482 //printf("Render 7\n");
483 package_renderer.initialize(mwindow,
484 command->get_edl(), // Copy of master EDL
490 //printf("Render 8\n");
498 // Get unfinished job
499 RenderPackage *package;
501 if(strategy == SINGLE_PASS_FARM)
503 //printf("Render 9\n");
504 package = packages->get_package(frames_per_second, -1, 1);
505 //printf("Render 10\n");
509 package = packages->get_package(0, -1, 1);
520 //printf("Render 11\n");
525 if(package_renderer.render_package(package))
527 // Result is also set directly by the RenderFarm.
528 //printf("Render 12\n");
530 frames_per_second = (double)(package->video_end - package->video_start) /
531 (double)(timer.get_difference() / 1000);
533 //printf("Render 13\n");
537 //printf("Render::run: Session finished.\n");
543 if(strategy == SINGLE_PASS_FARM || strategy == FILE_PER_LABEL_FARM)
545 farm_server->wait_clients();
551 !progress->is_cancelled())
553 ErrorBox error_box(PROGRAM_NAME ": Error",
554 mwindow->gui->get_abs_cursor_x(),
555 mwindow->gui->get_abs_cursor_y());
556 error_box.create_objects(_("Error rendering data."));
557 error_box.run_window();
560 // Delete the progress box
569 // mwindow->gui->lock_window();
570 // if(!result) mwindow->gui->statusbar->default_message();
571 // mwindow->gui->unlock_window();
573 // Paste all packages into timeline if desired
575 if(!result && load_mode != LOAD_NOTHING)
577 mwindow->gui->lock_window();
580 mwindow->undo->update_undo_before(_("render"), LOAD_ALL);
583 ArrayList<Asset*> *assets = packages->get_asset_list();
584 if(load_mode == LOAD_PASTE)
586 mwindow->load_assets(assets,
591 mwindow->edl->session->labels_follow_edits,
592 mwindow->edl->session->plugins_follow_edits);
593 assets->remove_all_objects();
597 mwindow->save_backup();
598 mwindow->undo->update_undo_after();
599 mwindow->update_plugin_guis();
600 mwindow->gui->update(1,
607 mwindow->sync_parameters(CHANGE_ALL);
608 mwindow->gui->unlock_window();
611 // Need to restart because brender always stops before render.
612 mwindow->restart_brender();
613 if(farm_server) delete farm_server;
616 delete playback_config;
619 // Must delete packages after server
621 delete default_asset;
625 int Render::test_existence(MWindow *mwindow, Asset *asset)
628 NewOrAppend window(mwindow);
629 // Append is not compatible with resample plugin.
630 result = window.test_file(asset);
634 // mwindow->purge_asset(asset->path);
635 // remove(asset->path); // overwrite
636 // append_to_file = 0;
640 result = 1; // cancel
644 // append_to_file = 1; // append
645 result = 0; // reset result;
652 void Render::create_filename(char *path,
659 int len = strlen(default_path);
660 char printf_string[BCTEXTLEN];
661 int found_number = 0;
663 for(i = 0, j = 0; i < number_start; i++, j++)
665 printf_string[j] = default_path[i];
669 sprintf(&printf_string[j], "%%0%dd", total_digits);
670 j = strlen(printf_string);
673 // Copy remainder of string
674 for( ; i < len; i++, j++)
676 printf_string[j] = default_path[i];
678 printf_string[j] = 0;
679 // Print the printf argument to the path
680 sprintf(path, printf_string, current_number);
683 void Render::get_starting_number(char *path,
690 int len = strlen(path);
691 char number_text[BCTEXTLEN];
697 // Search for first 0.
698 ptr = strchr(ptr, '0');
700 if(ptr && isdigit(*ptr))
702 number_start = ptr - path;
704 // Store the first number
705 char *ptr2 = number_text;
709 current_number = atol(number_text);
710 total_digits = strlen(number_text);
714 // No number found or number not long enough
715 if(total_digits < min_digits)
719 total_digits = min_digits;
729 int Render::load_defaults(Asset *asset)
731 mwindow->defaults->get("RENDER_PATH", asset->path);
732 // to_tracks = mwindow->defaults->get("RENDER_TO_TRACKS", 1);
733 strategy = mwindow->defaults->get("RENDER_STRATEGY", SINGLE_PASS);
734 load_mode = mwindow->defaults->get("RENDER_LOADMODE", LOAD_NEW_TRACKS);
735 asset->audio_data = mwindow->defaults->get("RENDER_AUDIO", 1);
736 asset->video_data = mwindow->defaults->get("RENDER_VIDEO", 1);
737 //printf("Render::load_defaults 1 %d %d\n", asset->audio_data, asset->video_data);
739 char string[BCTEXTLEN];
740 sprintf(string, "WAV");
741 mwindow->defaults->get("RENDER_FORMAT", string);
742 sprintf(asset->vcodec, QUICKTIME_YUV2);
743 mwindow->defaults->get("RENDER_COMPRESSION", asset->vcodec);
745 asset->format = File::strtoformat(mwindow->plugindb, string);
747 asset->bits = mwindow->defaults->get("RENDER_BITS", 16);
748 asset->dither = mwindow->defaults->get("RENDER_DITHER", 0);
749 asset->signed_ = mwindow->defaults->get("RENDER_SIGNED", 1);
750 asset->byte_order = mwindow->defaults->get("RENDER_BYTE_ORDER", 1);
755 asset->load_defaults(mwindow->defaults);
756 mwindow->defaults->get("RENDER_AUDIO_CODEC", asset->acodec);
757 mwindow->defaults->get("RENDER_VIDEO_CODEC", asset->vcodec);
758 //printf("Render 1 %d\n", default_asset->divx_fix_bitrate);
763 int Render::save_defaults(Asset *asset)
765 //printf("Render::save_defaults 1\n");
766 mwindow->defaults->update("RENDER_PATH", asset->path);
767 // mwindow->defaults->update("RENDER_TO_TRACKS", to_tracks);
768 mwindow->defaults->update("RENDER_STRATEGY", strategy);
769 mwindow->defaults->update("RENDER_LOADMODE", load_mode);
770 mwindow->defaults->update("RENDER_AUDIO", asset->audio_data);
771 mwindow->defaults->update("RENDER_VIDEO", asset->video_data);
772 //printf("Render::save_defaults 2\n");
774 mwindow->defaults->update("RENDER_FORMAT", File::formattostr(mwindow->plugindb, asset->format));
775 //printf("Render::save_defaults 3\n");
777 mwindow->defaults->update("RENDER_VCODEC", asset->vcodec);
778 mwindow->defaults->update("RENDER_BITS", asset->bits);
779 mwindow->defaults->update("RENDER_DITHER", asset->dither);
780 mwindow->defaults->update("RENDER_SIGNED", asset->signed_);
781 mwindow->defaults->update("RENDER_BYTE_ORDER", asset->byte_order);
783 asset->save_defaults(mwindow->defaults);
784 mwindow->defaults->update("RENDER_AUDIO_CODEC", asset->acodec);
785 mwindow->defaults->update("RENDER_VIDEO_CODEC", asset->vcodec);
786 //printf("Render::save_defaults 4\n");
797 RenderWindow::RenderWindow(MWindow *mwindow, Render *render, Asset *asset)
798 : BC_Window(PROGRAM_NAME ": Render",
799 mwindow->gui->get_root_w() / 2 - WIDTH / 2,
800 mwindow->gui->get_root_h() / 2 - HEIGHT / 2,
809 this->mwindow = mwindow;
810 this->render = render;
814 RenderWindow::~RenderWindow()
822 int RenderWindow::create_objects()
825 add_subwindow(new BC_Title(x,
827 (char*)((render->strategy == FILE_PER_LABEL || render->strategy == FILE_PER_LABEL_FARM) ?
828 _("Select the first file to render to:") :
829 _("Select a file to render to:"))));
832 format_tools = new FormatTools(mwindow,
835 format_tools->create_objects(x,
848 loadmode = new LoadMode(mwindow, this, x, y, &render->load_mode, 1);
849 loadmode->create_objects();
851 add_subwindow(new BC_OKButton(this));
852 add_subwindow(new BC_CancelButton(this));