00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "BaseSplitterFile.h"
00024
00025
00026
00027
00028
00029 CBaseSplitterFile::CBaseSplitterFile(IAsyncReader* pAsyncReader, HRESULT& hr, int cachelen)
00030 : m_pAsyncReader(pAsyncReader)
00031 , m_fStreaming(false)
00032 , m_pos(0), m_len(0)
00033 , m_bitbuff(0), m_bitlen(0)
00034 , m_cachepos(0), m_cachelen(0)
00035 {
00036 if(!m_pAsyncReader) {hr = E_UNEXPECTED; return;}
00037
00038 LONGLONG total = 0, available;
00039 hr = m_pAsyncReader->Length(&total, &available);
00040
00041 m_fStreaming = total == 0 && available > 0;
00042 m_len = available;
00043
00044 if(FAILED(hr) || !m_fStreaming && total != available || total < 0)
00045 {
00046 hr = E_FAIL;
00047 return;
00048 }
00049
00050 if(!SetCacheSize(cachelen))
00051 {
00052 hr = E_OUTOFMEMORY;
00053 return;
00054 }
00055
00056 hr = S_OK;
00057 }
00058
00059 bool CBaseSplitterFile::SetCacheSize(int cachelen)
00060 {
00061 m_pCache.Free();
00062 m_cachetotal = 0;
00063 m_pCache.Allocate((size_t)cachelen);
00064 if(!m_pCache) return false;
00065 m_cachetotal = cachelen;
00066 m_cachelen = 0;
00067 return true;
00068 }
00069
00070 __int64 CBaseSplitterFile::GetPos()
00071 {
00072 return m_pos - (m_bitlen>>3);
00073 }
00074
00075 __int64 CBaseSplitterFile::GetLength()
00076 {
00077 if(m_fStreaming)
00078 {
00079 LONGLONG total, available = 0;
00080 if(SUCCEEDED(m_pAsyncReader->Length(&total, &available))) m_len = available;
00081 }
00082
00083 return m_len;
00084 }
00085
00086 void CBaseSplitterFile::Seek(__int64 pos)
00087 {
00088 __int64 len = GetLength();
00089 m_pos = min(max(pos, 0), len);
00090 BitFlush();
00091 }
00092
00093 HRESULT CBaseSplitterFile::Read(BYTE* pData, __int64 len)
00094 {
00095 CheckPointer(m_pAsyncReader, E_NOINTERFACE);
00096
00097 HRESULT hr = S_OK;
00098
00099 if(m_cachetotal == 0 || !m_pCache)
00100 {
00101 hr = m_pAsyncReader->SyncRead(m_pos, (long)len, pData);
00102 m_pos += len;
00103 return hr;
00104 }
00105
00106 BYTE* pCache = m_pCache;
00107
00108 if(m_cachepos <= m_pos && m_pos < m_cachepos + m_cachelen)
00109 {
00110 __int64 minlen = min(len, m_cachelen - (m_pos - m_cachepos));
00111
00112 memcpy(pData, &pCache[m_pos - m_cachepos], (size_t)minlen);
00113
00114 len -= minlen;
00115 m_pos += minlen;
00116 pData += minlen;
00117 }
00118
00119 while(len > m_cachetotal)
00120 {
00121 hr = m_pAsyncReader->SyncRead(m_pos, (long)m_cachetotal, pData);
00122 if(S_OK != hr) return hr;
00123
00124 len -= m_cachetotal;
00125 m_pos += m_cachetotal;
00126 pData += m_cachetotal;
00127 }
00128
00129 while(len > 0)
00130 {
00131 __int64 tmplen = GetLength();
00132 __int64 maxlen = min(tmplen - m_pos, m_cachetotal);
00133 __int64 minlen = min(len, maxlen);
00134 if(minlen <= 0) return S_FALSE;
00135
00136 hr = m_pAsyncReader->SyncRead(m_pos, (long)maxlen, pCache);
00137 if(S_OK != hr) return hr;
00138
00139 m_cachepos = m_pos;
00140 m_cachelen = maxlen;
00141
00142 memcpy(pData, pCache, (size_t)minlen);
00143
00144 len -= minlen;
00145 m_pos += minlen;
00146 pData += minlen;
00147 }
00148
00149 return hr;
00150 }
00151
00152 UINT64 CBaseSplitterFile::BitRead(int nBits, bool fPeek)
00153 {
00154 ASSERT(nBits >= 0 && nBits <= 64);
00155
00156 while(m_bitlen < nBits)
00157 {
00158 m_bitbuff <<= 8;
00159 if(S_OK != Read((BYTE*)&m_bitbuff, 1)) {return 0;}
00160 m_bitlen += 8;
00161 }
00162
00163 int bitlen = m_bitlen - nBits;
00164
00165 UINT64 ret = (m_bitbuff >> bitlen) & ((1ui64 << nBits) - 1);
00166
00167 if(!fPeek)
00168 {
00169 m_bitbuff &= ((1ui64 << bitlen) - 1);
00170 m_bitlen = bitlen;
00171 }
00172
00173 return ret;
00174 }
00175
00176 void CBaseSplitterFile::BitByteAlign()
00177 {
00178 m_bitlen &= ~7;
00179 }
00180
00181 void CBaseSplitterFile::BitFlush()
00182 {
00183 m_bitlen = 0;
00184 }
00185
00186 HRESULT CBaseSplitterFile::ByteRead(BYTE* pData, __int64 len)
00187 {
00188 Seek(GetPos());
00189 return Read(pData, len);
00190 }
00191
00192 UINT64 CBaseSplitterFile::UExpGolombRead()
00193 {
00194 int n = -1;
00195 for(BYTE b = 0; !b; n++) b = BitRead(1);
00196 return (1ui64 << n) - 1 + BitRead(n);
00197 }
00198
00199 INT64 CBaseSplitterFile::SExpGolombRead()
00200 {
00201 UINT64 k = UExpGolombRead();
00202 return ((k&1) ? 1 : -1) * ((k + 1) >> 1);
00203 }
00204
00205 HRESULT CBaseSplitterFile::HasMoreData(__int64 len, DWORD ms)
00206 {
00207 __int64 available = GetLength() - GetPos();
00208
00209 if(!m_fStreaming)
00210 {
00211 return available < 1 ? E_FAIL : S_OK;
00212 }
00213
00214 if(available < len)
00215 {
00216 if(ms > 0) Sleep(ms);
00217 return S_FALSE;
00218 }
00219
00220 return S_OK;
00221 }
00222