00001 #include "amodule.h"
00002 #include "arender.h"
00003 #include "asset.h"
00004 #include "audiodevice.h"
00005 #include "bcsignals.h"
00006 #include "channeldb.h"
00007 #include "condition.h"
00008 #include "edl.h"
00009 #include "edlsession.h"
00010 #include "mutex.h"
00011 #include "mwindow.h"
00012 #include "playbackengine.h"
00013 #include "preferences.h"
00014 #include "preferencesthread.h"
00015 #include "renderengine.h"
00016 #include "mainsession.h"
00017 #include "tracks.h"
00018 #include "transportque.h"
00019 #include "videodevice.h"
00020 #include "vrender.h"
00021 #include "workarounds.h"
00022
00023
00024
00025 RenderEngine::RenderEngine(PlaybackEngine *playback_engine,
00026 Preferences *preferences,
00027 TransportCommand *command,
00028 Canvas *output,
00029 ArrayList<PluginServer*> *plugindb,
00030 ChannelDB *channeldb)
00031 : Thread(1, 0, 0)
00032 {
00033 this->playback_engine = playback_engine;
00034 this->output = output;
00035 this->plugindb = plugindb;
00036 this->channeldb = channeldb;
00037 audio = 0;
00038 video = 0;
00039 config = new PlaybackConfig;
00040 arender = 0;
00041 vrender = 0;
00042 do_audio = 0;
00043 do_video = 0;
00044 interrupted = 0;
00045 actual_frame_rate = 0;
00046 this->preferences = new Preferences;
00047 this->command = new TransportCommand;
00048 this->preferences->copy_from(preferences);
00049 this->command->copy_from(command);
00050 edl = new EDL;
00051 edl->create_objects();
00052
00053
00054 edl->copy_all(command->get_edl());
00055 audio_cache = 0;
00056 video_cache = 0;
00057 if(playback_engine && playback_engine->mwindow)
00058 mwindow = playback_engine->mwindow;
00059 else
00060 mwindow = 0;
00061 show_tc = 0;
00062
00063
00064 input_lock = new Condition(1, "RenderEngine::input_lock");
00065 start_lock = new Condition(1, "RenderEngine::start_lock");
00066 output_lock = new Condition(1, "RenderEngine::output_lock");
00067 interrupt_lock = new Mutex("RenderEngine::interrupt_lock");
00068 first_frame_lock = new Condition(1, "RenderEngine::first_frame_lock");
00069 reset_parameters();
00070 }
00071
00072 RenderEngine::~RenderEngine()
00073 {
00074 close_output();
00075 delete command;
00076 delete preferences;
00077 if(arender) delete arender;
00078 if(vrender) delete vrender;
00079 delete edl;
00080 delete input_lock;
00081 delete start_lock;
00082 delete output_lock;
00083 delete interrupt_lock;
00084 delete first_frame_lock;
00085 delete config;
00086 }
00087
00088 int RenderEngine::arm_command(TransportCommand *command,
00089 int ¤t_vchannel,
00090 int ¤t_achannel)
00091 {
00092
00093
00094
00095
00096
00097 input_lock->lock("RenderEngine::arm_command");
00098
00099
00100 this->command->copy_from(command);
00101
00102
00103
00104 preferences->brender_asset->frame_rate = command->get_edl()->session->frame_rate;
00105 preferences->brender_asset->width = command->get_edl()->session->output_w;
00106 preferences->brender_asset->height = command->get_edl()->session->output_h;
00107 preferences->brender_asset->use_header = 0;
00108 preferences->brender_asset->layers = 1;
00109 preferences->brender_asset->video_data = 1;
00110
00111 done = 0;
00112 interrupted = 0;
00113
00114
00115 this->config->copy_from(command->get_edl()->session->playback_config);
00116 VideoOutConfig *vconfig = this->config->vconfig;
00117 AudioOutConfig *aconfig = this->config->aconfig;
00118 if(command->realtime)
00119 {
00120 if(command->single_frame() && vconfig->driver != PLAYBACK_X11_GL)
00121 {
00122 vconfig->driver = PLAYBACK_X11;
00123 }
00124 }
00125 else
00126 {
00127 vconfig->driver = PLAYBACK_X11;
00128 }
00129
00130
00131
00132 get_duty();
00133
00134 if(do_audio)
00135 {
00136 fragment_len = aconfig->fragment_size;
00137
00138
00139 adjusted_fragment_len = (int64_t)((float)aconfig->fragment_size /
00140 command->get_speed() + 0.5);
00141 if(adjusted_fragment_len < aconfig->fragment_size)
00142 adjusted_fragment_len = aconfig->fragment_size;
00143 }
00144
00145
00146 if(do_video)
00147 {
00148 while(first_frame_lock->get_value() > 0)
00149 first_frame_lock->lock("RenderEngine::arm_command");
00150 }
00151 else
00152
00153 {
00154 while(first_frame_lock->get_value() <= 0)
00155 first_frame_lock->unlock();
00156 }
00157
00158 open_output();
00159 create_render_threads();
00160 arm_render_threads();
00161
00162 return 0;
00163 }
00164
00165 void RenderEngine::get_duty()
00166 {
00167 do_audio = 0;
00168 do_video = 0;
00169
00170
00171 if(!command->single_frame() &&
00172 edl->tracks->playable_audio_tracks() &&
00173 edl->session->audio_channels)
00174 {
00175 do_audio = 1;
00176 }
00177
00178 if(edl->tracks->playable_video_tracks())
00179 {
00180 do_video = 1;
00181 }
00182 }
00183
00184 void RenderEngine::create_render_threads()
00185 {
00186 if(do_video && !vrender)
00187 {
00188 vrender = new VRender(this);
00189 }
00190
00191 if(do_audio && !arender)
00192 {
00193 arender = new ARender(this);
00194 }
00195 }
00196
00197
00198 int RenderEngine::get_output_w()
00199 {
00200 return edl->session->output_w;
00201 }
00202
00203 int RenderEngine::get_output_h()
00204 {
00205 return edl->session->output_h;
00206 }
00207
00208 int RenderEngine::brender_available(int position, int direction)
00209 {
00210 if(playback_engine)
00211 {
00212 int64_t corrected_position = position;
00213 if(direction == PLAY_REVERSE)
00214 corrected_position--;
00215 return playback_engine->brender_available(corrected_position);
00216 }
00217 else
00218 return 0;
00219 }
00220
00221 Channel* RenderEngine::get_current_channel()
00222 {
00223 if(channeldb)
00224 {
00225 switch(config->vconfig->driver)
00226 {
00227 case PLAYBACK_BUZ:
00228 if(config->vconfig->buz_out_channel >= 0 &&
00229 config->vconfig->buz_out_channel < channeldb->size())
00230 {
00231 return channeldb->get(config->vconfig->buz_out_channel);
00232 }
00233 break;
00234 case VIDEO4LINUX2JPEG:
00235
00236 break;
00237 }
00238 }
00239 return 0;
00240 }
00241
00242 CICache* RenderEngine::get_acache()
00243 {
00244 if(playback_engine)
00245 return playback_engine->audio_cache;
00246 else
00247 return audio_cache;
00248 }
00249
00250 CICache* RenderEngine::get_vcache()
00251 {
00252 if(playback_engine)
00253 return playback_engine->video_cache;
00254 else
00255 return video_cache;
00256 }
00257
00258 void RenderEngine::set_acache(CICache *cache)
00259 {
00260 this->audio_cache = cache;
00261 }
00262
00263 void RenderEngine::set_vcache(CICache *cache)
00264 {
00265 this->video_cache = cache;
00266 }
00267
00268
00269 double RenderEngine::get_tracking_position()
00270 {
00271 if(playback_engine)
00272 return playback_engine->get_tracking_position();
00273 else
00274 return 0;
00275 }
00276
00277 int RenderEngine::open_output()
00278 {
00279 if(command->realtime)
00280 {
00281
00282 if(do_audio)
00283 {
00284 audio = new AudioDevice;
00285 if (audio->open_output(config->aconfig,
00286 edl->session->sample_rate,
00287 adjusted_fragment_len,
00288 edl->session->audio_channels,
00289 edl->session->real_time_playback))
00290 {
00291 do_audio = 0;
00292 delete audio;
00293 audio = 0;
00294 }
00295 }
00296
00297 if(do_video)
00298 {
00299 video = new VideoDevice;
00300 }
00301
00302
00303
00304
00305
00306 if(do_audio && do_video)
00307 {
00308 video->set_adevice(audio);
00309 audio->set_vdevice(video);
00310 }
00311
00312
00313
00314
00315 if(do_audio)
00316 {
00317 audio->set_software_positioning(edl->session->playback_software_position);
00318 audio->start_playback();
00319 }
00320
00321 if(do_video)
00322 {
00323 video->open_output(config->vconfig,
00324 edl->session->frame_rate,
00325 get_output_w(),
00326 get_output_h(),
00327 output,
00328 command->single_frame());
00329 Channel *channel = get_current_channel();
00330 if(channel) video->set_channel(channel);
00331 video->set_quality(80);
00332 video->set_cpus(preferences->processors);
00333 }
00334 }
00335
00336 return 0;
00337 }
00338
00339 int64_t RenderEngine::session_position()
00340 {
00341 if(do_audio)
00342 {
00343 return audio->current_position();
00344 }
00345
00346 if(do_video)
00347 {
00348 return (int64_t)((double)vrender->session_frame /
00349 edl->session->frame_rate *
00350 edl->session->sample_rate /
00351 command->get_speed() + 0.5);
00352 }
00353 }
00354
00355 void RenderEngine::reset_sync_position()
00356 {
00357 timer.update();
00358 }
00359
00360 int64_t RenderEngine::sync_position()
00361 {
00362
00363
00364
00365 if(do_audio)
00366 {
00367 return audio->current_position();
00368 }
00369
00370 if(do_video)
00371 {
00372 int64_t result = timer.get_scaled_difference(
00373 edl->session->sample_rate);
00374 return result;
00375 }
00376 }
00377
00378 PluginServer* RenderEngine::scan_plugindb(char *title,
00379 int data_type)
00380 {
00381 for(int i = 0; i < plugindb->total; i++)
00382 {
00383 PluginServer *server = plugindb->values[i];
00384 if(!strcasecmp(server->title, title) &&
00385 ((data_type == TRACK_AUDIO && server->audio) ||
00386 (data_type == TRACK_VIDEO && server->video)))
00387 return plugindb->values[i];
00388 }
00389 return 0;
00390 }
00391
00392 int RenderEngine::start_command()
00393 {
00394 if(command->realtime)
00395 {
00396 interrupt_lock->lock("RenderEngine::start_command");
00397 start_lock->lock("RenderEngine::start_command 1");
00398 Thread::start();
00399 start_lock->lock("RenderEngine::start_command 2");
00400 start_lock->unlock();
00401 }
00402 return 0;
00403 }
00404
00405 void RenderEngine::arm_render_threads()
00406 {
00407 if(do_audio)
00408 {
00409 arender->arm_command();
00410 }
00411
00412 if(do_video)
00413 {
00414 vrender->arm_command();
00415 }
00416 }
00417
00418
00419 void RenderEngine::start_render_threads()
00420 {
00421
00422 timer.update();
00423
00424 if(do_audio)
00425 {
00426 arender->start_command();
00427 }
00428
00429 if(do_video)
00430 {
00431 vrender->start_command();
00432 }
00433 }
00434
00435 void RenderEngine::update_framerate(float framerate)
00436 {
00437 playback_engine->mwindow->edl->session->actual_frame_rate = framerate;
00438 playback_engine->mwindow->preferences_thread->update_framerate();
00439 }
00440
00441 void RenderEngine::wait_render_threads()
00442 {
00443 if(do_audio)
00444 {
00445 arender->Thread::join();
00446 }
00447
00448 if(do_video)
00449 {
00450 vrender->Thread::join();
00451 }
00452 }
00453
00454 void RenderEngine::interrupt_playback()
00455 {
00456 interrupt_lock->lock("RenderEngine::interrupt_playback");
00457 interrupted = 1;
00458 if(audio)
00459 {
00460 audio->interrupt_playback();
00461 }
00462 if(video)
00463 {
00464
00465 video->interrupt_playback();
00466
00467 }
00468 interrupt_lock->unlock();
00469 }
00470
00471 int RenderEngine::close_output()
00472 {
00473 if(audio)
00474 {
00475 audio->close_all();
00476 delete audio;
00477 audio = 0;
00478 }
00479
00480
00481
00482 if(video)
00483 {
00484 video->close_all();
00485 delete video;
00486 video = 0;
00487 }
00488 return 0;
00489 }
00490
00491 void RenderEngine::get_output_levels(double *levels, int64_t position)
00492 {
00493 if(do_audio)
00494 {
00495 int history_entry = arender->get_history_number(arender->level_samples,
00496 position);
00497 for(int i = 0; i < MAXCHANNELS; i++)
00498 {
00499 if(arender->audio_out[i])
00500 levels[i] = arender->level_history[i][history_entry];
00501 }
00502 }
00503 }
00504
00505 void RenderEngine::get_module_levels(ArrayList<double> *module_levels, int64_t position)
00506 {
00507 if(do_audio)
00508 {
00509 for(int i = 0; i < arender->total_modules; i++)
00510 {
00511
00512 int history_entry = arender->get_history_number(((AModule*)arender->modules[i])->level_samples, position);
00513
00514 module_levels->append(((AModule*)arender->modules[i])->level_history[history_entry]);
00515 }
00516 }
00517 }
00518
00519
00520
00521
00522
00523 void RenderEngine::run()
00524 {
00525 start_render_threads();
00526 start_lock->unlock();
00527 interrupt_lock->unlock();
00528
00529 wait_render_threads();
00530
00531 interrupt_lock->lock("RenderEngine::run");
00532
00533
00534 if(interrupted)
00535 {
00536 playback_engine->tracking_position = playback_engine->get_tracking_position();
00537 }
00538
00539 close_output();
00540
00541
00542 if(playback_engine)
00543 {
00544 if(command->command == CURRENT_FRAME)
00545 {
00546
00547 playback_engine->tracking_position = command->playbackstart;
00548 }
00549 else
00550 {
00551
00552
00553 if(!interrupted)
00554 {
00555 if(do_audio)
00556 playback_engine->tracking_position =
00557 (double)arender->current_position /
00558 command->get_edl()->session->sample_rate;
00559 else
00560 if(do_video)
00561 {
00562 playback_engine->tracking_position =
00563 (double)vrender->current_position /
00564 command->get_edl()->session->frame_rate;
00565 }
00566 }
00567
00568 if(!interrupted) playback_engine->command->command = STOP;
00569 playback_engine->stop_tracking();
00570
00571 }
00572 playback_engine->is_playing_back = 0;
00573 }
00574
00575 input_lock->unlock();
00576 interrupt_lock->unlock();
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 int RenderEngine::reset_parameters()
00604 {
00605 start_position = 0;
00606 follow_loop = 0;
00607 end_position = 0;
00608 infinite = 0;
00609 start_position = 0;
00610 do_audio = 0;
00611 do_video = 0;
00612 done = 0;
00613 }
00614
00615 int RenderEngine::arm_playback_audio(int64_t input_length,
00616 int64_t amodule_render_fragment,
00617 int64_t playback_buffer,
00618 int64_t output_length)
00619 {
00620
00621 do_audio = 1;
00622
00623 arender = new ARender(this);
00624 arender->arm_playback(current_sample,
00625 input_length,
00626 amodule_render_fragment,
00627 playback_buffer,
00628 output_length);
00629 }
00630
00631 int RenderEngine::arm_playback_video(int every_frame,
00632 int64_t read_length,
00633 int64_t output_length,
00634 int track_w,
00635 int track_h,
00636 int output_w,
00637 int output_h)
00638 {
00639 do_video = 1;
00640 this->every_frame = every_frame;
00641
00642 vrender = new VRender(this);
00643
00644
00645
00646
00647
00648
00649
00650
00651 }
00652
00653 int RenderEngine::start_video()
00654 {
00655
00656 if(video) video->start_playback();
00657 vrender->start_playback();
00658 }
00659
00660
00661 int64_t RenderEngine::get_correction_factor(int reset)
00662 {
00663 if(!every_frame)
00664 {
00665 int64_t x;
00666
00667
00668 return x;
00669 }
00670 else
00671 return 0;
00672 }
00673