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