BaseSplitterFile.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:5k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "StdAfx.h"
  22. #include "BaseSplitterFile.h"
  23. //
  24. // CBaseSplitterFile
  25. //
  26. CBaseSplitterFile::CBaseSplitterFile(IAsyncReader* pAsyncReader, HRESULT& hr, int cachelen)
  27. : m_pAsyncReader(pAsyncReader)
  28. , m_fStreaming(false)
  29. , m_pos(0), m_len(0)
  30. , m_bitbuff(0), m_bitlen(0)
  31. , m_cachepos(0), m_cachelen(0)
  32. {
  33. if(!m_pAsyncReader) {hr = E_UNEXPECTED; return;}
  34. LONGLONG total = 0, available;
  35. hr = m_pAsyncReader->Length(&total, &available);
  36. m_fStreaming = total == 0 && available > 0;
  37. m_len = available;
  38. if(FAILED(hr) || !m_fStreaming && total != available || total < 0)
  39. {
  40. hr = E_FAIL;
  41. return;
  42. }
  43. if(!SetCacheSize(cachelen))
  44. {
  45. hr = E_OUTOFMEMORY; 
  46. return;
  47. }
  48. hr = S_OK;
  49. }
  50. bool CBaseSplitterFile::SetCacheSize(int cachelen)
  51. {
  52. m_pCache.Free();
  53. m_cachetotal = 0;
  54. m_pCache.Allocate((size_t)cachelen);
  55. if(!m_pCache) return false;
  56. m_cachetotal = cachelen;
  57. m_cachelen = 0;
  58. return true;
  59. }
  60. __int64 CBaseSplitterFile::GetPos()
  61. {
  62. return m_pos - (m_bitlen>>3);
  63. }
  64. __int64 CBaseSplitterFile::GetLength()
  65. {
  66. if(m_fStreaming)
  67. {
  68. LONGLONG total, available = 0;
  69. if(SUCCEEDED(m_pAsyncReader->Length(&total, &available))) m_len = available;
  70. }
  71. return m_len;
  72. }
  73. void CBaseSplitterFile::Seek(__int64 pos)
  74. {
  75. __int64 len = GetLength();
  76. m_pos = min(max(pos, 0), len);
  77. BitFlush();
  78. }
  79. HRESULT CBaseSplitterFile::Read(BYTE* pData, __int64 len)
  80. {
  81. CheckPointer(m_pAsyncReader, E_NOINTERFACE);
  82. HRESULT hr = S_OK;
  83. if(m_cachetotal == 0 || !m_pCache)
  84. {
  85. hr = m_pAsyncReader->SyncRead(m_pos, (long)len, pData);
  86. m_pos += len;
  87. return hr;
  88. }
  89. BYTE* pCache = m_pCache;
  90. if(m_cachepos <= m_pos && m_pos < m_cachepos + m_cachelen)
  91. {
  92. __int64 minlen = min(len, m_cachelen - (m_pos - m_cachepos));
  93. memcpy(pData, &pCache[m_pos - m_cachepos], (size_t)minlen);
  94. len -= minlen;
  95. m_pos += minlen;
  96. pData += minlen;
  97. }
  98. while(len > m_cachetotal)
  99. {
  100. hr = m_pAsyncReader->SyncRead(m_pos, (long)m_cachetotal, pData);
  101. if(S_OK != hr) return hr;
  102. len -= m_cachetotal;
  103. m_pos += m_cachetotal;
  104. pData += m_cachetotal;
  105. }
  106. while(len > 0)
  107. {
  108. __int64 tmplen = GetLength();
  109. __int64 maxlen = min(tmplen - m_pos, m_cachetotal);
  110. __int64 minlen = min(len, maxlen);
  111. if(minlen <= 0) return S_FALSE;
  112. hr = m_pAsyncReader->SyncRead(m_pos, (long)maxlen, pCache);
  113. if(S_OK != hr) return hr;
  114. m_cachepos = m_pos;
  115. m_cachelen = maxlen;
  116. memcpy(pData, pCache, (size_t)minlen);
  117. len -= minlen;
  118. m_pos += minlen;
  119. pData += minlen;
  120. }
  121. return hr;
  122. }
  123. UINT64 CBaseSplitterFile::BitRead(int nBits, bool fPeek)
  124. {
  125. ASSERT(nBits >= 0 && nBits <= 64);
  126. while(m_bitlen < nBits)
  127. {
  128. m_bitbuff <<= 8;
  129. if(S_OK != Read((BYTE*)&m_bitbuff, 1)) {return 0;} // EOF? // ASSERT(0);
  130. m_bitlen += 8;
  131. }
  132. int bitlen = m_bitlen - nBits;
  133. UINT64 ret = (m_bitbuff >> bitlen) & ((1ui64 << nBits) - 1);
  134. if(!fPeek)
  135. {
  136. m_bitbuff &= ((1ui64 << bitlen) - 1);
  137. m_bitlen = bitlen;
  138. }
  139. return ret;
  140. }
  141. void CBaseSplitterFile::BitByteAlign()
  142. {
  143. m_bitlen &= ~7;
  144. }
  145. void CBaseSplitterFile::BitFlush()
  146. {
  147. m_bitlen = 0;
  148. }
  149. HRESULT CBaseSplitterFile::ByteRead(BYTE* pData, __int64 len)
  150. {
  151.     Seek(GetPos());
  152. return Read(pData, len);
  153. }
  154. UINT64 CBaseSplitterFile::UExpGolombRead()
  155. {
  156. int n = -1;
  157. for(BYTE b = 0; !b; n++) b = BitRead(1);
  158. return (1ui64 << n) - 1 + BitRead(n);
  159. }
  160. INT64 CBaseSplitterFile::SExpGolombRead()
  161. {
  162. UINT64 k = UExpGolombRead();
  163. return ((k&1) ? 1 : -1) * ((k + 1) >> 1);
  164. }
  165. HRESULT CBaseSplitterFile::HasMoreData(__int64 len, DWORD ms)
  166. {
  167. __int64 available = GetLength() - GetPos();
  168. if(!m_fStreaming)
  169. {
  170. return available < 1 ? E_FAIL : S_OK;
  171. }
  172. if(available < len)
  173. {
  174. if(ms > 0) Sleep(ms);
  175. return S_FALSE;
  176. }
  177. return S_OK;
  178. }