aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamFile.cpp7
-rw-r--r--xbmc/filesystem/CacheStrategy.cpp147
-rw-r--r--xbmc/filesystem/CacheStrategy.h45
-rw-r--r--xbmc/filesystem/CircularCache.cpp29
-rw-r--r--xbmc/filesystem/CircularCache.h7
-rw-r--r--xbmc/filesystem/CurlFile.cpp67
-rw-r--r--xbmc/filesystem/CurlFile.h7
-rw-r--r--xbmc/filesystem/File.cpp6
-rw-r--r--xbmc/filesystem/File.h3
-rw-r--r--xbmc/filesystem/FileCache.cpp52
-rw-r--r--xbmc/filesystem/FileCache.h2
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();