1 // BZip2Encoder.h 2 3 #ifndef ZIP7_INC_COMPRESS_BZIP2_ENCODER_H 4 #define ZIP7_INC_COMPRESS_BZIP2_ENCODER_H 5 6 #include "../../Common/Defs.h" 7 #include "../../Common/MyCom.h" 8 9 #ifndef Z7_ST 10 #include "../../Windows/Synchronization.h" 11 #include "../../Windows/Thread.h" 12 #endif 13 14 #include "../ICoder.h" 15 16 #include "../Common/InBuffer.h" 17 #include "../Common/OutBuffer.h" 18 19 #include "BitmEncoder.h" 20 #include "BZip2Const.h" 21 #include "BZip2Crc.h" 22 23 namespace NCompress { 24 namespace NBZip2 { 25 26 class CMsbfEncoderTemp 27 { 28 UInt32 _pos; 29 unsigned _bitPos; 30 Byte _curByte; 31 Byte *_buf; 32 public: SetStream(Byte * buf)33 void SetStream(Byte *buf) { _buf = buf; } GetStream()34 Byte *GetStream() const { return _buf; } 35 Init()36 void Init() 37 { 38 _pos = 0; 39 _bitPos = 8; 40 _curByte = 0; 41 } 42 Flush()43 void Flush() 44 { 45 if (_bitPos < 8) 46 WriteBits(0, _bitPos); 47 } 48 WriteBits(UInt32 value,unsigned numBits)49 void WriteBits(UInt32 value, unsigned numBits) 50 { 51 while (numBits > 0) 52 { 53 unsigned numNewBits = MyMin(numBits, _bitPos); 54 numBits -= numNewBits; 55 56 _curByte = (Byte)(_curByte << numNewBits); 57 UInt32 newBits = value >> numBits; 58 _curByte |= Byte(newBits); 59 value -= (newBits << numBits); 60 61 _bitPos -= numNewBits; 62 63 if (_bitPos == 0) 64 { 65 _buf[_pos++] = _curByte; 66 _bitPos = 8; 67 } 68 } 69 } 70 GetBytePos()71 UInt32 GetBytePos() const { return _pos ; } GetPos()72 UInt32 GetPos() const { return _pos * 8 + (8 - _bitPos); } GetCurByte()73 Byte GetCurByte() const { return _curByte; } SetPos(UInt32 bitPos)74 void SetPos(UInt32 bitPos) 75 { 76 _pos = bitPos >> 3; 77 _bitPos = 8 - ((unsigned)bitPos & 7); 78 } SetCurState(unsigned bitPos,Byte curByte)79 void SetCurState(unsigned bitPos, Byte curByte) 80 { 81 _bitPos = 8 - bitPos; 82 _curByte = curByte; 83 } 84 }; 85 86 class CEncoder; 87 88 const unsigned kNumPassesMax = 10; 89 90 class CThreadInfo 91 { 92 public: 93 Byte *m_Block; 94 private: 95 Byte *m_MtfArray; 96 Byte *m_TempArray; 97 UInt32 *m_BlockSorterIndex; 98 99 CMsbfEncoderTemp *m_OutStreamCurrent; 100 101 Byte Lens[kNumTablesMax][kMaxAlphaSize]; 102 UInt32 Freqs[kNumTablesMax][kMaxAlphaSize]; 103 UInt32 Codes[kNumTablesMax][kMaxAlphaSize]; 104 105 Byte m_Selectors[kNumSelectorsMax]; 106 107 UInt32 m_CRCs[1 << kNumPassesMax]; 108 UInt32 m_NumCrcs; 109 110 void WriteBits2(UInt32 value, unsigned numBits); 111 void WriteByte2(Byte b); 112 void WriteBit2(Byte v); 113 void WriteCrc2(UInt32 v); 114 115 void EncodeBlock(const Byte *block, UInt32 blockSize); 116 UInt32 EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize); 117 void EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses); 118 public: 119 bool m_OptimizeNumTables; 120 CEncoder *Encoder; 121 #ifndef Z7_ST 122 NWindows::CThread Thread; 123 124 NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent; 125 NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent; 126 127 // it's not member of this thread. We just need one event per thread 128 NWindows::NSynchronization::CAutoResetEvent CanWriteEvent; 129 130 private: 131 UInt32 m_BlockIndex; 132 UInt64 m_UnpackSize; 133 public: 134 Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. 135 HRESULT Create(); 136 void FinishStream(bool needLeave); 137 THREAD_FUNC_RET_TYPE ThreadFunc(); 138 #endif 139 CThreadInfo()140 CThreadInfo(): m_Block(NULL), m_BlockSorterIndex(NULL) {} ~CThreadInfo()141 ~CThreadInfo() { Free(); } 142 bool Alloc(); 143 void Free(); 144 145 HRESULT EncodeBlock3(UInt32 blockSize); 146 }; 147 148 struct CEncProps 149 { 150 UInt32 BlockSizeMult; 151 UInt32 NumPasses; 152 UInt64 Affinity; 153 CEncPropsCEncProps154 CEncProps() 155 { 156 BlockSizeMult = (UInt32)(Int32)-1; 157 NumPasses = (UInt32)(Int32)-1; 158 Affinity = 0; 159 } 160 void Normalize(int level); DoOptimizeNumTablesCEncProps161 bool DoOptimizeNumTables() const { return NumPasses > 1; } 162 }; 163 164 class CEncoder Z7_final: 165 public ICompressCoder, 166 public ICompressSetCoderProperties, 167 #ifndef Z7_ST 168 public ICompressSetCoderMt, 169 #endif 170 public CMyUnknownImp 171 { 172 Z7_COM_QI_BEGIN2(ICompressCoder) 173 Z7_COM_QI_ENTRY(ICompressSetCoderProperties) 174 #ifndef Z7_ST 175 Z7_COM_QI_ENTRY(ICompressSetCoderMt) 176 #endif 177 Z7_COM_QI_END 178 Z7_COM_ADDREF_RELEASE 179 180 Z7_IFACE_COM7_IMP(ICompressCoder) 181 Z7_IFACE_COM7_IMP(ICompressSetCoderProperties) 182 #ifndef Z7_ST 183 Z7_IFACE_COM7_IMP(ICompressSetCoderMt) 184 #endif 185 186 #ifndef Z7_ST 187 UInt32 m_NumThreadsPrev; 188 #endif 189 public: 190 CInBuffer m_InStream; 191 #ifndef Z7_ST 192 Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. 193 #endif 194 CBitmEncoder<COutBuffer> m_OutStream; 195 CEncProps _props; 196 CBZip2CombinedCrc CombinedCrc; 197 198 #ifndef Z7_ST 199 CThreadInfo *ThreadsInfo; 200 NWindows::NSynchronization::CManualResetEvent CanProcessEvent; 201 NWindows::NSynchronization::CCriticalSection CS; 202 UInt32 NumThreads; 203 bool MtMode; 204 UInt32 NextBlockIndex; 205 206 bool CloseThreads; 207 bool StreamWasFinished; 208 NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent; 209 210 HRESULT Result; 211 ICompressProgressInfo *Progress; 212 #else 213 CThreadInfo ThreadsInfo; 214 #endif 215 216 UInt64 NumBlocks; 217 GetInProcessedSize()218 UInt64 GetInProcessedSize() const { return m_InStream.GetProcessedSize(); } 219 220 UInt32 ReadRleBlock(Byte *buf); 221 void WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte); 222 223 void WriteBits(UInt32 value, unsigned numBits); 224 void WriteByte(Byte b); 225 // void WriteBit(Byte v); 226 void WriteCrc(UInt32 v); 227 228 #ifndef Z7_ST 229 HRESULT Create(); 230 void Free(); 231 #endif 232 233 public: 234 CEncoder(); 235 #ifndef Z7_ST 236 ~CEncoder(); 237 #endif 238 Flush()239 HRESULT Flush() { return m_OutStream.Flush(); } 240 241 HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, 242 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); 243 }; 244 245 }} 246 247 #endif 248