4 #include "audiodevice.h"
8 #include "edlsession.h"
11 #include "playbackengine.h"
12 #include "preferences.h"
13 #include "preferencesthread.h"
14 #include "renderengine.h"
15 #include "mainsession.h"
17 #include "transportque.h"
18 #include "videodevice.h"
20 #include "workarounds.h"
24 RenderEngine::RenderEngine(PlaybackEngine *playback_engine,
25 Preferences *preferences,
26 TransportCommand *command,
28 ArrayList<PluginServer*> *plugindb,
32 this->playback_engine = playback_engine;
33 this->output = output;
34 this->plugindb = plugindb;
35 this->channeldb = channeldb;
38 config = new PlaybackConfig;
44 actual_frame_rate = 0;
45 this->preferences = new Preferences;
46 this->command = new TransportCommand;
47 this->preferences->copy_from(preferences);
48 this->command->copy_from(command);
50 edl->create_objects();
51 // EDL only changed in construction.
52 // The EDL contained in later commands is ignored.
53 edl->copy_all(command->get_edl());
56 if(playback_engine && playback_engine->mwindow)
57 mwindow = playback_engine->mwindow;
61 input_lock = new Condition(1, "RenderEngine::input_lock");
62 start_lock = new Condition(1, "RenderEngine::start_lock");
63 output_lock = new Condition(1, "RenderEngine::output_lock");
64 interrupt_lock = new Mutex("RenderEngine::interrupt_lock");
65 first_frame_lock = new Condition(1, "RenderEngine::first_frame_lock");
68 RenderEngine::~RenderEngine()
73 if(arender) delete arender;
74 if(vrender) delete vrender;
79 delete interrupt_lock;
80 delete first_frame_lock;
84 int RenderEngine::arm_command(TransportCommand *command,
85 int ¤t_vchannel,
86 int ¤t_achannel)
88 // Prevent this renderengine from accepting another command until finished.
89 // Since the renderengine is often deleted after the input_lock command it must
90 // be locked here as well as in the calling routine.
93 input_lock->lock("RenderEngine::arm_command");
96 this->command->copy_from(command);
98 // Fix background rendering asset to use current dimensions and ignore
100 preferences->brender_asset->frame_rate = command->get_edl()->session->frame_rate;
101 preferences->brender_asset->width = command->get_edl()->session->output_w;
102 preferences->brender_asset->height = command->get_edl()->session->output_h;
103 preferences->brender_asset->use_header = 0;
104 preferences->brender_asset->layers = 1;
105 preferences->brender_asset->video_data = 1;
110 // Retool configuration for this node
111 this->config->copy_from(command->get_edl()->session->playback_config);
112 VideoOutConfig *vconfig = this->config->vconfig;
113 AudioOutConfig *aconfig = this->config->aconfig;
114 if(command->realtime)
116 int device_channels = 0;
117 int edl_channels = 0;
118 if(command->single_frame())
120 vconfig->driver = PLAYBACK_X11;
122 edl_channels = command->get_edl()->session->video_channels;
127 edl_channels = command->get_edl()->session->video_channels;
130 for(int i = 0; i < MAX_CHANNELS; i++)
132 vconfig->do_channel[i] =
133 ((i == current_vchannel) &&
137 // GCC 3.2 optimization error causes do_channel[0] to always be 0 unless
139 Workarounds::clamp(vconfig->do_channel[i], 0, 1);
141 if(vconfig->do_channel[i])
149 device_channels = aconfig->total_output_channels();
150 edl_channels = command->get_edl()->session->audio_channels;
152 for(int i = 0; i < MAX_CHANNELS; i++)
155 aconfig->do_channel[i] =
156 (i == current_achannel &&
159 if(aconfig->do_channel[i])
170 vconfig->driver = PLAYBACK_X11;
171 for(int i = 0; i < MAX_CHANNELS; i++)
173 vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
174 vconfig->do_channel[i] = (i < command->get_edl()->session->video_channels);
175 aconfig->do_channel[i] = (i < command->get_edl()->session->audio_channels);
185 fragment_len = aconfig->fragment_size;
186 // Larger of audio_module_fragment and fragment length adjusted for speed
187 // Extra memory must be allocated for rendering slow motion.
188 adjusted_fragment_len = (int64_t)((float)aconfig->fragment_size /
189 command->get_speed() + 0.5);
190 if(adjusted_fragment_len < aconfig->fragment_size)
191 adjusted_fragment_len = aconfig->fragment_size;
194 // Set lock so audio doesn't start until video has started.
197 while(first_frame_lock->get_value() > 0)
198 first_frame_lock->lock("RenderEngine::arm_command");
201 // Set lock so audio doesn't wait for video which is never to come.
203 while(first_frame_lock->get_value() <= 0)
204 first_frame_lock->unlock();
208 create_render_threads();
209 arm_render_threads();
214 void RenderEngine::get_duty()
220 //printf("RenderEngine::get_duty 1 %d %d\n", edl->tracks->playable_audio_tracks(), config->vconfig->total_playable_channels());
221 if(!command->single_frame() &&
222 edl->tracks->playable_audio_tracks() &&
223 config->aconfig->total_playable_channels())
228 //printf("RenderEngine::get_duty 2 %d %d\n", edl->tracks->playable_video_tracks(), config->vconfig->total_playable_channels());
229 if(edl->tracks->playable_video_tracks() &&
230 config->vconfig->total_playable_channels())
236 void RenderEngine::create_render_threads()
238 if(do_video && !vrender)
240 vrender = new VRender(this);
243 if(do_audio && !arender)
245 arender = new ARender(this);
250 int RenderEngine::get_output_w()
252 return edl->calculate_output_w(1);
255 int RenderEngine::get_output_h()
257 return edl->calculate_output_h(1);
260 int RenderEngine::brender_available(int position, int direction)
264 int64_t corrected_position = position;
265 if(direction == PLAY_REVERSE)
266 corrected_position--;
267 return playback_engine->brender_available(corrected_position);
273 Channel* RenderEngine::get_current_channel()
277 switch(config->vconfig->driver)
280 if(config->vconfig->buz_out_channel >= 0 &&
281 config->vconfig->buz_out_channel < channeldb->size())
283 return channeldb->get(config->vconfig->buz_out_channel);
286 case VIDEO4LINUX2JPEG:
294 CICache* RenderEngine::get_acache()
297 return playback_engine->audio_cache;
302 CICache* RenderEngine::get_vcache()
305 return playback_engine->video_cache;
310 void RenderEngine::set_acache(CICache *cache)
312 this->audio_cache = cache;
315 void RenderEngine::set_vcache(CICache *cache)
317 this->video_cache = cache;
321 double RenderEngine::get_tracking_position()
324 return playback_engine->get_tracking_position();
329 int RenderEngine::open_output()
331 //printf("RenderEngine::open_output 1\n");
332 if(command->realtime)
337 audio = new AudioDevice;
342 video = new VideoDevice;
345 // Initialize sharing
349 if(do_audio && do_video)
351 video->set_adevice(audio);
352 audio->set_vdevice(video);
357 // Retool playback configuration
360 audio->open_output(config->aconfig,
361 edl->session->sample_rate,
362 adjusted_fragment_len,
363 edl->session->real_time_playback);
364 audio->set_software_positioning(edl->session->playback_software_position);
365 audio->start_playback();
370 video->open_output(config->vconfig,
371 edl->session->frame_rate,
375 command->single_frame());
376 Channel *channel = get_current_channel();
377 if(channel) video->set_channel(channel);
378 video->set_quality(80);
379 video->set_cpus(preferences->processors);
386 int64_t RenderEngine::session_position()
390 return audio->current_position();
395 return (int64_t)((double)vrender->session_frame /
396 edl->session->frame_rate *
397 edl->session->sample_rate /
398 command->get_speed() + 0.5);
402 void RenderEngine::reset_sync_position()
407 int64_t RenderEngine::sync_position()
410 // No danger of race conditions because the output devices are closed after all
414 return audio->current_position();
419 int64_t result = timer.get_scaled_difference(
420 edl->session->sample_rate);
425 PluginServer* RenderEngine::scan_plugindb(char *title,
428 for(int i = 0; i < plugindb->total; i++)
430 PluginServer *server = plugindb->values[i];
431 if(!strcasecmp(server->title, title) &&
432 ((data_type == TRACK_AUDIO && server->audio) ||
433 (data_type == TRACK_VIDEO && server->video)))
434 return plugindb->values[i];
439 int RenderEngine::start_command()
441 if(command->realtime)
443 interrupt_lock->lock("RenderEngine::start_command");
444 start_lock->lock("RenderEngine::start_command 1");
446 start_lock->lock("RenderEngine::start_command 2");
447 start_lock->unlock();
452 void RenderEngine::arm_render_threads()
456 arender->arm_command();
461 vrender->arm_command();
466 void RenderEngine::start_render_threads()
468 // Synchronization timer. Gets reset once again after the first video frame.
473 arender->start_command();
478 vrender->start_command();
482 void RenderEngine::update_framerate(float framerate)
484 playback_engine->mwindow->edl->session->actual_frame_rate = framerate;
485 playback_engine->mwindow->preferences_thread->update_framerate();
488 void RenderEngine::wait_render_threads()
492 arender->Thread::join();
496 vrender->Thread::join();
500 void RenderEngine::interrupt_playback()
502 interrupt_lock->lock("RenderEngine::interrupt_playback");
506 audio->interrupt_playback();
510 //printf("RenderEngine::interrupt_playback 3 %p\n", this);
511 video->interrupt_playback();
512 //printf("RenderEngine::interrupt_playback 4 %p\n", this);
514 interrupt_lock->unlock();
517 int RenderEngine::close_output()
519 //printf("RenderEngine::close_output 1\n");
522 //printf("RenderEngine::close_output 2\n");
532 //printf("RenderEngine::close_output 1\n");
534 //printf("RenderEngine::close_output 2\n");
536 //printf("RenderEngine::close_output 3\n");
539 //printf("RenderEngine::close_output 4\n");
543 void RenderEngine::get_output_levels(double *levels, int64_t position)
547 int history_entry = arender->get_history_number(arender->level_samples, position);
548 //printf("RenderEngine::get_output_levels %d\n", history_entry);
549 for(int i = 0; i < MAXCHANNELS; i++)
551 if(arender->audio_out[i])
552 levels[i] = arender->level_history[i][history_entry];
557 void RenderEngine::get_module_levels(ArrayList<double> *module_levels, int64_t position)
561 for(int i = 0; i < arender->total_modules; i++)
563 //printf("RenderEngine::get_module_levels %p %p\n", ((AModule*)arender->modules[i]), ((AModule*)arender->modules[i])->level_samples);
564 int history_entry = arender->get_history_number(((AModule*)arender->modules[i])->level_samples, position);
566 module_levels->append(((AModule*)arender->modules[i])->level_history[history_entry]);
575 void RenderEngine::run()
577 start_render_threads();
578 start_lock->unlock();
579 interrupt_lock->unlock();
581 wait_render_threads();
583 interrupt_lock->lock("RenderEngine::run");
588 playback_engine->tracking_position = playback_engine->get_tracking_position();
593 // Fix the tracking position
596 if(command->command == CURRENT_FRAME)
598 //printf("RenderEngine::run 4.1 %d\n", playback_engine->tracking_position);
599 playback_engine->tracking_position = command->playbackstart;
603 // Make sure transport doesn't issue a pause command next
604 //printf("RenderEngine::run 4.1 %d\n", playback_engine->tracking_position);
608 playback_engine->tracking_position =
609 (double)arender->current_position /
610 command->get_edl()->session->sample_rate;
614 playback_engine->tracking_position =
615 (double)vrender->current_position /
616 command->get_edl()->session->frame_rate;
620 if(!interrupted) playback_engine->command->command = STOP;
621 playback_engine->stop_tracking();
624 playback_engine->is_playing_back = 0;
627 input_lock->unlock();
628 interrupt_lock->unlock();
655 int RenderEngine::reset_parameters()
669 int RenderEngine::arm_playback_common(int64_t start_sample,
671 int64_t current_sample,
677 this->follow_loop = follow_loop;
678 this->start_position = start_sample;
679 this->end_position = end_sample;
680 this->reverse = reverse;
681 this->infinite = infinite;
682 this->current_sample = current_sample;
683 if(infinite) this->follow_loop = 0;
686 int RenderEngine::arm_playback_audio(int64_t input_length,
687 int64_t amodule_render_fragment,
688 int64_t playback_buffer,
689 int64_t output_length,
692 this->audio_channels = audio_channels;
696 arender = new ARender(this);
697 arender->arm_playback(current_sample,
699 amodule_render_fragment,
704 int RenderEngine::arm_playback_video(int every_frame,
706 int64_t output_length,
713 this->every_frame = every_frame;
715 vrender = new VRender(this);
716 // vrender->arm_playback(current_sample,
726 int RenderEngine::start_video()
728 // start video for realtime
729 if(video) video->start_playback();
730 vrender->start_playback();
734 int64_t RenderEngine::get_correction_factor(int reset)
739 // x = playbackengine->correction_factor;
740 // if(reset) playbackengine->correction_factor = 0;