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