Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/filters/parser/BaseSplitter/BaseSplitterFile.cpp')
-rw-r--r--src/filters/parser/BaseSplitter/BaseSplitterFile.cpp244
1 files changed, 244 insertions, 0 deletions
diff --git a/src/filters/parser/BaseSplitter/BaseSplitterFile.cpp b/src/filters/parser/BaseSplitter/BaseSplitterFile.cpp
new file mode 100644
index 000000000..42fb1be4b
--- /dev/null
+++ b/src/filters/parser/BaseSplitter/BaseSplitterFile.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2003-2006 Gabest
+ * http://www.gabest.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "StdAfx.h"
+#include "BaseSplitterFile.h"
+#include "../../../dsutil/dsutil.h"
+
+//
+// CBaseSplitterFile
+//
+
+CBaseSplitterFile::CBaseSplitterFile(IAsyncReader* pAsyncReader, HRESULT& hr, int cachelen, bool fRandomAccess, bool fStreaming)
+ : m_pAsyncReader(pAsyncReader)
+ , m_fStreaming(false)
+ , m_fRandomAccess(false)
+ , m_pos(0), m_len(0)
+ , m_bitbuff(0), m_bitlen(0)
+ , m_cachepos(0), m_cachelen(0)
+{
+ if(!m_pAsyncReader) {hr = E_UNEXPECTED; return;}
+
+ LONGLONG total = 0, available;
+ hr = m_pAsyncReader->Length(&total, &available);
+
+ m_fStreaming = total == 0 && available > 0;
+ m_fRandomAccess = total > 0 && total == available;
+ m_len = total;
+
+ if(FAILED(hr) || fRandomAccess && !m_fRandomAccess || !fStreaming && m_fStreaming || m_len < 0)
+ {
+ hr = E_FAIL;
+ return;
+ }
+
+ if(!SetCacheSize(cachelen))
+ {
+ hr = E_OUTOFMEMORY;
+ return;
+ }
+
+ hr = S_OK;
+}
+
+bool CBaseSplitterFile::SetCacheSize(int cachelen)
+{
+ m_pCache.Free();
+ m_cachetotal = 0;
+ m_pCache.Allocate((size_t)cachelen);
+ if(!m_pCache) return false;
+ m_cachetotal = cachelen;
+ m_cachelen = 0;
+ return true;
+}
+
+__int64 CBaseSplitterFile::GetPos()
+{
+ return m_pos - (m_bitlen>>3);
+}
+
+__int64 CBaseSplitterFile::GetAvailable()
+{
+ LONGLONG total, available = 0;
+ m_pAsyncReader->Length(&total, &available);
+ return available;
+}
+
+__int64 CBaseSplitterFile::GetLength(bool fUpdate)
+{
+ if(m_fStreaming)
+ {
+ m_len = GetAvailable();
+ }
+ else if(fUpdate)
+ {
+ LONGLONG total = 0, available;
+ m_pAsyncReader->Length(&total, &available);
+ m_len = total;
+ }
+
+ return m_len;
+}
+
+void CBaseSplitterFile::Seek(__int64 pos)
+{
+ __int64 len = GetLength();
+ m_pos = min(max(pos, 0), len);
+ BitFlush();
+}
+
+HRESULT CBaseSplitterFile::Read(BYTE* pData, __int64 len)
+{
+ CheckPointer(m_pAsyncReader, E_NOINTERFACE);
+
+ HRESULT hr = S_OK;
+
+ if(!m_fRandomAccess)
+ {
+ LONGLONG total = 0, available = -1;
+ m_pAsyncReader->Length(&total, &available);
+ if(total == available) {m_fRandomAccess = true; OnComplete();}
+ }
+
+ if(m_cachetotal == 0 || !m_pCache)
+ {
+ hr = m_pAsyncReader->SyncRead(m_pos, (long)len, pData);
+ m_pos += len;
+ return hr;
+ }
+
+ BYTE* pCache = m_pCache;
+
+ if(m_cachepos <= m_pos && m_pos < m_cachepos + m_cachelen)
+ {
+ __int64 minlen = min(len, m_cachelen - (m_pos - m_cachepos));
+
+ memcpy(pData, &pCache[m_pos - m_cachepos], (size_t)minlen);
+
+ len -= minlen;
+ m_pos += minlen;
+ pData += minlen;
+ }
+
+ while(len > m_cachetotal)
+ {
+ hr = m_pAsyncReader->SyncRead(m_pos, (long)m_cachetotal, pData);
+ if(S_OK != hr) return hr;
+
+ len -= m_cachetotal;
+ m_pos += m_cachetotal;
+ pData += m_cachetotal;
+ }
+
+ while(len > 0)
+ {
+ __int64 tmplen = GetLength();
+ __int64 maxlen = min(tmplen - m_pos, m_cachetotal);
+ __int64 minlen = min(len, maxlen);
+ if(minlen <= 0) return S_FALSE;
+
+ hr = m_pAsyncReader->SyncRead(m_pos, (long)maxlen, pCache);
+ if(S_OK != hr) return hr;
+
+ m_cachepos = m_pos;
+ m_cachelen = maxlen;
+
+ memcpy(pData, pCache, (size_t)minlen);
+
+ len -= minlen;
+ m_pos += minlen;
+ pData += minlen;
+ }
+
+ return hr;
+}
+
+UINT64 CBaseSplitterFile::BitRead(int nBits, bool fPeek)
+{
+ ASSERT(nBits >= 0 && nBits <= 64);
+
+ while(m_bitlen < nBits)
+ {
+ m_bitbuff <<= 8;
+ if(S_OK != Read((BYTE*)&m_bitbuff, 1)) {return 0;} // EOF? // ASSERT(0);
+ m_bitlen += 8;
+ }
+
+ int bitlen = m_bitlen - nBits;
+
+ UINT64 ret = (m_bitbuff >> bitlen) & ((1ui64 << nBits) - 1);
+
+ if(!fPeek)
+ {
+ m_bitbuff &= ((1ui64 << bitlen) - 1);
+ m_bitlen = bitlen;
+ }
+
+ return ret;
+}
+
+void CBaseSplitterFile::BitByteAlign()
+{
+ m_bitlen &= ~7;
+}
+
+void CBaseSplitterFile::BitFlush()
+{
+ m_bitlen = 0;
+}
+
+HRESULT CBaseSplitterFile::ByteRead(BYTE* pData, __int64 len)
+{
+ Seek(GetPos());
+ return Read(pData, len);
+}
+
+UINT64 CBaseSplitterFile::UExpGolombRead()
+{
+ int n = -1;
+ for(BYTE b = 0; !b; n++) b = BitRead(1);
+ return (1ui64 << n) - 1 + BitRead(n);
+}
+
+INT64 CBaseSplitterFile::SExpGolombRead()
+{
+ UINT64 k = UExpGolombRead();
+ return ((k&1) ? 1 : -1) * ((k + 1) >> 1);
+}
+
+HRESULT CBaseSplitterFile::HasMoreData(__int64 len, DWORD ms)
+{
+ __int64 available = GetLength() - GetPos();
+
+ if(!m_fStreaming)
+ {
+ return available < 1 ? E_FAIL : S_OK;
+ }
+
+ if(available < len)
+ {
+ if(ms > 0) Sleep(ms);
+ return S_FALSE;
+ }
+
+ return S_OK;
+}
+