1 // BZip2Encoder.h 2 3 #ifndef __COMPRESS_BZIP2_ENCODER_H 4 #define __COMPRESS_BZIP2_ENCODER_H 5 6 #include "../../Common/Defs.h" 7 #include "../../Common/MyCom.h" 8 9 #ifdef COMPRESS_BZIP2_MT 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 m_Pos; 29 int m_BitPos; 30 Byte m_CurByte; 31 Byte *Buffer; 32 public: SetStream(Byte * buffer)33 void SetStream(Byte *buffer) { Buffer = buffer; } GetStream()34 Byte *GetStream() const { return Buffer; } 35 Init()36 void Init() 37 { 38 m_Pos = 0; 39 m_BitPos = 8; 40 m_CurByte = 0; 41 } 42 Flush()43 void Flush() 44 { 45 if (m_BitPos < 8) 46 WriteBits(0, m_BitPos); 47 } 48 WriteBits(UInt32 value,int numBits)49 void WriteBits(UInt32 value, int numBits) 50 { 51 while (numBits > 0) 52 { 53 int numNewBits = MyMin(numBits, m_BitPos); 54 numBits -= numNewBits; 55 56 m_CurByte <<= numNewBits; 57 UInt32 newBits = value >> numBits; 58 m_CurByte |= Byte(newBits); 59 value -= (newBits << numBits); 60 61 m_BitPos -= numNewBits; 62 63 if (m_BitPos == 0) 64 { 65 Buffer[m_Pos++] = m_CurByte; 66 m_BitPos = 8; 67 } 68 } 69 } 70 GetBytePos()71 UInt32 GetBytePos() const { return m_Pos ; } GetPos()72 UInt32 GetPos() const { return m_Pos * 8 + (8 - m_BitPos); } GetCurByte()73 Byte GetCurByte() const { return m_CurByte; } SetPos(UInt32 bitPos)74 void SetPos(UInt32 bitPos) 75 { 76 m_Pos = bitPos / 8; 77 m_BitPos = 8 - ((int)bitPos & 7); 78 } SetCurState(int bitPos,Byte curByte)79 void SetCurState(int bitPos, Byte curByte) 80 { 81 m_BitPos = 8 - bitPos; 82 m_CurByte = curByte; 83 } 84 }; 85 86 class CEncoder; 87 88 const int 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 UInt32 m_BlockIndex; 111 112 void WriteBits2(UInt32 value, UInt32 numBits); 113 void WriteByte2(Byte b); 114 void WriteBit2(bool v); 115 void WriteCrc2(UInt32 v); 116 117 void EncodeBlock(const Byte *block, UInt32 blockSize); 118 UInt32 EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize); 119 void EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses); 120 public: 121 bool m_OptimizeNumTables; 122 CEncoder *Encoder; 123 #ifdef COMPRESS_BZIP2_MT 124 NWindows::CThread Thread; 125 126 NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent; 127 NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent; 128 129 // it's not member of this thread. We just need one event per thread 130 NWindows::NSynchronization::CAutoResetEvent CanWriteEvent; 131 132 UInt64 m_PackSize; 133 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 DWORD ThreadFunc(); 138 #endif 139 CThreadInfo()140 CThreadInfo(): m_BlockSorterIndex(0), m_Block(0) {} ~CThreadInfo()141 ~CThreadInfo() { Free(); } 142 bool Alloc(); 143 void Free(); 144 145 HRESULT EncodeBlock3(UInt32 blockSize); 146 }; 147 148 class CEncoder : 149 public ICompressCoder, 150 public ICompressSetCoderProperties, 151 #ifdef COMPRESS_BZIP2_MT 152 public ICompressSetCoderMt, 153 #endif 154 public CMyUnknownImp 155 { 156 UInt32 m_BlockSizeMult; 157 bool m_OptimizeNumTables; 158 159 UInt32 m_NumPassesPrev; 160 161 UInt32 m_NumThreadsPrev; 162 public: 163 CInBuffer m_InStream; 164 Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. 165 CBitmEncoder<COutBuffer> m_OutStream; 166 UInt32 NumPasses; 167 CBZip2CombinedCrc CombinedCrc; 168 169 #ifdef COMPRESS_BZIP2_MT 170 CThreadInfo *ThreadsInfo; 171 NWindows::NSynchronization::CManualResetEvent CanProcessEvent; 172 NWindows::NSynchronization::CCriticalSection CS; 173 UInt32 NumThreads; 174 bool MtMode; 175 UInt32 NextBlockIndex; 176 177 bool CloseThreads; 178 bool StreamWasFinished; 179 NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent; 180 181 HRESULT Result; 182 ICompressProgressInfo *Progress; 183 #else 184 CThreadInfo ThreadsInfo; 185 #endif 186 187 UInt32 ReadRleBlock(Byte *buffer); 188 void WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte); 189 190 void WriteBits(UInt32 value, UInt32 numBits); 191 void WriteByte(Byte b); 192 void WriteBit(bool v); 193 void WriteCrc(UInt32 v); 194 195 #ifdef COMPRESS_BZIP2_MT 196 HRESULT Create(); 197 void Free(); 198 #endif 199 200 public: 201 CEncoder(); 202 #ifdef COMPRESS_BZIP2_MT 203 ~CEncoder(); 204 #endif 205 Flush()206 HRESULT Flush() { return m_OutStream.Flush(); } 207 ReleaseStreams()208 void ReleaseStreams() 209 { 210 m_InStream.ReleaseStream(); 211 m_OutStream.ReleaseStream(); 212 } 213 214 class CFlusher 215 { 216 CEncoder *_coder; 217 public: CFlusher(CEncoder * coder)218 CFlusher(CEncoder *coder): _coder(coder) {} ~CFlusher()219 ~CFlusher() 220 { 221 _coder->ReleaseStreams(); 222 } 223 }; 224 225 #ifdef COMPRESS_BZIP2_MT 226 MY_UNKNOWN_IMP2(ICompressSetCoderMt, ICompressSetCoderProperties) 227 #else 228 MY_UNKNOWN_IMP1(ICompressSetCoderProperties) 229 #endif 230 231 HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, 232 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); 233 234 STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, 235 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); 236 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps); 237 238 #ifdef COMPRESS_BZIP2_MT 239 STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); 240 #endif 241 }; 242 243 }} 244 245 #endif 246