From: Good Guy Date: Sat, 12 Sep 2020 15:20:26 +0000 (-0600) Subject: add transition caching with pref, rev read frame caching, cache lock tweaks, fix... X-Git-Tag: 2020-09~11 X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=commitdiff_plain;h=45a8ba3455cf252332c03533a7590df5267ce9aa add transition caching with pref, rev read frame caching, cache lock tweaks, fix cache aging, push pref changes to render_engine, update ru.po, tweak undo menu text, incr max asset geom --- diff --git a/cinelerra-5.1/cinelerra/asset.C b/cinelerra-5.1/cinelerra/asset.C index fab58403..2828fe31 100644 --- a/cinelerra-5.1/cinelerra/asset.C +++ b/cinelerra-5.1/cinelerra/asset.C @@ -181,9 +181,9 @@ void Asset::boundaries() // sample_rate & frame_rate are user defined // CLAMP(sample_rate, 1, 1000000); // CLAMP(frame_rate, 0.001, 1000000); - CLAMP(channels, 0, 16); - CLAMP(width, 0, 10000); - CLAMP(height, 0, 10000); + CLAMP(channels, 0, MAX_CHANNELS-1); + CLAMP(width, 0, 32767); + CLAMP(height, 0, 32767); //printf("Asset::boundaries %d %d %f\n", __LINE__, sample_rate, frame_rate); } diff --git a/cinelerra-5.1/cinelerra/cache.C b/cinelerra-5.1/cinelerra/cache.C index 80bf347b..a93f1e1b 100644 --- a/cinelerra-5.1/cinelerra/cache.C +++ b/cinelerra-5.1/cinelerra/cache.C @@ -253,36 +253,29 @@ int CICache::get_oldest() int CICache::delete_oldest() { int result = 0; - total_lock->lock("CICache::delete_oldest"); CICacheItem *oldest = 0; -// at least 2 - if( first != last ) { - oldest = first; - CICacheItem *current = oldest->next; - while( current ) { + total_lock->lock("CICache::delete_oldest"); + if( first != last ) { // at least 2 + CICacheItem *current = first; + for( ; !oldest && current; current=current->next ) + if( !current->checked_out ) oldest = current; + for( ; current; current=current->next ) { + if( current->checked_out ) continue; if( current->age < oldest->age ) oldest = current; - current = current->next; + } +// delete oldest of at least 2 cache files + if( oldest ) { + remove_pointer(oldest); + result = 1; } } // settle for just deleting one frame - else if( first ) + else if( first && !first->checked_out ) result = first->file->delete_oldest(); - if( oldest ) { -// Got the oldest file. Try requesting cache purge from it. - if( oldest->file ) - oldest->file->purge_cache(); -// Delete the file if cache already empty and not checked out. - if( !oldest->checked_out ) - remove_pointer(oldest); - else - oldest = 0; - } total_lock->unlock(); - if( oldest ) { + if( oldest ) oldest->Garbage::remove_user(); - result = 1; - } return result; } diff --git a/cinelerra-5.1/cinelerra/editpanel.C b/cinelerra-5.1/cinelerra/editpanel.C index 1f75414f..bf33acba 100644 --- a/cinelerra-5.1/cinelerra/editpanel.C +++ b/cinelerra-5.1/cinelerra/editpanel.C @@ -1127,7 +1127,7 @@ EditUndo::EditUndo(MWindow *mwindow, EditPanel *panel, int x, int y) { this->mwindow = mwindow; this->panel = panel; - set_tooltip(_("Undo ( z )")); + set_tooltip(_("Undo ( z or Ctrl-z)")); } EditUndo::~EditUndo() { diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index c08a01db..57232271 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -270,7 +270,8 @@ FFStream::FFStream(FFMPEG *ffmpeg, AVStream *st, int fidx) frm_count = 0; nudge = AV_NOPTS_VALUE; seek_pos = curr_pos = 0; - seeked = 1; eof = 0; + seeking = 0; seeked = 1; + eof = 0; reading = writing = 0; hw_pixfmt = AV_PIX_FMT_NONE; hw_device_ctx = 0; @@ -714,6 +715,7 @@ int FFStream::seek(int64_t no, double rate) } } if( pos == curr_pos ) return 0; + seeking = -1; double secs = pos < 0 ? 0. : pos / rate; AVRational time_base = st->time_base; int64_t tstmp = time_base.num > 0 ? secs * time_base.den/time_base.num : 0; @@ -1222,8 +1224,20 @@ int FFVideoStream::load(VFrame *vframe, int64_t pos) int i = MAX_RETRY + pos - curr_pos; while( ret>=0 && !flushed && curr_pos<=pos && --i>=0 ) { ret = read_frame(frame); - if( ret > 0 ) ++curr_pos; + if( ret > 0 ) { + if( frame->key_frame && seeking < 0 ) + seeking = 1; + if( ffmpeg->file_base->get_use_cache() && seeking > 0 && curr_pos < pos ) { + VFrame *cache_frame = ffmpeg->file_base->new_cache_frame(vframe, curr_pos); + if( cache_frame ) { + ret = convert_cmodel(cache_frame, frame); + ffmpeg->file_base->put_cache_frame(); + } + } + ++curr_pos; + } } + seeking = 0; if( frame->format == AV_PIX_FMT_NONE || frame->width <= 0 || frame->height <= 0 ) ret = -1; if( ret >= 0 ) { diff --git a/cinelerra-5.1/cinelerra/ffmpeg.h b/cinelerra-5.1/cinelerra/ffmpeg.h index 1a514e1d..aa01785a 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.h +++ b/cinelerra-5.1/cinelerra/ffmpeg.h @@ -138,7 +138,7 @@ public: int64_t seek_pos, curr_pos; int fidx; int reading, writing; - int seeked, eof; + int seeking, seeked, eof; int hw_pixfmt; AVBufferRef *hw_device_ctx; diff --git a/cinelerra-5.1/cinelerra/file.C b/cinelerra-5.1/cinelerra/file.C index f9571c9d..6459ebe8 100644 --- a/cinelerra-5.1/cinelerra/file.C +++ b/cinelerra-5.1/cinelerra/file.C @@ -344,6 +344,25 @@ int File::delete_oldest() return frame_cache->delete_oldest(); } +// create cache frame using input vframe as template +VFrame *File::new_cache_frame(VFrame *vframe, int64_t position, int first_frame) +{ + return frame_cache->new_cache_frame(position, + vframe->get_w(), vframe->get_h(), vframe->get_color_model(), + current_layer, asset->frame_rate, first_frame); +} + +void File::put_cache_frame() +{ + return frame_cache->put_cache_frame(); +} + +int File::get_use_cache() +{ + return use_cache; +} + + // file driver in order of probe precidence // can be reordered in preferences->interface const char *File::default_probes[] = { diff --git a/cinelerra-5.1/cinelerra/file.h b/cinelerra-5.1/cinelerra/file.h index 6b660b5e..e0cf4fa3 100644 --- a/cinelerra-5.1/cinelerra/file.h +++ b/cinelerra-5.1/cinelerra/file.h @@ -236,6 +236,11 @@ public: // Get nearest colormodel that can be decoded without a temporary frame. // Used by read_frame. int colormodel_supported(int colormodel); +// create frame_cache vframe for position, use template vframe +// clear cache if first frame is a read miss + VFrame *new_cache_frame(VFrame *vframe, int64_t position, int first_frame); + void put_cache_frame(); + int get_use_cache(); // stubs for now static const char *compressiontostr(const char *codec) { return codec; } diff --git a/cinelerra-5.1/cinelerra/filebase.C b/cinelerra-5.1/cinelerra/filebase.C index 4671fc4a..e2e14891 100644 --- a/cinelerra-5.1/cinelerra/filebase.C +++ b/cinelerra-5.1/cinelerra/filebase.C @@ -300,3 +300,16 @@ int64_t FileBase::base_memory_usage() } +VFrame *FileBase::new_cache_frame(VFrame *vframe, int64_t position) +{ + return file->new_cache_frame(vframe, position, 0); +} +void FileBase::put_cache_frame() +{ + return file->put_cache_frame(); +} +int FileBase::get_use_cache() +{ + return file->get_use_cache(); +} + diff --git a/cinelerra-5.1/cinelerra/filebase.h b/cinelerra-5.1/cinelerra/filebase.h index 3fb8be42..77893f9e 100644 --- a/cinelerra-5.1/cinelerra/filebase.h +++ b/cinelerra-5.1/cinelerra/filebase.h @@ -132,6 +132,10 @@ public: int channel, int64_t len); void allocate_history(int len); +// create cache frames + VFrame *new_cache_frame(VFrame *vframe, int64_t position); + void put_cache_frame(); + int get_use_cache(); // For static functions to access it Asset *asset; diff --git a/cinelerra-5.1/cinelerra/framecache.C b/cinelerra-5.1/cinelerra/framecache.C index fdf7ef35..be6be51c 100644 --- a/cinelerra-5.1/cinelerra/framecache.C +++ b/cinelerra-5.1/cinelerra/framecache.C @@ -204,87 +204,67 @@ void FrameCache::put_frame(VFrame *frame, int64_t position, lock->unlock(); } - - +VFrame *FrameCache::new_cache_frame(int64_t position, int w, int h, + int color_model, int layer, double frame_rate, int first_frame) +{ + FrameCacheItem *item = 0; + lock->lock("FrameCache::put_vframe"); + if( frame_exists(position, layer, frame_rate, color_model, w, h, &item, -1) ) { + lock->unlock(); + return 0; + } + if( first_frame ) { + while( last ) delete last; + total_items = 0; + current_item = 0; + } + item = new FrameCacheItem; + item->data = new VFrame(w, h, color_model); + item->position = position; + item->layer = layer; + item->frame_rate = frame_rate; + item->source_id = -1; + item->age = position < 0 ? INT_MAX : get_age(); + put_item(item); + return item->data; +} +void FrameCache::put_cache_frame() +{ + lock->unlock(); +} int FrameCache::frame_exists(VFrame *format, int64_t position, int layer, double frame_rate, FrameCacheItem **item_return, int source_id) { FrameCacheItem *item = (FrameCacheItem*)get_item(position); -// printf("FrameCache::frame_exists %d item=%p item->position=%jd position=%jd\n", -// __LINE__, -// item, -// item ? item->position : 0, -// position); - - while(item && item->position == position) - { -// printf("FrameCache::frame_exists %d %f,%f %d,%d %d,%d format match=%d item->data=%p\n", -// __LINE__, -// item->frame_rate, -// frame_rate, -// item->layer, -// layer, -// item->source_id, -// source_id, -// format->equivalent(item->data, 1), -// item->data); -// format->dump_params(); - -// This originally tested the frame stacks because a change in the -// interpolate plugin could cause CR2 to interpolate or not interpolate. -// This was disabled. - if(EQUIV(item->frame_rate, frame_rate) && - layer == item->layer && - format->equivalent(item->data, 0) && - (source_id == -1 || item->source_id == -1 || source_id == item->source_id)) - { + for( ; item && item->position == position; item = (FrameCacheItem*)item->next ) { + if( !EQUIV(item->frame_rate, frame_rate) ) continue; + if( layer != item->layer ) continue; + if( !format->equivalent(item->data, 0) ) continue; + if( source_id == -1 || item->source_id == -1 || + source_id == item->source_id ) { *item_return = item; return 1; } - else - item = (FrameCacheItem*)item->next; } return 0; } -int FrameCache::frame_exists(int64_t position, - int layer, - double frame_rate, - int color_model, - int w, - int h, - FrameCacheItem **item_return, - int source_id) +int FrameCache::frame_exists(int64_t position, int layer, double frame_rate, + int color_model, int w, int h, FrameCacheItem **item_return, int source_id) { FrameCacheItem *item = (FrameCacheItem*)get_item(position); - while(item && item->position == position) - { -// printf("FrameCache::frame_exists %d %f,%f %d,%d %d,%d %d,%d\n", -// __LINE__, -// item->frame_rate, -// frame_rate, -// item->layer, -// layer, -// item->data->get_color_model(), -// color_model, -// item->data->get_w(), -// w, -// item->data->get_h(), -// h); - - if(EQUIV(item->frame_rate, frame_rate) && - layer == item->layer && - color_model == item->data->get_color_model() && - w == item->data->get_w() && - h == item->data->get_h() && - (source_id == -1 || item->source_id == -1 || source_id == item->source_id)) - { + for( ; item && item->position == position ; item = (FrameCacheItem*)item->next ) { + if( !EQUIV(item->frame_rate, frame_rate) ) continue; + if( layer != item->layer ) continue; + if( color_model != item->data->get_color_model() ) continue; + if( w != item->data->get_w() ) continue; + if( h != item->data->get_h() ) continue; + if( source_id == -1 || item->source_id == -1 || + source_id == item->source_id ) { *item_return = item; return 1; } - else - item = (FrameCacheItem*)item->next; } return 0; } diff --git a/cinelerra-5.1/cinelerra/framecache.h b/cinelerra-5.1/cinelerra/framecache.h index 54222ff7..429c5bba 100644 --- a/cinelerra-5.1/cinelerra/framecache.h +++ b/cinelerra-5.1/cinelerra/framecache.h @@ -85,6 +85,13 @@ public: double frame_rate, int use_copy, Indexable *indexable); +// create new cache vframe at position, return 0 if it already exists +// if first_frame set, clear cache before new vframe created +// if new vframe created, leave cache locked for frame load + VFrame *new_cache_frame(int64_t position, int w, int h, + int color_model, int layer, double frame_rate, + int first_frame); + void put_cache_frame(); void dump(); diff --git a/cinelerra-5.1/cinelerra/mainmenu.C b/cinelerra-5.1/cinelerra/mainmenu.C index 42e845c9..3a694f72 100644 --- a/cinelerra-5.1/cinelerra/mainmenu.C +++ b/cinelerra-5.1/cinelerra/mainmenu.C @@ -638,7 +638,7 @@ int DumpUndo::handle_event() // ================================================= edit -Undo::Undo(MWindow *mwindow) : BC_MenuItem(_("Undo"), "z", 'z') +Undo::Undo(MWindow *mwindow) : BC_MenuItem(_("Undo"), "z or Ctrl-z", 'z') { this->mwindow = mwindow; } diff --git a/cinelerra-5.1/cinelerra/mainundo.C b/cinelerra-5.1/cinelerra/mainundo.C index 9f69f8eb..2e960b3b 100644 --- a/cinelerra-5.1/cinelerra/mainundo.C +++ b/cinelerra-5.1/cinelerra/mainundo.C @@ -219,12 +219,11 @@ int MainUndo::undo() } } + mwindow->reset_caches(1); reset_creators(); - mwindow->reset_caches(); return 0; } - int MainUndo::redo() { mwindow->gui->close_keyvalue_popup(); @@ -247,8 +246,8 @@ int MainUndo::redo() update_caption(current ? current->get_description() : ""); } } + mwindow->reset_caches(1); reset_creators(); - mwindow->reset_caches(); //dump(); return 0; } diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C index 8319bfbd..bb04335f 100644 --- a/cinelerra-5.1/cinelerra/mwindow.C +++ b/cinelerra-5.1/cinelerra/mwindow.C @@ -303,7 +303,7 @@ MWindow::~MWindow() gui->del_keyboard_listener( (int (BC_WindowBase::*)(BC_WindowBase *)) &MWindowGUI::keyboard_listener); - reset_caches(); + reset_caches(0); #if 0 // release the hounds if( awindow && awindow->gui ) awindow->gui->close(0); @@ -4089,18 +4089,18 @@ void MWindow::update_preferences(Preferences *prefs) if( prefs != preferences ) preferences->copy_from(prefs); if( cwindow->playback_engine ) - cwindow->playback_engine->preferences->copy_from(prefs); + cwindow->playback_engine->update_preferences(prefs); for(int i = 0; i < vwindows.size(); i++) { VWindow *vwindow = vwindows[i]; if( !vwindow->is_running() ) continue; if( vwindow->playback_engine ) - vwindow->playback_engine->preferences->copy_from(prefs); + vwindow->playback_engine->update_preferences(prefs); } for(int i = 0; i < zwindows.size(); i++) { ZWindow *zwindow = zwindows[i]; if( !zwindow->is_running() ) continue; if( zwindow->zgui->playback_engine ) - zwindow->zgui->playback_engine->preferences->copy_from(prefs); + zwindow->zgui->playback_engine->update_preferences(prefs); } } @@ -4475,9 +4475,8 @@ int MWindow::create_aspect_ratio(float &w, float &h, int width, int height) return 0; } -void MWindow::reset_caches() +void MWindow::reset_caches(int locked) { - int locked = gui->get_window_lock(); if( locked ) gui->unlock_window(); awindow->gui->stop_vicon_drawing(1); if( cwindow->playback_engine ) diff --git a/cinelerra-5.1/cinelerra/mwindow.h b/cinelerra-5.1/cinelerra/mwindow.h index 2f89d2d9..d7e54b1c 100644 --- a/cinelerra-5.1/cinelerra/mwindow.h +++ b/cinelerra-5.1/cinelerra/mwindow.h @@ -565,7 +565,7 @@ public: void remove_indexfile(Indexable *indexable); void rebuild_indices(); // Asset removal from caches - void reset_caches(); + void reset_caches(int locked); void remove_from_caches(Indexable *idxbl); void remove_assets_from_project(int push_undo, int redraw, int delete_indexes, ArrayList *drag_assets /* mwindow->session->drag_assets */, diff --git a/cinelerra-5.1/cinelerra/mwindowedit.C b/cinelerra-5.1/cinelerra/mwindowedit.C index f75896d7..2bf9a97c 100644 --- a/cinelerra-5.1/cinelerra/mwindowedit.C +++ b/cinelerra-5.1/cinelerra/mwindowedit.C @@ -1562,7 +1562,7 @@ int MWindow::paste_edls(ArrayList *new_edls, int load_mode, // Delete current project if( load_mode == LOADMODE_REPLACE || load_mode == LOADMODE_REPLACE_CONCATENATE ) { - reset_caches(); + reset_caches(1); edl->save_defaults(defaults); hide_plugins(); edl->Garbage::remove_user(); diff --git a/cinelerra-5.1/cinelerra/new.C b/cinelerra-5.1/cinelerra/new.C index f24876bc..a9f4aaf2 100644 --- a/cinelerra-5.1/cinelerra/new.C +++ b/cinelerra-5.1/cinelerra/new.C @@ -98,8 +98,8 @@ void New::create_new_edl() int New::create_new_project(int load_mode) { mwindow->stop_playback(0); + mwindow->reset_caches(0); mwindow->gui->lock_window(); - mwindow->reset_caches(); memcpy(new_edl->session->achannel_positions, &mwindow->preferences->channel_positions[new_edl->session->audio_channels - 1], diff --git a/cinelerra-5.1/cinelerra/performanceprefs.C b/cinelerra-5.1/cinelerra/performanceprefs.C index 12a8fc95..e13cb2f6 100644 --- a/cinelerra-5.1/cinelerra/performanceprefs.C +++ b/cinelerra-5.1/cinelerra/performanceprefs.C @@ -63,7 +63,6 @@ void PerformancePrefs::create_objects() char string[BCTEXTLEN]; BC_Resources *resources = BC_WindowBase::get_resources(); BC_WindowBase *win; - int maxw, curw; node_list = 0; generate_node_list(); @@ -73,38 +72,31 @@ void PerformancePrefs::create_objects() int y0 = y; win = add_subwindow(new BC_Title(x, y + ys5, _("Cache size (MB):"), MEDIUMFONT, resources->text_default)); - maxw = win->get_w(); - int x1 = x + xmargin4; - win = add_subwindow(new BC_Title(x1, y + ys5, _("Use HW Device:"))); - x1 += win->get_w() + xs5; - PrefsUseHWDev *use_hw_dev = new PrefsUseHWDev(pwindow, this, x1, y); - use_hw_dev->create_objects(); - + int maxw = win->get_w(); int y1 = y += ys30; - win = add_subwindow(new BC_Title(x, y + ys5, _("Seconds to preroll renders:"))); - if((curw = win->get_w()) > maxw) - maxw = curw; - maxw += x + xs5; - - cache_size = new CICacheSize(maxw, y0, pwindow, this); + win = add_subwindow(new BC_Title(x, y1 + ys5, _("Seconds to preroll renders:"))); + maxw = bmax(win->get_w(), maxw); + int x2 = x + maxw + xs5; + int y2 = y += ys30; + cache_size = new CICacheSize(x2, y0, pwindow, this); cache_size->create_objects(); - - add_subwindow(new BC_Title(x, y + ys5, _("Seconds to preroll renders:"))); - PrefsRenderPreroll *preroll = new PrefsRenderPreroll(pwindow, this, maxw, y1); + PrefsRenderPreroll *preroll = new PrefsRenderPreroll(pwindow, this, x2, y1); preroll->create_objects(); + add_subwindow(new PrefsForceUniprocessor(pwindow, x, y2)); y += ys30; - x1 = x + xmargin4; - BC_Title *smp_title = new BC_Title(x1, y + ys5, _("Project SMP cpus:")); - add_subwindow(smp_title); - x1 += smp_title->get_w() + xs5; - PrefsProjectSMP *proj_smp = new PrefsProjectSMP(pwindow, this, x1, y); + int x1 = x + xmargin4; + add_subwindow(cache_transitions = new CacheTransitions(x1, y0, pwindow, this)); + win = add_subwindow(new BC_Title(x1, y1, _("Use HW Device:"))); + maxw = win->get_w(); + win = add_subwindow(new BC_Title(x1, y2, _("Project SMP cpus:"))); + maxw = bmax(win->get_w(), maxw); + x2 = x1 + maxw + xs5; + PrefsUseHWDev *use_hw_dev = new PrefsUseHWDev(pwindow, this, x2, y1); + use_hw_dev->create_objects(); + PrefsProjectSMP *proj_smp = new PrefsProjectSMP(pwindow, this, x2, y2); proj_smp->create_objects(); - PrefsForceUniprocessor *force_1cpu = new PrefsForceUniprocessor(pwindow, x, y); - add_subwindow(force_1cpu); - y += ys30; - // Background rendering add_subwindow(new BC_Bar(xs5, y, get_w() - xs10)); y += ys5; @@ -322,6 +314,20 @@ int CICacheSize::handle_event() return 0; } +CacheTransitions::CacheTransitions(int x, int y, + PreferencesWindow *pwindow, PerformancePrefs *subwindow) + : BC_CheckBox(x, y, pwindow->thread->preferences->cache_transitions, + _("Cache Transitions")) +{ + this->pwindow = pwindow; +} + +int CacheTransitions::handle_event() +{ + pwindow->thread->preferences->cache_transitions = get_value(); + return 0; +} + PrefsUseHWDev::PrefsUseHWDev(PreferencesWindow *pwindow, PerformancePrefs *subwindow, int x, int y) diff --git a/cinelerra-5.1/cinelerra/performanceprefs.h b/cinelerra-5.1/cinelerra/performanceprefs.h index e9acd3c7..6d15a416 100644 --- a/cinelerra-5.1/cinelerra/performanceprefs.h +++ b/cinelerra-5.1/cinelerra/performanceprefs.h @@ -46,6 +46,7 @@ public: int hot_node; CICacheSize *cache_size; + CacheTransitions *cache_transitions; PerfsUseHWDev *use_hw_dev; enum @@ -338,6 +339,18 @@ public: PreferencesWindow *pwindow; }; +class CacheTransitions : public BC_CheckBox +{ +public: + CacheTransitions(int x, int y, + PreferencesWindow *pwindow, + PerformancePrefs *subwindow); + + int handle_event(); + + PreferencesWindow *pwindow; +}; + class PrefsUseHWDevItems : public ArrayList { public: diff --git a/cinelerra-5.1/cinelerra/performanceprefs.inc b/cinelerra-5.1/cinelerra/performanceprefs.inc index f034704c..d69da52a 100644 --- a/cinelerra-5.1/cinelerra/performanceprefs.inc +++ b/cinelerra-5.1/cinelerra/performanceprefs.inc @@ -44,6 +44,7 @@ class PrefsRenderFarmSortNodes; class PrefsRenderFarmReset; class PrefsRenderFarmWatchdog; class CICacheSize; +class CacheTransitions; class PerfsUseHWDev; #endif diff --git a/cinelerra-5.1/cinelerra/playbackengine.C b/cinelerra-5.1/cinelerra/playbackengine.C index b15edd62..571afe2a 100644 --- a/cinelerra-5.1/cinelerra/playbackengine.C +++ b/cinelerra-5.1/cinelerra/playbackengine.C @@ -466,6 +466,12 @@ int PlaybackEngine::get_direction() return TransportCommand::get_direction(curr_command); } +void PlaybackEngine::update_preferences(Preferences *prefs) +{ + preferences->copy_from(prefs); + create_render_engine(); +} + void PlaybackEngine::send_command(int command, EDL *edl, int wait_tracking, int use_inout) { //printf("PlaybackEngine::send_command 1 %d\n", command); diff --git a/cinelerra-5.1/cinelerra/playbackengine.h b/cinelerra-5.1/cinelerra/playbackengine.h index 65935c2b..9fdb45fb 100644 --- a/cinelerra-5.1/cinelerra/playbackengine.h +++ b/cinelerra-5.1/cinelerra/playbackengine.h @@ -86,6 +86,7 @@ public: void stop_playback(int wait); void refresh_frame(int change_type, EDL *edl, int dir=1); int get_direction(); + void update_preferences(Preferences *prefs); // Maintain caches through console changes CICache *audio_cache, *video_cache; diff --git a/cinelerra-5.1/cinelerra/preferences.C b/cinelerra-5.1/cinelerra/preferences.C index f783fbfc..9800fcee 100644 --- a/cinelerra-5.1/cinelerra/preferences.C +++ b/cinelerra-5.1/cinelerra/preferences.C @@ -59,6 +59,7 @@ Preferences::Preferences() if( strlen(index_directory) ) fs.complete_path(index_directory); cache_size = 0x10000000; + cache_transitions = 1; index_size = 0x400000; index_count = 500; use_thumbnails = 1; @@ -206,6 +207,7 @@ void Preferences::copy_from(Preferences *that) for( int i=0; ifile_probes.size(); ++i ) this->file_probes.append(new ProbePref(*that->file_probes[i])); cache_size = that->cache_size; + cache_transitions = that->cache_transitions; project_smp = that->project_smp; force_uniprocessor = that->force_uniprocessor; strcpy(lv2_path, that->lv2_path); @@ -387,6 +389,7 @@ int Preferences::load_defaults(BC_Hash *defaults) use_brender = defaults->get("USE_BRENDER", use_brender); brender_fragment = defaults->get("BRENDER_FRAGMENT", brender_fragment); cache_size = defaults->get("CACHE_SIZE", cache_size); + cache_transitions = defaults->get("CACHE_TRANSITIONS", cache_transitions); local_rate = defaults->get("LOCAL_RATE", local_rate); use_renderfarm = defaults->get("USE_RENDERFARM", use_renderfarm); renderfarm_port = defaults->get("RENDERFARM_PORT", renderfarm_port); @@ -485,6 +488,7 @@ int Preferences::save_defaults(BC_Hash *defaults) defaults->update("ANDROID_PORT", android_port); defaults->update("CACHE_SIZE", cache_size); + defaults->update("CACHE_TRANSITIONS", cache_transitions); defaults->update("INDEX_DIRECTORY", index_directory); defaults->update("INDEX_SIZE", index_size); defaults->update("INDEX_COUNT", index_count); diff --git a/cinelerra-5.1/cinelerra/preferences.h b/cinelerra-5.1/cinelerra/preferences.h index dc658981..4b60577a 100644 --- a/cinelerra-5.1/cinelerra/preferences.h +++ b/cinelerra-5.1/cinelerra/preferences.h @@ -156,6 +156,7 @@ public: // Several caches of cache_size exist so multiply by 4. // rendering, playback, timeline, preview int64_t cache_size; + int cache_transitions; int use_renderfarm; int renderfarm_port; diff --git a/cinelerra-5.1/cinelerra/preferencesthread.C b/cinelerra-5.1/cinelerra/preferencesthread.C index 52de4f55..47f16efd 100644 --- a/cinelerra-5.1/cinelerra/preferencesthread.C +++ b/cinelerra-5.1/cinelerra/preferencesthread.C @@ -124,6 +124,7 @@ BC_Window* PreferencesThread::new_gui() redraw_overlays = 0; close_assets = 0; reload_plugins = 0; + reset_caches = 0; //int need_new_indexes = 0; rerender = 0; @@ -251,6 +252,9 @@ int PreferencesThread::apply_settings() File::setenv_path("LV2_PATH", preferences->lv2_path, 1); mwindow->restart_status = -1; } + if( preferences->cache_size != mwindow->preferences->cache_size || + preferences->cache_transitions != mwindow->preferences->cache_transitions ) + reset_caches = 1; if( mwindow->preferences->perpetual_session && !preferences->perpetual_session ) mwindow->remove_undo_data(); @@ -269,6 +273,8 @@ int PreferencesThread::apply_settings() else { BC_Trace::disable_locks(); } + if( reset_caches ) + mwindow->reset_caches(0); mwindow->reset_android_remote(); int ffmpeg_early_probe = mwindow->preferences->get_file_probe_armed("FFMPEG_Early"); diff --git a/cinelerra-5.1/cinelerra/preferencesthread.h b/cinelerra-5.1/cinelerra/preferencesthread.h index 5309b22a..653199b6 100644 --- a/cinelerra-5.1/cinelerra/preferencesthread.h +++ b/cinelerra-5.1/cinelerra/preferencesthread.h @@ -71,6 +71,7 @@ public: int rerender; int close_assets; int reload_plugins; + int reset_caches; PreferencesWindow *window; MWindow *mwindow; // Copy of mwindow preferences diff --git a/cinelerra-5.1/cinelerra/vmodule.C b/cinelerra-5.1/cinelerra/vmodule.C index 89d00f59..56444190 100644 --- a/cinelerra-5.1/cinelerra/vmodule.C +++ b/cinelerra-5.1/cinelerra/vmodule.C @@ -218,73 +218,50 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit, //printf("VModule::import_frame %d cache=%p\n", __LINE__, get_cache()); if( current_edit->asset ) { get_cache()->age(); - file = get_cache()->check_out(current_edit->asset, - get_edl()); + file = get_cache()->check_out(current_edit->asset, get_edl()); // get_cache()->dump(); } // File found if( file || nested_edl ) { -// Make all positions based on requested frame rate. - int64_t edit_startproject = Units::to_int64(current_edit->startproject * - frame_rate / - edl_rate); - int64_t edit_startsource = Units::to_int64(current_edit->startsource * - frame_rate / - edl_rate); -// Source position going forward - uint64_t position = direction_position - - edit_startproject + - edit_startsource; int64_t nested_position = 0; - - - - - -// apply speed curve to source position so the timeline agrees with the playback - if( track->has_speed() ) { -// integrate position from start of edit. - double speed_position = edit_startsource; - FloatAutos *speed_autos = (FloatAutos*)track->automation->autos[AUTOMATION_SPEED]; - speed_position += speed_autos->automation_integral(edit_startproject, - direction_position-edit_startproject, PLAY_FORWARD); -//printf("VModule::import_frame %d %jd %jd\n", __LINE__, position, (int64_t)speed_position); - position = (int64_t)speed_position; - } - - - - - - int asset_w; - int asset_h; - if( debug ) printf("VModule::import_frame %d\n", __LINE__); - - -// maybe apply speed curve here, so timeline reflects actual playback - - - -// if we hit the end of stream, freeze at last frame - uint64_t max_position = 0; +// Source position going forward, in edl framerate + int64_t pos = Units::to_int64((double)direction_position / frame_rate * edl_rate); + int64_t len = pos - current_edit->startproject; + FloatAutos *speed_autos = !track->has_speed() ? 0 : + (FloatAutos*)track->automation->autos[AUTOMATION_SPEED]; + if( speed_autos && len > 0 ) + len = speed_autos->automation_integral(current_edit->startproject, len, PLAY_FORWARD); + pos = current_edit->startsource + len; +// Make positions based on requested frame rate. + int64_t position = Units::to_int64((double)pos * frame_rate / edl_rate); + + int64_t max_position; + int asset_w, asset_h; if( file ) { + asset_w = current_edit->asset->width; + asset_h = current_edit->asset->height; max_position = Units::to_int64((double)file->get_video_length() * - frame_rate / - current_edit->asset->frame_rate - 1); + frame_rate / current_edit->asset->frame_rate - 1); } else { + asset_w = nested_edl->session->output_w; + asset_h = nested_edl->session->output_h; max_position = Units::to_int64(nested_edl->tracks->total_length() * frame_rate - 1); } +// if we hit the end of stream, freeze at last frame + CLAMP(position, 0, max_position); - - if( position > max_position ) position = max_position; - else - if( position < 0 ) position = 0; + VFrame *&input = commonrender ? + ((VRender*)commonrender)->input_temp : // Realtime playback + input_temp ; // Menu effect + VFrame::get_temp(input, asset_w, asset_h, get_edl()->session->color_model); int use_cache = renderengine && - renderengine->command->single_frame(); + ( renderengine->command->single_frame() || + renderengine->command->get_direction() == PLAY_REVERSE ); + // int use_asynchronous = !use_cache && // renderengine && // Try to make rendering go faster. @@ -299,24 +276,54 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit, // else file->stop_video_thread(); - int64_t normalized_position = Units::to_int64(position * - current_edit->asset->frame_rate / - frame_rate); -// printf("VModule::import_frame %d %lld %lld\n", -// __LINE__, -// position, -// normalized_position); +// cache transitions + VEdit *vnext = (VEdit *)current_edit->next; + pos = Units::to_int64((double)input_position / frame_rate * edl_rate); + if( renderengine && renderengine->preferences->cache_transitions && + renderengine->command->get_direction() == PLAY_FORWARD && + current_edit->next && current_edit->next->transition && + file->get_video_length() >= 0 && pos >= vnext->startproject && + pos < vnext->startproject + vnext->transition->length ) { + file->set_cache_frames(0); + file->set_layer(current_edit->channel); + VEdit *vnext = (VEdit *)current_edit->next; + Track *track = current_edit->track; + FloatAutos *speed_autos = (FloatAutos*)(track->has_speed() ? + track->automation->autos[AUTOMATION_SPEED] : 0); + int64_t end = vnext->startproject + vnext->transition->length; + int first_frame = 1; + int count = renderengine->preferences->cache_size / + input->get_data_size() / 2; // try to burn only 1/2 of cache + while( !result && pos < end && count > 0 ) { + int64_t curr_pos = pos - current_edit->startproject; + if( curr_pos > 0 && speed_autos ) + curr_pos = speed_autos->automation_integral( + current_edit->startproject, curr_pos, PLAY_FORWARD); + curr_pos += current_edit->startsource; + int64_t norm_pos = Units::to_int64((double)curr_pos * + current_edit->asset->frame_rate / edl_rate); + VFrame *cache_frame = file->new_cache_frame(input, norm_pos, first_frame); + if( cache_frame ) { + file->set_video_position(norm_pos, 0); + result = file->read_frame(cache_frame); + file->put_cache_frame(); + } + else if( first_frame ) // already loaded + break; + first_frame = 0; + ++pos; --count; + } + use_cache = 1; + } + + int64_t normalized_position = Units::to_int64((double)position * + current_edit->asset->frame_rate / frame_rate); +//printf("VModule::import_frame %d %lld %lld\n", __LINE__, position, normalized_position); file->set_layer(current_edit->channel); - file->set_video_position(normalized_position, - 0); - asset_w = current_edit->asset->width; - asset_h = current_edit->asset->height; -//printf("VModule::import_frame %d normalized_position=%lld\n", __LINE__, normalized_position); + file->set_video_position(normalized_position, 0); } else { if( debug ) printf("VModule::import_frame %d\n", __LINE__); - asset_w = nested_edl->session->output_w; - asset_h = nested_edl->session->output_h; // Get source position in nested frame rate in direction of playback. nested_position = Units::to_int64(position * nested_edl->session->frame_rate / @@ -375,35 +382,14 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit, !EQUIV(in_h, asset_h)) { //printf("VModule::import_frame %d file -> temp -> output\n", __LINE__); // Get temporary input buffer - VFrame **input = 0; -// Realtime playback - if( commonrender ) { - VRender *vrender = (VRender*)commonrender; -//printf("VModule::import_frame %d vrender->input_temp=%p\n", __LINE__, vrender->input_temp); - input = &vrender->input_temp; - } - else { -// Menu effect - input = &input_temp; - } - - - if( (*input) && - ((*input)->get_w() != asset_w || - (*input)->get_h() != asset_h) ) { - delete (*input); - (*input) = 0; - } - - if( !(*input) ) { - (*input) = - new VFrame(asset_w, asset_h, - get_edl()->session->color_model); - } + VFrame **input = commonrender ? // Realtime playback + &((VRender*)commonrender)->input_temp : + &input_temp ; // Menu effect + VFrame::get_temp(*input, asset_w, asset_h, + get_edl()->session->color_model); (*input)->copy_stacks(output); - // file -> temp -// Cache for single frame only +// Cache for single frame, reverse playback if( file ) { if( debug ) printf("VModule::import_frame %d this=%p file=%s\n", __LINE__, diff --git a/cinelerra-5.1/cinelerra/vrender.C b/cinelerra-5.1/cinelerra/vrender.C index 64384430..bcb87a4e 100644 --- a/cinelerra-5.1/cinelerra/vrender.C +++ b/cinelerra-5.1/cinelerra/vrender.C @@ -133,7 +133,8 @@ int VRender::process_buffer(int64_t input_position, int use_vconsole = 1; int use_brender = 0; int result = 0; - int use_cache = renderengine->command->single_frame(); + int use_cache = renderengine->command->single_frame() || + renderengine->command->get_direction() == PLAY_REVERSE; // int use_asynchronous = // renderengine->command->realtime && // renderengine->get_edl()->session->video_every_frame && diff --git a/cinelerra-5.1/po/ru.po b/cinelerra-5.1/po/ru.po index ccd575c7..93b35adc 100644 --- a/cinelerra-5.1/po/ru.po +++ b/cinelerra-5.1/po/ru.po @@ -1,20 +1,18 @@ -# translation of cin.po to russian -# translation of ru-4.po to -# translation of ru-3.po to -# translation of ru-2.po to -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# Translation of Cinelerra-GG Infinity to Russian +# Copyright (C) 2006-2019 Heroine Virtual Ltd. by Adam Williams +# Copyright (C) 2007-2020 mods for Cinelerra-GG by W.P.Morrow aka goodguy # This file is distributed under the same license as the PACKAGE package. # -# Andrew Randrianasulu , 2019, 2020. # Igor Vladimirsky aka igor_ubuntu 2016-2018 +# Andrew Randrianasulu randrianasulu@gmail.com> 2019-2020 msgid "" msgstr "" -"Project-Id-Version: CinelerraGG\n" -"Report-Msgid-Bugs-To: \n" +"Project-Id-Version: Cinelerra-GG Infinity\n" +"Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-09-01 04:28+0300\n" "PO-Revision-Date: 2020-09-06 15:06+0300\n" "Last-Translator: Andrew Randrianasulu \n" -"Language-Team: русский >\n" +"Language-Team: \n" "Language: ru_RU\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n"