add transition caching with pref, rev read frame caching, cache lock tweaks, fix...
authorGood Guy <[email protected]>
Sat, 12 Sep 2020 15:20:26 +0000 (09:20 -0600)
committerGood Guy <[email protected]>
Sat, 12 Sep 2020 15:20:26 +0000 (09:20 -0600)
29 files changed:
cinelerra-5.1/cinelerra/asset.C
cinelerra-5.1/cinelerra/cache.C
cinelerra-5.1/cinelerra/editpanel.C
cinelerra-5.1/cinelerra/ffmpeg.C
cinelerra-5.1/cinelerra/ffmpeg.h
cinelerra-5.1/cinelerra/file.C
cinelerra-5.1/cinelerra/file.h
cinelerra-5.1/cinelerra/filebase.C
cinelerra-5.1/cinelerra/filebase.h
cinelerra-5.1/cinelerra/framecache.C
cinelerra-5.1/cinelerra/framecache.h
cinelerra-5.1/cinelerra/mainmenu.C
cinelerra-5.1/cinelerra/mainundo.C
cinelerra-5.1/cinelerra/mwindow.C
cinelerra-5.1/cinelerra/mwindow.h
cinelerra-5.1/cinelerra/mwindowedit.C
cinelerra-5.1/cinelerra/new.C
cinelerra-5.1/cinelerra/performanceprefs.C
cinelerra-5.1/cinelerra/performanceprefs.h
cinelerra-5.1/cinelerra/performanceprefs.inc
cinelerra-5.1/cinelerra/playbackengine.C
cinelerra-5.1/cinelerra/playbackengine.h
cinelerra-5.1/cinelerra/preferences.C
cinelerra-5.1/cinelerra/preferences.h
cinelerra-5.1/cinelerra/preferencesthread.C
cinelerra-5.1/cinelerra/preferencesthread.h
cinelerra-5.1/cinelerra/vmodule.C
cinelerra-5.1/cinelerra/vrender.C
cinelerra-5.1/po/ru.po

index fab58403d7c54cfaefccc06232ffcf45d9f97589..2828fe31df7a535088d45da3713a084bd22edbd0 100644 (file)
@@ -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);
 }
 
index 80bf347b677a49d9aee95d011514719aa814f799..a93f1e1b994f7d800ad08d61e8e3deeff11f74c7 100644 (file)
@@ -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;
 }
 
index 1f75414f45a68d668661f96a24e3cbca3af9c4e5..bf33acba43bf1dce3e4af4d0215bf26fe9547223 100644 (file)
@@ -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()
 {
index c08a01db57d0431977e98c4ddd35913e413be33d..57232271b1473e750337eda8886b838df12e6f65 100644 (file)
@@ -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 ) {
index 1a514e1d57f8f58a4a3124dc411f0e2d408df065..aa01785a449020e8969931b20345c69b452533b9 100644 (file)
@@ -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;
index f9571c9d1dddd60bb37704dda5a18d0e740c8200..6459ebe8463e61cd48b5a8a2cac980e3cb4f8cab 100644 (file)
@@ -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[] = { 
index 6b660b5edf92597834f9d4da0eb278cf29a99dcf..e0cf4fa37f94cbc91fa57097ded6967ba413f23a 100644 (file)
@@ -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; }
index 4671fc4aab94032af9ddf77bf1e0693df87a247a..e2e148919983507615811af7a35ffc12c142ba9e 100644 (file)
@@ -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();
+}
+
index 3fb8be42087ac8195bc442357355cbaeeb2e35c7..77893f9e82ac9d7c3b1b35c38583dfe9225625b4 100644 (file)
@@ -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;
index fdf7ef358e11088c696869555efefbe5d354469c..be6be51cb119c029a0d079f9c0fff11baaf288df 100644 (file)
@@ -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;
 }
index 54222ff72ba7e3eb7472d79e03e6799e9a51cde4..429c5bbada836ee64b9269e7ad503832485f9668 100644 (file)
@@ -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();
 
index 42e845c9d6bff4e3911236ae690653580eafc424..3a694f72b6099155ab862fdb8ae929295f246f6e 100644 (file)
@@ -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;
 }
