X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.0%2Fcinelerra%2Frenderengine.C;fp=cinelerra-5.0%2Fcinelerra%2Frenderengine.C;h=0000000000000000000000000000000000000000;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hp=a77168c473801369a1a42dd2db2c3ab6045e5116;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.0/cinelerra/renderengine.C b/cinelerra-5.0/cinelerra/renderengine.C deleted file mode 100644 index a77168c4..00000000 --- a/cinelerra-5.0/cinelerra/renderengine.C +++ /dev/null @@ -1,584 +0,0 @@ - -/* - * CINELERRA - * Copyright (C) 2009 Adam Williams - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "amodule.h" -#include "arender.h" -#include "asset.h" -#include "audiodevice.h" -#include "bcsignals.h" -#include "channeldb.h" -#include "condition.h" -#include "edl.h" -#include "edlsession.h" -#include "mutex.h" -#include "mwindow.h" -#include "playbackengine.h" -#include "preferences.h" -#include "preferencesthread.h" -#include "renderengine.h" -#include "mainsession.h" -#include "tracks.h" -#include "transportque.h" -#include "videodevice.h" -#include "vrender.h" -#include "workarounds.h" - - - -RenderEngine::RenderEngine(PlaybackEngine *playback_engine, - Preferences *preferences, - Canvas *output, - ChannelDB *channeldb, - int is_nested) - : Thread(1, 0, 0) -{ - this->playback_engine = playback_engine; - this->output = output; - this->channeldb = channeldb; - this->is_nested = is_nested; - audio = 0; - video = 0; - config = new PlaybackConfig; - arender = 0; - vrender = 0; - do_audio = 0; - do_video = 0; - interrupted = 0; - this->preferences = new Preferences; - this->command = new TransportCommand; - this->preferences->copy_from(preferences); - edl = 0; - - audio_cache = 0; - video_cache = 0; - if(playback_engine && playback_engine->mwindow) - mwindow = playback_engine->mwindow; - else - mwindow = 0; - - input_lock = new Condition(1, "RenderEngine::input_lock"); - start_lock = new Condition(1, "RenderEngine::start_lock"); - output_lock = new Condition(1, "RenderEngine::output_lock"); - interrupt_lock = new Mutex("RenderEngine::interrupt_lock"); - first_frame_lock = new Condition(1, "RenderEngine::first_frame_lock"); -} - -RenderEngine::~RenderEngine() -{ - close_output(); - delete command; - delete preferences; - if(arender) delete arender; - if(vrender) delete vrender; - delete input_lock; - delete start_lock; - delete output_lock; - delete interrupt_lock; - delete first_frame_lock; - delete config; - edl->Garbage::remove_user(); -} - -EDL* RenderEngine::get_edl() -{ -// return command->get_edl(); - return edl; -} - -int RenderEngine::arm_command(TransportCommand *command) -{ - const int debug = 0; -// Prevent this renderengine from accepting another command until finished. -// Since the renderengine is often deleted after the input_lock command it must -// be locked here as well as in the calling routine. - if(debug) printf("RenderEngine::arm_command %d\n", __LINE__); - - - input_lock->lock("RenderEngine::arm_command"); - - if(!edl) - { - edl = new EDL; - edl->create_objects(); - edl->copy_all(command->get_edl()); - } - this->command->copy_from(command); - -// Fix background rendering asset to use current dimensions and ignore -// headers. - preferences->brender_asset->frame_rate = command->get_edl()->session->frame_rate; - preferences->brender_asset->width = command->get_edl()->session->output_w; - preferences->brender_asset->height = command->get_edl()->session->output_h; - preferences->brender_asset->use_header = 0; - preferences->brender_asset->layers = 1; - preferences->brender_asset->video_data = 1; - - done = 0; - interrupted = 0; - -// Retool configuration for this node - this->config->copy_from(command->get_edl()->session->playback_config); - VideoOutConfig *vconfig = this->config->vconfig; - AudioOutConfig *aconfig = this->config->aconfig; - if(command->realtime) - { - if(command->single_frame() && vconfig->driver != PLAYBACK_X11_GL) - { - vconfig->driver = PLAYBACK_X11; - } - } - else - { - vconfig->driver = PLAYBACK_X11; - } - - - - get_duty(); - - if(do_audio) - { - fragment_len = aconfig->fragment_size; -// Larger of audio_module_fragment and fragment length adjusted for speed -// Extra memory must be allocated for rendering slow motion. - float speed = command->get_speed(); - adjusted_fragment_len = speed >= 1.0 ? - (int64_t)(aconfig->fragment_size * speed + 0.5) : - (int64_t)(aconfig->fragment_size / speed + 0.5) ; - if(adjusted_fragment_len < aconfig->fragment_size) - adjusted_fragment_len = aconfig->fragment_size; - } - -// Set lock so audio doesn't start until video has started. - if(do_video) - { - while(first_frame_lock->get_value() > 0) - first_frame_lock->lock("RenderEngine::arm_command"); - } - else -// Set lock so audio doesn't wait for video which is never to come. - { - while(first_frame_lock->get_value() <= 0) - first_frame_lock->unlock(); - } - - open_output(); - create_render_threads(); - arm_render_threads(); - if(debug) printf("RenderEngine::arm_command %d\n", __LINE__); - - return 0; -} - -void RenderEngine::get_duty() -{ - do_audio = 0; - do_video = 0; - -//printf("RenderEngine::get_duty %d\n", __LINE__); - if(!command->single_frame() && - get_edl()->tracks->playable_audio_tracks() && - get_edl()->session->audio_channels) - { - do_audio = 1; - } - -//printf("RenderEngine::get_duty %d\n", __LINE__); - if(get_edl()->tracks->playable_video_tracks()) - { -//printf("RenderEngine::get_duty %d\n", __LINE__); - do_video = 1; - } -} - -void RenderEngine::create_render_threads() -{ - if(do_video && !vrender) - { - vrender = new VRender(this); - } - - if(do_audio && !arender) - { - arender = new ARender(this); - } -} - - -int RenderEngine::get_output_w() -{ - return get_edl()->session->output_w; -} - -int RenderEngine::get_output_h() -{ - return get_edl()->session->output_h; -} - -int RenderEngine::brender_available(int position, int direction) -{ - if(playback_engine) - { - int64_t corrected_position = position; - if(direction == PLAY_REVERSE) - corrected_position--; - return playback_engine->brender_available(corrected_position); - } - else - return 0; -} - -Channel* RenderEngine::get_current_channel() -{ - if(channeldb) - { - switch(config->vconfig->driver) - { - case PLAYBACK_BUZ: - if(config->vconfig->buz_out_channel >= 0 && - config->vconfig->buz_out_channel < channeldb->size()) - { - return channeldb->get(config->vconfig->buz_out_channel); - } - break; - case VIDEO4LINUX2JPEG: - case VIDEO4LINUX2MPEG: - break; - } - } - return 0; -} - -CICache* RenderEngine::get_acache() -{ - if(playback_engine) - return playback_engine->audio_cache; - else - return audio_cache; -} - -CICache* RenderEngine::get_vcache() -{ - if(playback_engine) - return playback_engine->video_cache; - else - return video_cache; -} - -void RenderEngine::set_acache(CICache *cache) -{ - this->audio_cache = cache; -} - -void RenderEngine::set_vcache(CICache *cache) -{ - this->video_cache = cache; -} - - -double RenderEngine::get_tracking_position() -{ - if(playback_engine) - return playback_engine->get_tracking_position(); - else - return 0; -} - -int RenderEngine::open_output() -{ - if(command->realtime && !is_nested) - { -// Allocate devices - if(do_audio) - { - audio = new AudioDevice(mwindow); - } - - if(do_video) - { - video = new VideoDevice(mwindow); - } - -// Initialize sharing - - -// Start playback - if(do_audio && do_video) - { - video->set_adevice(audio); - audio->set_vdevice(video); - } - - - -// Retool playback configuration - if(do_audio) - { - if(audio->open_output(config->aconfig, - get_edl()->session->sample_rate, - adjusted_fragment_len, - get_edl()->session->audio_channels, - get_edl()->session->real_time_playback)) - do_audio = 0; - else - { - audio->set_software_positioning( - get_edl()->session->playback_software_position); - audio->start_playback(); - } - } - - if(do_video) - { - video->open_output(config->vconfig, - get_edl()->session->frame_rate, - get_output_w(), - get_output_h(), - output, - command->single_frame()); - Channel *channel = get_current_channel(); - if(channel) video->set_channel(channel); - video->set_quality(80); - video->set_cpus(preferences->processors); - } - } - - return 0; -} - -void RenderEngine::reset_sync_position() -{ - timer.update(); -} - -int64_t RenderEngine::sync_position() -{ -// Use audio device -// No danger of race conditions because the output devices are closed after all -// threads join. - if(do_audio) - { - return audio->current_position(); - } - - if(do_video) - { - int64_t result = timer.get_scaled_difference( - get_edl()->session->sample_rate); - return result; - } - return 0; -} - - -int RenderEngine::start_command() -{ - if(command->realtime && !is_nested) - { - interrupt_lock->lock("RenderEngine::start_command"); - start_lock->lock("RenderEngine::start_command 1"); - Thread::start(); - start_lock->lock("RenderEngine::start_command 2"); - start_lock->unlock(); - } - return 0; -} - -void RenderEngine::arm_render_threads() -{ - if(do_audio) - { - arender->arm_command(); - } - - if(do_video) - { - vrender->arm_command(); - } -} - - -void RenderEngine::start_render_threads() -{ -// Synchronization timer. Gets reset once again after the first video frame. - timer.update(); - - if(do_audio) - { - arender->start_command(); - } - - if(do_video) - { - vrender->start_command(); - } -} - -void RenderEngine::update_framerate(float framerate) -{ - playback_engine->mwindow->session->actual_frame_rate = framerate; - playback_engine->mwindow->preferences_thread->update_framerate(); -} - -void RenderEngine::wait_render_threads() -{ - if(do_audio) - { - arender->Thread::join(); - } - - if(do_video) - { - vrender->Thread::join(); - } -} - -void RenderEngine::interrupt_playback() -{ - interrupt_lock->lock("RenderEngine::interrupt_playback"); - interrupted = 1; - if(do_audio && arender) - { - arender->interrupt_playback(); - } - - if(do_video && vrender) - { - vrender->interrupt_playback(); - } - interrupt_lock->unlock(); -} - -int RenderEngine::close_output() -{ -// Nested engines share devices - if(!is_nested) - { - if(audio) - { - audio->close_all(); - delete audio; - audio = 0; - } - - - - if(video) - { - video->close_all(); - delete video; - video = 0; - } - } - - return 0; -} - -void RenderEngine::get_output_levels(double *levels, int64_t position) -{ - if(do_audio) - { - int history_entry = arender->get_history_number(arender->level_samples, - position); - for(int i = 0; i < MAXCHANNELS; i++) - { - if(arender->audio_out[i]) - levels[i] = arender->level_history[i][history_entry]; - } - } -} - -void RenderEngine::get_module_levels(ArrayList *module_levels, int64_t position) -{ - if(do_audio) - { - for(int i = 0; i < arender->total_modules; i++) - { -//printf("RenderEngine::get_module_levels %p %p\n", ((AModule*)arender->modules[i]), ((AModule*)arender->modules[i])->level_samples); - int history_entry = arender->get_history_number(((AModule*)arender->modules[i])->level_samples, position); - - module_levels->append(((AModule*)arender->modules[i])->level_history[history_entry]); - } - } -} - - - - - -void RenderEngine::run() -{ - start_render_threads(); - start_lock->unlock(); - interrupt_lock->unlock(); - - wait_render_threads(); - - interrupt_lock->lock("RenderEngine::run"); - - - if(interrupted) - { - playback_engine->tracking_position = playback_engine->get_tracking_position(); - } - - close_output(); - -// Fix the tracking position - if(playback_engine) - { - if(command->command == CURRENT_FRAME) - { -//printf("RenderEngine::run 4.1 %d\n", playback_engine->tracking_position); - playback_engine->tracking_position = command->playbackstart; - } - else - { -// Make sure transport doesn't issue a pause command next -//printf("RenderEngine::run 4.1 %d\n", playback_engine->tracking_position); - if(!interrupted) - { - if(do_audio) - playback_engine->tracking_position = - (double)arender->current_position / - command->get_edl()->session->sample_rate; - else - if(do_video) - { - playback_engine->tracking_position = - (double)vrender->current_position / - command->get_edl()->session->frame_rate; - } - } - - if(!interrupted) playback_engine->command->command = STOP; - playback_engine->stop_tracking(); - - } - playback_engine->is_playing_back = 0; - } - - input_lock->unlock(); - interrupt_lock->unlock(); -} - - -