Clean up VideoProviderCache a bit

Originally committed to SVN as r6454.
This commit is contained in:
Thomas Goyne 2012-02-07 23:16:41 +00:00
parent 1075b71976
commit 003322813e
2 changed files with 40 additions and 80 deletions

View File

@ -41,88 +41,54 @@
#include "main.h" #include "main.h"
#include "video_frame.h" #include "video_frame.h"
#ifndef AGI_PRE
#include <algorithm>
#include <tr1/functional>
#endif
/// DOCME /// A video frame and its frame number
/// @class CachedFrame struct CachedFrame : public AegiVideoFrame {
/// @brief DOCME int frame_number;
///
/// DOCME
struct CachedFrame {
/// DOCME
AegiVideoFrame frame;
/// DOCME
int n;
}; };
/// @brief Constructor
/// @param parent
///
VideoProviderCache::VideoProviderCache(VideoProvider *parent) VideoProviderCache::VideoProviderCache(VideoProvider *parent)
: master(parent) : master(parent)
, cacheMax(OPT_GET("Provider/Video/Cache/Size")->GetInt() << 20) // convert MB to bytes , max_cache_size(OPT_GET("Provider/Video/Cache/Size")->GetInt() << 20) // convert MB to bytes
{ {
} }
/// @brief Destructor
///
VideoProviderCache::~VideoProviderCache() { VideoProviderCache::~VideoProviderCache() {
while (cache.size()) { for_each(cache.begin(), cache.end(), std::tr1::mem_fn(&AegiVideoFrame::Clear));
cache.front().frame.Clear();
cache.pop_front();
}
} }
/// @brief Get frame
/// @param n
/// @return
///
const AegiVideoFrame VideoProviderCache::GetFrame(int n) { const AegiVideoFrame VideoProviderCache::GetFrame(int n) {
size_t total_size = 0;
// See if frame is cached // See if frame is cached
CachedFrame cached; for (std::list<CachedFrame>::iterator cur = cache.begin(); cur != cache.end(); ++cur) {
for (std::list<CachedFrame>::iterator cur=cache.begin();cur!=cache.end();cur++) { if (cur->frame_number == n) {
cached = *cur; cache.push_front(*cur);
if (cached.n == n) {
cache.erase(cur); cache.erase(cur);
cache.push_back(cached); return cache.front();
return cached.frame;
} }
total_size += cur->memSize;
} }
// Not cached, retrieve it // Not cached, retrieve it
const AegiVideoFrame frame = master->GetFrame(n); const AegiVideoFrame frame = master->GetFrame(n);
const AegiVideoFrame *srcFrame = &frame;
// Cache frame // Cache full, use oldest frame
Cache(n,*srcFrame); if (total_size >= max_cache_size) {
return *srcFrame; cache.push_front(cache.back());
} cache.pop_back();
/// @brief Add to cache
/// @param n
/// @param frame
void VideoProviderCache::Cache(int n,const AegiVideoFrame frame) {
// Cache full, use frame at front
if (GetCurCacheSize() >= cacheMax) {
cache.push_back(cache.front());
cache.pop_front();
} }
// Cache not full, insert new one // Cache not full, insert new one
else { else
cache.push_back(CachedFrame()); cache.push_front(CachedFrame());
}
// Cache // Cache
cache.back().n = n; cache.front().frame_number = n;
cache.back().frame.CopyFrom(frame); cache.front().CopyFrom(frame);
} return cache.front();
/// @brief Get the current size of the cache
/// @return Returns the size in bytes
unsigned VideoProviderCache::GetCurCacheSize() {
int sz = 0;
for (std::list<CachedFrame>::iterator i = cache.begin(); i != cache.end(); i++)
sz += i->frame.memSize;
return sz;
} }

View File

@ -36,41 +36,35 @@
#ifndef AGI_PRE #ifndef AGI_PRE
#include <list> #include <list>
#include <memory>
#endif #endif
#include "include/aegisub/video_provider.h" #include "include/aegisub/video_provider.h"
#include <libaegisub/scoped_ptr.h>
struct CachedFrame; struct CachedFrame;
/// DOCME
/// @class VideoProviderCache /// @class VideoProviderCache
/// @brief DOCME /// @brief A wrapper around a video provider which provides LRU caching
///
/// DOCME
class VideoProviderCache : public VideoProvider { class VideoProviderCache : public VideoProvider {
/// DOCME /// The source provider to get frames from
std::auto_ptr<VideoProvider> master; agi::scoped_ptr<VideoProvider> master;
/// DOCME /// @brief Maximum size of the cache in bytes
unsigned int cacheMax; ///
/// Note that this is a soft limit. The cache stops allocating new frames
/// once it has exceeded the limit, but it never tries to shrink
const size_t max_cache_size;
/// DOCME /// Cache of video frames with the most recently used ones at the front
std::list<CachedFrame> cache; std::list<CachedFrame> cache;
void Cache(int n,const AegiVideoFrame frame);
AegiVideoFrame GetCachedFrame(int n);
// Cache functions
unsigned GetCurCacheSize();
public: public:
// Base methods
const AegiVideoFrame GetFrame(int n);
VideoProviderCache(VideoProvider *master); VideoProviderCache(VideoProvider *master);
virtual ~VideoProviderCache(); ~VideoProviderCache();
const AegiVideoFrame GetFrame(int n);
// Override the following methods:
int GetFrameCount() const { return master->GetFrameCount(); } int GetFrameCount() const { return master->GetFrameCount(); }
int GetWidth() const { return master->GetWidth(); } int GetWidth() const { return master->GetWidth(); }
int GetHeight() const { return master->GetHeight(); } int GetHeight() const { return master->GetHeight(); }