add Autosave continuous backups by Andras Reuss and Andrew-R
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / framecache.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bcsignals.h"
23 #include "clip.h"
24 #include "cstrdup.h"
25 #include "edl.h"
26 #include "framecache.h"
27 #include "indexable.h"
28 #include "mutex.h"
29 #include "vframe.h"
30
31
32 #include <limits.h>
33 #include <math.h>
34 #include <string.h>
35 #include <unistd.h>
36
37
38
39 FrameCacheItem::FrameCacheItem()
40  : CacheItemBase()
41 {
42         data = 0;
43         position = 0;
44         frame_rate = (double)30000.0 / 1001;
45 }
46
47 FrameCacheItem::~FrameCacheItem()
48 {
49         delete data;
50 }
51
52 int FrameCacheItem::get_size()
53 {
54         if(data) return data->get_data_size() + (path ? strlen(path)+1 : 0);
55         return 0;
56 }
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 FrameCache::FrameCache()
73  : CacheBase()
74 {
75 }
76
77 FrameCache::~FrameCache()
78 {
79 }
80
81
82 VFrame* FrameCache::get_frame_ptr(int64_t position, int layer, double frame_rate,
83                 int color_model, int w, int h, int source_id)
84 {
85         lock->lock("FrameCache::get_frame_ptr");
86         VFrame *vframe = get_vframe(position, w, h, color_model,
87                         layer, frame_rate, source_id);
88         if( vframe ) return vframe;  // not unlocked
89         lock->unlock();
90         return 0;
91 }
92
93 VFrame *FrameCache::get_vframe(int64_t position, int w, int h,
94                 int color_model, int layer, double frame_rate,
95                 int source_id)
96 {
97         FrameCacheItem *item = 0;
98         int ret = frame_exists(position, layer, frame_rate,
99                         w, h, color_model, &item, source_id);
100         if( ret && position >= 0 && item )
101                 item->age = get_age();
102         return ret && item ? item->data : 0;
103 }
104
105 VFrame *FrameCache::get_frame(int64_t position, int w, int h,
106                 int color_model, int layer, double frame_rate,
107                 int source_id)
108 {
109         lock->lock("FrameCache::get_frame");
110         VFrame *frame = get_vframe(position, w, h,
111                         color_model, layer, frame_rate, source_id);
112         lock->unlock();
113         return frame;
114 }
115
116 // Returns 1 if frame exists in cache and copies it to the frame argument.
117 int FrameCache::get_frame(VFrame *frame, int64_t position,
118                 int layer, double frame_rate, int source_id)
119 {
120         lock->lock("FrameCache::get_frame");
121         VFrame *vframe = get_vframe(position,
122                         frame->get_w(), frame->get_h(), frame->get_color_model(),
123                         layer, frame_rate, source_id);
124         if( vframe )
125                 frame->copy_from(vframe);
126         lock->unlock();
127         return vframe ? 1 : 0;
128 }
129
130
131 void FrameCache::put_vframe(VFrame *frame, int64_t position,
132                 int layer, double frame_rate, int source_id)
133 {
134         FrameCacheItem *item = new FrameCacheItem;
135         item->data = frame;
136         item->position = position;
137         item->layer = layer;
138         item->frame_rate = frame_rate;
139         item->source_id = source_id;
140         item->age = position < 0 ? INT_MAX : get_age();
141         put_item(item);
142 }
143
144 // Puts frame in cache if the frame doesn't already exist.
145 void FrameCache::put_frame(VFrame *frame, int64_t position,
146                 int layer, double frame_rate, int use_copy, Indexable *idxbl)
147 {
148         int source_id = idxbl ? idxbl->id : -1;
149         lock->lock("FrameCache::put_frame");
150         VFrame *vframe = get_vframe(position,
151                         frame->get_w(), frame->get_h(), frame->get_color_model(),
152                         layer, frame_rate, source_id);
153         if( !vframe ) {
154                 if( use_copy ) frame = new VFrame(*frame);
155                 put_vframe(frame, position, layer, frame_rate, source_id);
156         }
157         lock->unlock();
158 }
159
160 // get vframe for keys, overwrite frame if found
161 int FrameCache::get_cache_frame(VFrame *frame, int64_t position,
162                 int layer, double frame_rate)
163 {
164         lock->lock("FrameCache::get_cache_frame");
165         VFrame *vframe = get_vframe(position,
166                 frame->get_w(), frame->get_h(), frame->get_color_model(),
167                 layer, frame_rate, -1);
168         if( vframe )
169                 frame->copy_from(vframe);
170         lock->unlock();
171         return vframe ? 1 : 0;
172 }
173
174 // adds or replaces vframe, consumes frame if not use_copy
175 void FrameCache::put_cache_frame(VFrame *frame, int64_t position,
176                 int layer, double frame_rate, int use_copy)
177 {
178         lock->lock("FrameCache::put_cache_frame");
179         FrameCacheItem *item = 0;
180         int w = frame->get_w(), h = frame->get_h(); 
181         int color_model = frame->get_color_model();
182         int ret = frame_exists(position, layer, frame_rate,
183                         w, h, color_model, &item, -1);
184         if( use_copy ) {
185 // do not use shm here, puts too much pressure on 32bit systems
186                 VFrame *vframe = new VFrame(w, h, color_model, 0);
187                 vframe->copy_from(frame);
188                 frame = vframe;
189         }
190         if( ret ) {
191                 delete item->data;
192                 item->data = frame;
193         }
194         else
195                 put_vframe(frame, position, layer, frame_rate, -1);
196         lock->unlock();
197 }
198
199
200 int FrameCache::frame_exists(VFrame *format, int64_t position,
201         int layer, double frame_rate, FrameCacheItem **item_return, int source_id)
202 {
203         FrameCacheItem *item = (FrameCacheItem*)get_item(position);
204         for( ; item && item->position == position; item = (FrameCacheItem*)item->next ) {
205                 if( !EQUIV(item->frame_rate, frame_rate) ) continue;
206                 if( layer != item->layer ) continue;
207                 if( !format->equivalent(item->data, 0) ) continue;
208                 if( source_id == -1 || item->source_id == -1 ||
209                     source_id == item->source_id ) {
210                         *item_return = item;
211                         return 1;
212                 }
213         }
214         return 0;
215 }
216
217 int FrameCache::frame_exists(int64_t position, int layer, double frame_rate,
218                 int w, int h, int color_model, FrameCacheItem **item_return, int source_id)
219 {
220         FrameCacheItem *item = (FrameCacheItem*)get_item(position);
221         for( ; item && item->position == position ; item = (FrameCacheItem*)item->next ) {
222                 if( !EQUIV(item->frame_rate, frame_rate) ) continue;
223                 if( layer != item->layer ) continue;
224                 if( color_model != item->data->get_color_model() ) continue;
225                 if( w != item->data->get_w() ) continue;
226                 if( h != item->data->get_h() ) continue;
227                 if( source_id == -1 || item->source_id == -1 ||
228                     source_id == item->source_id ) {
229                         *item_return = item;
230                         return 1;
231                 }
232         }
233         return 0;
234 }
235
236
237 void FrameCache::dump()
238 {
239 //      lock->lock("FrameCache::dump");
240         printf("FrameCache::dump 1 %d\n", total());
241         FrameCacheItem *item = (FrameCacheItem *)first;
242         while( item ) {
243                 printf("  position=%jd frame_rate=%f age=%d size=%ld\n",
244                         item->position, item->frame_rate, item->age,
245                         item->data->get_data_size());
246                 item = (FrameCacheItem*)item->next;
247         }
248 //      lock->unlock();
249 }
250
251
252
253