1 // CoderMixer2.h 2 3 #ifndef __CODER_MIXER2_H 4 #define __CODER_MIXER2_H 5 6 #include "../../../Common/MyCom.h" 7 #include "../../../Common/MyVector.h" 8 9 #include "../../ICoder.h" 10 11 #include "../../Common/CreateCoder.h" 12 13 #ifdef _7ZIP_ST 14 #define USE_MIXER_ST 15 #else 16 #define USE_MIXER_MT 17 #ifndef _SFX 18 #define USE_MIXER_ST 19 #endif 20 #endif 21 22 #ifdef USE_MIXER_MT 23 #include "../../Common/StreamBinder.h" 24 #include "../../Common/VirtThread.h" 25 #endif 26 27 28 29 #ifdef USE_MIXER_ST 30 31 class CSequentialInStreamCalcSize: 32 public ISequentialInStream, 33 public CMyUnknownImp 34 { 35 public: 36 MY_UNKNOWN_IMP1(ISequentialInStream) 37 38 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); 39 private: 40 CMyComPtr<ISequentialInStream> _stream; 41 UInt64 _size; 42 bool _wasFinished; 43 public: SetStream(ISequentialInStream * stream)44 void SetStream(ISequentialInStream *stream) { _stream = stream; } Init()45 void Init() 46 { 47 _size = 0; 48 _wasFinished = false; 49 } ReleaseStream()50 void ReleaseStream() { _stream.Release(); } GetSize()51 UInt64 GetSize() const { return _size; } WasFinished()52 bool WasFinished() const { return _wasFinished; } 53 }; 54 55 56 class COutStreamCalcSize: 57 public ISequentialOutStream, 58 public IOutStreamFinish, 59 public CMyUnknownImp 60 { 61 CMyComPtr<ISequentialOutStream> _stream; 62 UInt64 _size; 63 public: 64 MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish) 65 66 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); 67 STDMETHOD(OutStreamFinish)(); 68 SetStream(ISequentialOutStream * stream)69 void SetStream(ISequentialOutStream *stream) { _stream = stream; } ReleaseStream()70 void ReleaseStream() { _stream.Release(); } Init()71 void Init() { _size = 0; } GetSize()72 UInt64 GetSize() const { return _size; } 73 }; 74 75 #endif 76 77 78 79 namespace NCoderMixer2 { 80 81 struct CBond 82 { 83 UInt32 PackIndex; 84 UInt32 UnpackIndex; 85 Get_InIndexCBond86 UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; } Get_OutIndexCBond87 UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; } 88 }; 89 90 91 struct CCoderStreamsInfo 92 { 93 UInt32 NumStreams; 94 }; 95 96 97 struct CBindInfo 98 { 99 CRecordVector<CCoderStreamsInfo> Coders; 100 CRecordVector<CBond> Bonds; 101 CRecordVector<UInt32> PackStreams; 102 unsigned UnpackCoder; 103 GetNum_Bonds_and_PackStreamsCBindInfo104 unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); } 105 FindBond_for_PackStreamCBindInfo106 int FindBond_for_PackStream(UInt32 packStream) const 107 { 108 FOR_VECTOR (i, Bonds) 109 if (Bonds[i].PackIndex == packStream) 110 return i; 111 return -1; 112 } 113 FindBond_for_UnpackStreamCBindInfo114 int FindBond_for_UnpackStream(UInt32 unpackStream) const 115 { 116 FOR_VECTOR (i, Bonds) 117 if (Bonds[i].UnpackIndex == unpackStream) 118 return i; 119 return -1; 120 } 121 SetUnpackCoderCBindInfo122 bool SetUnpackCoder() 123 { 124 bool isOk = false; 125 FOR_VECTOR(i, Coders) 126 { 127 if (FindBond_for_UnpackStream(i) < 0) 128 { 129 if (isOk) 130 return false; 131 UnpackCoder = i; 132 isOk = true; 133 } 134 } 135 return isOk; 136 } 137 IsStream_in_PackStreamsCBindInfo138 bool IsStream_in_PackStreams(UInt32 streamIndex) const 139 { 140 return FindStream_in_PackStreams(streamIndex) >= 0; 141 } 142 FindStream_in_PackStreamsCBindInfo143 int FindStream_in_PackStreams(UInt32 streamIndex) const 144 { 145 FOR_VECTOR(i, PackStreams) 146 if (PackStreams[i] == streamIndex) 147 return i; 148 return -1; 149 } 150 151 152 // that function is used before Maps is calculated 153 GetStream_for_CoderCBindInfo154 UInt32 GetStream_for_Coder(UInt32 coderIndex) const 155 { 156 UInt32 streamIndex = 0; 157 for (UInt32 i = 0; i < coderIndex; i++) 158 streamIndex += Coders[i].NumStreams; 159 return streamIndex; 160 } 161 162 // ---------- Maps Section ---------- 163 164 CRecordVector<UInt32> Coder_to_Stream; 165 CRecordVector<UInt32> Stream_to_Coder; 166 167 void ClearMaps(); 168 bool CalcMapsAndCheck(); 169 170 // ---------- End of Maps Section ---------- 171 ClearCBindInfo172 void Clear() 173 { 174 Coders.Clear(); 175 Bonds.Clear(); 176 PackStreams.Clear(); 177 178 ClearMaps(); 179 } 180 GetCoder_for_StreamCBindInfo181 void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const 182 { 183 coderIndex = Stream_to_Coder[streamIndex]; 184 coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex]; 185 } 186 }; 187 188 189 190 class CCoder 191 { 192 CLASS_NO_COPY(CCoder); 193 public: 194 CMyComPtr<ICompressCoder> Coder; 195 CMyComPtr<ICompressCoder2> Coder2; 196 UInt32 NumStreams; 197 198 UInt64 UnpackSize; 199 const UInt64 *UnpackSizePointer; 200 201 CRecordVector<UInt64> PackSizes; 202 CRecordVector<const UInt64 *> PackSizePointers; 203 204 bool Finish; 205 CCoder()206 CCoder(): Finish(false) {} 207 208 void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish); 209 210 HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const; 211 GetUnknown()212 IUnknown *GetUnknown() const 213 { 214 return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; 215 } 216 QueryInterface(REFGUID iid,void ** pp)217 HRESULT QueryInterface(REFGUID iid, void** pp) const 218 { 219 return GetUnknown()->QueryInterface(iid, pp); 220 } 221 }; 222 223 224 225 class CMixer 226 { 227 bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex); 228 229 protected: 230 CBindInfo _bi; 231 FindBond_for_Stream(bool forInputStream,UInt32 streamIndex)232 int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const 233 { 234 if (EncodeMode == forInputStream) 235 return _bi.FindBond_for_UnpackStream(streamIndex); 236 else 237 return _bi.FindBond_for_PackStream(streamIndex); 238 } 239 240 CBoolVector IsFilter_Vector; 241 CBoolVector IsExternal_Vector; 242 bool EncodeMode; 243 public: 244 unsigned MainCoderIndex; 245 246 // bool InternalPackSizeError; 247 CMixer(bool encodeMode)248 CMixer(bool encodeMode): 249 EncodeMode(encodeMode), 250 MainCoderIndex(0) 251 // , InternalPackSizeError(false) 252 {} 253 254 /* 255 Sequence of calling: 256 257 SetBindInfo(); 258 for each coder 259 AddCoder(); 260 SelectMainCoder(); 261 262 for each file 263 { 264 ReInit() 265 for each coder 266 SetCoderInfo(); 267 Code(); 268 } 269 */ 270 SetBindInfo(const CBindInfo & bindInfo)271 virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) 272 { 273 _bi = bindInfo; 274 IsFilter_Vector.Clear(); 275 MainCoderIndex = 0; 276 return S_OK; 277 } 278 279 virtual void AddCoder(const CCreatedCoder &cod) = 0; 280 virtual CCoder &GetCoder(unsigned index) = 0; 281 virtual void SelectMainCoder(bool useFirst) = 0; 282 virtual void ReInit() = 0; 283 virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0; 284 virtual HRESULT Code( 285 ISequentialInStream * const *inStreams, 286 ISequentialOutStream * const *outStreams, 287 ICompressProgressInfo *progress, 288 bool &dataAfterEnd_Error) = 0; 289 virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0; 290 291 bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex); 292 bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex); 293 bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex); 294 }; 295 296 297 298 299 #ifdef USE_MIXER_ST 300 301 struct CCoderST: public CCoder 302 { 303 bool CanRead; 304 bool CanWrite; 305 CCoderSTCCoderST306 CCoderST(): CanRead(false), CanWrite(false) {} 307 }; 308 309 310 struct CStBinderStream 311 { 312 CSequentialInStreamCalcSize *InStreamSpec; 313 COutStreamCalcSize *OutStreamSpec; 314 CMyComPtr<IUnknown> StreamRef; 315 CStBinderStreamCStBinderStream316 CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {} 317 }; 318 319 320 class CMixerST: 321 public IUnknown, 322 public CMixer, 323 public CMyUnknownImp 324 { 325 HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ 326 UInt32 outStreamIndex, ISequentialInStream **inStreamRes); 327 HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ 328 UInt32 inStreamIndex, ISequentialInStream **inStreamRes); 329 HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ 330 UInt32 outStreamIndex, ISequentialOutStream **outStreamRes); 331 332 HRESULT FinishStream(UInt32 streamIndex); 333 HRESULT FinishCoder(UInt32 coderIndex); 334 335 public: 336 CObjectVector<CCoderST> _coders; 337 338 CObjectVector<CStBinderStream> _binderStreams; 339 340 MY_UNKNOWN_IMP 341 342 CMixerST(bool encodeMode); 343 ~CMixerST(); 344 345 virtual void AddCoder(const CCreatedCoder &cod); 346 virtual CCoder &GetCoder(unsigned index); 347 virtual void SelectMainCoder(bool useFirst); 348 virtual void ReInit(); SetCoderInfo(unsigned coderIndex,const UInt64 * unpackSize,const UInt64 * const * packSizes,bool finish)349 virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) 350 { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } 351 virtual HRESULT Code( 352 ISequentialInStream * const *inStreams, 353 ISequentialOutStream * const *outStreams, 354 ICompressProgressInfo *progress, 355 bool &dataAfterEnd_Error); 356 virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; 357 358 HRESULT GetMainUnpackStream( 359 ISequentialInStream * const *inStreams, 360 ISequentialInStream **inStreamRes); 361 }; 362 363 #endif 364 365 366 367 368 #ifdef USE_MIXER_MT 369 370 class CCoderMT: public CCoder, public CVirtThread 371 { 372 CLASS_NO_COPY(CCoderMT) 373 CRecordVector<ISequentialInStream*> InStreamPointers; 374 CRecordVector<ISequentialOutStream*> OutStreamPointers; 375 376 private: 377 void Execute(); 378 public: 379 bool EncodeMode; 380 HRESULT Result; 381 CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; 382 CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; 383 Release()384 void Release() 385 { 386 InStreamPointers.Clear(); 387 OutStreamPointers.Clear(); 388 unsigned i; 389 for (i = 0; i < InStreams.Size(); i++) 390 InStreams[i].Release(); 391 for (i = 0; i < OutStreams.Size(); i++) 392 OutStreams[i].Release(); 393 } 394 395 class CReleaser 396 { 397 CLASS_NO_COPY(CReleaser) 398 CCoderMT &_c; 399 public: CReleaser(CCoderMT & c)400 CReleaser(CCoderMT &c): _c(c) {} ~CReleaser()401 ~CReleaser() { _c.Release(); } 402 }; 403 CCoderMT()404 CCoderMT(): EncodeMode(false) {} ~CCoderMT()405 ~CCoderMT() { CVirtThread::WaitThreadFinish(); } 406 407 void Code(ICompressProgressInfo *progress); 408 }; 409 410 411 class CMixerMT: 412 public IUnknown, 413 public CMixer, 414 public CMyUnknownImp 415 { 416 CObjectVector<CStreamBinder> _streamBinders; 417 418 HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); 419 HRESULT ReturnIfError(HRESULT code); 420 421 public: 422 CObjectVector<CCoderMT> _coders; 423 424 MY_UNKNOWN_IMP 425 426 virtual HRESULT SetBindInfo(const CBindInfo &bindInfo); 427 virtual void AddCoder(const CCreatedCoder &cod); 428 virtual CCoder &GetCoder(unsigned index); 429 virtual void SelectMainCoder(bool useFirst); 430 virtual void ReInit(); SetCoderInfo(unsigned coderIndex,const UInt64 * unpackSize,const UInt64 * const * packSizes,bool finish)431 virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) 432 { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); } 433 virtual HRESULT Code( 434 ISequentialInStream * const *inStreams, 435 ISequentialOutStream * const *outStreams, 436 ICompressProgressInfo *progress, 437 bool &dataAfterEnd_Error); 438 virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; 439 CMixerMT(bool encodeMode)440 CMixerMT(bool encodeMode): CMixer(encodeMode) {} 441 }; 442 443 #endif 444 445 } 446 447 #endif 448