00001 #ifndef BRENDER_H 00002 #define BRENDER_H 00003 00004 00005 00006 // The master node of the background renderer needs a separate memory space 00007 // because few of the codecs are reentrant. 00008 00009 // To solve the problem, the master node forks itself and treats the forked 00010 // master node as the first node of a renderfarm. There is no real master node 00011 // of the renderfarm. The BRender object is a thread in order to 00012 // join the forked master node. 00013 00014 // If renderfarm is enabled, the extra renderfarm nodes are treated normally. 00015 // Unfortunately because of the codec problem, only one copy of Cinelerra 00016 // can be running on a single renderfarm. This means either background 00017 // rendering or foreground rendering can be happening but not both. 00018 00019 // A BRenderThread client runs in the background and a BRender object 00020 // interfaces the main window. The BRender client recieves commands to 00021 // restart, start, and stop background rendering on its own time to avoid 00022 // interrupting the main window. 00023 00024 // Whenever a change happens to the timeline, we calculate the last position 00025 // which hasn't changed and the end of the contiguous renderfarm output. 00026 // Then we restart the background renderfarm at the 00027 // lesser of the positions. You can't conditionally restart only 00028 // if one of the current jobs was after the position because you need a new EDL. 00029 00030 // The two problems to emerge are which job is the last job in the contiguous 00031 // set of finished jobs and if position of change is before the last job, 00032 // how to truncate and restart the output file. 00033 00034 // It's easy to use image sequences as the output file to solve the 00035 // file truncation problem. 00036 // Figuring out the end of the contiguous output means recording the 00037 // state of every output file and constructing a kind of EDL for the 00038 // background output as certain output files cluster together. 00039 // This is needed anyway for playback. 00040 00041 #include "arraylist.h" 00042 #include "bcwindowbase.inc" 00043 #include "brender.inc" 00044 #include "condition.inc" 00045 #include "edl.inc" 00046 #include "mutex.inc" 00047 #include "mwindow.inc" 00048 #include "packagedispatcher.inc" 00049 #include "preferences.inc" 00050 #include "renderfarm.inc" 00051 #include "thread.h" 00052 #include "bctimer.inc" 00053 00054 00055 00056 00057 00058 00059 00060 class BRender : public Thread 00061 { 00062 public: 00063 BRender(MWindow *mwindow); 00064 ~BRender(); 00065 00066 // Give the last position of the EDL which hasn't changed. 00067 // We copy the EDL and restart rendering at the lesser of position and 00068 // our position. 00069 void restart(EDL *edl); 00070 // Stop background rendering for a foreground render. This blocks until 00071 // it really stops. 00072 void stop(); 00073 00074 00075 // Get last contiguous frame from map, with locking. 00076 // Only needed by BRenderThread::start but nothing really uses it. 00077 int get_last_contiguous(int64_t brender_start); 00078 // Allocate map with locking 00079 void allocate_map(int64_t brender_start, int64_t start, int64_t end); 00080 // Mark a frame as finished 00081 int set_video_map(int64_t position, int value); 00082 00083 void initialize(); 00084 void run(); 00085 00086 00087 00088 MWindow *mwindow; 00089 00090 00091 00092 00093 // Simple map of finished chunks 00094 unsigned char *map; 00095 int64_t map_size; 00096 Mutex *map_lock; 00097 00098 // Status of each map entry. This way we get the last contiguous as well as the 00099 // ones which are actually rendered. 00100 enum 00101 { 00102 NOT_SCANNED, 00103 SCANNED, 00104 RENDERED 00105 }; 00106 00107 // Invalidate the map until reallocation when a new edit operation is performed. 00108 int map_valid; 00109 00110 // Constantly recalculate this after every frame instead of searching 00111 int last_contiguous; 00112 00113 // Wait until stop commands are finished 00114 Condition *completion_lock; 00115 BRenderThread *thread; 00116 // PID of master node for killing. 00117 int master_pid; 00118 // Path of socket 00119 char socket_path[BCTEXTLEN]; 00120 // Arguments for execvp 00121 char *arguments[4]; 00122 Timer *timer; 00123 }; 00124 00125 class BRenderCommand 00126 { 00127 public: 00128 BRenderCommand(); 00129 ~BRenderCommand(); 00130 00131 // Transfers EDL pointer but doesn't create a new EDL. 00132 void copy_from(BRenderCommand *command); 00133 // Make new EDL 00134 void copy_edl(EDL *edl); 00135 00136 EDL *edl; 00137 enum 00138 { 00139 BRENDER_NONE, 00140 BRENDER_RESTART, 00141 BRENDER_STOP 00142 }; 00143 int command; 00144 // The location of the last change. 00145 double position; 00146 // The earliest point to include in background rendering would be stored in the 00147 // EDL. 00148 }; 00149 00150 class BRenderThread : public Thread 00151 { 00152 public: 00153 BRenderThread(MWindow *mwindow, BRender *brender); 00154 ~BRenderThread(); 00155 00156 int is_done(int do_lock); 00157 void send_command(BRenderCommand *command); 00158 void run(); 00159 void stop(); 00160 void start(); 00161 void initialize(); 00162 00163 MWindow *mwindow; 00164 BRender *brender; 00165 BRenderCommand *command_queue; 00166 BRenderCommand *command; 00167 Condition *input_lock; 00168 Mutex *thread_lock; 00169 // Render farm server. Deleted when stopped. Created when restarted. 00170 RenderFarmServer *farm_server; 00171 PackageDispatcher *packages; 00172 // Copy of preferences with modified render farm. 00173 Preferences *preferences; 00174 // Render farm polls these. 00175 int farm_result; 00176 double fps_result; 00177 // Not used 00178 int64_t total_frames; 00179 Mutex *total_frames_lock; 00180 int done; 00181 }; 00182 00183 00184 00185 00186 00187 00188 00189 #endif
1.4.4