home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Meia / source / MPEGCache.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  2.8 KB  |  139 lines

  1. #include <string.h>
  2.  
  3. #include "MPEGCache.h"
  4.  
  5. VDMPEGCache::VDMPEGCache(int nBlocks, int nBlockLen)
  6.     : mpCacheMemory(new char[nBlockLen * nBlocks])
  7.     , mNextAgeValue(0)
  8.     , mBlockSize(nBlockLen)
  9. {
  10.     VDASSERT(mpCacheMemory);
  11.  
  12.     for(int i=0; i<nBlocks; ++i) {
  13.         CacheEntry e;
  14.  
  15.         e.pos = 0;
  16.         e.len = 0;
  17.         e.next = -1;
  18.         e.age = 0;
  19.  
  20.         mCacheBlocks.push_back(e);
  21.     }
  22. }
  23.  
  24. VDMPEGCache::~VDMPEGCache() {
  25.     delete[] mpCacheMemory;
  26. }
  27.  
  28. bool VDMPEGCache::Read(void *pData, int64 bytepos, int len, int offset) {
  29.     VDASSERTPTR(this);
  30.     VDASSERTPTR(pData);
  31.     VDASSERT(bytepos != 0);
  32.     VDASSERT(len > 0);
  33.  
  34.     if (mpCacheMemory) {
  35.         int nBlocks = mCacheBlocks.size();
  36.  
  37.         for(int i=0; i<nBlocks; ++i) {
  38.             if (mCacheBlocks[i].pos == bytepos) {
  39.                 ++mNextAgeValue;
  40.  
  41. //                VDDEBUG2("Cache hit  : %16I64x + %-5d (%5d)\n", bytepos, offset, len);
  42.  
  43.                 while(len > 0) {
  44.  
  45.                     VDASSERT(i>=0);
  46.  
  47.                     int blen = mCacheBlocks[i].len - offset;
  48.  
  49.                     if (blen > len)
  50.                         blen = len;
  51.  
  52.                     VDASSERT(blen > 0);
  53.  
  54.                     memcpy(pData, mpCacheMemory + mBlockSize * i + offset, blen);
  55.  
  56.                     pData = (char *)pData + blen;
  57.                     len -= blen;
  58.  
  59.                     mCacheBlocks[i].age = mNextAgeValue;
  60.  
  61.                     i = mCacheBlocks[i].next;
  62.                     offset = 0;
  63.                 }
  64.  
  65.                 VDASSERT(!len);
  66.  
  67.                 return true;
  68.             }
  69.         }
  70.     }
  71.  
  72. //    VDDEBUG2("Cache miss : %16I64x + %-5d (%5d)\n", bytepos, offset, len);
  73.  
  74.     return false;
  75. }
  76.  
  77. void VDMPEGCache::Write(const void *pData, int64 bytepos, int len) {
  78.     VDASSERTPTR(this);
  79.     VDASSERTPTR(pData);
  80.     VDASSERT(bytepos != 0);
  81.     VDASSERT(len > 0);
  82.  
  83.     if (!mpCacheMemory || (size_t)len > mCacheBlocks.size()*mBlockSize)
  84.         return;
  85.  
  86. //    VDDEBUG2("Cache store: %16I64x +       (%5d)\n", bytepos, len);
  87.  
  88.     ++mNextAgeValue;
  89.  
  90.     int victim = Evict(), next_victim;
  91.  
  92.     while(len > 0) {
  93.         int blen = mBlockSize>len ? mBlockSize : len;
  94.         len -= blen;
  95.  
  96.         // Age must be set before next evict to avoid getting the same block
  97.         // twice
  98.  
  99.         mCacheBlocks[victim].age = mNextAgeValue;
  100.  
  101.         next_victim = -1;
  102.         if (len)
  103.             next_victim = Evict();
  104.  
  105.         memcpy(mpCacheMemory + mBlockSize*victim, pData, blen);
  106.  
  107.         mCacheBlocks[victim].pos = bytepos;
  108.         mCacheBlocks[victim].len = blen;
  109.         mCacheBlocks[victim].next = next_victim;
  110.  
  111.         // Only write out a non-zero byte position for the first block.
  112.  
  113.         bytepos = 0;
  114.         pData = (char *)pData + blen;
  115.         victim = next_victim;
  116.     }
  117. }
  118.  
  119. int VDMPEGCache::Evict() {
  120.     int nBlocks = mCacheBlocks.size();
  121.  
  122.     // Evict the block with the oldest age
  123.  
  124.     unsigned oldest_age = 0;
  125.     int oldest_age_idx = 0;        // all else failing, evict block 0
  126.  
  127.     for(int i=0; i<nBlocks; ++i) {
  128.         unsigned age_delta = mNextAgeValue - mCacheBlocks[i].age;
  129.  
  130.         if (age_delta > oldest_age) {
  131.             oldest_age_idx = i;
  132.             oldest_age = age_delta;
  133.         }
  134.     }
  135.  
  136.     return oldest_age_idx;
  137. }
  138.  
  139.