diff options
-rw-r--r-- | xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp | 7 | ||||
-rw-r--r-- | xbmc/filesystem/CacheStrategy.cpp | 147 | ||||
-rw-r--r-- | xbmc/filesystem/CacheStrategy.h | 45 | ||||
-rw-r--r-- | xbmc/filesystem/CircularCache.cpp | 29 | ||||
-rw-r--r-- | xbmc/filesystem/CircularCache.h | 7 | ||||
-rw-r--r-- | xbmc/filesystem/CurlFile.cpp | 67 | ||||
-rw-r--r-- | xbmc/filesystem/CurlFile.h | 7 | ||||
-rw-r--r-- | xbmc/filesystem/File.cpp | 6 | ||||
-rw-r--r-- | xbmc/filesystem/File.h | 3 | ||||
-rw-r--r-- | xbmc/filesystem/FileCache.cpp | 52 | ||||
-rw-r--r-- | xbmc/filesystem/FileCache.h | 2 |
11 files changed, 320 insertions, 52 deletions
diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp index 66626860ce..68063cd4fa 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp @@ -51,8 +51,13 @@ bool CDVDInputStreamFile::Open(const char* strFile, const std::string& content) if (!m_pFile) return false; + unsigned int flags = READ_TRUNCATED | READ_BITRATE | READ_CHUNKED; + + if (content == "video/mp4" || content == "video/x-msvideo" || content == "video/avi") + flags |= READ_MULTI_STREAM; + // open file in binary mode - if (!m_pFile->Open(strFile, READ_TRUNCATED | READ_BITRATE | READ_CHUNKED)) + if (!m_pFile->Open(strFile, flags)) { delete m_pFile; m_pFile = NULL; diff --git a/xbmc/filesystem/CacheStrategy.cpp b/xbmc/filesystem/CacheStrategy.cpp index 6ffd02c575..7de6b8711a 100644 --- a/xbmc/filesystem/CacheStrategy.cpp +++ b/xbmc/filesystem/CacheStrategy.cpp @@ -229,9 +229,16 @@ int64_t CSimpleFileCache::Seek(int64_t iFilePosition) return iFilePosition; } -void CSimpleFileCache::Reset(int64_t iSourcePosition) +void CSimpleFileCache::Reset(int64_t iSourcePosition, bool clearAnyway) { LARGE_INTEGER pos; + if (!clearAnyway && IsCachedPosition(iSourcePosition)) + { + pos.QuadPart = m_nReadPosition = iSourcePosition - m_nStartPosition; + SetFilePointerEx(m_hCacheFileRead, pos, NULL, FILE_BEGIN); + return; + } + pos.QuadPart = 0; SetFilePointerEx(m_hCacheFileWrite, pos, NULL, FILE_BEGIN); @@ -247,3 +254,141 @@ void CSimpleFileCache::EndOfInput() m_hDataAvailEvent->Set(); } +int64_t CSimpleFileCache::CachedDataEndPosIfSeekTo(int64_t iFilePosition) +{ + if (iFilePosition >= m_nStartPosition && iFilePosition <= m_nStartPosition + m_nWritePosition) + return m_nStartPosition + m_nWritePosition; + return iFilePosition; +} + +int64_t CSimpleFileCache::CachedDataEndPos() +{ + return m_nStartPosition + m_nWritePosition; +} + +bool CSimpleFileCache::IsCachedPosition(int64_t iFilePosition) +{ + return iFilePosition >= m_nStartPosition && iFilePosition <= m_nStartPosition + m_nWritePosition; +} + +CCacheStrategy *CSimpleFileCache::CreateNew() +{ + return new CSimpleFileCache(); +} + + +CSimpleDoubleCache::CSimpleDoubleCache(CCacheStrategy *impl) +{ + assert(NULL != impl); + m_pCache = impl; + m_pCacheOld = NULL; +} + +CSimpleDoubleCache::~CSimpleDoubleCache() +{ + delete m_pCache; + delete m_pCacheOld; +} + +int CSimpleDoubleCache::Open() +{ + return m_pCache->Open(); +} + +void CSimpleDoubleCache::Close() +{ + m_pCache->Close(); + if (m_pCacheOld) + { + delete m_pCacheOld; + m_pCacheOld = NULL; + } +} + +int CSimpleDoubleCache::WriteToCache(const char *pBuffer, size_t iSize) +{ + return m_pCache->WriteToCache(pBuffer, iSize); +} + +int CSimpleDoubleCache::ReadFromCache(char *pBuffer, size_t iMaxSize) +{ + return m_pCache->ReadFromCache(pBuffer, iMaxSize); +} + +int64_t CSimpleDoubleCache::WaitForData(unsigned int iMinAvail, unsigned int iMillis) +{ + return m_pCache->WaitForData(iMinAvail, iMillis); +} + +int64_t CSimpleDoubleCache::Seek(int64_t iFilePosition) +{ + return m_pCache->Seek(iFilePosition); +} + +void CSimpleDoubleCache::Reset(int64_t iSourcePosition, bool clearAnyway) +{ + if (!clearAnyway && m_pCache->IsCachedPosition(iSourcePosition) + && (!m_pCacheOld || !m_pCacheOld->IsCachedPosition(iSourcePosition) + || m_pCache->CachedDataEndPos() >= m_pCacheOld->CachedDataEndPos())) + { + m_pCache->Reset(iSourcePosition, clearAnyway); + return; + } + if (!m_pCacheOld) + { + CSimpleFileCache *pCacheNew = new CSimpleFileCache(); + if (pCacheNew->Open() != CACHE_RC_OK) + { + delete pCacheNew; + m_pCache->Reset(iSourcePosition, clearAnyway); + return; + } + pCacheNew->Reset(iSourcePosition, clearAnyway); + m_pCacheOld = m_pCache; + m_pCache = pCacheNew; + return; + } + m_pCacheOld->Reset(iSourcePosition, clearAnyway); + CCacheStrategy *tmp = m_pCacheOld; + m_pCacheOld = m_pCache; + m_pCache = tmp; +} + +void CSimpleDoubleCache::EndOfInput() +{ + m_pCache->EndOfInput(); +} + +bool CSimpleDoubleCache::IsEndOfInput() +{ + return m_pCache->IsEndOfInput(); +} + +void CSimpleDoubleCache::ClearEndOfInput() +{ + m_pCache->ClearEndOfInput(); +} + +int64_t CSimpleDoubleCache::CachedDataEndPos() +{ + return m_pCache->CachedDataEndPos(); +} + +int64_t CSimpleDoubleCache::CachedDataEndPosIfSeekTo(int64_t iFilePosition) +{ + int64_t ret = m_pCache->CachedDataEndPosIfSeekTo(iFilePosition); + if (m_pCacheOld) + return std::max(ret, m_pCacheOld->CachedDataEndPosIfSeekTo(iFilePosition)); + return ret; +} + +bool CSimpleDoubleCache::IsCachedPosition(int64_t iFilePosition) +{ + return m_pCache->IsCachedPosition(iFilePosition) || (m_pCacheOld && m_pCacheOld->IsCachedPosition(iFilePosition)); +} + +CCacheStrategy *CSimpleDoubleCache::CreateNew() +{ + return new CSimpleDoubleCache(m_pCache->CreateNew()); +} + diff --git a/xbmc/filesystem/CacheStrategy.h b/xbmc/filesystem/CacheStrategy.h index c99d3e6c8e..8b33beba7f 100644 --- a/xbmc/filesystem/CacheStrategy.h +++ b/xbmc/filesystem/CacheStrategy.h @@ -51,12 +51,18 @@ public: virtual int64_t WaitForData(unsigned int iMinAvail, unsigned int iMillis) = 0; virtual int64_t Seek(int64_t iFilePosition) = 0; - virtual void Reset(int64_t iSourcePosition) = 0; + virtual void Reset(int64_t iSourcePosition, bool clearAnyway=true) = 0; virtual void EndOfInput(); // mark the end of the input stream so that Read will know when to return EOF virtual bool IsEndOfInput(); virtual void ClearEndOfInput(); + virtual int64_t CachedDataEndPosIfSeekTo(int64_t iFilePosition) = 0; + virtual int64_t CachedDataEndPos() = 0; + virtual bool IsCachedPosition(int64_t iFilePosition) = 0; + + virtual CCacheStrategy *CreateNew() = 0; + CEvent m_space; protected: bool m_bEndOfInput; @@ -77,9 +83,15 @@ public: virtual int64_t WaitForData(unsigned int iMinAvail, unsigned int iMillis) ; virtual int64_t Seek(int64_t iFilePosition); - virtual void Reset(int64_t iSourcePosition); + virtual void Reset(int64_t iSourcePosition, bool clearAnyway=true); virtual void EndOfInput(); + virtual int64_t CachedDataEndPosIfSeekTo(int64_t iFilePosition); + virtual int64_t CachedDataEndPos(); + virtual bool IsCachedPosition(int64_t iFilePosition); + + virtual CCacheStrategy *CreateNew(); + int64_t GetAvailableRead(); protected: @@ -91,6 +103,35 @@ protected: volatile int64_t m_nReadPosition; }; +class CSimpleDoubleCache : public CCacheStrategy{ +public: + CSimpleDoubleCache(CCacheStrategy *impl); + virtual ~CSimpleDoubleCache(); + + virtual int Open() ; + virtual void Close() ; + + virtual int WriteToCache(const char *pBuffer, size_t iSize) ; + virtual int ReadFromCache(char *pBuffer, size_t iMaxSize) ; + virtual int64_t WaitForData(unsigned int iMinAvail, unsigned int iMillis) ; + + virtual int64_t Seek(int64_t iFilePosition); + virtual void Reset(int64_t iSourcePosition, bool clearAnyway=true); + virtual void EndOfInput(); + virtual bool IsEndOfInput(); + virtual void ClearEndOfInput(); + + virtual int64_t CachedDataEndPosIfSeekTo(int64_t iFilePosition); + virtual int64_t CachedDataEndPos(); + virtual bool IsCachedPosition(int64_t iFilePosition); + + virtual CCacheStrategy *CreateNew(); + +protected: + CCacheStrategy *m_pCache; + CCacheStrategy *m_pCacheOld; +}; + } #endif diff --git a/xbmc/filesystem/CircularCache.cpp b/xbmc/filesystem/CircularCache.cpp index 251a634e0a..fa2f83a9f1 100644 --- a/xbmc/filesystem/CircularCache.cpp +++ b/xbmc/filesystem/CircularCache.cpp @@ -211,11 +211,38 @@ int64_t CCircularCache::Seek(int64_t pos) return CACHE_RC_ERROR; } -void CCircularCache::Reset(int64_t pos) +void CCircularCache::Reset(int64_t pos, bool clearAnyway) { CSingleLock lock(m_sync); + if (!clearAnyway && IsCachedPosition(pos)) + { + m_cur = pos; + return; + } m_end = pos; m_beg = pos; m_cur = pos; } +int64_t CCircularCache::CachedDataEndPosIfSeekTo(int64_t iFilePosition) +{ + if (IsCachedPosition(iFilePosition)) + return m_end; + return iFilePosition; +} + +int64_t CCircularCache::CachedDataEndPos() +{ + return m_end; +} + +bool CCircularCache::IsCachedPosition(int64_t iFilePosition) +{ + return iFilePosition >= m_beg && iFilePosition <= m_end; +} + +CCacheStrategy *CCircularCache::CreateNew() +{ + return new CCircularCache(m_size - m_size_back, m_size_back); +} + diff --git a/xbmc/filesystem/CircularCache.h b/xbmc/filesystem/CircularCache.h index 7b5025a8ea..d815628094 100644 --- a/xbmc/filesystem/CircularCache.h +++ b/xbmc/filesystem/CircularCache.h @@ -41,8 +41,13 @@ public: virtual int64_t WaitForData(unsigned int minimum, unsigned int iMillis) ; virtual int64_t Seek(int64_t pos) ; - virtual void Reset(int64_t pos) ; + virtual void Reset(int64_t pos, bool clearAnyway=true) ; + virtual int64_t CachedDataEndPosIfSeekTo(int64_t iFilePosition); + virtual int64_t CachedDataEndPos(); + virtual bool IsCachedPosition(int64_t iFilePosition); + + virtual CCacheStrategy *CreateNew(); protected: int64_t m_beg; /**< index in file (not buffer) of beginning of valid data */ int64_t m_end; /**< index in file (not buffer) of end of valid data */ diff --git a/xbmc/filesystem/CurlFile.cpp b/xbmc/filesystem/CurlFile.cpp index 1226f5760d..04018086a1 100644 --- a/xbmc/filesystem/CurlFile.cpp +++ b/xbmc/filesystem/CurlFile.cpp @@ -256,6 +256,8 @@ CCurlFile::CReadState::CReadState() m_headerdone = false; m_readBuffer = 0; m_isPaused = false; + m_curlHeaderList = NULL; + m_curlAliasList = NULL; } CCurlFile::CReadState::~CReadState() @@ -366,6 +368,15 @@ void CCurlFile::CReadState::Disconnect() m_fileSize = 0; m_bufferSize = 0; m_readBuffer = 0; + + /* cleanup */ + if( m_curlHeaderList ) + g_curlInterface.slist_free_all(m_curlHeaderList); + m_curlHeaderList = NULL; + + if( m_curlAliasList ) + g_curlInterface.slist_free_all(m_curlAliasList); + m_curlAliasList = NULL; } @@ -374,14 +385,13 @@ CCurlFile::~CCurlFile() CSingleLock lock(s_hostMapLock); Close(); delete m_state; + delete m_oldState; g_curlInterface.Unload(); } CCurlFile::CCurlFile() { g_curlInterface.Load(); // loads the curl dll and resolves exports etc. - m_curlAliasList = NULL; - m_curlHeaderList = NULL; m_opened = false; m_forWrite = false; m_inError = false; @@ -402,6 +412,7 @@ CCurlFile::CCurlFile() m_httpauth = ""; m_proxytype = PROXY_HTTP; m_state = new CReadState(); + m_oldState = NULL; m_skipshout = false; m_httpresponse = -1; } @@ -418,19 +429,13 @@ void CCurlFile::Close() Write(NULL, 0); m_state->Disconnect(); + delete m_oldState; + m_oldState = NULL; m_url.Empty(); m_referer.Empty(); m_cookie.Empty(); - /* cleanup */ - if( m_curlAliasList ) - g_curlInterface.slist_free_all(m_curlAliasList); - if( m_curlHeaderList ) - g_curlInterface.slist_free_all(m_curlHeaderList); - - m_curlAliasList = NULL; - m_curlHeaderList = NULL; m_opened = false; m_forWrite = false; m_inError = false; @@ -498,11 +503,11 @@ void CCurlFile::SetCommonOptions(CReadState* state) g_curlInterface.easy_setopt(h, CURLOPT_FAILONERROR, 1); // enable support for icecast / shoutcast streams - if ( NULL == m_curlAliasList ) + if ( NULL == state->m_curlAliasList ) // m_curlAliasList is used only by this one place, but SetCommonOptions can // be called multiple times, only append to list if it's empty. - m_curlAliasList = g_curlInterface.slist_append(m_curlAliasList, "ICY 200 OK"); - g_curlInterface.easy_setopt(h, CURLOPT_HTTP200ALIASES, m_curlAliasList); + state->m_curlAliasList = g_curlInterface.slist_append(state->m_curlAliasList, "ICY 200 OK"); + g_curlInterface.easy_setopt(h, CURLOPT_HTTP200ALIASES, state->m_curlAliasList); // never verify peer, we don't have any certificates to do this g_curlInterface.easy_setopt(h, CURLOPT_SSL_VERIFYPEER, 0); @@ -618,22 +623,22 @@ void CCurlFile::SetCommonOptions(CReadState* state) void CCurlFile::SetRequestHeaders(CReadState* state) { - if(m_curlHeaderList) + if(state->m_curlHeaderList) { - g_curlInterface.slist_free_all(m_curlHeaderList); - m_curlHeaderList = NULL; + g_curlInterface.slist_free_all(state->m_curlHeaderList); + state->m_curlHeaderList = NULL; } MAPHTTPHEADERS::iterator it; for(it = m_requestheaders.begin(); it != m_requestheaders.end(); it++) { CStdString buffer = it->first + ": " + it->second; - m_curlHeaderList = g_curlInterface.slist_append(m_curlHeaderList, buffer.c_str()); + state->m_curlHeaderList = g_curlInterface.slist_append(state->m_curlHeaderList, buffer.c_str()); } // add user defined headers - if (m_curlHeaderList && state->m_easyHandle) - g_curlInterface.easy_setopt(state->m_easyHandle, CURLOPT_HTTPHEADER, m_curlHeaderList); + if (state->m_easyHandle) + g_curlInterface.easy_setopt(state->m_easyHandle, CURLOPT_HTTPHEADER, state->m_curlHeaderList); } void CCurlFile::SetCorrectHeaders(CReadState* state) @@ -1170,6 +1175,14 @@ int64_t CCurlFile::Seek(int64_t iFilePosition, int iWhence) if(m_state->Seek(nextPos)) return nextPos; + if (m_oldState && m_oldState->Seek(nextPos)) + { + CReadState *tmp = m_state; + m_state = m_oldState; + m_oldState = tmp; + return nextPos; + } + if(!m_seekable) return -1; @@ -1177,32 +1190,34 @@ int64_t CCurlFile::Seek(int64_t iFilePosition, int iWhence) if(m_multisession) { CURL url(m_url); - oldstate = m_state; + oldstate = m_oldState; + m_oldState = m_state; m_state = new CReadState(); g_curlInterface.easy_aquire(url.GetProtocol(), url.GetHostName(), &m_state->m_easyHandle, &m_state->m_multiHandle ); - // setup common curl options - SetCommonOptions(m_state); + m_state->m_fileSize = m_oldState->m_fileSize; } else m_state->Disconnect(); + // re-setup common curl options + SetCommonOptions(m_state); + /* caller might have changed some headers (needed for daap)*/ SetRequestHeaders(m_state); m_state->m_filePos = nextPos; - if (oldstate) - m_state->m_fileSize = oldstate->m_fileSize; long response = m_state->Connect(m_bufferSize); if(response < 0 && (m_state->m_fileSize == 0 || m_state->m_fileSize != m_state->m_filePos)) { m_seekable = false; - if(oldstate) + if(m_multisession && m_oldState) { delete m_state; - m_state = oldstate; + m_state = m_oldState; + m_oldState = oldstate; } return -1; } diff --git a/xbmc/filesystem/CurlFile.h b/xbmc/filesystem/CurlFile.h index fefd5722de..86c6c4ddcc 100644 --- a/xbmc/filesystem/CurlFile.h +++ b/xbmc/filesystem/CurlFile.h @@ -121,6 +121,9 @@ namespace XFILE CHttpHeader m_httpheader; bool m_headerdone; + struct XCURL::curl_slist* m_curlHeaderList; + struct XCURL::curl_slist* m_curlAliasList; + size_t ReadCallback(char *buffer, size_t size, size_t nitems); size_t WriteCallback(char *buffer, size_t size, size_t nitems); size_t HeaderCallback(void *ptr, size_t size, size_t nmemb); @@ -145,6 +148,7 @@ namespace XFILE protected: CReadState* m_state; + CReadState* m_oldState; unsigned int m_bufferSize; int64_t m_writeOffset; @@ -182,9 +186,6 @@ namespace XFILE int m_stillRunning; // Is background url fetch still in progress? - struct XCURL::curl_slist* m_curlAliasList; - struct XCURL::curl_slist* m_curlHeaderList; - typedef std::map<CStdString, CStdString> MAPHTTPHEADERS; MAPHTTPHEADERS m_requestheaders; diff --git a/xbmc/filesystem/File.cpp b/xbmc/filesystem/File.cpp index 3281a3d0b0..cc6d51a6f6 100644 --- a/xbmc/filesystem/File.cpp +++ b/xbmc/filesystem/File.cpp @@ -227,12 +227,14 @@ bool CFile::Open(const CStdString& strFileName, unsigned int flags) } CURL url(URIUtils::SubstitutePath(strFileName)); - if ( (flags & READ_NO_CACHE) == 0 && URIUtils::IsInternetStream(url, true) && !CUtil::IsPicture(strFileName) ) + bool isInternetStream = URIUtils::IsInternetStream(url, true); + if ( (flags & READ_NO_CACHE) == 0 && isInternetStream && !CUtil::IsPicture(strFileName) ) m_flags |= READ_CACHED; if (m_flags & READ_CACHED) { - m_pFile = new CFileCache(); + // for internet stream, if it contains multiple stream, file cache need handle it specially. + m_pFile = new CFileCache((m_flags & READ_MULTI_STREAM)!=0 && isInternetStream); return m_pFile->Open(url); } diff --git a/xbmc/filesystem/File.h b/xbmc/filesystem/File.h index 0be788ef10..2cc6cfe55e 100644 --- a/xbmc/filesystem/File.h +++ b/xbmc/filesystem/File.h @@ -64,6 +64,9 @@ public: /* calcuate bitrate for file while reading */ #define READ_BITRATE 0x10 +/* indicate the caller will seek between multiple streams in the file frequently */ +#define READ_MULTI_STREAM 0x20 + class CFileStreamBuffer; class CFile diff --git a/xbmc/filesystem/FileCache.cpp b/xbmc/filesystem/FileCache.cpp index 39241ef9a5..5dfd38d877 100644 --- a/xbmc/filesystem/FileCache.cpp +++ b/xbmc/filesystem/FileCache.cpp @@ -78,7 +78,7 @@ private: }; -CFileCache::CFileCache() : CThread("FileCache") +CFileCache::CFileCache(bool useDoubleCache) : CThread("FileCache") { m_bDeleteCache = true; m_nSeekResult = 0; @@ -88,8 +88,20 @@ CFileCache::CFileCache() : CThread("FileCache") if (g_advancedSettings.m_cacheMemBufferSize == 0) m_pCache = new CSimpleFileCache(); else - m_pCache = new CCircularCache(g_advancedSettings.m_cacheMemBufferSize - , std::max<unsigned int>( g_advancedSettings.m_cacheMemBufferSize / 4, 1024 * 1024)); + { + size_t front = g_advancedSettings.m_cacheMemBufferSize; + size_t back = std::max<size_t>( g_advancedSettings.m_cacheMemBufferSize / 4, 1024 * 1024); + if (useDoubleCache) + { + front = front / 2; + back = back / 2; + } + m_pCache = new CCircularCache(front, back); + } + if (useDoubleCache) + { + m_pCache = new CSimpleDoubleCache(m_pCache); + } m_seekPossible = 0; m_cacheFull = false; } @@ -198,6 +210,7 @@ void CFileCache::Process() CWriteRate limiter; CWriteRate average; + bool cacheReachEOF = false; while (!m_bStop) { @@ -205,21 +218,30 @@ void CFileCache::Process() if (m_seekEvent.WaitMSec(0)) { m_seekEvent.Reset(); - CLog::Log(LOGDEBUG,"%s, request seek on source to %"PRId64, __FUNCTION__, m_seekPos); - m_nSeekResult = m_source.Seek(m_seekPos, SEEK_SET); - if (m_nSeekResult != m_seekPos) + int64_t cacheMaxPos = m_pCache->CachedDataEndPosIfSeekTo(m_seekPos); + cacheReachEOF = cacheMaxPos == m_source.GetLength(); + bool sourceSeekFailed = false; + if (!cacheReachEOF) { - CLog::Log(LOGERROR,"%s, error %d seeking. seek returned %"PRId64, __FUNCTION__, (int)GetLastError(), m_nSeekResult); - m_seekPossible = m_source.IoControl(IOCTRL_SEEK_POSSIBLE, NULL); + CLog::Log(LOGDEBUG,"%s, request seek on source to %"PRId64, __FUNCTION__, cacheMaxPos); + m_nSeekResult = m_source.Seek(cacheMaxPos, SEEK_SET); + if (m_nSeekResult != cacheMaxPos) + { + CLog::Log(LOGERROR,"%s, error %d seeking. seek returned %"PRId64, __FUNCTION__, (int)GetLastError(), m_nSeekResult); + m_seekPossible = m_source.IoControl(IOCTRL_SEEK_POSSIBLE, NULL); + sourceSeekFailed = true; + } } - else + if (!sourceSeekFailed) { - m_pCache->Reset(m_seekPos); - average.Reset(m_seekPos); - limiter.Reset(m_seekPos); - m_writePos = m_seekPos; + m_pCache->Reset(m_seekPos, false); m_readPos = m_seekPos; + m_writePos = m_pCache->CachedDataEndPos(); + assert(m_writePos == cacheMaxPos); + average.Reset(m_writePos); + limiter.Reset(m_writePos); m_cacheFull = false; + m_nSeekResult = m_seekPos; } m_seekEnded.Set(); @@ -243,7 +265,9 @@ void CFileCache::Process() } } - int iRead = m_source.Read(buffer.get(), m_chunkSize); + int iRead = 0; + if (!cacheReachEOF) + iRead = m_source.Read(buffer.get(), m_chunkSize); if (iRead == 0) { CLog::Log(LOGINFO, "CFileCache::Process - Hit eof."); diff --git a/xbmc/filesystem/FileCache.h b/xbmc/filesystem/FileCache.h index c12025f77f..f13151e1ed 100644 --- a/xbmc/filesystem/FileCache.h +++ b/xbmc/filesystem/FileCache.h @@ -31,7 +31,7 @@ namespace XFILE class CFileCache : public IFile, public CThread { public: - CFileCache(); + CFileCache(bool useDoubleCache=false); CFileCache(CCacheStrategy *pCache, bool bDeleteCache=true); virtual ~CFileCache(); |