Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

brender.C

Go to the documentation of this file.
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 // Create socket for background process.
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 // Start background instance of executable since codecs aren't reentrant
00110         Thread::start();
00111 
00112 // Wait for local node to start
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 //printf("BRender::run 1 %d\n", getpid());
00123 
00124 
00125 // Construct executable command with the designated filesystem port
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 //printf("BRender::fork_background 1 %s\n", socket_path);
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 //printf("BRender::fork_background 1 %d\n", master_pid);
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 // Give the last position of the EDL which hasn't changed.
00169 // We copy the EDL and restart rendering at the lesser of position and
00170 // our position.
00171 void BRender::restart(EDL *edl)
00172 {
00173 //printf("BRender::restart 1\n");
00174         BRenderCommand *new_command = new BRenderCommand;
00175         map_valid = 0;
00176         new_command->copy_edl(edl);
00177         new_command->command = BRenderCommand::BRENDER_RESTART;
00178 //printf("BRender::restart 2\n");
00179         thread->send_command(new_command);
00180 //printf("BRender::restart 3\n");
00181 // Map should be reallocated before this returns.
00182 }
00183 
00184 void BRender::stop()
00185 {
00186 //printf("BRender::stop 1\n");
00187         BRenderCommand *new_command = new BRenderCommand;
00188 //printf("BRender::stop 1\n");
00189         new_command->command = BRenderCommand::BRENDER_STOP;
00190 //printf("BRender::stop 1\n");
00191         thread->send_command(new_command);
00192 //printf("BRender::stop 1\n");
00193         completion_lock->lock("BRender::stop");
00194 //printf("BRender::stop 2\n");
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 // Zero all before brender start
00223         bzero(map, brender_start);
00224 // Zero all after current start
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 // Preroll
00247         if(position < 0)
00248         {
00249                 ;
00250         }
00251         else
00252 // In range
00253         if(position < map_size)
00254         {
00255                 map[position] = value;
00256         }
00257         else
00258 // Obsolete EDL
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 // Maintain last contiguous here to reduce search time
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 // EDL should be zeroed if copied
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 // Got new command
00422                 if(command_queue)
00423                 {
00424                         ;
00425                 }
00426                 else
00427 // Wait for new command
00428                 {
00429                         thread_lock->unlock();
00430                         input_lock->lock("BRenderThread::run 2");
00431                         thread_lock->lock("BRenderThread::run 3");
00432                 }
00433 
00434 // Pull the command off
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 // Process the command here to avoid delay.
00447 // Quit condition
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 //                      if(command) delete command;
00459 //                      command = new_command;
00460                 }
00461                 else
00462                 if(new_command->command == BRenderCommand::BRENDER_RESTART)
00463                 {
00464 // Compare EDL's and get last equivalent position in new EDL
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 //printf("BRenderThread::run 4\n");
00474                         brender->completion_lock->lock("BRenderThread::run 4");
00475 //printf("BRenderThread::run 5\n");
00476 
00477                         if(new_command->edl->tracks->total_playable_vtracks())
00478                         {
00479                                 if(command) delete command;
00480                                 command = new_command;
00481 //printf("BRenderThread::run 6\n");
00482                                 start();
00483 //printf("BRenderThread::run 7\n");
00484                         }
00485                         else
00486                         {
00487 //printf("BRenderThread::run 8 %p\n", farm_server);
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 // Reset return parameters
00514         farm_result = 0;
00515         fps_result = 0;
00516         total_frames = 0;
00517         int result = 0;
00518 
00519 // Allocate render farm.
00520         if(!farm_server)
00521         {
00522 //printf("BRenderThread::start 1\n");
00523                 preferences = new Preferences;
00524                 preferences->copy_from(mwindow->preferences);
00525                 packages = new PackageDispatcher;
00526 
00527 // Fix preferences to use local node
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 //printf("BRenderThread::start 1 %s\n", brender->socket_path);
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 // Get last contiguous and reset map.
00545 // If the framerate changes, last good should be 0 from the user.
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 //sleep(1);
00567 
00568                 brender->allocate_map(brender_start, start_frame, end_frame);
00569 //sleep(1);
00570 //printf("BRenderThread::start 2\n");
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 //sleep(1);
00582 //printf("BRenderThread::start 3 %d\n", result);
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 //sleep(1);
00595 //printf("BRenderThread::start 4\n");
00596                 result = farm_server->start_clients();
00597 
00598 //sleep(1);
00599 // No local rendering because of codec problems.
00600 
00601 
00602 // Abort
00603                 if(result)
00604                 {
00605 // No-one must be retrieving a package when packages are deleted.
00606 //printf("BRenderThread::start 7 %p\n", farm_server);
00607                         delete farm_server;
00608                         delete packages;
00609 //printf("BRenderThread::start 8 %p\n", preferences);
00610                         delete preferences;
00611 //printf("BRenderThread::start 9\n");
00612                         farm_server = 0;
00613                         packages = 0;
00614                         preferences = 0;
00615                 }
00616 //sleep(1);
00617 //printf("BRenderThread::start 10\n");
00618 
00619         }
00620 }
00621 
00622 

Generated on Sun Jan 8 13:38:50 2006 for Cinelerra-svn by  doxygen 1.4.4