index 9f69f8eb4754b8064dfc28590a202e24e4b70e62..2e960b3b2fb1c7f62ba01a6b84cf9fc1880508d1 100644 (file)
@@ -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;
 }
index 8319bfbdead591e94afdb0a1e3ae7f79c87b36d2..bb04335f118e6b85f9bac7a95ad323fa65c5ce93 100644 (file)
@@ -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 )
index 2f89d2d904adda968d1ec99e26444f113c24a821..d7e54b1cba31e3cd1d144ae34ba5463e2f5648e5 100644 (file)
@@ -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<Indexable*> *drag_assets /* mwindow->session->drag_assets */,
index f75896d73ec01602ef76e31b5560aeecedd103b6..2bf9a97cf2192127e6a7863c447b84e292a7c3ff 100644 (file)
@@ -1562,7 +1562,7 @@ int MWindow::paste_edls(ArrayList<EDL*> *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();
index f24876bc09a11dbae1a9ff7e9e08c455ec77dc97..a9f4aaf235a3efcb97b3ee8c68730b6375828873 100644 (file)
@@ -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],
index 12a8fc950cfb5a0d1389d6d01516cabce78537f6..e13cb2f65f2d4b0a3523146d4822973758ae964c 100644 (file)
@@ -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)
index e9acd3c70f8c9212170ec900c36ceb078209ee3f..6d15a416380313428e3c7dcb224f28163577095c 100644 (file)
@@ -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<BC_ListBoxItem *>
 {
 public:
index f034704c535b17178a8d283270f5a2ecc59142d9..d69da52a29c9d7caa44da6dabe819f3a76b8d727 100644 (file)
@@ -44,6 +44,7 @@ class PrefsRenderFarmSortNodes;
 class PrefsRenderFarmReset;
 class PrefsRenderFarmWatchdog;
 class CICacheSize;
+class CacheTransitions;
 class PerfsUseHWDev;
 
 #endif
index b15edd62c1636d0de0b135b479d35d97fb4c7071..571afe2a83a174a3eaeeab536182258131839d2b 100644 (file)
@@ -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);
index 65935c2bd9d5c8850fcb68aa0c5608b764f5699e..9fdb45fbc428fd5b7b8d35be2b5ebee141b33d55 100644 (file)
@@ -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;
index f783fbfc8998eb60c2b513e89b1f2838861f6f55..9800fceec14100454dca4b53eb2fe72522c4ef4f 100644 (file)
@@ -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; i<that->file_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);
index dc6589819dd54af5dd9837b6560a9495fd650dde..4b60577ab9f2b7dab56422b3a831b1ee6d2b2e1b 100644 (file)
@@ -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;
index 52de4f5526a2888d8e8dd2341c709916f2c40339..47f16efd8345f2594f11e081d66b6ed08ccc9ce6 100644 (file)
@@ -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");
index 5309b22adcc1bc7ee49a60fe90107efe9373d9d8..653199b6bf7762af70b31192bf20e77742cdbbb7 100644 (file)
@@ -71,6 +71,7 @@ public:
        int rerender;
        int close_assets;
        int reload_plugins;
+       int reset_caches;
        PreferencesWindow *window;
        MWindow *mwindow;
 // Copy of mwindow preferences
index 89d00f59427d9ba70a59702a9559017b2286ca9d..5644419070e68b754238378fca4c86b281287fa1 100644 (file)
@@ -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__,
index 6438443019e6bc9bfee9a12395663a8d56d08ae2..bcb87a4e6e99cd3e13c953c6f8889df4059efa80 100644 (file)
@@ -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 &&
index ccd575c757e9da7149de9164959084ebec58b248..93b35adc73a0fbc22c935d3c5cfe943b8bad179c 100644 (file)
@@ -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 <[email protected]>, 2019, 2020.
 # Igor Vladimirsky aka igor_ubuntu <[email protected]> 2016-2018
+# Andrew Randrianasulu [email protected]> 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: <[email protected]>\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 <[email protected]>\n"
-"Language-Team: русский <Igor Vladimirsky aka igor_ubuntu <[email protected]>>\n"
+"Language-Team: <[email protected]>\n"
 "Language: ru_RU\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"