forked from mia/Aegisub
Clean up VideoProviderCache a bit
Originally committed to SVN as r6454.
This commit is contained in:
parent
1075b71976
commit
003322813e
2 changed files with 40 additions and 80 deletions
|
@ -41,88 +41,54 @@
|
|||
#include "main.h"
|
||||
#include "video_frame.h"
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <algorithm>
|
||||
#include <tr1/functional>
|
||||
#endif
|
||||
|
||||
/// DOCME
|
||||
/// @class CachedFrame
|
||||
/// @brief DOCME
|
||||
///
|
||||
/// DOCME
|
||||
struct CachedFrame {
|
||||
/// DOCME
|
||||
AegiVideoFrame frame;
|
||||
|
||||
/// DOCME
|
||||
int n;
|
||||
/// A video frame and its frame number
|
||||
struct CachedFrame : public AegiVideoFrame {
|
||||
int frame_number;
|
||||
};
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param parent
|
||||
///
|
||||
VideoProviderCache::VideoProviderCache(VideoProvider *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() {
|
||||
while (cache.size()) {
|
||||
cache.front().frame.Clear();
|
||||
cache.pop_front();
|
||||
}
|
||||
for_each(cache.begin(), cache.end(), std::tr1::mem_fn(&AegiVideoFrame::Clear));
|
||||
}
|
||||
|
||||
/// @brief Get frame
|
||||
/// @param n
|
||||
/// @return
|
||||
///
|
||||
const AegiVideoFrame VideoProviderCache::GetFrame(int n) {
|
||||
size_t total_size = 0;
|
||||
|
||||
// See if frame is cached
|
||||
CachedFrame cached;
|
||||
for (std::list<CachedFrame>::iterator cur=cache.begin();cur!=cache.end();cur++) {
|
||||
cached = *cur;
|
||||
if (cached.n == n) {
|
||||
for (std::list<CachedFrame>::iterator cur = cache.begin(); cur != cache.end(); ++cur) {
|
||||
if (cur->frame_number == n) {
|
||||
cache.push_front(*cur);
|
||||
cache.erase(cur);
|
||||
cache.push_back(cached);
|
||||
return cached.frame;
|
||||
return cache.front();
|
||||
}
|
||||
|
||||
total_size += cur->memSize;
|
||||
}
|
||||
|
||||
// Not cached, retrieve it
|
||||
const AegiVideoFrame frame = master->GetFrame(n);
|
||||
const AegiVideoFrame *srcFrame = &frame;
|
||||
|
||||
// Cache frame
|
||||
Cache(n,*srcFrame);
|
||||
return *srcFrame;
|
||||
}
|
||||
|
||||
/// @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 full, use oldest frame
|
||||
if (total_size >= max_cache_size) {
|
||||
cache.push_front(cache.back());
|
||||
cache.pop_back();
|
||||
}
|
||||
|
||||
// Cache not full, insert new one
|
||||
else {
|
||||
cache.push_back(CachedFrame());
|
||||
}
|
||||
else
|
||||
cache.push_front(CachedFrame());
|
||||
|
||||
// Cache
|
||||
cache.back().n = n;
|
||||
cache.back().frame.CopyFrom(frame);
|
||||
}
|
||||
|
||||
/// @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;
|
||||
cache.front().frame_number = n;
|
||||
cache.front().CopyFrom(frame);
|
||||
return cache.front();
|
||||
}
|
||||
|
|
|
@ -36,41 +36,35 @@
|
|||
|
||||
#ifndef AGI_PRE
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
#include "include/aegisub/video_provider.h"
|
||||
|
||||
#include <libaegisub/scoped_ptr.h>
|
||||
|
||||
struct CachedFrame;
|
||||
|
||||
/// DOCME
|
||||
/// @class VideoProviderCache
|
||||
/// @brief DOCME
|
||||
///
|
||||
/// DOCME
|
||||
/// @brief A wrapper around a video provider which provides LRU caching
|
||||
class VideoProviderCache : public VideoProvider {
|
||||
/// DOCME
|
||||
std::auto_ptr<VideoProvider> master;
|
||||
/// The source provider to get frames from
|
||||
agi::scoped_ptr<VideoProvider> master;
|
||||
|
||||
/// DOCME
|
||||
unsigned int cacheMax;
|
||||
/// @brief Maximum size of the cache in bytes
|
||||
///
|
||||
/// 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;
|
||||
|
||||
void Cache(int n,const AegiVideoFrame frame);
|
||||
AegiVideoFrame GetCachedFrame(int n);
|
||||
|
||||
// Cache functions
|
||||
unsigned GetCurCacheSize();
|
||||
|
||||
public:
|
||||
// Base methods
|
||||
const AegiVideoFrame GetFrame(int n);
|
||||
VideoProviderCache(VideoProvider *master);
|
||||
virtual ~VideoProviderCache();
|
||||
~VideoProviderCache();
|
||||
|
||||
const AegiVideoFrame GetFrame(int n);
|
||||
|
||||
// Override the following methods:
|
||||
int GetFrameCount() const { return master->GetFrameCount(); }
|
||||
int GetWidth() const { return master->GetWidth(); }
|
||||
int GetHeight() const { return master->GetHeight(); }
|
||||
|
|
Loading…
Reference in a new issue