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

playbackengine.C

Go to the documentation of this file.
00001 #include "cache.h"
00002 #include "condition.h"
00003 #include "defaults.h"
00004 #include "edl.h"
00005 #include "edlsession.h"
00006 #include "localsession.h"
00007 #include "mbuttons.h"
00008 #include "mutex.h"
00009 #include "mwindow.h"
00010 #include "mwindowgui.h"
00011 #include "patchbay.h"
00012 #include "tracking.h"
00013 #include "playbackengine.h"
00014 #include "playtransport.h"
00015 #include "preferences.h"
00016 #include "renderengine.h"
00017 #include "mainsession.h"
00018 #include "trackcanvas.h"
00019 #include "transportque.h"
00020 #include "videodevice.h"
00021 #include "vrender.h"
00022 
00023 
00024 PlaybackEngine::PlaybackEngine(MWindow *mwindow, Canvas *output)
00025  : Thread(1, 0, 0)
00026 {
00027         this->mwindow = mwindow;
00028         this->output = output;
00029         is_playing_back = 0;
00030         tracking_position = 0;
00031         tracking_active = 0;
00032         audio_cache = 0;
00033         video_cache = 0;
00034         last_command = STOP;
00035         tracking_lock = new Mutex("PlaybackEngine::tracking_lock");
00036         tracking_done = new Condition(1, "PlaybackEngine::tracking_done");
00037         pause_lock = new Condition(0, "PlaybackEngine::pause_lock");
00038         start_lock = new Condition(0, "PlaybackEngine::start_lock");
00039         render_engine = 0;
00040         debug = 0;
00041 }
00042 
00043 PlaybackEngine::~PlaybackEngine()
00044 {
00045         done = 1;
00046         que->send_command(STOP,
00047                 CHANGE_NONE, 
00048                 0,
00049                 0);
00050         interrupt_playback();
00051 
00052         Thread::join();
00053         delete preferences;
00054         delete command;
00055         delete que;
00056         delete_render_engine();
00057         delete audio_cache;
00058         delete video_cache;
00059         delete tracking_lock;
00060         delete tracking_done;
00061         delete pause_lock;
00062         delete start_lock;
00063 }
00064 
00065 int PlaybackEngine::create_objects()
00066 {
00067         int result = 0;
00068         preferences = new Preferences;
00069         command = new TransportCommand;
00070         que = new TransportQue;
00071 // Set the first change to maximum
00072         que->command.change_type = CHANGE_ALL;
00073 
00074         preferences->copy_from(mwindow->preferences);
00075 
00076         done = 0;
00077         Thread::start();
00078         start_lock->lock("PlaybackEngine::create_objects");
00079         return result;
00080 }
00081 
00082 ChannelDB* PlaybackEngine::get_channeldb()
00083 {
00084         PlaybackConfig *config = command->get_edl()->session->playback_config;
00085         switch(config->vconfig->driver)
00086         {
00087                 case VIDEO4LINUX2JPEG:
00088                         return mwindow->channeldb_v4l2jpeg;
00089                         break;
00090                 case PLAYBACK_BUZ:
00091                         return mwindow->channeldb_buz;
00092                         break;
00093         }
00094         return 0;
00095 }
00096 
00097 int PlaybackEngine::create_render_engine()
00098 {
00099 // Fix playback configurations
00100         int current_vchannel = 0;
00101         int current_achannel = 0;
00102 
00103         delete_render_engine();
00104 
00105 
00106         render_engine = new RenderEngine(this,
00107                 preferences, 
00108                 command, 
00109                 output,
00110                 mwindow->plugindb,
00111                 get_channeldb());  
00112         return 0;
00113 }
00114 
00115 void PlaybackEngine::delete_render_engine()
00116 {
00117         delete render_engine;
00118         render_engine = 0;
00119 }
00120 
00121 void PlaybackEngine::arm_render_engine()
00122 {
00123         int current_achannel = 0, current_vchannel = 0;
00124         if(render_engine)
00125                 render_engine->arm_command(command,
00126                         current_achannel,
00127                         current_vchannel);
00128 }
00129 
00130 void PlaybackEngine::start_render_engine()
00131 {
00132         if(render_engine) render_engine->start_command();
00133 }
00134 
00135 void PlaybackEngine::wait_render_engine()
00136 {
00137         if(command->realtime && render_engine)
00138         {
00139                 render_engine->join();
00140         }
00141 }
00142 
00143 void PlaybackEngine::create_cache()
00144 {
00145         if(audio_cache) delete audio_cache;
00146         audio_cache = 0;
00147         if(video_cache) delete video_cache;
00148         video_cache = 0;
00149         if(!audio_cache) 
00150                 audio_cache = new CICache(command->get_edl(), preferences, mwindow->plugindb);
00151         else
00152                 audio_cache->set_edl(command->get_edl());
00153 
00154         if(!video_cache) 
00155                 video_cache = new CICache(command->get_edl(), preferences, mwindow->plugindb);
00156         else
00157                 video_cache->set_edl(command->get_edl());
00158 }
00159 
00160 
00161 void PlaybackEngine::perform_change()
00162 {
00163         switch(command->change_type)
00164         {
00165                 case CHANGE_ALL:
00166                         create_cache();
00167                 case CHANGE_EDL:
00168                         audio_cache->set_edl(command->get_edl());
00169                         video_cache->set_edl(command->get_edl());
00170                         create_render_engine();
00171                 case CHANGE_PARAMS:
00172                         if(command->change_type != CHANGE_EDL &&
00173                                 command->change_type != CHANGE_ALL)
00174                                 render_engine->edl->synchronize_params(command->get_edl());
00175                 case CHANGE_NONE:
00176                         break;
00177         }
00178 }
00179 
00180 void PlaybackEngine::sync_parameters(EDL *edl)
00181 {
00182 // TODO: lock out render engine from keyframe deletions
00183         command->get_edl()->synchronize_params(edl);
00184         if(render_engine) render_engine->edl->synchronize_params(edl);
00185 }
00186 
00187 
00188 void PlaybackEngine::interrupt_playback(int wait_tracking)
00189 {
00190         if(render_engine)
00191                 render_engine->interrupt_playback();
00192 
00193 // Stop pausing
00194         pause_lock->unlock();
00195 
00196 // Wait for tracking to finish if it is running
00197         if(wait_tracking)
00198         {
00199                 tracking_done->lock("PlaybackEngine::interrupt_playback");
00200                 tracking_done->unlock();
00201         }
00202 }
00203 
00204 
00205 // Return 1 if levels exist
00206 int PlaybackEngine::get_output_levels(double *levels, long position)
00207 {
00208         int result = 0;
00209         if(render_engine && render_engine->do_audio)
00210         {
00211                 result = 1;
00212                 render_engine->get_output_levels(levels, position);
00213         }
00214         return result;
00215 }
00216 
00217 
00218 int PlaybackEngine::get_module_levels(ArrayList<double> *module_levels, long position)
00219 {
00220         int result = 0;
00221         if(render_engine && render_engine->do_audio)
00222         {
00223                 result = 1;
00224                 render_engine->get_module_levels(module_levels, position);
00225         }
00226         return result;
00227 }
00228 
00229 int PlaybackEngine::brender_available(long position)
00230 {
00231         return 0;
00232 }
00233 
00234 void PlaybackEngine::init_cursor()
00235 {
00236 }
00237 
00238 void PlaybackEngine::stop_cursor()
00239 {
00240 }
00241 
00242 
00243 void PlaybackEngine::init_tracking()
00244 {
00245         if(!command->single_frame()) 
00246                 tracking_active = 1;
00247         else
00248                 tracking_active = 0;
00249 
00250         tracking_position = command->playbackstart;
00251         tracking_done->lock("PlaybackEngine::init_tracking");
00252         init_cursor();
00253 }
00254 
00255 void PlaybackEngine::stop_tracking()
00256 {
00257         tracking_active = 0;
00258         stop_cursor();
00259         tracking_done->unlock();
00260 }
00261 
00262 void PlaybackEngine::update_tracking(double position)
00263 {
00264         tracking_lock->lock("PlaybackEngine::update_tracking");
00265 
00266         tracking_position = position;
00267 
00268 // Signal that the timer is accurate.
00269         if(tracking_active) tracking_active = 2;
00270         tracking_timer.update();
00271         tracking_lock->unlock();
00272 }
00273 
00274 double PlaybackEngine::get_tracking_position()
00275 {
00276         double result = 0;
00277 
00278         tracking_lock->lock("PlaybackEngine::get_tracking_position");
00279 
00280 
00281 // Adjust for elapsed time since last update_tracking.
00282 // But tracking timer isn't accurate until the first update_tracking
00283 // so wait.
00284         if(tracking_active == 2)
00285         {
00286 //printf("PlaybackEngine::get_tracking_position %d %d %d\n", command->get_direction(), tracking_position, tracking_timer.get_scaled_difference(command->get_edl()->session->sample_rate));
00287 
00288 
00289 // Don't interpolate when every frame is played.
00290                 if(command->get_edl()->session->video_every_frame &&
00291                         render_engine &&
00292                         render_engine->do_video)
00293                 {
00294                         result = tracking_position;
00295                 }
00296                 else
00297 // Interpolate
00298                 {
00299                         double loop_start = command->get_edl()->local_session->loop_start;
00300                         double loop_end = command->get_edl()->local_session->loop_end;
00301                         double loop_size = loop_end - loop_start;
00302 
00303                         if(command->get_direction() == PLAY_FORWARD)
00304                         {
00305 // Interpolate
00306                                 result = tracking_position + 
00307                                         command->get_speed() * 
00308                                         tracking_timer.get_difference() /
00309                                         1000.0;
00310 
00311 // Compensate for loop
00312 //printf("PlaybackEngine::get_tracking_position 1 %d\n", command->get_edl()->local_session->loop_playback);
00313                                 if(command->get_edl()->local_session->loop_playback)
00314                                 {
00315                                         while(result > loop_end) result -= loop_size;
00316                                 }
00317                         }
00318                         else
00319                         {
00320 // Interpolate
00321                                 result = tracking_position - 
00322                                         command->get_speed() * 
00323                                         tracking_timer.get_difference() /
00324                                         1000.0;
00325 
00326 // Compensate for loop
00327                                 if(command->get_edl()->local_session->loop_playback)
00328                                 {
00329                                         while(result < loop_start) result += loop_size;
00330                                 }
00331                         }
00332 
00333                 }
00334         }
00335         else
00336                 result = tracking_position;
00337 
00338         tracking_lock->unlock();
00339 //printf("PlaybackEngine::get_tracking_position %f %f %d\n", result, tracking_position, tracking_active);
00340 
00341 // Adjust for loop
00342 
00343         return result;
00344 }
00345 
00346 void PlaybackEngine::update_transport(int command, int paused)
00347 {
00348 //      mwindow->gui->lock_window();
00349 //      mwindow->gui->mbuttons->transport->update_gui_state(command, paused);
00350 //      mwindow->gui->unlock_window();
00351 }
00352 
00353 void PlaybackEngine::run()
00354 {
00355         start_lock->unlock();
00356 
00357         do
00358         {
00359 // Wait for current command to finish
00360                 que->output_lock->lock("PlaybackEngine::run");
00361 
00362 //printf("PlaybackEngine::run 1\n");
00363                 wait_render_engine();
00364 //printf("PlaybackEngine::run 2\n");
00365 
00366 
00367 // Read the new command
00368                 que->input_lock->lock("PlaybackEngine::run");
00369                 if(done) return;
00370 
00371                 command->copy_from(&que->command);
00372                 que->command.reset();
00373                 que->input_lock->unlock();
00374 
00375 
00376 
00377                 switch(command->command)
00378                 {
00379 // Parameter change only
00380                         case COMMAND_NONE:
00381 //                              command->command = last_command;
00382                                 perform_change();
00383                                 break;
00384 
00385                         case PAUSE:
00386                                 init_cursor();
00387                                 pause_lock->lock("PlaybackEngine::run");
00388                                 stop_cursor();
00389                                 break;
00390 
00391                         case STOP:
00392 // No changing
00393                                 break;
00394 
00395                         case CURRENT_FRAME:
00396                                 last_command = command->command;
00397                                 perform_change();
00398                                 arm_render_engine();
00399 // Dispatch the command
00400                                 start_render_engine();
00401                                 break;
00402 
00403                         default:
00404                                 last_command = command->command;
00405                                 is_playing_back = 1;
00406                                 if(command->command == SINGLE_FRAME_FWD ||
00407                                         command->command == SINGLE_FRAME_REWIND)
00408                                 {
00409                                         command->playbackstart = get_tracking_position();
00410                                 }
00411 
00412                                 perform_change();
00413                                 arm_render_engine();
00414 
00415 // Start tracking after arming so the tracking position doesn't change.
00416 // The tracking for a single frame command occurs during PAUSE
00417                                 init_tracking();
00418 
00419 // Dispatch the command
00420                                 start_render_engine();
00421                                 break;
00422                 }
00423 
00424 
00425 //printf("PlaybackEngine::run 100\n");
00426         }while(!done);
00427 }
00428 
00429 
00430 

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