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 CCoder()204 CCoder() {} 205 206 void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes); 207 GetUnknown()208 IUnknown *GetUnknown() const 209 { 210 return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; 211 } 212 QueryInterface(REFGUID iid,void ** pp)213 HRESULT QueryInterface(REFGUID iid, void** pp) const 214 { 215 return GetUnknown()->QueryInterface(iid, pp); 216 } 217 }; 218 219 220 221 class CMixer 222 { 223 bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex); 224 225 protected: 226 CBindInfo _bi; 227 FindBond_for_Stream(bool forInputStream,UInt32 streamIndex)228 int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const 229 { 230 if (EncodeMode == forInputStream) 231 return _bi.FindBond_for_UnpackStream(streamIndex); 232 else 233 return _bi.FindBond_for_PackStream(streamIndex); 234 } 235 236 CBoolVector IsFilter_Vector; 237 CBoolVector IsExternal_Vector; 238 bool EncodeMode; 239 public: 240 unsigned MainCoderIndex; 241 CMixer(bool encodeMode)242 CMixer(bool encodeMode): 243 EncodeMode(encodeMode), 244 MainCoderIndex(0) 245 {} 246 247 /* 248 Sequence of calling: 249 250 SetBindInfo(); 251 for each coder 252 AddCoder(); 253 SelectMainCoder(); 254 255 for each file 256 { 257 ReInit() 258 for each coder 259 SetCoderInfo(); 260 Code(); 261 } 262 */ 263 SetBindInfo(const CBindInfo & bindInfo)264 virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) 265 { 266 _bi = bindInfo; 267 IsFilter_Vector.Clear(); 268 MainCoderIndex = 0; 269 return S_OK; 270 } 271 272 virtual void AddCoder(const CCreatedCoder &cod) = 0; 273 virtual CCoder &GetCoder(unsigned index) = 0; 274 virtual void SelectMainCoder(bool useFirst) = 0; 275 virtual void ReInit() = 0; 276 virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0; 277 virtual HRESULT Code( 278 ISequentialInStream * const *inStreams, 279 ISequentialOutStream * const *outStreams, 280 ICompressProgressInfo *progress) = 0; 281 virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0; 282 283 bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex); 284 bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex); 285 bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex); 286 }; 287 288 289 290 291 #ifdef USE_MIXER_ST 292 293 struct CCoderST: public CCoder 294 { 295 bool CanRead; 296 bool CanWrite; 297 CCoderSTCCoderST298 CCoderST(): CanRead(false), CanWrite(false) {} 299 }; 300 301 302 struct CStBinderStream 303 { 304 CSequentialInStreamCalcSize *InStreamSpec; 305 COutStreamCalcSize *OutStreamSpec; 306 CMyComPtr<IUnknown> StreamRef; 307 CStBinderStreamCStBinderStream308 CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {} 309 }; 310 311 312 class CMixerST: 313 public IUnknown, 314 public CMixer, 315 public CMyUnknownImp 316 { 317 HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ 318 UInt32 outStreamIndex, ISequentialInStream **inStreamRes); 319 HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ 320 UInt32 inStreamIndex, ISequentialInStream **inStreamRes); 321 HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ 322 UInt32 outStreamIndex, ISequentialOutStream **outStreamRes); 323 324 HRESULT FinishStream(UInt32 streamIndex); 325 HRESULT FinishCoder(UInt32 coderIndex); 326 327 public: 328 CObjectVector<CCoderST> _coders; 329 330 CObjectVector<CStBinderStream> _binderStreams; 331 332 MY_UNKNOWN_IMP 333 334 CMixerST(bool encodeMode); 335 ~CMixerST(); 336 337 virtual void AddCoder(const CCreatedCoder &cod); 338 virtual CCoder &GetCoder(unsigned index); 339 virtual void SelectMainCoder(bool useFirst); 340 virtual void ReInit(); SetCoderInfo(unsigned coderIndex,const UInt64 * unpackSize,const UInt64 * const * packSizes)341 virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) 342 { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); } 343 virtual HRESULT Code( 344 ISequentialInStream * const *inStreams, 345 ISequentialOutStream * const *outStreams, 346 ICompressProgressInfo *progress); 347 virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; 348 349 HRESULT GetMainUnpackStream( 350 ISequentialInStream * const *inStreams, 351 ISequentialInStream **inStreamRes); 352 }; 353 354 #endif 355 356 357 358 359 #ifdef USE_MIXER_MT 360 361 class CCoderMT: public CCoder, public CVirtThread 362 { 363 CLASS_NO_COPY(CCoderMT) 364 CRecordVector<ISequentialInStream*> InStreamPointers; 365 CRecordVector<ISequentialOutStream*> OutStreamPointers; 366 367 private: 368 void Execute(); 369 public: 370 bool EncodeMode; 371 HRESULT Result; 372 CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; 373 CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; 374 Release()375 void Release() 376 { 377 InStreamPointers.Clear(); 378 OutStreamPointers.Clear(); 379 unsigned i; 380 for (i = 0; i < InStreams.Size(); i++) 381 InStreams[i].Release(); 382 for (i = 0; i < OutStreams.Size(); i++) 383 OutStreams[i].Release(); 384 } 385 386 class CReleaser 387 { 388 CLASS_NO_COPY(CReleaser) 389 CCoderMT &_c; 390 public: CReleaser(CCoderMT & c)391 CReleaser(CCoderMT &c): _c(c) {} ~CReleaser()392 ~CReleaser() { _c.Release(); } 393 }; 394 CCoderMT()395 CCoderMT(): EncodeMode(false) {} ~CCoderMT()396 ~CCoderMT() { CVirtThread::WaitThreadFinish(); } 397 398 void Code(ICompressProgressInfo *progress); 399 }; 400 401 402 class CMixerMT: 403 public IUnknown, 404 public CMixer, 405 public CMyUnknownImp 406 { 407 CObjectVector<CStreamBinder> _streamBinders; 408 409 HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); 410 HRESULT ReturnIfError(HRESULT code); 411 412 public: 413 CObjectVector<CCoderMT> _coders; 414 415 MY_UNKNOWN_IMP 416 417 virtual HRESULT SetBindInfo(const CBindInfo &bindInfo); 418 virtual void AddCoder(const CCreatedCoder &cod); 419 virtual CCoder &GetCoder(unsigned index); 420 virtual void SelectMainCoder(bool useFirst); 421 virtual void ReInit(); SetCoderInfo(unsigned coderIndex,const UInt64 * unpackSize,const UInt64 * const * packSizes)422 virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) 423 { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); } 424 virtual HRESULT Code( 425 ISequentialInStream * const *inStreams, 426 ISequentialOutStream * const *outStreams, 427 ICompressProgressInfo *progress); 428 virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; 429 CMixerMT(bool encodeMode)430 CMixerMT(bool encodeMode): CMixer(encodeMode) {} 431 }; 432 433 #endif 434 435 } 436 437 #endif 438