• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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