ret = read_frame(frame);
if( ret > 0 ) {
if( frame->key_frame && seeking < 0 ) {
- seeking = 1;
- ffmpeg->purge_cache();
- }
- if( ffmpeg->get_use_cache() && seeking > 0 && curr_pos < pos ) {
- VFrame *cache_frame = ffmpeg->new_cache_frame(vframe, curr_pos);
- if( cache_frame ) {
- ret = convert_cmodel(cache_frame, frame);
- ffmpeg->put_cache_frame();
+ int use_cache = ffmpeg->get_use_cache();
+ if( use_cache < 0 ) {
+// for reverse read, reload file frame_cache from keyframe to pos
+ ffmpeg->purge_cache();
+ seeking = 1;
}
+ else
+ seeking = 0;
+ }
+ if( seeking > 0 && curr_pos < pos ) {
+ int vw =vframe->get_w(), vh = vframe->get_h();
+ int vcolor_model = vframe->get_color_model();
+ VFrame *cache_frame = new VFrame(vw, vh, vcolor_model);
+ ret = convert_cmodel(cache_frame, frame);
+ if( ret > 0 )
+ ffmpeg->put_cache_frame(cache_frame, curr_pos);
}
++curr_pos;
}
return ret;
}
-VFrame *FFMPEG::new_cache_frame(VFrame *vframe, int64_t position)
-{
- return file_base->file->new_cache_frame(vframe, position, 0);
-}
-
-void FFMPEG::put_cache_frame()
+void FFMPEG::put_cache_frame(VFrame *frame, int64_t position)
{
- return file_base->file->put_cache_frame();
+ file_base->file->put_cache_frame(frame, position, 0);
}
int FFMPEG::get_use_cache()
static double to_secs(int64_t time, AVRational time_base);
int info(char *text, int len);
- VFrame *new_cache_frame(VFrame *vframe, int64_t position);
- void put_cache_frame();
+ void put_cache_frame(VFrame *frame, int64_t position);
int get_use_cache();
void purge_cache();
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)
+int File::get_cache_frame(VFrame *frame, int64_t position)
{
- return frame_cache->new_cache_frame(position,
- vframe->get_w(), vframe->get_h(), vframe->get_color_model(),
- current_layer, asset->frame_rate, first_frame);
+ return frame_cache->get_cache_frame(frame, position,
+ current_layer, asset->frame_rate);
}
-void File::put_cache_frame()
+void File::put_cache_frame(VFrame *frame, int64_t position, int use_copy)
{
- return frame_cache->put_cache_frame();
+ frame_cache->put_cache_frame(frame,
+ position, current_layer, asset->frame_rate, use_copy);
}
int File::get_use_cache()
if( debug ) PRINT_TRACE
int result = 0;
int supported_colormodel = colormodel_supported(frame->get_color_model());
- int advance_position = 1;
- int cache_active = use_cache || asset->single_frame ? 1 : 0;
+ int do_read = 1;
+// if reverse playback reading, use_cache is -1
+ int cache_active = asset->single_frame ? 1 : use_cache;
int64_t cache_position = !asset->single_frame ? current_frame : -1;
// Test cache
- if( cache_active && frame_cache->get_frame(frame, cache_position,
- current_layer, asset->frame_rate) ) {
-// Can't advance position if cache used.
-//printf("File::read_frame %d\n", __LINE__);
- advance_position = 0;
+ if( cache_active ) {
+ if( get_cache_frame(frame, cache_position) ) {
+ do_read = 0;
+ }
+ else if( cache_active < 0 && frame_cache->cache_items() > 0 ) {
+// reverse reading and cache miss, clear cache for new readahead
+ purge_cache();
+ }
}
-// Need temp
- else if( frame->get_color_model() != BC_COMPRESSED &&
- (supported_colormodel != frame->get_color_model() ||
- (!file->can_scale_input() &&
- (frame->get_w() != asset->width ||
- frame->get_h() != asset->height))) ) {
-
-// printf("File::read_frame %d\n", __LINE__);
-// Can't advance position here because it needs to be added to cache
- if( temp_frame ) {
- if( !temp_frame->params_match(asset->width, asset->height, supported_colormodel) ) {
- delete temp_frame;
- temp_frame = 0;
+// Need to read
+ if( do_read ) {
+ VFrame *vframe = frame;
+ if( frame->get_color_model() != BC_COMPRESSED &&
+ (supported_colormodel != frame->get_color_model() ||
+ (!file->can_scale_input() &&
+ (frame->get_w() != asset->width ||
+ frame->get_h() != asset->height))) ) {
+ if( temp_frame ) {
+ if( !temp_frame->params_match(asset->width, asset->height,
+ supported_colormodel) ) {
+ delete temp_frame; temp_frame = 0;
+ }
+ }
+ if( !temp_frame ) {
+ temp_frame = new VFrame(asset->width, asset->height,
+ supported_colormodel, 0);
+ temp_frame->clear_frame();
}
- }
- if( !temp_frame ) {
- temp_frame = new VFrame(asset->width, asset->height, supported_colormodel, 0);
- temp_frame->clear_frame();
+ temp_frame->copy_stacks(frame);
+ vframe = temp_frame;
}
-
-// printf("File::read_frame %d\n", __LINE__);
- temp_frame->copy_stacks(frame);
- result = file->read_frame(temp_frame);
- if( !result )
- frame->transfer_from(temp_frame);
- else if( result && frame->get_status() > 0 )
- frame->set_status(-1);
-//printf("File::read_frame %d\n", __LINE__);
- }
- else {
-// Can't advance position here because it needs to be added to cache
-//printf("File::read_frame %d\n", __LINE__);
- result = file->read_frame(frame);
- if( result && frame->get_status() > 0 )
+ result = file->read_frame(vframe);
+ if( !result ) {
+ if( frame != vframe )
+ frame->transfer_from(vframe);
+ if( cache_active > 0 )
+ put_cache_frame(frame, cache_position, 1);
+ }
+ else if( frame->get_status() > 0 )
frame->set_status(-1);
//for( int i = 0; i < 100 * 1000; i++ ) ((float*)frame->get_rows()[0])[i] = 1.0;
}
if( result && !current_frame )
frame->clear_frame();
- if( cache_active && advance_position && frame->get_status() > 0 )
- frame_cache->put_frame(frame, cache_position,
- current_layer, asset->frame_rate, 1, 0);
//printf("File::read_frame %d\n", __LINE__);
- if( advance_position ) current_frame++;
+ if( do_read ) current_frame++;
if( debug ) PRINT_TRACE
return 0;
}
// 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_cache_frame(VFrame *vframe, int64_t position);
+ void put_cache_frame(VFrame *frame, int64_t position, int use_copy);
int get_use_cache();
// stubs for now
}
-// Returns 1 if frame exists in cache and copies it to the frame argument.
-int FrameCache::get_frame(VFrame *frame,
- int64_t position,
- int layer,
- double frame_rate,
- int source_id)
-{
- lock->lock("FrameCache::get_frame");
- FrameCacheItem *result = 0;
-
- if(frame_exists(frame,
- position,
- layer,
- frame_rate,
- &result,
- source_id))
- {
- if(result->data)
- {
-// Frame may have come from the readahead thread.
-// Those frames are in the codec color model.
-// But to pass frame_exists, they must be identical.
-// BC_CModels::transfer(frame->get_rows(),
-// result->data->get_rows(),
-// result->data->get_y(),
-// result->data->get_u(),
-// result->data->get_v(),
-// frame->get_y(),
-// frame->get_u(),
-// frame->get_v(),
-// 0,
-// 0,
-// result->data->get_w(),
-// result->data->get_h(),
-// 0,
-// 0,
-// frame->get_w(),
-// frame->get_h(),
-// result->data->get_color_model(),
-// frame->get_color_model(),
-// 0,
-// result->data->get_w(),
-// frame->get_w());
-
-// no context data since keyframe updates may vary input
- frame->copy_from(result->data);
- }
- result->age = get_age();
- }
-
-
-
-
- lock->unlock();
- if(result) return 1;
- return 0;
-}
-
-
-VFrame* FrameCache::get_frame_ptr(int64_t position,
- int layer,
- double frame_rate,
- int color_model,
- int w,
- int h,
- int source_id)
+VFrame* FrameCache::get_frame_ptr(int64_t position, int layer, double frame_rate,
+ int color_model, int w, int h, int source_id)
{
lock->lock("FrameCache::get_frame_ptr");
- FrameCacheItem *result = 0;
- if(frame_exists(position,
- layer,
- frame_rate,
- color_model,
- w,
- h,
- &result,
- source_id))
- {
- result->age = get_age();
- return result->data;
- }
-
-
+ VFrame *vframe = get_vframe(position, w, h, color_model,
+ layer, frame_rate, source_id);
+ if( vframe ) return vframe; // not unlocked
lock->unlock();
return 0;
}
-// Puts frame in cache if enough space exists and the frame doesn't already
-// exist.
-void FrameCache::put_frame(VFrame *frame, int64_t position,
- int layer, double frame_rate, int use_copy, Indexable *indexable)
+VFrame *FrameCache::get_vframe(int64_t position, int w, int h,
+ int color_model, int layer, double frame_rate,
+ int source_id)
{
- lock->lock("FrameCache::put_frame");
FrameCacheItem *item = 0;
- int source_id = -1;
- if(indexable) source_id = indexable->id;
-
-//printf("FrameCache::put_frame %d position=%jd\n", __LINE__, position);
-
- if(frame_exists(frame, position, layer, frame_rate, &item, source_id)) {
+ int ret = frame_exists(position, layer, frame_rate,
+ w, h, color_model, &item, source_id);
+ if( ret && position >= 0 && item )
item->age = get_age();
- lock->unlock();
- return;
- }
+ return ret && item ? item->data : 0;
+}
+VFrame *FrameCache::get_frame(int64_t position, int w, int h,
+ int color_model, int layer, double frame_rate,
+ int source_id)
+{
+ lock->lock("FrameCache::get_frame");
+ VFrame *frame = get_vframe(position, w, h,
+ color_model, layer, frame_rate, source_id);
+ lock->unlock();
+ return frame;
+}
- item = new FrameCacheItem;
+// Returns 1 if frame exists in cache and copies it to the frame argument.
+int FrameCache::get_frame(VFrame *frame, int64_t position,
+ int layer, double frame_rate, int source_id)
+{
+ lock->lock("FrameCache::get_frame");
+ VFrame *vframe = get_vframe(position,
+ frame->get_w(), frame->get_h(), frame->get_color_model(),
+ layer, frame_rate, source_id);
+ if( vframe )
+ frame->copy_from(vframe);
+ lock->unlock();
+ return vframe ? 1 : 0;
+}
- item->data = use_copy ? new VFrame(*frame) : frame;
-// Copy metadata
+void FrameCache::put_vframe(VFrame *frame, int64_t position,
+ int layer, double frame_rate, int source_id)
+{
+ FrameCacheItem *item = new FrameCacheItem;
+ item->data = frame;
item->position = position;
item->layer = layer;
item->frame_rate = frame_rate;
item->source_id = source_id;
- if(indexable)
- item->path = cstrdup(indexable->path);
-
item->age = position < 0 ? INT_MAX : get_age();
-
-//printf("FrameCache::put_frame %d position=%jd\n", __LINE__, position);
put_item(item);
- 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)
+// Puts frame in cache if the frame doesn't already exist.
+void FrameCache::put_frame(VFrame *frame, int64_t position,
+ int layer, double frame_rate, int use_copy, Indexable *idxbl)
{
- 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;
+ int source_id = idxbl ? idxbl->id : -1;
+ lock->lock("FrameCache::put_frame");
+ VFrame *vframe = get_vframe(position,
+ frame->get_w(), frame->get_h(), frame->get_color_model(),
+ layer, frame_rate, source_id);
+ if( !vframe ) {
+ if( use_copy ) frame = new VFrame(*frame);
+ put_vframe(frame, position, layer, frame_rate, source_id);
}
- 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;
+ lock->unlock();
}
-void FrameCache::put_cache_frame()
+
+// get vframe for keys, overwrite frame if found
+int FrameCache::get_cache_frame(VFrame *frame, int64_t position,
+ int layer, double frame_rate)
{
+ lock->lock("FrameCache::get_cache_frame");
+ VFrame *vframe = get_vframe(position,
+ frame->get_w(), frame->get_h(), frame->get_color_model(),
+ layer, frame_rate, -1);
+ if( vframe )
+ frame->copy_from(vframe);
lock->unlock();
+ return vframe ? 1 : 0;
}
+// adds or replaces vframe, consumes frame if not use_copy
+void FrameCache::put_cache_frame(VFrame *frame, int64_t position,
+ int layer, double frame_rate, int use_copy)
+{
+ lock->lock("FrameCache::put_cache_frame");
+ FrameCacheItem *item = 0;
+ int w = frame->get_w(), h = frame->get_h();
+ int color_model = frame->get_color_model();
+ int ret = frame_exists(position, layer, frame_rate,
+ w, h, color_model, &item, -1);
+ if( use_copy ) frame = new VFrame(*frame);
+ if( ret ) {
+ delete item->data;
+ item->data = frame;
+ }
+ else
+ put_vframe(frame, position, layer, frame_rate, -1);
+ lock->unlock();
+}
+
+
int FrameCache::frame_exists(VFrame *format, int64_t position,
int layer, double frame_rate, 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)
+ int w, int h, int color_model, FrameCacheItem **item_return, int source_id)
{
FrameCacheItem *item = (FrameCacheItem*)get_item(position);
for( ; item && item->position == position ; item = (FrameCacheItem*)item->next ) {
FrameCache();
~FrameCache();
-// Returns 1 if frame exists in cache and copies it to the frame argument.
- int get_frame(VFrame *frame,
- int64_t position,
- int layer,
- double frame_rate,
- int source_id = -1);
// Returns pointer to cache entry if frame exists or 0.
// If a frame is found, the frame cache is left in the locked state until
// unlock is called. If nothing is found, the frame cache is unlocked before
// returning. This keeps the item from being deleted.
// asset - supplied by user if the cache is not part of a file.
- VFrame* get_frame_ptr(int64_t position,
- int layer,
- double frame_rate,
- int color_model,
- int w,
- int h,
- int source_id = -1);
+ VFrame* get_frame_ptr(int64_t position, int layer, double frame_rate,
+ int color_model, int w, int h, int source_id);
+// lock and call get_vframe
+ VFrame *get_vframe(int64_t position, int w, int h,
+ int color_model, int layer, double frame_rate,
+ int source_id);
+// caller holds lock
+ VFrame *get_frame(int64_t position, int w, int h,
+ int color_model, int layer, double frame_rate,
+ int source_id);
+// Returns 1 if frame exists in cache and copies it to the frame argument.
+ int get_frame(VFrame *frame, int64_t position,
+ int layer, double frame_rate, int source_id);
// Puts the frame in cache.
// use_copy - if 1 a copy of the frame is made. if 0 the argument is stored.
// The copy of the frame is deleted by FrameCache in a future delete_oldest.
// asset - supplied by user if the cache is not part of a file.
- void put_frame(VFrame *frame,
- int64_t position,
- int layer,
- 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();
-
+// caller holds lock
+ void put_vframe(VFrame *frame, int64_t position,
+ int layer, double frame_rate, int source_id);
+// lock, call get_vframe, if exists: ret = 0; else add frame, ret = 1; unlock
+ void put_frame(VFrame *frame, int64_t position,
+ int layer, double frame_rate, int use_copy, Indexable *idxbl);
+ int get_cache_frame(VFrame *frame, int64_t position,
+ int layer, double frame_rate);
+ void put_cache_frame(VFrame *frame, int64_t position,
+ int layer, double frame_rate, int use_copy);
void dump();
-
-
-
-
private:
// Return 1 if matching frame exists.
// Return 0 if not.
int frame_exists(VFrame *format,
- int64_t position,
- int layer,
- double frame_rate,
- FrameCacheItem **item_return,
- int source_id);
- int frame_exists(int64_t position,
- int layer,
- double frame_rate,
- int color_model,
- int w,
- int h,
- FrameCacheItem **item_return,
- int source_id);
+ int64_t position, int layer, double frame_rate,
+ FrameCacheItem **item_return, int source_id);
+ int frame_exists(int64_t position, int layer, double frame_rate,
+ int w, int h, int color_model,
+ FrameCacheItem **item_return, int source_id);
};
-
-
#endif
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->get_direction() == PLAY_REVERSE );
+ int use_cache = renderengine->command->single_frame() ? 1 :
+ renderengine->command->get_direction() == PLAY_REVERSE ? -1 : 0;
// int use_asynchronous = !use_cache &&
// renderengine &&
// else
file->stop_video_thread();
-// 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 &&
+ if( renderengine->preferences->cache_transitions && !use_cache &&
+// cache transitions not using cache and inside transition
+ vnext && vnext->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);
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();
+ if( first_frame ) {
+ if( file->get_cache_frame(input, norm_pos) )
+ break; // if inside a cache run
+ first_frame = 0;
+ file->purge_cache(); // start new run
}
- else if( first_frame ) // already loaded
- break;
- first_frame = 0;
+ file->set_cache_frames(1);
+ file->set_video_position(norm_pos, 0);
+ result = file->read_frame(input);
++pos; --count;
}
use_cache = 1;
__LINE__,
this,
current_edit->asset->path);
- if( use_cache ) file->set_cache_frames(1);
+ if( use_cache )
+ file->set_cache_frames(use_cache);
result = file->read_frame((*input));
- if( use_cache ) file->set_cache_frames(0);
+ if( use_cache )
+ file->set_cache_frames(0);
(*input)->set_opengl_state(VFrame::RAM);
}
else
else if( file ) {
// Cache single frames
//memset(output->get_rows()[0], 0xff, 1024);
- if( use_cache ) file->set_cache_frames(1);
+ if( use_cache )
+ file->set_cache_frames(use_cache);
result = file->read_frame(output);
- if( use_cache ) file->set_cache_frames(0);
+ if( use_cache )
+ file->set_cache_frames(0);
output->set_opengl_state(VFrame::RAM);
}
}
int use_vconsole = 1;
int use_brender = 0;
int result = 0;
- int use_cache = renderengine->command->single_frame() ||
- renderengine->command->get_direction() == PLAY_REVERSE;
+ int use_cache = renderengine->command->single_frame() ? 1 :
+ renderengine->command->get_direction() == PLAY_REVERSE ? -1 : 0;
// int use_asynchronous =
// renderengine->command->realtime &&
// renderengine->get_edl()->session->video_every_frame &&