00001 #include "asset.h"
00002 #include "bcsignals.h"
00003 #include "brender.h"
00004 #include "clip.h"
00005 #include "condition.h"
00006 #include "edl.h"
00007 #include "edlsession.h"
00008 #include "language.h"
00009 #include "mainsession.h"
00010 #include "mtimebar.h"
00011 #include "mutex.h"
00012 #include "mwindowgui.h"
00013 #include "mwindow.h"
00014 #include "packagedispatcher.h"
00015 #include "preferences.h"
00016 #include "renderfarm.h"
00017 #include "tracks.h"
00018 #include "units.h"
00019
00020
00021 #include <errno.h>
00022 #include <signal.h>
00023 #include <string.h>
00024 #include <sys/wait.h>
00025 #include <unistd.h>
00026
00027
00028
00029 extern "C"
00030 {
00031 #include <uuid/uuid.h>
00032 }
00033
00034
00035
00036
00037
00038
00039 BRender::BRender(MWindow *mwindow)
00040 : Thread()
00041 {
00042 this->mwindow = mwindow;
00043 map_lock = new Mutex("BRender::map_lock");
00044 completion_lock = new Condition(0, "BRender::completion_lock");
00045 timer = new Timer;
00046 socket_path[0] = 0;
00047 thread = 0;
00048 master_pid = -1;
00049 arguments[0] = arguments[1] = arguments[2] = 0;
00050 map = 0;
00051 map_size = 0;
00052 map_valid = 0;
00053 last_contiguous + 0;
00054 set_synchronous(1);
00055 }
00056
00057 BRender::~BRender()
00058 {
00059 TRACE("BRender::~BRender 1\n");
00060 if(thread)
00061 {
00062 TRACE("BRender::~BRender 2\n");
00063 stop();
00064 TRACE("BRender::~BRender 3\n");
00065 delete thread;
00066 TRACE("BRender::~BRender 4\n");
00067 }
00068
00069
00070 TRACE("BRender::~BRender 5\n");
00071 if(master_pid >= 0)
00072 {
00073 kill(master_pid, SIGKILL);
00074 TRACE("BRender::~BRender 6\n");
00075 Thread::join();
00076 TRACE("BRender::~BRender 7\n");
00077 }
00078
00079 TRACE("BRender::~BRender 8\n");
00080 delete map_lock;
00081 TRACE("BRender::~BRender 9\n");
00082 delete completion_lock;
00083 TRACE("BRender::~BRender 10\n");
00084 UNSET_TEMP(socket_path);
00085 remove(socket_path);
00086 TRACE("BRender::~BRender 11\n");
00087 if(arguments[0]) delete [] arguments[0];
00088 TRACE("BRender::~BRender 12\n");
00089 if(arguments[1]) delete [] arguments[1];
00090 TRACE("BRender::~BRender 13\n");
00091 if(arguments[2]) delete [] arguments[2];
00092 TRACE("BRender::~BRender 14\n");
00093 if(map) delete [] map;
00094 TRACE("BRender::~BRender 15\n");
00095 delete timer;
00096 TRACE("BRender::~BRender 100\n");
00097 }
00098
00099 void BRender::initialize()
00100 {
00101 timer->update();
00102
00103 uuid_t socket_temp;
00104 sprintf(socket_path, "/tmp/cinelerra.");
00105 uuid_generate(socket_temp);
00106 uuid_unparse(socket_temp, socket_path + strlen(socket_path));
00107 SET_TEMP(socket_path);
00108
00109
00110 Thread::start();
00111
00112
00113 thread = new BRenderThread(mwindow, this);
00114 thread->initialize();
00115 }
00116
00117 void BRender::run()
00118 {
00119 char string[BCTEXTLEN];
00120 int size;
00121 FILE *fd;
00122
00123
00124
00125
00126 fd = fopen("/proc/self/cmdline", "r");
00127 if(fd)
00128 {
00129 fread(string, 1, BCTEXTLEN, fd);
00130 fclose(fd);
00131 }
00132 else
00133 perror(_("BRender::fork_background: can't open /proc/self/cmdline.\n"));
00134
00135 arguments[0] = new char[strlen(string) + 1];
00136 strcpy(arguments[0], string);
00137
00138 strcpy(string, "-b");
00139 arguments[1] = new char[strlen(string) + 1];
00140 strcpy(arguments[1], string);
00141
00142 arguments[2] = new char[strlen(socket_path) + 1];
00143 strcpy(arguments[2], socket_path);
00144
00145
00146 arguments[3] = 0;
00147
00148 int pid = vfork();
00149 if(!pid)
00150 {
00151 execvp(arguments[0], arguments);
00152 perror("BRender::fork_background");
00153 _exit(0);
00154 }
00155
00156 master_pid = pid;
00157
00158
00159
00160
00161 int return_value;
00162 if(waitpid(master_pid, &return_value, WUNTRACED) < 0)
00163 {
00164 perror("BRender::run waitpid");
00165 }
00166 }
00167
00168
00169
00170
00171 void BRender::restart(EDL *edl)
00172 {
00173
00174 BRenderCommand *new_command = new BRenderCommand;
00175 map_valid = 0;
00176 new_command->copy_edl(edl);
00177 new_command->command = BRenderCommand::BRENDER_RESTART;
00178
00179 thread->send_command(new_command);
00180
00181
00182 }
00183
00184 void BRender::stop()
00185 {
00186
00187 BRenderCommand *new_command = new BRenderCommand;
00188
00189 new_command->command = BRenderCommand::BRENDER_STOP;
00190
00191 thread->send_command(new_command);
00192
00193 completion_lock->lock("BRender::stop");
00194
00195 }
00196
00197
00198
00199 int BRender::get_last_contiguous(int64_t brender_start)
00200 {
00201 int result;
00202 map_lock->lock("BRender::get_last_contiguous");
00203 if(map_valid)
00204 result = last_contiguous;
00205 else
00206 result = brender_start;
00207 map_lock->unlock();
00208 return result;
00209 }
00210
00211 void BRender::allocate_map(int64_t brender_start, int64_t start, int64_t end)
00212 {
00213 map_lock->lock("BRender::allocate_map");
00214 unsigned char *old_map = map;
00215 map = new unsigned char[end];
00216 if(old_map)
00217 {
00218 memcpy(map, old_map, start);
00219 delete [] old_map;
00220 }
00221
00222
00223 bzero(map, brender_start);
00224
00225 bzero(map + start, end - start);
00226
00227 map_size = end;
00228 map_valid = 1;
00229 last_contiguous = start;
00230 mwindow->session->brender_end = (double)last_contiguous /
00231 mwindow->edl->session->frame_rate;
00232 map_lock->unlock();
00233 }
00234
00235 int BRender::set_video_map(int64_t position, int value)
00236 {
00237 int update_gui = 0;
00238 map_lock->lock("BRender::set_video_map");
00239
00240
00241 if(value == BRender::NOT_SCANNED)
00242 {
00243 printf(_("BRender::set_video_map called to set NOT_SCANNED\n"));
00244 }
00245
00246
00247 if(position < 0)
00248 {
00249 ;
00250 }
00251 else
00252
00253 if(position < map_size)
00254 {
00255 map[position] = value;
00256 }
00257 else
00258
00259 {
00260 printf(_("BRender::set_video_map %d: attempt to set beyond end of map %d.\n"),
00261 position,
00262 map_size);
00263 }
00264
00265
00266 if(position == last_contiguous)
00267 {
00268 int i;
00269 for(i = position + 1; i < map_size && map[i]; i++)
00270 {
00271 ;
00272 }
00273 last_contiguous = i;
00274 mwindow->session->brender_end = (double)last_contiguous /
00275 mwindow->edl->session->frame_rate;
00276
00277 if(timer->get_difference() > 1000 || last_contiguous >= map_size)
00278 {
00279 update_gui = 1;
00280 timer->update();
00281 }
00282 }
00283
00284 map_lock->unlock();
00285
00286 if(update_gui)
00287 {
00288 mwindow->gui->lock_window("BRender::set_video_map");
00289 mwindow->gui->timebar->update(1, 0);
00290 mwindow->gui->timebar->flush();
00291 mwindow->gui->unlock_window();
00292 }
00293 return 0;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 BRenderCommand::BRenderCommand()
00310 {
00311 edl = 0;
00312 command = BRENDER_NONE;
00313 position = 0.0;
00314 }
00315
00316 BRenderCommand::~BRenderCommand()
00317 {
00318
00319 if(edl) delete edl;
00320 }
00321
00322 void BRenderCommand::copy_from(BRenderCommand *src)
00323 {
00324 this->edl = src->edl;
00325 src->edl = 0;
00326 this->position = src->position;
00327 this->command = src->command;
00328 }
00329
00330
00331 void BRenderCommand::copy_edl(EDL *edl)
00332 {
00333 this->edl = new EDL;
00334 this->edl->create_objects();
00335 this->edl->copy_all(edl);
00336 this->position = 0;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 BRenderThread::BRenderThread(MWindow *mwindow, BRender *brender)
00351 : Thread(1)
00352 {
00353 this->mwindow = mwindow;
00354 this->brender = brender;
00355 input_lock = new Condition(0, "BRenderThread::input_lock");
00356 thread_lock = new Mutex("BRenderThread::thread_lock");
00357 total_frames_lock = new Mutex("BRenderThread::total_frames_lock");
00358 command_queue = 0;
00359 command = 0;
00360 done = 0;
00361 farm_server = 0;
00362 farm_result = 0;
00363 preferences = 0;
00364 }
00365
00366 BRenderThread::~BRenderThread()
00367 {
00368 thread_lock->lock("BRenderThread::~BRenderThread");
00369 done = 1;
00370 input_lock->unlock();
00371 thread_lock->unlock();
00372 Thread::join();
00373 delete input_lock;
00374 delete thread_lock;
00375 delete total_frames_lock;
00376 if(command) delete command;
00377 if(command_queue) delete command_queue;
00378 if(preferences) delete preferences;
00379 }
00380
00381
00382 void BRenderThread::initialize()
00383 {
00384 Thread::start();
00385 }
00386
00387 void BRenderThread::send_command(BRenderCommand *command)
00388 {
00389 TRACE("BRenderThread::send_command 1");
00390 thread_lock->lock("BRenderThread::send_command");
00391 TRACE("BRenderThread::send_command 10");
00392
00393 if(this->command_queue)
00394 {
00395 delete this->command_queue;
00396 this->command_queue = 0;
00397 }
00398 this->command_queue = command;
00399 TRACE("BRenderThread::send_command 20");
00400
00401
00402 input_lock->unlock();
00403 thread_lock->unlock();
00404 }
00405
00406 int BRenderThread::is_done(int do_lock)
00407 {
00408 if(do_lock) thread_lock->lock("BRenderThread::is_done");
00409 int result = done;
00410 if(do_lock) thread_lock->unlock();
00411 return result;
00412 }
00413
00414 void BRenderThread::run()
00415 {
00416 while(!is_done(1))
00417 {
00418 BRenderCommand *new_command = 0;
00419 thread_lock->lock("BRenderThread::run 1");
00420
00421
00422 if(command_queue)
00423 {
00424 ;
00425 }
00426 else
00427
00428 {
00429 thread_lock->unlock();
00430 input_lock->lock("BRenderThread::run 2");
00431 thread_lock->lock("BRenderThread::run 3");
00432 }
00433
00434
00435 if(!is_done(0))
00436 {
00437 new_command = command_queue;
00438 command_queue = 0;
00439 }
00440
00441 thread_lock->unlock();
00442
00443
00444
00445
00446
00447
00448 if(!new_command)
00449 {
00450 ;
00451 }
00452 else
00453 if(new_command->command == BRenderCommand::BRENDER_STOP)
00454 {
00455 stop();
00456 delete new_command;
00457 new_command = 0;
00458
00459
00460 }
00461 else
00462 if(new_command->command == BRenderCommand::BRENDER_RESTART)
00463 {
00464
00465 if(command && command->edl)
00466 new_command->position =
00467 new_command->edl->equivalent_output(command->edl);
00468 else
00469 new_command->position = 0;
00470
00471
00472 stop();
00473
00474 brender->completion_lock->lock("BRenderThread::run 4");
00475
00476
00477 if(new_command->edl->tracks->total_playable_vtracks())
00478 {
00479 if(command) delete command;
00480 command = new_command;
00481
00482 start();
00483
00484 }
00485 else
00486 {
00487
00488 delete new_command;
00489 new_command = 0;
00490 }
00491 }
00492 }
00493 }
00494
00495 void BRenderThread::stop()
00496 {
00497 if(farm_server)
00498 {
00499 farm_result = 1;
00500 farm_server->wait_clients();
00501 delete farm_server;
00502 delete packages;
00503 delete preferences;
00504 farm_server = 0;
00505 packages = 0;
00506 preferences = 0;
00507 }
00508 brender->completion_lock->unlock();
00509 }
00510
00511 void BRenderThread::start()
00512 {
00513
00514 farm_result = 0;
00515 fps_result = 0;
00516 total_frames = 0;
00517 int result = 0;
00518
00519
00520 if(!farm_server)
00521 {
00522
00523 preferences = new Preferences;
00524 preferences->copy_from(mwindow->preferences);
00525 packages = new PackageDispatcher;
00526
00527
00528 if(!preferences->use_renderfarm)
00529 {
00530 preferences->use_renderfarm = 1;
00531 preferences->delete_nodes();
00532 }
00533 preferences->add_node(brender->socket_path,
00534 0,
00535 1,
00536 preferences->local_rate);
00537
00538 preferences->brender_asset->use_header = 0;
00539 preferences->brender_asset->frame_rate = command->edl->session->frame_rate;
00540 preferences->brender_asset->width = command->edl->session->output_w;
00541 preferences->brender_asset->height = command->edl->session->output_h;
00542 preferences->brender_asset->interlace_mode = command->edl->session->interlace_mode;
00543
00544
00545
00546 int brender_start = (int)(command->edl->session->brender_start *
00547 command->edl->session->frame_rate);
00548 int last_contiguous = brender->last_contiguous;
00549 int last_good = (int)(command->edl->session->frame_rate *
00550 command->position);
00551 if(last_good < 0) last_good = last_contiguous;
00552 int start_frame = MIN(last_contiguous, last_good);
00553 start_frame = MAX(start_frame, brender_start);
00554 int64_t end_frame = Units::round(command->edl->tracks->total_video_length() *
00555 command->edl->session->frame_rate);
00556 if(end_frame < start_frame) end_frame = start_frame;
00557
00558
00559 printf("BRenderThread::start 1 map=%d equivalent=%d brender_start=%d result=%d end=%d\n",
00560 last_contiguous,
00561 last_good,
00562 brender_start,
00563 start_frame,
00564 end_frame);
00565
00566
00567
00568 brender->allocate_map(brender_start, start_frame, end_frame);
00569
00570
00571
00572 result = packages->create_packages(mwindow,
00573 command->edl,
00574 preferences,
00575 BRENDER_FARM,
00576 preferences->brender_asset,
00577 (double)start_frame / command->edl->session->frame_rate,
00578 (double)end_frame / command->edl->session->frame_rate,
00579 0);
00580
00581
00582
00583 farm_server = new RenderFarmServer(mwindow->plugindb,
00584 packages,
00585 preferences,
00586 0,
00587 &farm_result,
00588 &total_frames,
00589 total_frames_lock,
00590 preferences->brender_asset,
00591 command->edl,
00592 brender);
00593
00594
00595
00596 result = farm_server->start_clients();
00597
00598
00599
00600
00601
00602
00603 if(result)
00604 {
00605
00606
00607 delete farm_server;
00608 delete packages;
00609
00610 delete preferences;
00611
00612 farm_server = 0;
00613 packages = 0;
00614 preferences = 0;
00615 }
00616
00617
00618
00619 }
00620 }
00621
00622