From: Good Guy Date: Sun, 26 Apr 2020 01:41:57 +0000 (-0600) Subject: split resource_thread update into separate audio/video threads, boxblur layout tweaks X-Git-Tag: 2020-04~4 X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=commitdiff_plain;h=fb3e53778e49a406768506de9bf8edfd3d4c36e6 split resource_thread update into separate audio/video threads, boxblur layout tweaks --- diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C index 8c0dd6c0..8b93262c 100644 --- a/cinelerra-5.1/cinelerra/mwindow.C +++ b/cinelerra-5.1/cinelerra/mwindow.C @@ -4456,11 +4456,7 @@ void MWindow::remove_from_caches(Indexable *idxbl) delete gui->render_engine; gui->render_engine = 0; } - if( gui->resource_thread->render_engine_id == idxbl->id ) { - gui->resource_thread->render_engine_id = -1; - delete gui->resource_thread->render_engine; - gui->resource_thread->render_engine = 0; - } + gui->resource_thread->close_indexable(idxbl); if( !idxbl->is_asset ) return; Asset *asset = (Asset *)idxbl; audio_cache->delete_entry(asset); diff --git a/cinelerra-5.1/cinelerra/mwindowgui.C b/cinelerra-5.1/cinelerra/mwindowgui.C index a9e93c64..7b92aa32 100644 --- a/cinelerra-5.1/cinelerra/mwindowgui.C +++ b/cinelerra-5.1/cinelerra/mwindowgui.C @@ -159,7 +159,7 @@ void MWindowGUI::create_objects() lock_window("MWindowGUI::create_objects"); const int debug = 0; - resource_thread = new ResourceThread(mwindow, this); + resource_thread = new ResourceThread(mwindow); resource_thread->create_objects(); @@ -1809,6 +1809,7 @@ void MWindowGUI::delete_y_pane(int cursor_y) void MWindowGUI::stop_pane_drag() { + if( !dragging_pane ) return; dragging_pane = 0; resource_thread->stop_draw(0); diff --git a/cinelerra-5.1/cinelerra/resourcethread.C b/cinelerra-5.1/cinelerra/resourcethread.C index 895dd506..27794d27 100644 --- a/cinelerra-5.1/cinelerra/resourcethread.C +++ b/cinelerra-5.1/cinelerra/resourcethread.C @@ -71,27 +71,12 @@ ResourceThreadItem::~ResourceThreadItem() } - - - - - -VResourceThreadItem::VResourceThreadItem(ResourcePixmap *pixmap, - int pane_number, - int picon_x, - int picon_y, - int picon_w, - int picon_h, - double frame_rate, - int64_t position, - int layer, - Indexable *indexable, - int operation_count) - : ResourceThreadItem(pixmap, - pane_number, - indexable, - TRACK_VIDEO, - operation_count) +VResourceThreadItem::VResourceThreadItem(ResourcePixmap *pixmap, int pane_number, + int picon_x, int picon_y, int picon_w, int picon_h, + double frame_rate, int64_t position, int layer, + Indexable *indexable, int operation_count) + : ResourceThreadItem(pixmap, pane_number, + indexable, TRACK_VIDEO, operation_count) { this->picon_x = picon_x; this->picon_y = picon_y; @@ -107,25 +92,11 @@ VResourceThreadItem::~VResourceThreadItem() } - - - - - - -AResourceThreadItem::AResourceThreadItem(ResourcePixmap *pixmap, - int pane_number, - Indexable *indexable, - int x, - int channel, - int64_t start, - int64_t end, - int operation_count) - : ResourceThreadItem(pixmap, - pane_number, - indexable, - TRACK_AUDIO, - operation_count) +AResourceThreadItem::AResourceThreadItem(ResourcePixmap *pixmap, int pane_number, + Indexable *indexable, int x, int channel, + int64_t start, int64_t end, int operation_count) + : ResourceThreadItem(pixmap, pane_number, + indexable, TRACK_AUDIO, operation_count) { this->x = x; this->channel = channel; @@ -137,124 +108,157 @@ AResourceThreadItem::~AResourceThreadItem() { } +ResourceAudioThread::ResourceAudioThread(ResourceThread *resource_thread) + : ResourceThreadBase(resource_thread) +{ + this->resource_thread = resource_thread; + audio_buffer = 0; + audio_asset = 0; + audio_source = 0; + for(int i = 0; i < MAXCHANNELS; i++) + temp_buffer[i] = 0; + timer = new Timer; + prev_x = -1; + prev_h = 0; + prev_l = 0; +} +ResourceAudioThread::~ResourceAudioThread() +{ + delete audio_buffer; + for(int i = 0; i < MAXCHANNELS; i++) + delete temp_buffer[i]; + delete timer; + if( audio_asset ) audio_asset->remove_user(); +} +void ResourceAudioThread::start_draw() +{ + prev_x = -1; + prev_h = 0; + prev_l = 0; + ResourceThreadItem *item = items.last; +// Tag last audio item to cause refresh. + if( item ) item->last = 1; + timer->update(); + ResourceThreadBase::start_draw(); +} +File *ResourceAudioThread::get_audio_source(Asset *asset) +{ + MWindow *mwindow = resource_thread->mwindow; + if( interrupted ) asset = 0; + if( audio_asset && audio_asset != asset && (!asset || + strcmp(audio_asset->path, asset->path)) ) { + mwindow->audio_cache->check_in(audio_asset); + audio_source = 0; + audio_asset->remove_user(); + audio_asset = 0; + } + if( !audio_asset && asset ) { + audio_asset = asset; + audio_asset->add_user(); + audio_source = mwindow->audio_cache->check_out(asset, mwindow->edl); + } + return audio_source; +} +void ResourceAudioThread::add_wave(ResourcePixmap *pixmap, int pane_number, + Indexable *indexable, int x, int channel, + int64_t source_start, int64_t source_end) +{ + item_lock->lock("ResourceThreadBase::item_lock"); + items.append(new AResourceThreadItem(pixmap, pane_number, + indexable, x, channel, source_start, source_end, + resource_thread->operation_count)); + item_lock->unlock(); +} +ResourceVideoThread::ResourceVideoThread(ResourceThread *resource_thread) + : ResourceThreadBase(resource_thread) +{ + this->resource_thread = resource_thread; + video_asset = 0; + video_source = 0; + temp_picon = 0; + temp_picon2 = 0; +} +ResourceVideoThread::~ResourceVideoThread() +{ + delete temp_picon; + delete temp_picon2; + if( video_asset ) video_asset->remove_user(); +} +File *ResourceVideoThread::get_video_source(Asset *asset) +{ + MWindow *mwindow = resource_thread->mwindow; + if( interrupted ) asset = 0; + if( video_asset && video_asset != asset && (!asset || + strcmp(video_asset->path, asset->path)) ) { + mwindow->video_cache->check_in(video_asset); + video_source = 0; + video_asset->remove_user(); + video_asset = 0; + } + if( !video_asset && asset ) { + video_asset = asset; + video_asset->add_user(); + video_source = mwindow->video_cache->check_out(asset, mwindow->edl); + } + return video_source; +} +void ResourceVideoThread::add_picon(ResourcePixmap *pixmap, int pane_number, + int picon_x, int picon_y, int picon_w, int picon_h, + double frame_rate, int64_t position, int layer, + Indexable *indexable) +{ + item_lock->lock("ResourceThreadBase::item_lock"); + items.append(new VResourceThreadItem(pixmap, pane_number, + picon_x, picon_y, picon_w, picon_h, + frame_rate, position, layer, indexable, + resource_thread->operation_count)); + item_lock->unlock(); +} - -ResourceThread::ResourceThread(MWindow *mwindow, MWindowGUI *gui) +ResourceThreadBase::ResourceThreadBase(ResourceThread *resource_thread) : Thread(1, 0, 0) { -//printf("ResourceThread::ResourceThread %d %p\n", __LINE__, this); - this->mwindow = mwindow; - this->gui = gui; + this->resource_thread = resource_thread; interrupted = 1; done = 1; - temp_picon = 0; - temp_picon2 = 0; - draw_lock = new Condition(0, "ResourceThread::draw_lock", 0); - item_lock = new Mutex("ResourceThread::item_lock"); - audio_buffer = 0; - for(int i = 0; i < MAXCHANNELS; i++) - temp_buffer[i] = 0; - timer = new Timer; - prev_x = -1; - prev_h = 0; - prev_l = 0; - operation_count = 0; + draw_lock = new Condition(0, "ResourceThreadBase::draw_lock", 0); + item_lock = new Mutex("ResourceThreadBase::item_lock"); render_engine = 0; render_engine_id = -1; - audio_asset = 0; - audio_source = 0; - video_asset = 0; - video_source = 0; } -ResourceThread::~ResourceThread() +ResourceThreadBase::~ResourceThreadBase() { stop(); delete draw_lock; delete item_lock; - delete temp_picon; - delete temp_picon2; - delete audio_buffer; - for(int i = 0; i < MAXCHANNELS; i++) - delete temp_buffer[i]; - delete timer; delete render_engine; - if( audio_asset ) audio_asset->remove_user(); - if( video_asset ) video_asset->remove_user(); } -void ResourceThread::create_objects() +void ResourceThreadBase::create_objects() { done = 0; Thread::start(); } -void ResourceThread::add_picon(ResourcePixmap *pixmap, - int pane_number, - int picon_x, - int picon_y, - int picon_w, - int picon_h, - double frame_rate, - int64_t position, - int layer, - Indexable *indexable) -{ - item_lock->lock("ResourceThread::item_lock"); - - items.append(new VResourceThreadItem(pixmap, - pane_number, - picon_x, - picon_y, - picon_w, - picon_h, - frame_rate, - position, - layer, - indexable, - operation_count)); - item_lock->unlock(); -} - -void ResourceThread::add_wave(ResourcePixmap *pixmap, - int pane_number, - Indexable *indexable, - int x, - int channel, - int64_t source_start, - int64_t source_end) -{ - item_lock->lock("ResourceThread::item_lock"); - - items.append(new AResourceThreadItem(pixmap, - pane_number, - indexable, - x, - channel, - source_start, - source_end, - operation_count)); - item_lock->unlock(); -} - -void ResourceThread::reset(int pane_number) +void ResourceThreadBase::reset(int pane_number) { - item_lock->lock("ResourceThread::reset"); + item_lock->lock("ResourceThreadBase::reset"); ResourceThreadItem *item = items.first; while( item ) { ResourceThreadItem *next_item = item->next; @@ -264,82 +268,46 @@ void ResourceThread::reset(int pane_number) item_lock->unlock(); } - - - - - - - - - -void ResourceThread::stop_draw(int reset) +void ResourceThreadBase::stop_draw(int reset) { - if(!interrupted) - { + if( !interrupted ) { interrupted = 1; - item_lock->lock("ResourceThread::stop_draw"); - -//printf("ResourceThread::stop_draw %d %d\n", __LINE__, reset); + item_lock->lock("ResourceThreadBase::stop_draw"); +//printf("ResourceThreadBase::stop_draw %d %d\n", __LINE__, reset); //BC_Signals::dump_stack(); if( reset ) { ResourceThreadItem *item; while( (item=items.last) != 0 ) delete item; - ++operation_count; } item_lock->unlock(); - prev_x = -1; - prev_h = 0; - prev_l = 0; } } -void ResourceThread::start_draw() +void ResourceThreadBase::start_draw() { interrupted = 0; -// Tag last audio item to cause refresh. - ResourceThreadItem *item = items.last; - while( item && item->data_type!=TRACK_AUDIO ) item = item->previous; - if( item ) item->last = 1; - timer->update(); draw_lock->unlock(); } -void ResourceThread::run() +void ResourceThreadBase::run() { - while(!done) - { - - draw_lock->lock("ResourceThread::run"); - while(!interrupted) - { -// Pull off item - item_lock->lock("ResourceThread::run"); + MWindow *mwindow = resource_thread->mwindow; + while( !done ) { + draw_lock->lock("ResourceThreadBase::run"); + while( !interrupted ) { + item_lock->lock("ResourceThreadBase::run"); ResourceThreadItem *item = items.first; items.remove_pointer(item); item_lock->unlock(); -//printf("ResourceThread::run %d %d\n", __LINE__, items.size()); - if(!item) break; - - switch( item->data_type ) { - case TRACK_VIDEO: - do_video((VResourceThreadItem*)item); - break; - case TRACK_AUDIO: - do_audio((AResourceThreadItem*)item); - break; - } - + if( !item ) break; + draw_item(item); delete item; } - - get_audio_source(0); - get_video_source(0); mwindow->age_caches(); } } -void ResourceThread::stop() +void ResourceThreadBase::stop() { if( !done ) { done = 1; @@ -350,28 +318,21 @@ void ResourceThread::stop() } -void ResourceThread::open_render_engine(EDL *nested_edl, - int do_audio, - int do_video) +void ResourceThreadBase::open_render_engine(EDL *nested_edl, + int do_audio, int do_video) { - if(render_engine && render_engine_id != nested_edl->id) - { - delete render_engine; - render_engine = 0; + if( render_engine && render_engine_id != nested_edl->id ) { + delete render_engine; render_engine = 0; } - if(!render_engine) - { + if( !render_engine ) { + MWindow *mwindow = resource_thread->mwindow; TransportCommand command; - if(do_audio) - command.command = NORMAL_FWD; - else - command.command = CURRENT_FRAME; + command.command = do_audio ? NORMAL_FWD : CURRENT_FRAME; command.get_edl()->copy_all(nested_edl); command.change_type = CHANGE_ALL; command.realtime = 0; - render_engine = new RenderEngine(0, - mwindow->preferences, 0, 0); + render_engine = new RenderEngine(0, mwindow->preferences, 0, 0); render_engine_id = nested_edl->id; render_engine->set_vcache(mwindow->video_cache); render_engine->set_acache(mwindow->audio_cache); @@ -379,103 +340,40 @@ void ResourceThread::open_render_engine(EDL *nested_edl, } } -File *ResourceThread::get_audio_source(Asset *asset) +void ResourceThreadBase::close_render_engine() { - if( interrupted ) asset = 0; - - if( audio_asset && audio_asset != asset && (!asset || - strcmp(audio_asset->path, asset->path)) ) - { - mwindow->audio_cache->check_in(audio_asset); - audio_source = 0; - audio_asset->remove_user(); - audio_asset = 0; - - } - if( !audio_asset && asset ) - { - audio_asset = asset; - audio_asset->add_user(); - audio_source = mwindow->audio_cache->check_out(asset, mwindow->edl); - } - return audio_source; + delete render_engine; render_engine = 0; + render_engine_id = -1; } -File *ResourceThread::get_video_source(Asset *asset) +void ResourceVideoThread::draw_item(ResourceThreadItem *item) { - if( interrupted ) asset = 0; - - if( video_asset && video_asset != asset && (!asset || - strcmp(video_asset->path, asset->path)) ) - { - mwindow->video_cache->check_in(video_asset); - video_source = 0; - video_asset->remove_user(); - video_asset = 0; - - } - if( !video_asset && asset ) - { - video_asset = asset; - video_asset->add_user(); - video_source = mwindow->video_cache->check_out(asset, mwindow->edl); - } - return video_source; + do_video((VResourceThreadItem *)item); } -void ResourceThread::do_video(VResourceThreadItem *item) +void ResourceVideoThread::do_video(VResourceThreadItem *item) { int source_w = 0; int source_h = 0; int source_id = -1; int source_cmodel = -1; - if(item->indexable->is_asset) - { + if( item->indexable->is_asset ) { Asset *asset = (Asset*)item->indexable; source_w = asset->width; source_h = asset->height; source_id = asset->id; source_cmodel = BC_RGB888; } - else - { + else { EDL *nested_edl = (EDL*)item->indexable; source_w = nested_edl->session->output_w; source_h = nested_edl->session->output_h; source_id = nested_edl->id; source_cmodel = nested_edl->session->color_model; } - - if(temp_picon && - (temp_picon->get_w() != source_w || - temp_picon->get_h() != source_h || - temp_picon->get_color_model() != source_cmodel)) - { - delete temp_picon; - temp_picon = 0; - } - - if(!temp_picon) - { - temp_picon = new VFrame(0, -1, source_w, source_h, source_cmodel, -1); - } - -// Get temporary to copy cached frame to - if(temp_picon2 && - (temp_picon2->get_w() != item->picon_w || - temp_picon2->get_h() != item->picon_h)) - { - delete temp_picon2; - temp_picon2 = 0; - } - - if(!temp_picon2) - { - temp_picon2 = new VFrame( item->picon_w, item->picon_h, BC_RGB888, 0); - } - - + VFrame::get_temp(temp_picon, source_w, source_h, source_cmodel); + VFrame::get_temp(temp_picon2, item->picon_w, item->picon_h, BC_RGB888); // Search frame cache again. @@ -483,6 +381,7 @@ void ResourceThread::do_video(VResourceThreadItem *item) int need_conversion = 0; EDL *nested_edl = 0; Asset *asset = 0; + MWindow *mwindow = resource_thread->mwindow; picon_frame = mwindow->frame_cache->get_frame_ptr(item->position, item->layer, item->frame_rate, BC_RGB888, @@ -495,9 +394,7 @@ void ResourceThread::do_video(VResourceThreadItem *item) // Unlock the get_frame_ptr command mwindow->frame_cache->unlock(); } - else - if(!item->indexable->is_asset) - { + else if( !item->indexable->is_asset ) { nested_edl = (EDL*)item->indexable; open_render_engine(nested_edl, 0, 1); @@ -512,97 +409,77 @@ void ResourceThread::do_video(VResourceThreadItem *item) need_conversion = 1; } - else - { + else { asset = (Asset*)item->indexable; File *source = get_video_source(asset); - if(!source) - return; + if(!source) return; source->set_layer(item->layer); int64_t normalized_position = (int64_t)(item->position * - asset->frame_rate / - item->frame_rate); - source->set_video_position(normalized_position, - 0); - + asset->frame_rate / item->frame_rate); + source->set_video_position(normalized_position, 0); source->read_frame(temp_picon); - + get_video_source(0); need_conversion = 1; } - if(need_conversion) - { + if( need_conversion ) { picon_frame = new VFrame(item->picon_w, item->picon_h, BC_RGB888, 0); - BC_CModels::transfer(picon_frame->get_rows(), temp_picon->get_rows(), - 0, 0, 0, 0, 0, 0, - 0, 0, temp_picon->get_w(), temp_picon->get_h(), - 0, 0, picon_frame->get_w(), picon_frame->get_h(), - source_cmodel, BC_RGB888, 0, - temp_picon->get_bytes_per_line(), - picon_frame->get_bytes_per_line()); + picon_frame->transfer_from(temp_picon); temp_picon2->copy_from(picon_frame); mwindow->frame_cache->put_frame(picon_frame, item->position, item->layer, mwindow->edl->session->frame_rate, 0, item->indexable); } // Allow escape here - if(interrupted) - return; + if(interrupted) return; + MWindowGUI *gui = mwindow->gui; // Draw the picon - mwindow->gui->lock_window("ResourceThread::do_video"); - + gui->lock_window("ResourceThreadBase::do_video"); // It was interrupted while waiting. - if(interrupted) - { - mwindow->gui->unlock_window(); + if( interrupted ) { + gui->unlock_window(); return; } - - // Test for pixmap existence first - if(item->operation_count == operation_count) - { + if( item->operation_count == resource_thread->operation_count ) { ArrayList &resource_pixmaps = gui->resource_pixmaps; int i = resource_pixmaps.total; while( --i >= 0 && resource_pixmaps[i] != item->pixmap ); if( i >= 0 ) { item->pixmap->draw_vframe(temp_picon2, - item->picon_x, - item->picon_y, - item->picon_w, - item->picon_h, - 0, - 0); - - mwindow->gui->update(0, IGNORE_THREAD, 0, 0, 0, 0, 0); + item->picon_x, item->picon_y, + item->picon_w, item->picon_h, 0, 0); + gui->update(0, IGNORE_THREAD, 0, 0, 0, 0, 0); } } - mwindow->gui->unlock_window(); + gui->unlock_window(); } #define BUFFERSIZE 65536 -void ResourceThread::do_audio(AResourceThreadItem *item) +void ResourceAudioThread::draw_item(ResourceThreadItem *item) +{ + do_audio((AResourceThreadItem *)item); +} + +void ResourceAudioThread::do_audio(AResourceThreadItem *item) { // Search again - WaveCacheItem *wave_item; - double high = 0; - double low = 0; - const int debug = 0; - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); - if((wave_item = mwindow->wave_cache->get_wave(item->indexable->id, - item->channel, item->start, item->end))) - { + double high = 0, low = 0; + MWindow *mwindow = resource_thread->mwindow; + WaveCacheItem * wave_item = + mwindow->wave_cache->get_wave(item->indexable->id, + item->channel, item->start, item->end); + if( wave_item ) { high = wave_item->high; low = wave_item->low; mwindow->wave_cache->unlock(); } - else - { + else { int first_sample = 1; int64_t start = item->start; int64_t end = item->end; @@ -610,22 +487,14 @@ void ResourceThread::do_audio(AResourceThreadItem *item) double *buffer_samples = !audio_buffer ? 0 : audio_buffer->get_data(); - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); - for(int64_t sample = start; sample < end; sample++) - { - double value; + for( int64_t sample=start; samplechannel == audio_channel && item->indexable->id == audio_asset_id && sample >= audio_start && - sample < audio_start + audio_samples) - { - ; - } - else -// Load new buffer - { + sample < audio_start + audio_samples) {} + else { // Load new buffer if(!audio_buffer) { audio_buffer = new Samples(BUFFERSIZE); buffer_samples = audio_buffer->get_data(); @@ -633,151 +502,185 @@ void ResourceThread::do_audio(AResourceThreadItem *item) int64_t total_samples = item->indexable->get_audio_samples(); int fragment = BUFFERSIZE; - if(fragment + sample > total_samples) + if( fragment + sample > total_samples ) fragment = total_samples - sample; - if(!item->indexable->is_asset) - { - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); + if( !item->indexable->is_asset ) { open_render_engine((EDL*)item->indexable, 1, 0); - if(debug) printf("ResourceThread::do_audio %d %p\n", __LINE__, render_engine); - if(render_engine->arender) - { - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); + if( render_engine->arender ) { int source_channels = item->indexable->get_audio_channels(); - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); - for(int i = 0; i < MAXCHANNELS; i++) - { - if(i < source_channels && - !temp_buffer[i]) - { + for( int i=0; i= source_channels && - temp_buffer[i]) - { - delete temp_buffer[i]; - temp_buffer[i] = 0; + else if( i >= source_channels && temp_buffer[i] ) { + delete temp_buffer[i]; temp_buffer[i] = 0; } } - - - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); - render_engine->arender->process_buffer( - temp_buffer, - fragment, - sample); - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); + render_engine->arender-> + process_buffer( temp_buffer, fragment, sample); memcpy(buffer_samples, temp_buffer[item->channel]->get_data(), fragment * sizeof(double)); } - else - { - if(debug) printf("ResourceThread::do_audio %d %d\n", __LINE__, fragment); + else { if(fragment > 0) bzero(buffer_samples, sizeof(double) * fragment); - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); - } } - else - { + else { Asset *asset = (Asset*)item->indexable; File *source = get_audio_source(asset); - if(!source) - return; - + if( !source ) return; source->set_channel(item->channel); source->set_audio_position(sample); source->read_samples(audio_buffer, fragment); + get_audio_source(0); } - audio_asset_id = item->indexable->id; audio_channel = item->channel; audio_start = sample; audio_samples = fragment; } - - - value = buffer_samples[sample - audio_start]; - if(first_sample) - { + double value = buffer_samples[sample - audio_start]; + if( first_sample ) { high = low = value; first_sample = 0; } - else - { - if(value > high) - high = value; - else - if(value < low) - low = value; + else { + if( value > high ) high = value; + else if( value < low ) low = value; } } - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); // If it's a nested EDL, store all the channels - mwindow->wave_cache->put_wave(item->indexable, - item->channel, - item->start, - item->end, - high, - low); - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); + mwindow->wave_cache->put_wave(item->indexable, item->channel, + item->start, item->end, high, low); } - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); // Allow escape here - if(interrupted) - return; + if(interrupted) return; - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); + MWindowGUI *gui = mwindow->gui; // Draw the column - mwindow->gui->lock_window("ResourceThread::do_audio"); - if(interrupted) - { - mwindow->gui->unlock_window(); + gui->lock_window("ResourceThreadBase::do_audio"); + if( interrupted ) { + gui->unlock_window(); return; } - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); - if(item->operation_count == operation_count) - { - + if( item->operation_count == resource_thread->operation_count ) { // Test for pixmap existence first ArrayList &resource_pixmaps = gui->resource_pixmaps; int i = resource_pixmaps.total; while( --i >= 0 && resource_pixmaps[i] != item->pixmap ); - if( i >= 0 ) - { - if(prev_x == item->x - 1) - { + if( i >= 0 ) { + if( prev_x == item->x-1 ) { high = MAX(high, prev_l); low = MIN(low, prev_h); } prev_x = item->x; prev_h = high; prev_l = low; - if(gui->pane[item->pane_number]) + if( gui->pane[item->pane_number] ) item->pixmap->draw_wave( gui->pane[item->pane_number]->canvas, - item->x, - high, - low); - if(timer->get_difference() > 250 || item->last) - { - mwindow->gui->update(0, IGNORE_THREAD, 0, 0, 0, 0, 0); + item->x, high, low); + if( timer->get_difference() > 250 || item->last ) { + gui->update(0, IGNORE_THREAD, 0, 0, 0, 0, 0); timer->update(); } } } - if(debug) printf("ResourceThread::do_audio %d\n", __LINE__); - mwindow->gui->unlock_window(); + gui->unlock_window(); +} +ResourceThread::ResourceThread(MWindow *mwindow) +{ + this->mwindow = mwindow; + audio_thread = 0; + video_thread = 0; + interrupted = 1; + operation_count = 0; } +ResourceThread::~ResourceThread() +{ + delete audio_thread; + delete video_thread; +} +void ResourceThread::create_objects() +{ + audio_thread = new ResourceAudioThread(this); + audio_thread->create_objects(); + video_thread = new ResourceVideoThread(this); + video_thread->create_objects(); +} +void ResourceThread::stop_draw(int reset) +{ + if( !interrupted ) { + interrupted = 1; + audio_thread->stop_draw(reset); + video_thread->stop_draw(reset); + ++operation_count; + } +} + +void ResourceThread::start_draw() +{ + if( interrupted ) { + interrupted = 0; + audio_thread->start_draw(); + video_thread->start_draw(); + } +} + +// Be sure to stop_draw before changing the asset table, +// closing files. +void ResourceThread::add_picon(ResourcePixmap *pixmap, int pane_number, + int picon_x, int picon_y, int picon_w, int picon_h, + double frame_rate, int64_t position, int layer, + Indexable *indexable) +{ + video_thread->add_picon(pixmap, pane_number, + picon_x, picon_y, picon_w, picon_h, + frame_rate, position, layer, indexable); +} + +void ResourceThread::add_wave(ResourcePixmap *pixmap, int pane_number, + Indexable *indexable, int x, int channel, +// samples relative to asset rate + int64_t source_start, int64_t source_end) +{ + audio_thread->add_wave(pixmap, pane_number, + indexable, x, channel, source_start, source_end); +} + +void ResourceThread::run() +{ + audio_thread->run(); + video_thread->run(); +} + +void ResourceThread::stop() +{ + audio_thread->stop(); + video_thread->stop(); +} + +void ResourceThread::reset(int pane_number) +{ + audio_thread->reset(pane_number); + video_thread->reset(pane_number); +} + +void ResourceThread::close_indexable(Indexable *idxbl) +{ + if( audio_thread && audio_thread->render_engine_id == idxbl->id ) + audio_thread->close_render_engine(); + if( video_thread && audio_thread->render_engine_id == idxbl->id ) + video_thread->close_render_engine(); +} diff --git a/cinelerra-5.1/cinelerra/resourcethread.h b/cinelerra-5.1/cinelerra/resourcethread.h index 51f462c9..1f8fada5 100644 --- a/cinelerra-5.1/cinelerra/resourcethread.h +++ b/cinelerra-5.1/cinelerra/resourcethread.h @@ -48,133 +48,96 @@ class ResourceThreadItem : public ListItem { public: - ResourceThreadItem(ResourcePixmap *pixmap, - int pane_number, - Indexable *indexable, - int data_type, - int operation_count); + ResourceThreadItem(ResourcePixmap *pixmap, int pane_number, + Indexable *indexable, int data_type, int operation_count); virtual ~ResourceThreadItem(); ResourcePixmap *pixmap; Indexable *indexable; - int data_type; - int operation_count; - int last; - int pane_number; + int data_type, pane_number; + int operation_count, last; }; class AResourceThreadItem : public ResourceThreadItem { public: - AResourceThreadItem(ResourcePixmap *pixmap, - int pane_number, - Indexable *indexable, - int x, - int channel, - int64_t start, - int64_t end, - int operation_count); + AResourceThreadItem(ResourcePixmap *pixmap, int pane_number, + Indexable *indexable, int x, int channel, + int64_t start, int64_t end, int operation_count); ~AResourceThreadItem(); - int x; - int channel; - int64_t start; - int64_t end; + int x, channel; + int64_t start, end; }; class VResourceThreadItem : public ResourceThreadItem { public: - VResourceThreadItem(ResourcePixmap *pixmap, - int pane_number, - int picon_x, - int picon_y, - int picon_w, - int picon_h, - double frame_rate, - int64_t position, - int layer, - Indexable *indexable, - int operation_count); + VResourceThreadItem(ResourcePixmap *pixmap, int pane_number, + int picon_x, int picon_y, int picon_w, int picon_h, + double frame_rate, int64_t position, int layer, + Indexable *indexable, int operation_count); ~VResourceThreadItem(); - - - int picon_x; - int picon_y; - int picon_w; - int picon_h; + int picon_x, picon_y; + int picon_w, picon_h; double frame_rate; int64_t position; int layer; }; -class ResourceThread : public Thread +class ResourceThreadBase : public Thread { public: - ResourceThread(MWindow *mwindow, MWindowGUI *gui); - ~ResourceThread(); - + ResourceThreadBase(ResourceThread *resource_thread); + ~ResourceThreadBase(); void create_objects(); -// reset - delete all picons. Used for index building. void stop_draw(int reset); - void start_draw(); + virtual void start_draw(); + virtual void draw_item(ResourceThreadItem *item) = 0; + void close_render_engine(); // Be sure to stop_draw before changing the asset table, // closing files. - void add_picon(ResourcePixmap *pixmap, - int pane_number, - int picon_x, - int picon_y, - int picon_w, - int picon_h, - double frame_rate, - int64_t position, - int layer, - Indexable *indexable); - - void add_wave(ResourcePixmap *pixmap, - int pane_number, - Indexable *indexable, - int x, - int channel, -// samples relative to asset rate - int64_t source_start, - int64_t source_end); - void run(); void stop(); void reset(int pane_number); - void do_video(VResourceThreadItem *item); - void do_audio(AResourceThreadItem *item); - void open_render_engine(EDL *nested_edl, - int do_audio, - int do_video); + int do_audio, int do_video); - File *get_video_source(Asset *asset); - File *get_audio_source(Asset *asset); - - MWindow *mwindow; - MWindowGUI *gui; + ResourceThread *resource_thread; Condition *draw_lock; Mutex *item_lock; List items; int interrupted; int done; - VFrame *temp_picon; - VFrame *temp_picon2; // Render engine for nested EDL RenderEngine *render_engine; // ID of nested EDL being rendered int render_engine_id; +}; + +class ResourceAudioThread : public ResourceThreadBase +{ +public: + ResourceAudioThread(ResourceThread *resource_thread); + ~ResourceAudioThread(); + void start_draw(); + File *get_audio_source(Asset *asset); + void draw_item(ResourceThreadItem *item); + void do_audio(AResourceThreadItem *item); + + void add_wave(ResourcePixmap *pixmap, int pane_number, + Indexable *indexable, int x, int channel, + // samples relative to asset rate + int64_t source_start, int64_t source_end); + + ResourceThread *resource_thread; Asset *audio_asset; File *audio_source; - Asset *video_asset; - File *video_source; // Current audio buffer for spanning multiple pixels Samples *audio_buffer; @@ -190,11 +153,66 @@ public: int prev_x; double prev_h; double prev_l; -// Incremented after every start_draw to prevent overlapping operations - int operation_count; +}; + +class ResourceVideoThread : public ResourceThreadBase +{ +public: + ResourceVideoThread(ResourceThread *resource_thread); + ~ResourceVideoThread(); + File *get_video_source(Asset *asset); + void draw_item(ResourceThreadItem *item); + void do_video(VResourceThreadItem *item); + +// Be sure to stop_draw before changing the asset table, +// closing files. + void add_picon(ResourcePixmap *pixmap, int pane_number, + int picon_x, int picon_y, int picon_w, int picon_h, + double frame_rate, int64_t position, int layer, + Indexable *indexable); + + ResourceThread *resource_thread; + Asset *video_asset; + File *video_source; + + VFrame *temp_picon; + VFrame *temp_picon2; }; +class ResourceThread +{ +public: + ResourceThread(MWindow *mwindow); + ~ResourceThread(); -#endif + void create_objects(); +// reset - delete all picons. Used for index building. + void stop_draw(int reset); + void start_draw(); + +// Be sure to stop_draw before changing the asset table, +// closing files. + void add_picon(ResourcePixmap *pixmap, int pane_number, + int picon_x, int picon_y, int picon_w, int picon_h, + double frame_rate, int64_t position, int layer, + Indexable *indexable); + + void add_wave(ResourcePixmap *pixmap, int pane_number, + Indexable *indexable, int x, int channel, +// samples relative to asset rate + int64_t source_start, int64_t source_end); + + void run(); + void stop(); + void reset(int pane_number); + void close_indexable(Indexable*); + MWindow *mwindow; + ResourceAudioThread *audio_thread; + ResourceVideoThread *video_thread; + int operation_count; + int interrupted; +}; + +#endif diff --git a/cinelerra-5.1/plugins/boxblur/boxblur.C b/cinelerra-5.1/plugins/boxblur/boxblur.C index 006439af..9c5d5bcf 100644 --- a/cinelerra-5.1/plugins/boxblur/boxblur.C +++ b/cinelerra-5.1/plugins/boxblur/boxblur.C @@ -421,7 +421,7 @@ BoxBlurPower::BoxBlurPower(BoxBlurWindow *gui, int x, int y, int w, } BoxBlurWindow::BoxBlurWindow(BoxBlurEffect *plugin) - : PluginClientWindow(plugin, xS(360), yS(246), xS(360), yS(246), 0) + : PluginClientWindow(plugin, xS(360), yS(260), xS(360), yS(260), 0) { this->plugin = plugin; blur_horz = 0; @@ -445,13 +445,14 @@ BoxBlurWindow::~BoxBlurWindow() void BoxBlurWindow::create_objects() { int x = xS(10), y = yS(10); + int ys10 = yS(10), ys20 = yS(20), ys30 = yS(30), ys40 = yS(40); int t1 = x, t2 = t1+xS(24), t3 = t2+xS(100), t4 = t3+xS(24); int ww = get_w() - 2*x, bar_o = xS(30), bar_m = xS(15); int margin = plugin->get_theme()->widget_border; - BC_TitleBar *tbar; - add_subwindow(tbar = new BC_TitleBar(x, y, ww, bar_o, bar_m, _("Position & Size"))); - y += tbar->get_h() + margin; + BC_TitleBar *tbar; + add_subwindow(tbar = new BC_TitleBar(x, y, ww, bar_o, bar_m, _("Position & Size"))); + y += ys20; int x1 = ww - BoxBlurDrag::calculate_w(this) - margin; add_subwindow(drag = new BoxBlurDrag(this, plugin, x1, y)); drag->create_objects(); @@ -465,32 +466,32 @@ void BoxBlurWindow::create_objects() add_subwindow(title = new BC_Title(t3, y, _("W:"))); box_w = new BoxBlurW(this, t4, y); box_w->create_objects(); - y += bmax(title->get_h(), box_w->get_h()) + margin; + y += ys30; add_subwindow(title = new BC_Title(t1, y, _("Y:"))); box_y = new BoxBlurY(this, t2, y); box_y->create_objects(); add_subwindow(title = new BC_Title(t3, y, _("H:"))); box_h = new BoxBlurH(this, t4, y); box_h->create_objects(); - y += bmax(title->get_h(), box_h->get_h()) + 2*margin; + y += ys40; add_subwindow(tbar = new BC_TitleBar(x, y, ww, bar_o, bar_m, _("Blur"))); - y += tbar->get_h() + margin; + y += ys20; blur_horz = new BoxBlurRadius(this, x, y, ww, _("Horz:"), &plugin->config.horz_radius); blur_horz->create_objects(); - y += blur_horz->get_h() + margin; + y += ys30; blur_vert = new BoxBlurRadius(this, x, y, ww, _("Vert:"), &plugin->config.vert_radius); blur_vert->create_objects(); - y += blur_vert->get_h() + margin; + y += ys30; blur_power = new BoxBlurPower(this, x, y, ww, _("Power:"), &plugin->config.power); blur_power->create_objects(); - y += blur_power->get_h() + margin + yS(8); + y += ys40; BC_Bar *bar; add_subwindow(bar = new BC_Bar(x, y, ww)); - y += bar->get_h() + 2*margin; + y += ys10; add_subwindow(reset = new BoxBlurReset(this, x, y)); x1 = x + ww - BoxBlurPreset::calculate_w(this);