diff -r cinelerra/hvirtual/cinelerra/file.C base-cvs/hvirtual/cinelerra/file.C
30,251d29
<  FrameCache::FrameCache(int cache_size) 
<  {
<  	cache_enabled = 0;
<  	this->cache_size = cache_size;
<  	timer.update();
<  }
<  
<  FrameCache::~FrameCache() 
<  {
< 	reset();
<  }
<  
<  void FrameCache::reset() 
<  {	
<  	change_lock.lock();
<  	FrameCacheTree::iterator iterator = cache_tree.begin();
<  	while (iterator != cache_tree.end()) {
<  		delete iterator->second;
<  		iterator++;
< 	}
<  	cache_tree.clear();
<  	cache_tree_bytime.clear();
<  	change_lock.unlock();
<  }
<  
<  void FrameCache::enable_cache() 
<  {	
<  	cache_enabled = 1;
<  }
<  
<  
<  void FrameCache::disable_cache() 
<  {
<  	cache_enabled = 0;
<  }
<  
<  void FrameCache::unlock_cache()
<  { 
<  	change_lock.unlock();
<  }
<  
<  void FrameCache::lock_cache()
<  { 
<  	change_lock.lock();
<  }
<  
<  inline int FrameCache::compare_with_frame(FrameCacheElement *element, 
<  					int frame_number, 
<  					int frame_layer,
<  					int frame_width,
<  					int frame_height,
<  					int frame_color_model)
<  {
<  	if (	element->frame_number == frame_number && 
< 		element->frame_layer == frame_layer && 
<  		element->frame->get_w() == frame_width && 
<  		element->frame->get_h() == frame_height && 
<  		element->frame->get_color_model() == frame_color_model)
<  			return 1; 
<  		else
<  			return 0;
<  }
<  
<  FrameCacheTree::iterator FrameCache::find_element_byframe(long frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model)
<  {
<  	FrameCacheTree::iterator iterator = cache_tree.find(frame_number);
<    	if(iterator != cache_tree.end()) {
<  		do {
<  			if (compare_with_frame(iterator->second, 
<  						frame_number, 
<  						frame_layer,
<  						frame_width,
<  						frame_height,
<  						frame_color_model))
<  			{
<  				
<  				return iterator;
<  			}
<  			iterator++;
<  		} while (iterator->first == frame_number);
<  	}
<  	return cache_tree.end();
<  }
<  
<  FrameCacheTree_ByTime::iterator FrameCache::find_element_bytime(long long frame_time_diff, long frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model)
<  {
<  	FrameCacheTree_ByTime::iterator iterator = cache_tree_bytime.find(frame_time_diff);
<    	if(iterator != cache_tree_bytime.end()) {
<  		do {	
<  			if (compare_with_frame(iterator->second, 
<  						frame_number, 
<  						frame_layer,
<  						frame_width,
<  						frame_height,
<  						frame_color_model))
<  			{
<  				
<  				return iterator;
<  			}
<  			iterator++;
<  		} while (iterator->first == frame_time_diff);
<  	}
<  	return cache_tree_bytime.end();
<  }
<  
<   
<  // implicitly locks the class, needs to be unlocked after the call
<  // this is the best behaviour, everything else just complicates things and
<  // causes races (because you don't know the state of cache_enabled during the call).
<  VFrame *FrameCache::get_frame(long frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model)
<  {
<  
<  	change_lock.lock();
<  	if (!cache_enabled) return 0;
<  //	printf("Looking for - frame: %li, layer: %i, w: %i, h:%i, cm: %i\n", frame_number, frame_layer, frame_width, frame_height, frame_color_model);
<  	FrameCacheTree::iterator iterator= find_element_byframe(frame_number, 
<  								frame_layer,
<  								frame_width,
<  								frame_height,
<  								frame_color_model);
<  	// update timestamp in other tree
<  	if (iterator != cache_tree.end())
<  	{
<  		FrameCacheElement *cache_element = iterator->second;
<  		FrameCacheTree_ByTime::iterator iterator_bytime;
<  		// this tree node always exists
<  		iterator_bytime = find_element_bytime(cache_element->time_diff,
<  								frame_number, 
<  								frame_layer,
<  								frame_width,
<  								frame_height,
<  								frame_color_model);
<  		if (cache_element != iterator_bytime->second)
<  		{
<  			printf("FrameCache: Something severely wrong in the cache engine!! this: %p\n", this);
<  			dump();
<  			return 0;
<  		};
<  //		printf("Cache hit - frame: %li, layer: %i, w: %i, h:%i, cm: %i\n", frame_number, frame_layer, frame_width, frame_height, frame_color_model);
<  		// delete & replace with new key
<  		cache_tree_bytime.erase(iterator_bytime);
<  		cache_element->time_diff = timer.get_difference();
<  		cache_tree_bytime.insert(std::pair<long long, FrameCacheElement *> (cache_element->time_diff, cache_element)); 
<  		return (cache_element->frame);
<  	};
<  	return 0;
<  } 
< 
<  void FrameCache::add_frame(long frame_number, int frame_layer, VFrame *frame, int do_not_copy_frame) 
<  {
<  	
<  	if (!cache_enabled) return;
<  	change_lock.lock();
<  	
<  //	printf("%p, adding frame:  %li, layer: %i, w: %i, h:%i cm:%i\n",this, frame_number, frame_layer, frame->get_w(),frame->get_h(), frame->get_color_model());
<  	
<  	FrameCacheElement *cache_element;
<  
<  	// currently cache size can only grow, not shrink
<  	if (cache_tree.size() >= cache_size) 
<  	{
<  		// delete the oldest element
<  		FrameCacheTree_ByTime::iterator iterator_bytime = cache_tree_bytime.begin();
<  		cache_element = iterator_bytime->second;
<  		FrameCacheTree::iterator iterator = find_element_byframe(cache_element->frame_number,
<  									cache_element->frame_layer,
<  									cache_element->frame->get_w(),
<  									cache_element->frame->get_h(),
<  									cache_element->frame->get_color_model());
<  //	printf("Deleting oldest frame: - frame: %li, layer: %i, w: %i, h:%i, cm: %i\n", cache_element->frame_number, cache_element->frame_layer, cache_element->frame->get_w(), cache_element->frame->get_h(), cache_element->frame->get_color_model());
<  		delete cache_element->frame;
<  		cache_tree.erase(iterator);
<    		cache_tree_bytime.erase(iterator_bytime);
<  	} else
<  	{
<  		cache_element = new FrameCacheElement;
<  	}
<  	
<  	if (do_not_copy_frame) 
<  	{
<  		cache_element->frame = frame;
<  	} else
<  	{
<  		cache_element->frame = new VFrame(0,
<  					frame->get_w(),
<  					frame->get_h(),
<  					frame->get_color_model());
<  		cache_element->frame->copy_from(frame);
<  	}
<  	cache_element->frame_layer = frame_layer;
<  	cache_element->frame_number = frame_number;
<  	cache_element->time_diff = timer.get_difference();
<  
<  // insert the same data into both trees under different keys
<  	
<  	cache_tree.insert(std::pair<long, FrameCacheElement *> (cache_element->frame_number, cache_element));
<  	cache_tree_bytime.insert(std::pair<long long, FrameCacheElement *> (cache_element->time_diff, cache_element)); 
<  	change_lock.unlock();
<  }
<  
<  void FrameCache::dump() 
< {	
<  	printf("Dump of frames' cache %p, cache_tree:\n", this);
<  	{
<  		FrameCacheTree::iterator iterator = cache_tree.begin();
<  		while (iterator != cache_tree.end()) {
<  			FrameCacheElement *cache_element = iterator->second;
<  			printf("%p, frame: %li, layer: %i, w: %i, h:%i, cm: %i, time_diff: %i\n", cache_element, cache_element->frame_number, cache_element->frame_layer, cache_element->frame->get_w(), cache_element->frame->get_h(), cache_element->frame->get_color_model(), cache_element->time_diff);
<  			iterator++;
<  		}
<  	}
<  	printf("cache_tree_bytime:\n", this);
<  	{
<  		FrameCacheTree_ByTime::iterator iterator = cache_tree_bytime.begin();
<  		while (iterator != cache_tree_bytime.end()) {
<  			FrameCacheElement *cache_element = iterator->second;
<  			printf("%p, frame: %li, layer: %i, w: %i, h:%i, cm: %i, time_diff: %li\n", cache_element, cache_element->frame_number, cache_element->frame_layer, cache_element->frame->get_w(), cache_element->frame->get_h(), cache_element->frame->get_color_model(), cache_element->time_diff);
<  			iterator++;
<  		}
<  	}
<  }
< 
257,258c35
< 	frames_cache = new FrameCache();
<   	reset_parameters();
---
> 	reset_parameters();
283d59
< 	delete frames_cache;
303d78
< 	frames_cache->reset();
1076a852
> 
1114c890
< 			
---
> 
1118,1154c894,916
< 			VFrame *temp_frame2 = frames_cache->get_frame(current_frame, current_layer, asset->width, asset->height, supported_colormodel);
< 			if (temp_frame2) 
< 			{
< 				delete temp_frame;
< 				frame->copy_from(temp_frame2);
< 				// cache is implicitly locked on cache hit
< 				frames_cache->unlock_cache();
< 			} else
< 			{
< 				frames_cache->unlock_cache();
< 				file->read_frame(temp_frame);
< 
< 				cmodel_transfer(frame->get_rows(), 
< 					temp_frame->get_rows(),
< 					0,
< 					0,
< 					0,
< 					0,
< 					0,
< 					0,
< 					0, 
< 					0, 
< 					temp_frame->get_w(), 
< 					temp_frame->get_h(),
< 					0, 
< 					0, 
< 					frame->get_w(), 
< 					frame->get_h(),
< 					temp_frame->get_color_model(), 
< 					frame->get_color_model(),
< 					0,
< 					temp_frame->get_w(),
< 					frame->get_w());
< printf("File::read_frame 6\n");
< 				frames_cache->add_frame(current_frame, current_layer, frame);
< 				current_frame++;
< 			}
---
> 			file->read_frame(temp_frame);
> 			cmodel_transfer(frame->get_rows(), 
> 				temp_frame->get_rows(),
> 				0,
> 				0,
> 				0,
> 				0,
> 				0,
> 				0,
> 				0, 
> 				0, 
> 				temp_frame->get_w(), 
> 				temp_frame->get_h(),
> 				0, 
> 				0, 
> 				frame->get_w(), 
> 				frame->get_h(),
> 				temp_frame->get_color_model(), 
> 				frame->get_color_model(),
> 				0,
> 				temp_frame->get_w(),
> 				frame->get_w());
> //printf("File::read_frame 6\n");
1159,1170c921
< 			VFrame *temp_frame2 = frames_cache->get_frame(current_frame, current_layer, asset->width, asset->height, frame->get_color_model());
< 			if (temp_frame2) 
< 			{
< 				frame->copy_from(temp_frame2);
< 				frames_cache->unlock_cache();
< 			} else
< 			{
< 				frames_cache->unlock_cache();
< 				file->read_frame(frame);
< 				frames_cache->add_frame(current_frame, current_layer, frame);
< 				current_frame++;
< 			}
---
> 			file->read_frame(frame);
1174a926
> 		current_frame++;
diff -r cinelerra/hvirtual/cinelerra/file.h base-cvs/hvirtual/cinelerra/file.h
20,60d19
< #include <map>
< #include "timer.h"
< // ======================================= include file types here
< 
< 
< class FrameCacheElement {
< public:
< 	int frame_layer;
< 	int frame_number;
< 	long long time_diff;
< 	VFrame *frame;
< };
< 
< typedef std::multimap<int, FrameCacheElement*> FrameCacheTree;
< typedef std::multimap<long long, FrameCacheElement*> FrameCacheTree_ByTime;
< 
< 
< class FrameCache {
< public:
< 	FrameCache(int cache_size = 100);
< 	~FrameCache();
< 	VFrame *get_frame(long frame_number, int frame_layer, int frame_width, int frame_height, int color_model); // implicit lock
< 	void add_frame(long frame_number, int frame_layer, VFrame *frame, int do_not_copy_frame = 0); 
< 	void unlock_cache();
< 	void lock_cache();
< 	void reset();		
< 	void disable_cache();
< 	void enable_cache();
< 	void dump();
< 	
< private:
< 	int compare_with_frame(FrameCacheElement *element, int frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model);
< 	FrameCacheTree::iterator find_element_byframe(long frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model);
< 	FrameCacheTree_ByTime::iterator find_element_bytime(long long frame_time_diff, long frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model);
< 	Mutex change_lock;
< 	int cache_enabled;
< 	int cache_size;
< 	FrameCacheTree cache_tree;
< 	FrameCacheTree_ByTime cache_tree_bytime;
< 	Timer timer;
< };
61a21
> // ======================================= include file types here
223,224d182
< 	FrameCache *frames_cache;
< 
diff -r cinelerra/hvirtual/cinelerra/resourcepixmap.C base-cvs/hvirtual/cinelerra/resourcepixmap.C
735,737c735
< 		int cache_hit; // so we know whether to relase a lock at the end or was it already
< 		VFrame *final_picon_frame;
<  		int64_t source_frame = project_frame + edit->startsource;
---
> 		int64_t source_frame = project_frame + edit->startsource;
742c740
< //		VFrame *src = source->read_frame(BC_RGB888);
---
> 		VFrame *src = source->read_frame(BC_RGB888);
744,807c742,743
< 		source->frames_cache->enable_cache();           // we do enabling and disabling of cache 
< 								// on our own, so File doesn't use it's own caching
< 		if ((final_picon_frame = source->frames_cache->get_frame(source->current_frame,
< 									source->current_layer,
< 									picon_w,
< 									picon_h,
< 									BC_RGB888)))
< 		{
< 			cache_hit = 1;
< 			
< 		} else
< 		{
< 			source->frames_cache->unlock_cache(); // implicitly locked
< 			cache_hit = 0;	
< 			long now_current_frame = source->current_frame;
< 			source->frames_cache->disable_cache();
< 			VFrame *src = source->read_frame(BC_RGB888);
< 					if (src) 
< 			{
< 				final_picon_frame = new VFrame (0, 
< 							picon_w,
< 							picon_h,
< 							BC_RGB888);
< 				cmodel_transfer(final_picon_frame->get_rows(), 
< 					src->get_rows(),
< 					final_picon_frame->get_y(),
< 					final_picon_frame->get_u(),
< 					final_picon_frame->get_v(),
< 					src->get_y(),
< 					src->get_u(),
< 					src->get_v(),
< 					0, 
< 					0, 
< 					src->get_w(), 
< 					src->get_h(),
< 					0, 
< 					0, 
< 					picon_w, 
< 					picon_h,
< 					src->get_color_model(), 
< 					BC_RGB888,
< 					0,
< 					src->get_w(),
< 					picon_w);
< 	
< 				source->frames_cache->enable_cache();
< 				source->frames_cache->add_frame(now_current_frame,
< 								source->current_layer,
< 								final_picon_frame,
< 								1); // do not do a copy of frame. keep this one
< 				source->frames_cache->disable_cache();
< 	
< 			} else 
< 			{
< 				final_picon_frame = 0;
< 			}
< 		}
< 		
< 
< 
< //		if(src)
< //			draw_vframe(src, 
< 		if(final_picon_frame)
< 			draw_vframe(final_picon_frame, 
---
> 		if(src)
> 			draw_vframe(src, 
815,817d750
< 		if (cache_hit)
< 			source->frames_cache->unlock_cache(); // implicitly locked
< 
