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
31class CSequentialInStreamCalcSize:
32  public ISequentialInStream,
33  public CMyUnknownImp
34{
35public:
36  MY_UNKNOWN_IMP1(ISequentialInStream)
37
38  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
39private:
40  CMyComPtr<ISequentialInStream> _stream;
41  UInt64 _size;
42  bool _wasFinished;
43public:
44  void SetStream(ISequentialInStream *stream) { _stream = stream;  }
45  void Init()
46  {
47    _size = 0;
48    _wasFinished = false;
49  }
50  void ReleaseStream() { _stream.Release(); }
51  UInt64 GetSize() const { return _size; }
52  bool WasFinished() const { return _wasFinished; }
53};
54
55
56class COutStreamCalcSize:
57  public ISequentialOutStream,
58  public IOutStreamFinish,
59  public CMyUnknownImp
60{
61  CMyComPtr<ISequentialOutStream> _stream;
62  UInt64 _size;
63public:
64  MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish)
65
66  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
67  STDMETHOD(OutStreamFinish)();
68
69  void SetStream(ISequentialOutStream *stream) { _stream = stream; }
70  void ReleaseStream() { _stream.Release(); }
71  void Init() { _size = 0; }
72  UInt64 GetSize() const { return _size; }
73};
74
75#endif
76
77
78
79namespace NCoderMixer2 {
80
81struct CBond
82{
83  UInt32 PackIndex;
84  UInt32 UnpackIndex;
85
86  UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; }
87  UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; }
88};
89
90
91struct CCoderStreamsInfo
92{
93  UInt32 NumStreams;
94};
95
96
97struct CBindInfo
98{
99  CRecordVector<CCoderStreamsInfo> Coders;
100  CRecordVector<CBond> Bonds;
101  CRecordVector<UInt32> PackStreams;
102  unsigned UnpackCoder;
103
104  unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); }
105
106  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
114  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
122  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
138  bool IsStream_in_PackStreams(UInt32 streamIndex) const
139  {
140    return FindStream_in_PackStreams(streamIndex) >= 0;
141  }
142
143  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
154  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
172  void Clear()
173  {
174    Coders.Clear();
175    Bonds.Clear();
176    PackStreams.Clear();
177
178    ClearMaps();
179  }
180
181  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
190class CCoder
191{
192  CLASS_NO_COPY(CCoder);
193public:
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  CCoder() {}
205
206  void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes);
207
208  IUnknown *GetUnknown() const
209  {
210    return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;
211  }
212
213  HRESULT QueryInterface(REFGUID iid, void** pp) const
214  {
215    return GetUnknown()->QueryInterface(iid, pp);
216  }
217};
218
219
220
221class CMixer
222{
223  bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex);
224
225protected:
226  CBindInfo _bi;
227
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;
239public:
240  unsigned MainCoderIndex;
241
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
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
293struct CCoderST: public CCoder
294{
295  bool CanRead;
296  bool CanWrite;
297
298  CCoderST(): CanRead(false), CanWrite(false) {}
299};
300
301
302struct CStBinderStream
303{
304  CSequentialInStreamCalcSize *InStreamSpec;
305  COutStreamCalcSize *OutStreamSpec;
306  CMyComPtr<IUnknown> StreamRef;
307
308  CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}
309};
310
311
312class 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
327public:
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();
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
361class CCoderMT: public CCoder, public CVirtThread
362{
363  CLASS_NO_COPY(CCoderMT)
364  CRecordVector<ISequentialInStream*> InStreamPointers;
365  CRecordVector<ISequentialOutStream*> OutStreamPointers;
366
367private:
368  void Execute();
369public:
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    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() { CVirtThread::WaitThreadFinish(); }
397
398  void Code(ICompressProgressInfo *progress);
399};
400
401
402class 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
412public:
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();
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
430  CMixerMT(bool encodeMode): CMixer(encodeMode) {}
431};
432
433#endif
434
435}
436
437#endif
438