4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
23 #include "bcsignals.h"
26 #include "condition.h"
28 #include "edlsession.h"
30 #include "mainsession.h"
33 #include "mwindowgui.h"
35 #include "packagedispatcher.h"
36 #include "preferences.h"
37 #include "renderfarm.h"
60 BRender::BRender(MWindow *mwindow)
63 this->mwindow = mwindow;
64 map_lock = new Mutex("BRender::map_lock");
65 completion_lock = new Condition(0, "BRender::completion_lock");
70 arguments[0] = arguments[1] = arguments[2] = 0;
80 TRACE("BRender::~BRender 1\n");
83 TRACE("BRender::~BRender 2\n");
85 TRACE("BRender::~BRender 3\n");
87 TRACE("BRender::~BRender 4\n");
91 TRACE("BRender::~BRender 5\n");
94 kill(master_pid, SIGKILL);
95 TRACE("BRender::~BRender 6\n");
96 TRACE("BRender::~BRender 7\n");
100 TRACE("BRender::~BRender 8\n");
102 TRACE("BRender::~BRender 9\n");
103 delete completion_lock;
104 TRACE("BRender::~BRender 10\n");
105 UNSET_TEMP(socket_path);
107 TRACE("BRender::~BRender 11\n");
108 if(arguments[0]) delete [] arguments[0];
109 TRACE("BRender::~BRender 12\n");
110 if(arguments[1]) delete [] arguments[1];
111 TRACE("BRender::~BRender 13\n");
112 if(arguments[2]) delete [] arguments[2];
113 TRACE("BRender::~BRender 14\n");
114 if(map) delete [] map;
115 TRACE("BRender::~BRender 15\n");
117 TRACE("BRender::~BRender 100\n");
120 void BRender::initialize()
123 // Create socket for background process.
125 sprintf(socket_path, "/tmp/cinelerra.");
126 uuid_generate(socket_temp);
127 uuid_unparse(socket_temp, socket_path + strlen(socket_path));
128 SET_TEMP(socket_path);
130 // Start background instance of executable since codecs aren't reentrant
133 // Wait for local node to start
134 thread = new BRenderThread(mwindow, this);
135 thread->initialize();
140 char string[BCTEXTLEN];
142 //printf("BRender::run 1 %d\n", getpid());
145 // Construct executable command with the designated filesystem port
146 fd = fopen("/proc/self/cmdline", "r");
149 (void)fread(string, 1, BCTEXTLEN, fd);
153 perror(_("BRender::fork_background: can't open /proc/self/cmdline.\n"));
155 arguments[0] = new char[strlen(string) + 1];
156 strcpy(arguments[0], string);
158 strcpy(string, "-b");
159 arguments[1] = new char[strlen(string) + 1];
160 strcpy(arguments[1], string);
162 arguments[2] = new char[strlen(socket_path) + 1];
163 strcpy(arguments[2], socket_path);
164 //printf("BRender::fork_background 1 %s\n", socket_path);
171 execvp(arguments[0], arguments);
172 perror("BRender::fork_background");
177 //printf("BRender::fork_background 1 %d\n", master_pid);
182 if(waitpid(master_pid, &return_value, WUNTRACED) < 0)
184 perror("BRender::run waitpid");
188 // Give the last position of the EDL which hasn't changed.
189 // We copy the EDL and restart rendering at the lesser of position and
191 void BRender::restart(EDL *edl)
193 //printf("BRender::restart 1\n");
194 BRenderCommand *new_command = new BRenderCommand;
196 new_command->copy_edl(edl);
197 new_command->command = BRenderCommand::BRENDER_RESTART;
198 //printf("BRender::restart 2\n");
199 thread->send_command(new_command);
200 //printf("BRender::restart 3\n");
201 // Map should be reallocated before this returns.
206 //printf("BRender::stop 1\n");
207 BRenderCommand *new_command = new BRenderCommand;
208 //printf("BRender::stop 1\n");
209 new_command->command = BRenderCommand::BRENDER_STOP;
210 //printf("BRender::stop 1\n");
211 thread->send_command(new_command);
212 //printf("BRender::stop 1\n");
213 completion_lock->lock("BRender::stop");
214 //printf("BRender::stop 2\n");
219 int BRender::get_last_contiguous(int64_t brender_start)
222 map_lock->lock("BRender::get_last_contiguous");
224 result = last_contiguous;
226 result = brender_start;
231 void BRender::allocate_map(int64_t brender_start, int64_t start, int64_t end)
233 map_lock->lock("BRender::allocate_map");
234 unsigned char *old_map = map;
235 map = new unsigned char[end];
238 memcpy(map, old_map, start);
242 // Zero all before brender start
243 bzero(map, brender_start);
244 // Zero all after current start
245 bzero(map + start, end - start);
249 last_contiguous = start;
250 mwindow->session->brender_end = (double)last_contiguous /
251 mwindow->edl->session->frame_rate;
255 int BRender::set_video_map(int64_t position, int value)
258 map_lock->lock("BRender::set_video_map");
261 if(value == BRender::NOT_SCANNED)
263 printf(_("BRender::set_video_map called to set NOT_SCANNED\n"));
273 if(position < map_size)
275 map[position] = value;
280 printf(_("BRender::set_video_map %jd: attempt to set beyond end of map %jd.\n"),
284 // Maintain last contiguous here to reduce search time
285 if(position == last_contiguous)
288 for(i = position + 1; i < map_size && map[i]; i++)
293 mwindow->session->brender_end = (double)last_contiguous /
294 mwindow->edl->session->frame_rate;
296 if(timer->get_difference() > 1000 || last_contiguous >= map_size)
307 mwindow->gui->lock_window("BRender::set_video_map");
308 mwindow->gui->update_timebar(1);
309 mwindow->gui->unlock_window();
327 BRenderCommand::BRenderCommand()
330 command = BRENDER_NONE;
334 BRenderCommand::~BRenderCommand()
336 // EDL should be zeroed if copied
337 if(edl) edl->Garbage::remove_user();
340 void BRenderCommand::copy_from(BRenderCommand *src)
342 this->edl = src->edl;
344 this->position = src->position;
345 this->command = src->command;
349 void BRenderCommand::copy_edl(EDL *edl)
352 this->edl->create_objects();
353 this->edl->copy_all(edl);
368 BRenderThread::BRenderThread(MWindow *mwindow, BRender *brender)
371 this->mwindow = mwindow;
372 this->brender = brender;
373 input_lock = new Condition(0, "BRenderThread::input_lock");
374 thread_lock = new Mutex("BRenderThread::thread_lock");
375 total_frames_lock = new Mutex("BRenderThread::total_frames_lock");
384 BRenderThread::~BRenderThread()
386 thread_lock->lock("BRenderThread::~BRenderThread");
388 input_lock->unlock();
389 thread_lock->unlock();
393 delete total_frames_lock;
394 if(command) delete command;
395 if(command_queue) delete command_queue;
396 if(preferences) delete preferences;
400 void BRenderThread::initialize()
405 void BRenderThread::send_command(BRenderCommand *command)
407 TRACE("BRenderThread::send_command 1");
408 thread_lock->lock("BRenderThread::send_command");
409 TRACE("BRenderThread::send_command 10");
411 if(this->command_queue)
413 delete this->command_queue;
414 this->command_queue = 0;
416 this->command_queue = command;
417 TRACE("BRenderThread::send_command 20");
420 input_lock->unlock();
421 thread_lock->unlock();
424 int BRenderThread::is_done(int do_lock)
426 if(do_lock) thread_lock->lock("BRenderThread::is_done");
428 if(do_lock) thread_lock->unlock();
432 void BRenderThread::run()
436 BRenderCommand *new_command = 0;
437 thread_lock->lock("BRenderThread::run 1");
445 // Wait for new command
447 thread_lock->unlock();
448 input_lock->lock("BRenderThread::run 2");
449 thread_lock->lock("BRenderThread::run 3");
452 // Pull the command off
455 new_command = command_queue;
459 thread_lock->unlock();
464 // Process the command here to avoid delay.
471 if(new_command->command == BRenderCommand::BRENDER_STOP)
476 // if(command) delete command;
477 // command = new_command;
480 if(new_command->command == BRenderCommand::BRENDER_RESTART)
482 // Compare EDL's and get last equivalent position in new EDL
483 if(command && command->edl)
484 new_command->position =
485 new_command->edl->equivalent_output(command->edl);
487 new_command->position = 0;
491 //printf("BRenderThread::run 4\n");
492 brender->completion_lock->lock("BRenderThread::run 4");
493 //printf("BRenderThread::run 5\n");
495 if(new_command->edl->tracks->total_playable_vtracks())
497 if(command) delete command;
498 command = new_command;
499 //printf("BRenderThread::run 6\n");
501 //printf("BRenderThread::run 7\n");
505 //printf("BRenderThread::run 8 %p\n", farm_server);
513 void BRenderThread::stop()
518 farm_server->wait_clients();
526 brender->completion_lock->unlock();
529 void BRenderThread::start()
531 // Reset return parameters
537 // Allocate render farm.
540 //printf("BRenderThread::start 1\n");
541 preferences = new Preferences;
542 preferences->copy_from(mwindow->preferences);
543 packages = new PackageDispatcher;
545 // Fix preferences to use local node
546 if(!preferences->use_renderfarm)
548 preferences->use_renderfarm = 1;
549 preferences->delete_nodes();
551 preferences->add_node(brender->socket_path,
554 preferences->local_rate);
555 //printf("BRenderThread::start 1 %s\n", brender->socket_path);
556 preferences->brender_asset->use_header = 0;
557 preferences->brender_asset->frame_rate = command->edl->session->frame_rate;
558 preferences->brender_asset->width = command->edl->session->output_w;
559 preferences->brender_asset->height = command->edl->session->output_h;
560 preferences->brender_asset->interlace_mode = command->edl->session->interlace_mode;
562 // Get last contiguous and reset map.
563 // If the framerate changes, last good should be 0 from the user.
564 int brender_start = (int)(command->edl->session->brender_start *
565 command->edl->session->frame_rate);
566 int last_contiguous = brender->last_contiguous;
567 int last_good = (int)(command->edl->session->frame_rate *
569 if(last_good < 0) last_good = last_contiguous;
570 int start_frame = MIN(last_contiguous, last_good);
571 start_frame = MAX(start_frame, brender_start);
572 int64_t end_frame = Units::round(command->edl->tracks->total_video_length() *
573 command->edl->session->frame_rate);
574 if(end_frame < start_frame) end_frame = start_frame;
577 printf("BRenderThread::start 1 map=%d equivalent=%d brender_start=%d result=%d end=%jd\n",
578 last_contiguous, last_good, brender_start, start_frame, end_frame);
582 brender->allocate_map(brender_start, start_frame, end_frame);
584 //printf("BRenderThread::start 2\n");
586 result = packages->create_packages(mwindow,
590 preferences->brender_asset,
591 (double)start_frame / command->edl->session->frame_rate,
592 (double)end_frame / command->edl->session->frame_rate,
596 //printf("BRenderThread::start 3 %d\n", result);
597 farm_server = new RenderFarmServer(mwindow,
604 preferences->brender_asset,
609 //printf("BRenderThread::start 4\n");
610 result = farm_server->start_clients();
613 // No local rendering because of codec problems.
619 // No-one must be retrieving a package when packages are deleted.
620 //printf("BRenderThread::start 7 %p\n", farm_server);
623 //printf("BRenderThread::start 8 %p\n", preferences);
625 //printf("BRenderThread::start 9\n");
631 //printf("BRenderThread::start 10\n");