4 #include "audiodevice.h"
9 #include "edlsession.h"
12 #include "playbackengine.h"
13 #include "preferences.h"
14 #include "preferencesthread.h"
15 #include "renderengine.h"
16 #include "mainsession.h"
18 #include "transportque.h"
19 #include "videodevice.h"
21 #include "workarounds.h"
25 RenderEngine::RenderEngine(PlaybackEngine *playback_engine,
26 Preferences *preferences,
27 TransportCommand *command,
29 ArrayList<PluginServer*> *plugindb,
33 this->playback_engine = playback_engine;
34 this->output = output;
35 this->plugindb = plugindb;
36 this->channeldb = channeldb;
39 config = new PlaybackConfig;
45 actual_frame_rate = 0;
46 this->preferences = new Preferences;
47 this->command = new TransportCommand;
48 this->preferences->copy_from(preferences);
49 this->command->copy_from(command);
51 edl->create_objects();
52 // EDL only changed in construction.
53 // The EDL contained in later commands is ignored.
54 edl->copy_all(command->get_edl());
57 if(playback_engine && playback_engine->mwindow)
58 mwindow = playback_engine->mwindow;
64 input_lock = new Condition(1, "RenderEngine::input_lock");
65 start_lock = new Condition(1, "RenderEngine::start_lock");
66 output_lock = new Condition(1, "RenderEngine::output_lock");
67 interrupt_lock = new Mutex("RenderEngine::interrupt_lock");
68 first_frame_lock = new Condition(1, "RenderEngine::first_frame_lock");
72 RenderEngine::~RenderEngine()
77 if(arender) delete arender;
78 if(vrender) delete vrender;
83 delete interrupt_lock;
84 delete first_frame_lock;
88 int RenderEngine::arm_command(TransportCommand *command,
89 int ¤t_vchannel,
90 int ¤t_achannel)
92 // Prevent this renderengine from accepting another command until finished.
93 // Since the renderengine is often deleted after the input_lock command it must
94 // be locked here as well as in the calling routine.
97 input_lock->lock("RenderEngine::arm_command");
100 this->command->copy_from(command);
102 // Fix background rendering asset to use current dimensions and ignore
104 preferences->brender_asset->frame_rate = command->get_edl()->session->frame_rate;
105 preferences->brender_asset->width = command->get_edl()->session->output_w;
106 preferences->brender_asset->height = command->get_edl()->session->output_h;
107 preferences->brender_asset->use_header = 0;
108 preferences->brender_asset->layers = 1;
109 preferences->brender_asset->video_data = 1;
114 // Retool configuration for this node
115 this->config->copy_from(command->get_edl()->session->playback_config);
116 VideoOutConfig *vconfig = this->config->vconfig;
117 AudioOutConfig *aconfig = this->config->aconfig;
118 if(command->realtime)
120 if(command->single_frame() && vconfig->driver != PLAYBACK_X11_GL)
122 vconfig->driver = PLAYBACK_X11;
127 vconfig->driver = PLAYBACK_X11;
136 fragment_len = aconfig->fragment_size;
137 // Larger of audio_module_fragment and fragment length adjusted for speed
138 // Extra memory must be allocated for rendering slow motion.
139 adjusted_fragment_len = (int64_t)((float)aconfig->fragment_size /
140 command->get_speed() + 0.5);
141 if(adjusted_fragment_len < aconfig->fragment_size)
142 adjusted_fragment_len = aconfig->fragment_size;
145 // Set lock so audio doesn't start until video has started.
148 while(first_frame_lock->get_value() > 0)
149 first_frame_lock->lock("RenderEngine::arm_command");
152 // Set lock so audio doesn't wait for video which is never to come.
154 while(first_frame_lock->get_value() <= 0)
155 first_frame_lock->unlock();
159 create_render_threads();
160 arm_render_threads();
165 void RenderEngine::get_duty()
171 if(!command->single_frame() &&
172 edl->tracks->playable_audio_tracks() &&
173 edl->session->audio_channels)
178 if(edl->tracks->playable_video_tracks())
184 void RenderEngine::create_render_threads()
186 if(do_video && !vrender)
188 vrender = new VRender(this);
191 if(do_audio && !arender)
193 arender = new ARender(this);
198 int RenderEngine::get_output_w()
200 return edl->session->output_w;
203 int RenderEngine::get_output_h()
205 return edl->session->output_h;
208 int RenderEngine::brender_available(int position, int direction)
212 int64_t corrected_position = position;
213 if(direction == PLAY_REVERSE)
214 corrected_position--;
215 return playback_engine->brender_available(corrected_position);
221 Channel* RenderEngine::get_current_channel()
225 switch(config->vconfig->driver)
228 if(config->vconfig->buz_out_channel >= 0 &&
229 config->vconfig->buz_out_channel < channeldb->size())
231 return channeldb->get(config->vconfig->buz_out_channel);
234 case VIDEO4LINUX2JPEG:
242 CICache* RenderEngine::get_acache()
245 return playback_engine->audio_cache;
250 CICache* RenderEngine::get_vcache()
253 return playback_engine->video_cache;
258 void RenderEngine::set_acache(CICache *cache)
260 this->audio_cache = cache;
263 void RenderEngine::set_vcache(CICache *cache)
265 this->video_cache = cache;
269 double RenderEngine::get_tracking_position()
272 return playback_engine->get_tracking_position();
277 int RenderEngine::open_output()
279 if(command->realtime)
284 audio = new AudioDevice;
285 if (audio->open_output(config->aconfig,
286 edl->session->sample_rate,
287 adjusted_fragment_len,
288 edl->session->audio_channels,
289 edl->session->real_time_playback))
299 video = new VideoDevice;
302 // Initialize sharing
306 if(do_audio && do_video)
308 video->set_adevice(audio);
309 audio->set_vdevice(video);
314 // Retool playback configuration
317 audio->set_software_positioning(edl->session->playback_software_position);
318 audio->start_playback();
323 video->open_output(config->vconfig,
324 edl->session->frame_rate,
328 command->single_frame());
329 Channel *channel = get_current_channel();
330 if(channel) video->set_channel(channel);
331 video->set_quality(80);
332 video->set_cpus(preferences->processors);
339 int64_t RenderEngine::session_position()
343 return audio->current_position();
348 return (int64_t)((double)vrender->session_frame /
349 edl->session->frame_rate *
350 edl->session->sample_rate /
351 command->get_speed() + 0.5);
355 void RenderEngine::reset_sync_position()
360 int64_t RenderEngine::sync_position()
363 // No danger of race conditions because the output devices are closed after all
367 return audio->current_position();
372 int64_t result = timer.get_scaled_difference(
373 edl->session->sample_rate);
378 PluginServer* RenderEngine::scan_plugindb(char *title,
381 for(int i = 0; i < plugindb->total; i++)
383 PluginServer *server = plugindb->values[i];
384 if(!strcasecmp(server->title, title) &&
385 ((data_type == TRACK_AUDIO && server->audio) ||
386 (data_type == TRACK_VIDEO && server->video)))
387 return plugindb->values[i];
392 int RenderEngine::start_command()
394 if(command->realtime)
396 interrupt_lock->lock("RenderEngine::start_command");
397 start_lock->lock("RenderEngine::start_command 1");
399 start_lock->lock("RenderEngine::start_command 2");
400 start_lock->unlock();
405 void RenderEngine::arm_render_threads()
409 arender->arm_command();
414 vrender->arm_command();
419 void RenderEngine::start_render_threads()
421 // Synchronization timer. Gets reset once again after the first video frame.
426 arender->start_command();
431 vrender->start_command();
435 void RenderEngine::update_framerate(float framerate)
437 playback_engine->mwindow->edl->session->actual_frame_rate = framerate;
438 playback_engine->mwindow->preferences_thread->update_framerate();
441 void RenderEngine::wait_render_threads()
445 arender->Thread::join();
450 vrender->Thread::join();
454 void RenderEngine::interrupt_playback()
456 interrupt_lock->lock("RenderEngine::interrupt_playback");
460 audio->interrupt_playback();
464 //printf("RenderEngine::interrupt_playback 3 %p\n", this);
465 video->interrupt_playback();
466 //printf("RenderEngine::interrupt_playback 4 %p\n", this);
468 interrupt_lock->unlock();
471 int RenderEngine::close_output()
491 void RenderEngine::get_output_levels(double *levels, int64_t position)
495 int history_entry = arender->get_history_number(arender->level_samples,
497 for(int i = 0; i < MAXCHANNELS; i++)
499 if(arender->audio_out[i])
500 levels[i] = arender->level_history[i][history_entry];
505 void RenderEngine::get_module_levels(ArrayList<double> *module_levels, int64_t position)
509 for(int i = 0; i < arender->total_modules; i++)
511 //printf("RenderEngine::get_module_levels %p %p\n", ((AModule*)arender->modules[i]), ((AModule*)arender->modules[i])->level_samples);
512 int history_entry = arender->get_history_number(((AModule*)arender->modules[i])->level_samples, position);
514 module_levels->append(((AModule*)arender->modules[i])->level_history[history_entry]);
523 void RenderEngine::run()
525 start_render_threads();
526 start_lock->unlock();
527 interrupt_lock->unlock();
529 wait_render_threads();
531 interrupt_lock->lock("RenderEngine::run");
536 playback_engine->tracking_position = playback_engine->get_tracking_position();
541 // Fix the tracking position
544 if(command->command == CURRENT_FRAME)
546 //printf("RenderEngine::run 4.1 %d\n", playback_engine->tracking_position);
547 playback_engine->tracking_position = command->playbackstart;
551 // Make sure transport doesn't issue a pause command next
552 //printf("RenderEngine::run 4.1 %d\n", playback_engine->tracking_position);
556 playback_engine->tracking_position =
557 (double)arender->current_position /
558 command->get_edl()->session->sample_rate;
562 playback_engine->tracking_position =
563 (double)vrender->current_position /
564 command->get_edl()->session->frame_rate;
568 if(!interrupted) playback_engine->command->command = STOP;
569 playback_engine->stop_tracking();
572 playback_engine->is_playing_back = 0;
575 input_lock->unlock();
576 interrupt_lock->unlock();
603 int RenderEngine::reset_parameters()
615 int RenderEngine::arm_playback_audio(int64_t input_length,
616 int64_t amodule_render_fragment,
617 int64_t playback_buffer,
618 int64_t output_length)
623 arender = new ARender(this);
624 arender->arm_playback(current_sample,
626 amodule_render_fragment,
631 int RenderEngine::arm_playback_video(int every_frame,
633 int64_t output_length,
640 this->every_frame = every_frame;
642 vrender = new VRender(this);
643 // vrender->arm_playback(current_sample,
653 int RenderEngine::start_video()
655 // start video for realtime
656 if(video) video->start_playback();
657 vrender->start_playback();
661 int64_t RenderEngine::get_correction_factor(int reset)
666 // x = playbackengine->correction_factor;
667 // if(reset) playbackengine->correction_factor = 0;
677 // c-file-style: "linux"