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