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 "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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(); }
|
||||||
|
|
Loading…
Reference in a new issue