Added a decoded frame cache to PRSFile

Originally committed to SVN as r296.
This commit is contained in:
Rodrigo Braz Monteiro 2006-04-03 15:02:53 +00:00
parent 820af47c64
commit b973d58bee
4 changed files with 102 additions and 8 deletions

View file

@ -49,6 +49,9 @@
///////////////
// Constructor
PRSFile::PRSFile () {
// Cache data
cacheMemSize = 0;
maxCache = 8 << 20;
}
@ -56,6 +59,7 @@ PRSFile::PRSFile () {
// Destructor
PRSFile::~PRSFile() {
Reset();
ClearCache();
}
@ -71,6 +75,17 @@ void PRSFile::Reset() {
}
///////////////////
// Clear the cache
void PRSFile::ClearCache() {
// Clear list of cached frames
frameCache.clear();
// Zero size
cacheMemSize = 0;
}
////////
// Save
void PRSFile::Save(std::string path) {
@ -251,23 +266,61 @@ void PRSFile::DrawFrame(int n,PRSVideoFrame *frame) {
// Draw the blocks
int nblocks = (int) blocks.size();
for (int i=0;i<nblocks;i++) {
// Get display and image pair
// Get display block and frame
PRSDisplay *display = blocks[i];
PRSImage *image = GetImageByID(display->id);
if (!image) continue;
// Decode PNG
PRSVideoFrame *overFrame = image->GetDecodedFrame();
PRSVideoFrame *overFrame = CachedGetFrameByID(display->id);
// Draw image on frame
if (overFrame) overFrame->Overlay(frame,display->x,display->y,display->alpha,display->blend);
// Clean up
delete overFrame;
// DON'T delete the frame!
// The cache takes care of doing so.
}
}
///////////////////////////////////////////////////////////////////
// Gets a frame from cache, or load it there if it's not available
PRSVideoFrame* PRSFile::CachedGetFrameByID(int id) {
// Check if the image is already decoded on cache, fetch it if it is
PRSVideoFrame *frame = NULL;
std::list<PRSCachedFrame>::iterator cur;
for (cur=frameCache.begin();cur!=frameCache.end();cur++) {
if ((*cur).id == id) {
return (*cur).frame;
}
}
// It isn't; decode and add it to cache
// Get image
PRSImage *image = GetImageByID(id);
if (!image) return NULL;
// Get frame
frame = image->GetDecodedFrame();
// Add to cache
if (frame) {
// Add and raise size
PRSCachedFrame cached;
cached.frame = frame;
cached.id = id;
frameCache.push_front(cached);
cached.frame = NULL;
cacheMemSize += frame->GetSize();
// If memory has been exceeded, remove stuff from the back until it isn't anymore
while (cacheMemSize > maxCache && frameCache.size() > 1) {
cacheMemSize -= frameCache.back().frame->GetSize();
frameCache.pop_back();
}
}
// Return it
return frame;
}
////////////////////////////////////////////////
// Finds which display blocks are at a position
void PRSFile::GetDisplayBlocksAtFrame(int n,std::vector<PRSDisplay*> &blocks) {

View file

@ -56,6 +56,9 @@ class PRSDisplay;
class PRSFile {
private:
std::list<PRSEntry*> entryList;
std::list<PRSCachedFrame> frameCache;
int cacheMemSize;
int maxCache;
void Reset();
public:
@ -74,6 +77,8 @@ public:
bool HasDataAtFrame(int n);
void DrawFrame(int n,PRSVideoFrame *frame);
PRSImage *GetImageByID(int id);
PRSVideoFrame *CachedGetFrameByID(int id);
void ClearCache();
PRSImage *FindDuplicateImage(PRSImage *img);
};

View file

@ -141,3 +141,26 @@ void PRSVideoFrame::Overlay(PRSVideoFrame *dstFrame,int x,int y,unsigned char al
}
}
}
//////////////////
// Get frame size
int PRSVideoFrame::GetSize() {
return sizeof(PRSVideoFrame) + pitch * h;
}
//////////////////////
// Cached constructor
PRSCachedFrame::PRSCachedFrame () {
frame = 0;
id = -1;
}
/////////////////////
// Cached destructor
PRSCachedFrame::~PRSCachedFrame() {
delete frame;
frame = 0;
}

View file

@ -64,4 +64,17 @@ public:
~PRSVideoFrame();
void Overlay(PRSVideoFrame *dst,int x,int y,unsigned char alpha=255,unsigned char blend=0);
int GetSize();
};
///////////////////////////
// Video frame cache class
class PRSCachedFrame {
public:
PRSCachedFrame();
~PRSCachedFrame();
PRSVideoFrame *frame;
int id;
};