00001 #ifndef VideoExcel_ImageCache_h
00002 #define VideoExcel_ImageCache_h
00003
00004 #ifndef RICHARD
00005
00006 #endif
00007
00008 #include "OglGui/OglImageCache.h"
00009
00010 #include "TableDataSource.h"
00011 #include "Visualization/RgbOglImage.h"
00012
00013 #ifdef USE_BOOST_THREADS
00014
00015
00016 #include "threadpool23/threadpool.hpp"
00017
00018
00019
00020 #endif
00021
00022
00023 namespace Impala {
00024 namespace Application {
00025 namespace VideoExcel {
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 class ImageCache
00072 {
00073 public:
00074 typedef Impala::Core::Array::Array2dVec3UInt8 Array2dVec3UInt8;
00075 typedef std::pair<int, OGLIMAGE*> ImageWithID;
00076
00077 static void InitializeCache(TableDataSource *source, int size)
00078 {
00079 if (sInstance)
00080 {
00081 ILOG_WARN("ImageCache already initialized. Skipping.");
00082 return;
00083 }
00084 sInstance = new ImageCache(source, size);
00085 }
00086
00087 static ImageCache* GetInstance()
00088 {
00089 if (!sInstance)
00090 {
00091 ILOG_ERROR("You forgot to initialize ImageCache with a source.");
00092 return 0;
00093 }
00094 return sInstance;
00095 }
00096
00097
00098 OGLIMAGE* GetImage(int id, String column)
00099 {
00100 OGLIMAGE *i = GetImageFromCache(id, column);
00101 if (!i)
00102 i = LoadImage(id, column);
00103 return i;
00104 }
00105
00106 OGLIMAGE* GetImageFromCache(int id, String column)
00107 {
00108
00109
00110
00111
00112 for (int i=0; i<mImages.size(); i++)
00113 {
00114 if (id == mImages[i]->first) {
00115
00116 UpdateLRU(i);
00117 return mImages[i]->second;
00118 }
00119 }
00120 return 0;
00121 }
00122
00123 #ifndef USE_BOOST_THREADS
00124 OGLIMAGE* LoadImage(int id, String column)
00125 {
00126
00127
00128 Array2dVec3UInt8* ar = mSource->GetImageDataByID(column, id);
00129 if (ar == 0)
00130 return 0;
00131
00132 ImageWithID *p = GetLeastUsedImageFromCache();
00133 if (p->second)
00134 {
00135 ReleaseOglImage(p->second);
00136 ILOG_DEBUG("Refcount for least used image now " <<
00137 p->second->refCount);
00138 }
00139 else
00140 ILOG_DEBUG("Cache not yet grown to max size, growing...");
00141
00142 p->second = Visualization::RgbOglImage::OglImage(ar);
00143 p->first = id;
00144 return p->second;
00145 }
00146 #else
00147 OGLIMAGE* LoadImage(int id, String column)
00148 {
00149
00150
00151
00152
00153
00154
00155
00156 ImageWithID *p = GetLeastUsedImageFromCache();
00157 if (p->second)
00158 {
00159 ReleaseOglImage(p->second);
00160 ILOG_DEBUG("Refcount for least used image now " <<
00161 p->second->refCount);
00162 }
00163 else
00164 ILOG_DEBUG("Cache not yet grown to max size, growing...");
00165
00166 p->second = Visualization::RgbOglImage::OglImage(mEmptyArray);
00167 p->first = id;
00168
00169
00170
00171
00172 OglImageLoader loader(mSource, column, id, p->second);
00173
00174 mThreadPool->schedule(loader);
00175
00176 mActiveTasks = true;
00177
00178 return p->second;
00179 }
00180 #endif
00181
00182 #ifndef USE_BOOST_THREADS
00183 bool
00184 IsLoadingImages()
00185 {
00186 return false;
00187 }
00188 #else
00189 bool
00190 IsLoadingImages()
00191 {
00192 if (!mActiveTasks)
00193 return false;
00194
00195 ILOG_DEBUG("TP check: Size " << mThreadPool->size() << " Active tasks " << mThreadPool->active() << " Pending tasks " << mThreadPool->pending());
00196
00197 if (mThreadPool->active() == 0)
00198 mActiveTasks = false;
00199
00200 return true;
00201 }
00202 #endif
00203
00204
00205 int GetImageCacheMaxSize()
00206 {
00207 return mCacheSize;
00208 }
00209
00210
00211 void PreloadCache()
00212 {
00213
00214 int preload = mCacheSize;
00215 if (mSource->GetTotalRows() < mCacheSize)
00216 preload = mSource->GetTotalRows();
00217 ILOG_INFO("Preloading " << preload << " images...");
00218 for (int i=0; i<preload; i++)
00219 {
00220 if (i%100==0)
00221 ILOG_DEBUG("Preloading image " << i << " of " << preload);
00222 LoadImage(i, "");
00223 }
00224 }
00225
00226 private:
00227 ImageCache(TableDataSource* source, int size)
00228 {
00229 Init(source, size);
00230 }
00231
00232 ImageCache(ImageCache const&){};
00233 ImageCache& operator=(ImageCache const&){};
00234
00235 ImageWithID* GetLeastUsedImageFromCache()
00236 {
00237 int item = mLRU.front();
00238 UpdateLRU(item);
00239 return mImages[item];
00240 }
00241
00242 void UpdateLRU(int index)
00243 {
00244 mLRU.remove(index);
00245 mLRU.push_back(index);
00246 }
00247
00248 void Init(TableDataSource* source, int size)
00249 {
00250 mCacheSize = size;
00251 ILOG_DEBUG("Initializing image cache for "<< mCacheSize <<" OGLIMAGEs");
00252
00253 #ifdef USE_BOOST_THREADS
00254 mEmptyArray = Core::Array::ArrayCreate<Core::Array::Array2dVec3UInt8>(0, 0, 0, 0);
00255 mThreadPool = new boost::threadpool::pool();
00256 mThreadPool->size_controller().resize(8);
00257 mActiveTasks = false;
00258 #endif
00259
00260 mSource = source;
00261
00262 for (int i=0; i<mCacheSize; i++)
00263 {
00264 mImages.push_back(new ImageWithID(-1, 0));
00265 mLRU.push_back(i);
00266 }
00267 }
00268
00269 #ifdef USE_BOOST_THREADS
00270 class OglImageLoader {
00271 public:
00272 OglImageLoader(TableDataSource *s, std::string column, int row, OGLIMAGE *result)
00273 {
00274 mSource = s;
00275 mColumn = column;
00276 mRow = row;
00277 mImage = result;
00278 }
00279
00280 void operator()() {
00281 ILOG_DEBUG("Worker thread retrieving " << mColumn << "x" << mRow);
00282 LoadImage();
00283 }
00284
00285 int LoadImage()
00286 {
00287 Array2dVec3UInt8* ar = mSource->GetImageDataByID(mColumn, mRow);
00288 if (ar == 0)
00289 return 0;
00290
00291
00292
00293
00294
00295
00296
00297
00298 mImage->imageHandle = ar;
00299 mImage->h = ar->CH();
00300 mImage->w = ar->CW();
00301 mImage->changed = 1;
00302 ILOG_DEBUG("Loaded image " << mColumn << "x" << mRow << " as " << mImage->w << "x" << mImage->h <<" pixels in " << mImage);
00303
00304 return 1;
00305 }
00306
00307 private:
00308 TableDataSource *mSource;
00309 std::string mColumn;
00310 int mRow;
00311 OGLIMAGE* mImage;
00312 };
00313 #endif
00314
00315
00316 int mCacheSize;
00317
00318 std::list<int> mLRU;
00319 std::vector<ImageWithID*> mImages;
00320 TableDataSource* mSource;
00321
00322 static ImageCache* sInstance;
00323
00324 #ifdef USE_BOOST_THREADS
00325 Core::Array::Array2dVec3UInt8* mEmptyArray;
00326 boost::threadpool::pool *mThreadPool;
00327 bool mActiveTasks;
00328 #endif
00329
00330 ILOG_VAR_DEC;
00331 };
00332
00333 ImageCache* ImageCache::sInstance = 0;
00334
00335 ILOG_VAR_INIT(ImageCache, Application.VideoExcel);
00336
00337 }
00338 }
00339 }
00340 #endif // ImageCache_h
00341
00342
00343