4 #include "audiodevice.h"
6 #include "edlsession.h"
8 #include "playbackengine.h"
9 #include "preferences.h"
10 #include "preferencesthread.h"
11 #include "renderengine.h"
12 #include "mainsession.h"
14 #include "transportque.h"
15 #include "videodevice.h"
17 #include "workarounds.h"
21 RenderEngine::RenderEngine(PlaybackEngine *playback_engine,
22 Preferences *preferences,
23 TransportCommand *command,
25 ArrayList<PluginServer*> *plugindb,
26 ArrayList<Channel*> *channeldb,
30 this->playback_engine = playback_engine;
31 this->output = output;
32 this->plugindb = plugindb;
33 this->channeldb = channeldb;
34 this->head_number = head_number;
43 actual_frame_rate = 0;
44 this->preferences = new Preferences;
45 this->command = new TransportCommand;
46 *this->preferences = *preferences;
47 *this->command = *command;
49 edl->create_objects();
50 // EDL only changed in construction.
51 // The EDL contained in later commands is ignored.
52 *this->edl = *command->get_edl();
55 if(playback_engine && playback_engine->mwindow)
56 mwindow = playback_engine->mwindow;
61 RenderEngine::~RenderEngine()
63 //printf("RenderEngine::~RenderEngine 1\n");
65 //printf("RenderEngine::~RenderEngine 2\n");
67 //printf("RenderEngine::~RenderEngine 4\n");
69 //printf("RenderEngine::~RenderEngine 5\n");
70 if(arender) delete arender;
71 //printf("RenderEngine::~RenderEngine 6\n");
72 if(vrender) delete vrender;
74 //printf("RenderEngine::~RenderEngine 7\n");
77 int RenderEngine::arm_command(TransportCommand *command,
78 int ¤t_vchannel,
79 int ¤t_achannel)
81 // Prevent this renderengine from accepting another command until finished.
82 // Since the renderengine is often deleted after the input_lock command it must
83 // be locked here as well as in the calling routine.
89 //printf("RenderEngine::arm_command 1\n");
90 *this->command = *command;
91 //this->command->get_edl()->dump();
92 //printf("RenderEngine::arm_command 2\n");
93 int playback_strategy = command->get_edl()->session->playback_strategy;
94 this->config = command->get_edl()->session->playback_config[playback_strategy].values[head_number];
96 // Fix background rendering asset to use current dimensions and ignore
98 preferences->brender_asset->frame_rate = command->get_edl()->session->frame_rate;
99 preferences->brender_asset->width = command->get_edl()->session->output_w;
100 preferences->brender_asset->height = command->get_edl()->session->output_h;
101 preferences->brender_asset->use_header = 0;
102 preferences->brender_asset->layers = 1;
103 preferences->brender_asset->video_data = 1;
105 //printf("RenderEngine::arm_command 3 %p %p\n", this->edl, command->get_edl());
109 // Retool configuration for this node
110 VideoOutConfig *vconfig = this->config->vconfig;
111 AudioOutConfig *aconfig = this->config->aconfig;
112 if(command->realtime)
114 int device_channels, edl_channels;
115 if(command->single_frame())
117 vconfig->driver = PLAYBACK_X11;
119 edl_channels = command->get_edl()->session->video_channels;
124 for(int i = 0; i < MAX_CHANNELS; i++)
126 vconfig->do_channel[i] =
127 ((i == current_vchannel) &&
131 // GCC 3.2 optimization error causes do_channel[0] to always be 0 unless
133 Workarounds::clamp(vconfig->do_channel[i], 0, 1);
135 //printf("RenderEngine::arm_command 1 %d\n", vconfig->do_channel[0]);
136 if(vconfig->do_channel[i])
144 device_channels = aconfig->total_output_channels();
145 edl_channels = command->get_edl()->session->audio_channels;
146 //printf("RenderEngine::arm_command device_channels=%d\n", device_channels);
147 for(int i = 0; i < MAX_CHANNELS; i++)
150 aconfig->do_channel[i] =
151 (i == current_achannel &&
154 if(aconfig->do_channel[i])
161 // printf("RenderEngine::arm_command current_achannel=%d ", current_achannel);
162 // for(int i = 0; i < MAXCHANNELS; i++)
163 // printf("%d", aconfig->do_channel[i]);
169 this->config->playback_strategy = PLAYBACK_LOCALHOST;
170 vconfig->driver = PLAYBACK_X11;
171 vconfig->playback_strategy = PLAYBACK_LOCALHOST;
172 aconfig->playback_strategy = PLAYBACK_LOCALHOST;
173 for(int i = 0; i < MAX_CHANNELS; i++)
175 vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
176 vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
177 aconfig->do_channel[i] = (i < command->get_edl()->session->audio_channels);
182 //printf("RenderEngine::arm_command %p\n", vconfig);
184 //printf("RenderEngine::arm_command 4 %f %f\n", this->command->playbackstart, command->playbackstart);
190 // Larger of audio_module_fragment and fragment length adjusted for speed
191 // Extra memory must be allocated for rendering slow motion.
192 adjusted_fragment_len = (int64_t)((float)edl->session->audio_module_fragment /
193 command->get_speed() + 0.5);
194 if(adjusted_fragment_len < edl->session->audio_module_fragment)
195 adjusted_fragment_len = edl->session->audio_module_fragment;
198 //printf("RenderEngine::arm_command 5 %d %d\n", do_audio, do_video);
200 //printf("RenderEngine::arm_command 6 %d %d\n", do_audio, do_video);
201 create_render_threads();
202 arm_render_threads();
204 //printf("RenderEngine::arm_command 8\n");
208 void RenderEngine::get_duty()
214 //printf("RenderEngine::get_duty 1 %d %d\n", edl->tracks->playable_audio_tracks(), config->vconfig->total_playable_channels());
215 if(!command->single_frame() &&
216 edl->tracks->playable_audio_tracks() &&
217 config->aconfig->total_playable_channels())
222 //printf("RenderEngine::get_duty 2 %d %d\n", edl->tracks->playable_video_tracks(), config->vconfig->total_playable_channels());
223 if(edl->tracks->playable_video_tracks() &&
224 config->vconfig->total_playable_channels())
230 void RenderEngine::create_render_threads()
232 if(do_video && !vrender)
234 vrender = new VRender(this);
237 if(do_audio && !arender)
239 arender = new ARender(this);
244 int RenderEngine::get_output_w()
246 return edl->calculate_output_w(config->playback_strategy != PLAYBACK_LOCALHOST);
249 int RenderEngine::get_output_h()
251 return edl->calculate_output_h(config->playback_strategy != PLAYBACK_LOCALHOST);
254 int RenderEngine::brender_available(int position, int direction)
258 int64_t corrected_position = position;
259 if(direction == PLAY_REVERSE)
260 corrected_position--;
261 return playback_engine->brender_available(corrected_position);
267 Channel* RenderEngine::get_current_channel()
271 if(config->vconfig->buz_out_channel >= 0 &&
272 config->vconfig->buz_out_channel < channeldb->total)
274 return channeldb->values[config->vconfig->buz_out_channel];
280 CICache* RenderEngine::get_acache()
283 return playback_engine->audio_cache;
288 CICache* RenderEngine::get_vcache()
291 return playback_engine->video_cache;
296 void RenderEngine::set_acache(CICache *cache)
298 this->audio_cache = cache;
301 void RenderEngine::set_vcache(CICache *cache)
303 this->video_cache = cache;
307 double RenderEngine::get_tracking_position()
310 return playback_engine->get_tracking_position();
315 int RenderEngine::open_output()
317 //printf("RenderEngine::open_output 1\n");
318 if(command->realtime)
323 audio = new AudioDevice;
327 video = new VideoDevice;
330 // Initialize sharing
334 if(do_audio && do_video)
336 video->set_adevice(audio);
337 audio->set_vdevice(video);
342 // Retool playback configuration
345 audio->open_output(config->aconfig,
346 edl->session->sample_rate,
347 adjusted_fragment_len,
348 edl->session->real_time_playback);
349 audio->set_software_positioning(edl->session->playback_software_position);
350 audio->start_playback();
355 video->open_output(config->vconfig,
356 edl->session->frame_rate,
360 command->single_frame());
361 //printf("RenderEngine::open_output 1 %d\n", config->vconfig->driver);
362 Channel *channel = get_current_channel();
363 //printf("RenderEngine::open_output 1 %d\n", config->vconfig->driver);
364 if(channel) video->set_channel(channel);
365 //printf("RenderEngine::open_output 1 %d\n", config->vconfig->driver);
366 video->set_quality(80);
367 //printf("RenderEngine::open_output 1 %d\n", edl->session->smp);
368 video->set_cpus(edl->session->smp + 1);
369 //printf("RenderEngine::open_output 2 %d\n", config->vconfig->driver);
372 //printf("RenderEngine::open_output 2\n");
376 int64_t RenderEngine::session_position()
380 return audio->current_position();
385 return (int64_t)((double)vrender->session_frame /
386 edl->session->frame_rate *
387 edl->session->sample_rate /
388 command->get_speed() + 0.5);
392 int64_t RenderEngine::sync_position()
394 switch(edl->session->playback_strategy)
396 case PLAYBACK_LOCALHOST:
397 case PLAYBACK_MULTIHEAD:
399 // No danger of race conditions because the output devices are closed after all
401 //printf("RenderEngine::sync_position 1\n");
404 return audio->current_position();
407 //printf("RenderEngine::sync_position 2\n");
410 return timer.get_scaled_difference(edl->session->sample_rate);
414 case PLAYBACK_BLONDSYMPHONY:
419 PluginServer* RenderEngine::scan_plugindb(char *title)
421 for(int i = 0; i < plugindb->total; i++)
423 if(!strcasecmp(plugindb->values[i]->title, title))
424 return plugindb->values[i];
429 int RenderEngine::start_command()
431 //printf("RenderEngine::start_command 1 %d\n", command->realtime);
432 if(command->realtime)
434 interrupt_lock.lock();
439 //printf("RenderEngine::start_command 2 %p %d\n", this, Thread::get_tid());
444 void RenderEngine::arm_render_threads()
446 //printf("RenderEngine::arm_render_threads 1 %d %d\n", do_audio, do_video);
449 arender->arm_command();
454 //printf("RenderEngine::arm_render_threads 1 %d %d\n", do_audio, do_video);
455 vrender->arm_command();
456 //printf("RenderEngine::arm_render_threads 2 %d %d\n", do_audio, do_video);
461 void RenderEngine::start_render_threads()
463 // Synchronization timer
468 arender->start_command();
473 vrender->start_command();
477 void RenderEngine::update_framerate(float framerate)
479 playback_engine->mwindow->edl->session->actual_frame_rate = framerate;
480 playback_engine->mwindow->preferences_thread->update_framerate();
483 void RenderEngine::wait_render_threads()
487 arender->Thread::join();
489 //printf("RenderEngine::wait_render_threads 1\n");
492 vrender->Thread::join();
494 //printf("RenderEngine::wait_render_threads 2\n");
497 int RenderEngine::wait_for_completion()
504 void RenderEngine::interrupt_playback()
506 //printf("RenderEngine::interrupt_playback 0 %p\n", this);
507 interrupt_lock.lock();
511 //printf("RenderEngine::interrupt_playback 1 %p\n", this);
512 audio->interrupt_playback();
513 //printf("RenderEngine::interrupt_playback 2 %p\n", this);
517 //printf("RenderEngine::interrupt_playback 3 %p\n", this);
518 video->interrupt_playback();
519 //printf("RenderEngine::interrupt_playback 4 %p\n", this);
521 interrupt_lock.unlock();
524 int RenderEngine::close_output()
526 //printf("RenderEngine::close_output 1\n");
529 //printf("RenderEngine::close_output 2\n");
539 //printf("RenderEngine::close_output 1\n");
541 //printf("RenderEngine::close_output 2\n");
543 //printf("RenderEngine::close_output 3\n");
546 //printf("RenderEngine::close_output 4\n");
550 void RenderEngine::get_output_levels(double *levels, int64_t position)
554 int history_entry = arender->get_history_number(arender->level_samples, position);
555 //printf("RenderEngine::get_output_levels %d\n", history_entry);
556 for(int i = 0; i < MAXCHANNELS; i++)
558 if(arender->audio_out[i])
559 levels[i] = arender->level_history[i][history_entry];
564 void RenderEngine::get_module_levels(ArrayList<double> *module_levels, int64_t position)
568 for(int i = 0; i < arender->total_modules; i++)
570 //printf("RenderEngine::get_module_levels %p %p\n", ((AModule*)arender->modules[i]), ((AModule*)arender->modules[i])->level_samples);
571 int history_entry = arender->get_history_number(((AModule*)arender->modules[i])->level_samples, position);
573 module_levels->append(((AModule*)arender->modules[i])->level_history[history_entry]);
582 void RenderEngine::run()
584 //printf("RenderEngine::run 1 %p\n", this);
585 start_render_threads();
587 interrupt_lock.unlock();
589 //printf("RenderEngine::run 2\n");
590 wait_render_threads();
591 //printf("RenderEngine::run 3\n");
593 interrupt_lock.lock();
594 //printf("RenderEngine::run 4\n");
597 //printf("RenderEngine::run 5\n");
601 playback_engine->tracking_position = playback_engine->get_tracking_position();
603 //printf("RenderEngine::run 6\n");
606 //printf("RenderEngine::run 7\n");
608 // Fix the tracking position
611 if(command->command == CURRENT_FRAME)
613 //printf("RenderEngine::run 4.1 %d\n", playback_engine->tracking_position);
614 playback_engine->tracking_position = command->playbackstart;
618 // Make sure transport doesn't issue a pause command next
619 //printf("RenderEngine::run 4.1 %d\n", playback_engine->tracking_position);
623 playback_engine->tracking_position =
624 (double)arender->current_position /
625 command->get_edl()->session->sample_rate;
629 playback_engine->tracking_position =
630 (double)vrender->current_position /
631 command->get_edl()->session->frame_rate;
635 if(!interrupted) playback_engine->command->command = STOP;
636 //printf("RenderEngine::run 8\n");
637 playback_engine->stop_tracking();
639 //printf("RenderEngine::run 9\n");
641 playback_engine->is_playing_back = 0;
644 //printf("RenderEngine::run 10\n");
646 //printf("RenderEngine::run 6\n");
647 interrupt_lock.unlock();
648 //printf("RenderEngine::run 7 %p\n", this);
675 int RenderEngine::reset_parameters()
689 int RenderEngine::arm_playback_common(int64_t start_sample,
691 int64_t current_sample,
697 this->follow_loop = follow_loop;
698 this->start_position = start_sample;
699 this->end_position = end_sample;
700 this->reverse = reverse;
701 this->infinite = infinite;
702 this->current_sample = current_sample;
703 if(infinite) this->follow_loop = 0;
706 int RenderEngine::arm_playback_audio(int64_t input_length,
707 int64_t amodule_render_fragment,
708 int64_t playback_buffer,
709 int64_t output_length,
712 this->audio_channels = audio_channels;
716 arender = new ARender(this);
717 arender->arm_playback(current_sample,
719 amodule_render_fragment,
724 int RenderEngine::arm_playback_video(int every_frame,
726 int64_t output_length,
733 this->every_frame = every_frame;
735 vrender = new VRender(this);
736 // vrender->arm_playback(current_sample,
746 int RenderEngine::start_video()
748 // start video for realtime
749 if(video) video->start_playback();
750 vrender->start_playback();
754 int64_t RenderEngine::get_correction_factor(int reset)
759 // x = playbackengine->correction_factor;
760 // if(reset) playbackengine->correction_factor = 0;
767 int RenderEngine::wait_for_startup()
769 if(do_audio) arender->wait_for_startup();
770 if(do_video) vrender->wait_for_startup();