Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.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 <math.h>
33 #include <string.h>
34 #include <unistd.h>
35
36
37
38 FrameCacheItem::FrameCacheItem()
39  : CacheItemBase()
40 {
41         data = 0;
42         position = 0;
43         frame_rate = (double)30000.0 / 1001;
44 }
45
46 FrameCacheItem::~FrameCacheItem()
47 {
48         delete data;
49 }
50
51 int FrameCacheItem::get_size()
52 {
53         if(data) return data->get_data_size() + (path ? strlen(path)+1 : 0);
54         return 0;
55 }
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 FrameCache::FrameCache()
72  : CacheBase()
73 {
74 }
75
76 FrameCache::~FrameCache()
77 {
78 }
79
80
81 // Returns 1 if frame exists in cache and copies it to the frame argument.
82 int FrameCache::get_frame(VFrame *frame, 
83         int64_t position,
84         int layer,
85         double frame_rate,
86         int source_id)
87 {
88         lock->lock("FrameCache::get_frame");
89         FrameCacheItem *result = 0;
90
91         if(frame_exists(frame,
92                 position, 
93                 layer,
94                 frame_rate,
95                 &result,
96                 source_id))
97         {
98                 if(result->data) 
99                 {
100 // Frame may have come from the readahead thread.
101 // Those frames are in the codec color model.
102 // But to pass frame_exists, they must be identical.
103 //                      BC_CModels::transfer(frame->get_rows(), 
104 //                              result->data->get_rows(),
105 //                              result->data->get_y(),
106 //                              result->data->get_u(),
107 //                              result->data->get_v(),
108 //                              frame->get_y(),
109 //                              frame->get_u(),
110 //                              frame->get_v(),
111 //                              0, 
112 //                              0, 
113 //                              result->data->get_w(), 
114 //                              result->data->get_h(),
115 //                              0, 
116 //                              0, 
117 //                              frame->get_w(), 
118 //                              frame->get_h(),
119 //                              result->data->get_color_model(), 
120 //                              frame->get_color_model(),
121 //                              0,
122 //                              result->data->get_w(),
123 //                              frame->get_w());
124
125
126                         frame->copy_from(result->data);
127
128
129 // This would have copied the color matrix for interpolate, but
130 // required the same plugin stack as the reader.
131 //                      frame->copy_stacks(result->data);
132                         frame->copy_params(result->data);
133                 }
134                 result->age = get_age();
135         }
136
137
138
139
140         lock->unlock();
141         if(result) return 1;
142         return 0;
143 }
144
145
146 VFrame* FrameCache::get_frame_ptr(int64_t position,
147         int layer,
148         double frame_rate,
149         int color_model,
150         int w,
151         int h,
152         int source_id)
153 {
154         lock->lock("FrameCache::get_frame_ptr");
155         FrameCacheItem *result = 0;
156         if(frame_exists(position,
157                 layer,
158                 frame_rate,
159                 color_model,
160                 w,
161                 h,
162                 &result,
163                 source_id))
164         {
165                 result->age = get_age();
166                 return result->data;
167         }
168
169
170         lock->unlock();
171         return 0;
172 }
173
174 // Puts frame in cache if enough space exists and the frame doesn't already
175 // exist.
176 void FrameCache::put_frame(VFrame *frame, 
177         int64_t position,
178         int layer,
179         double frame_rate,
180         int use_copy,
181         Indexable *indexable)
182 {
183         lock->lock("FrameCache::put_frame");
184         FrameCacheItem *item = 0;
185         int source_id = -1;
186         if(indexable) source_id = indexable->id;
187
188 //printf("FrameCache::put_frame %d position=%jd\n", __LINE__, position);
189
190         if(frame_exists(frame,
191                 position, 
192                 layer,
193                 frame_rate,
194                 &item,
195                 source_id))
196         {
197                 item->age = get_age();
198                 lock->unlock();
199                 return;
200         }
201
202
203         item = new FrameCacheItem;
204
205         if(use_copy)
206         {
207                 item->data = new VFrame(*frame);
208         }
209         else
210         {
211                 item->data = frame;
212         }
213
214 // Copy metadata
215         item->position = position;
216         item->layer = layer;
217         item->frame_rate = frame_rate;
218         item->source_id = source_id;
219         if(indexable) 
220                 item->path = cstrdup(indexable->path);
221
222         item->age = get_age();
223
224 //printf("FrameCache::put_frame %d position=%jd\n", __LINE__, position);
225         put_item(item);
226         lock->unlock();
227 }
228
229
230
231
232 int FrameCache::frame_exists(VFrame *format,
233         int64_t position, 
234         int layer,
235         double frame_rate,
236         FrameCacheItem **item_return,
237         int source_id)
238 {
239         FrameCacheItem *item = (FrameCacheItem*)get_item(position);
240 // printf("FrameCache::frame_exists %d item=%p item->position=%jd position=%jd\n",
241 // __LINE__,
242 // item,
243 // item ? item->position : 0,
244 // position);
245
246         while(item && item->position == position)
247         {
248 // printf("FrameCache::frame_exists %d %f,%f %d,%d %d,%d format match=%d item->data=%p\n",
249 // __LINE__,
250 // item->frame_rate,
251 // frame_rate,
252 // item->layer,
253 // layer,
254 // item->source_id,
255 // source_id,
256 // format->equivalent(item->data, 1),
257 // item->data);
258 // format->dump_params();
259
260 // This originally tested the frame stacks because a change in the 
261 // interpolate plugin could cause CR2 to interpolate or not interpolate.
262 // This was disabled.
263                 if(EQUIV(item->frame_rate, frame_rate) &&
264                         layer == item->layer &&
265                         format->equivalent(item->data, 0) &&
266                         (source_id == -1 || item->source_id == -1 || source_id == item->source_id))
267                 {
268                         *item_return = item;
269                         return 1;
270                 }
271                 else
272                         item = (FrameCacheItem*)item->next;
273         }
274         return 0;
275 }
276
277 int FrameCache::frame_exists(int64_t position, 
278         int layer,
279         double frame_rate,
280         int color_model,
281         int w,
282         int h,
283         FrameCacheItem **item_return,
284         int source_id)
285 {
286         FrameCacheItem *item = (FrameCacheItem*)get_item(position);
287         while(item && item->position == position)
288         {
289 // printf("FrameCache::frame_exists %d %f,%f %d,%d %d,%d %d,%d\n",
290 // __LINE__,
291 // item->frame_rate,
292 // frame_rate,
293 // item->layer,
294 // layer,
295 // item->data->get_color_model(),
296 // color_model,
297 // item->data->get_w(),
298 // w,
299 // item->data->get_h(),
300 // h);
301
302                 if(EQUIV(item->frame_rate, frame_rate) &&
303                         layer == item->layer &&
304                         color_model == item->data->get_color_model() &&
305                         w == item->data->get_w() &&
306                         h == item->data->get_h() &&
307                         (source_id == -1 || item->source_id == -1 || source_id == item->source_id))
308                 {
309                         *item_return = item;
310                         return 1;
311                 }
312                 else
313                         item = (FrameCacheItem*)item->next;
314         }
315         return 0;
316 }
317
318
319 void FrameCache::dump()
320 {
321 //      lock->lock("FrameCache::dump");
322         printf("FrameCache::dump 1 %d\n", total());
323         FrameCacheItem *item = (FrameCacheItem *)first;
324         while( item ) {
325                 printf("  position=%jd frame_rate=%f age=%d size=%jd\n", 
326                         item->position, item->frame_rate, item->age,
327                         item->data->get_data_size());
328                 item = (FrameCacheItem*)item->next;
329         }
330 //      lock->unlock();
331 }
332
333
334
335