xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Common/CoderMixer2.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // CoderMixer2.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "CoderMixer2.h"
6 
7 #ifdef USE_MIXER_ST
8 
Z7_COM7F_IMF(CSequentialInStreamCalcSize::Read (void * data,UInt32 size,UInt32 * processedSize))9 Z7_COM7F_IMF(CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize))
10 {
11   UInt32 realProcessed = 0;
12   HRESULT result = S_OK;
13   if (_stream)
14     result = _stream->Read(data, size, &realProcessed);
15   _size += realProcessed;
16   if (size != 0 && realProcessed == 0)
17     _wasFinished = true;
18   if (processedSize)
19     *processedSize = realProcessed;
20   return result;
21 }
22 
23 
Z7_COM7F_IMF(COutStreamCalcSize::Write (const void * data,UInt32 size,UInt32 * processedSize))24 Z7_COM7F_IMF(COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize))
25 {
26   HRESULT result = S_OK;
27   if (_stream)
28     result = _stream->Write(data, size, &size);
29   _size += size;
30   if (processedSize)
31     *processedSize = size;
32   return result;
33 }
34 
Z7_COM7F_IMF(COutStreamCalcSize::OutStreamFinish ())35 Z7_COM7F_IMF(COutStreamCalcSize::OutStreamFinish())
36 {
37   HRESULT result = S_OK;
38   if (_stream)
39   {
40     CMyComPtr<IOutStreamFinish> outStreamFinish;
41     _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish);
42     if (outStreamFinish)
43       result = outStreamFinish->OutStreamFinish();
44   }
45   return result;
46 }
47 
48 #endif
49 
50 
51 
52 
53 namespace NCoderMixer2 {
54 
BoolVector_Fill_False(CBoolVector & v,unsigned size)55 static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
56 {
57   v.ClearAndSetSize(size);
58   bool *p = &v[0];
59   for (unsigned i = 0; i < size; i++)
60     p[i] = false;
61 }
62 
63 
CheckDataAfterEnd(bool & dataAfterEnd_Error) const64 HRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const
65 {
66   if (Coder)
67   {
68     if (PackSizePointers.IsEmpty() || !PackSizePointers[0])
69       return S_OK;
70     CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
71     Coder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);
72     // if (!getInStreamProcessedSize) return E_FAIL;
73     if (getInStreamProcessedSize)
74     {
75       UInt64 processed;
76       RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed))
77       if (processed != (UInt64)(Int64)-1)
78       {
79         const UInt64 size = PackSizes[0];
80         if (processed < size && Finish)
81           dataAfterEnd_Error = true;
82         if (processed > size)
83         {
84           // InternalPackSizeError = true;
85           // return S_FALSE;
86         }
87       }
88     }
89   }
90   else if (Coder2)
91   {
92     CMyComPtr<ICompressGetInStreamProcessedSize2> getInStreamProcessedSize2;
93     Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2);
94     if (getInStreamProcessedSize2)
95     FOR_VECTOR (i, PackSizePointers)
96     {
97       if (!PackSizePointers[i])
98         continue;
99       UInt64 processed;
100       RINOK(getInStreamProcessedSize2->GetInStreamProcessedSize2(i, &processed))
101       if (processed != (UInt64)(Int64)-1)
102       {
103         const UInt64 size = PackSizes[i];
104         if (processed < size && Finish)
105           dataAfterEnd_Error = true;
106         else if (processed > size)
107         {
108           // InternalPackSizeError = true;
109           // return S_FALSE;
110         }
111       }
112     }
113   }
114 
115   return S_OK;
116 }
117 
118 
119 
120 class CBondsChecks
121 {
122   CBoolVector _coderUsed;
123 
124   bool Init();
125   bool CheckCoder(unsigned coderIndex);
126 public:
127   const CBindInfo *BindInfo;
128 
129   bool Check();
130 };
131 
CheckCoder(unsigned coderIndex)132 bool CBondsChecks::CheckCoder(unsigned coderIndex)
133 {
134   const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex];
135 
136   if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex])
137     return false;
138   _coderUsed[coderIndex] = true;
139 
140   const UInt32 start = BindInfo->Coder_to_Stream[coderIndex];
141 
142   for (unsigned i = 0; i < coder.NumStreams; i++)
143   {
144     UInt32 ind = start + i;
145 
146     if (BindInfo->IsStream_in_PackStreams(ind))
147       continue;
148 
149     const int bond = BindInfo->FindBond_for_PackStream(ind);
150     if (bond < 0)
151       return false;
152     if (!CheckCoder(BindInfo->Bonds[(unsigned)bond].UnpackIndex))
153       return false;
154   }
155 
156   return true;
157 }
158 
Check()159 bool CBondsChecks::Check()
160 {
161   BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size());
162 
163   if (!CheckCoder(BindInfo->UnpackCoder))
164     return false;
165 
166   FOR_VECTOR(i, _coderUsed)
167     if (!_coderUsed[i])
168       return false;
169 
170   return true;
171 }
172 
ClearMaps()173 void CBindInfo::ClearMaps()
174 {
175   Coder_to_Stream.Clear();
176   Stream_to_Coder.Clear();
177 }
178 
CalcMapsAndCheck()179 bool CBindInfo::CalcMapsAndCheck()
180 {
181   ClearMaps();
182 
183   UInt32 numStreams = 0;
184 
185   if (Coders.Size() == 0)
186     return false;
187   if (Coders.Size() - 1 != Bonds.Size())
188     return false;
189 
190   FOR_VECTOR(i, Coders)
191   {
192     Coder_to_Stream.Add(numStreams);
193 
194     const CCoderStreamsInfo &c = Coders[i];
195 
196     for (unsigned j = 0; j < c.NumStreams; j++)
197       Stream_to_Coder.Add(i);
198 
199     numStreams += c.NumStreams;
200   }
201 
202   if (numStreams != GetNum_Bonds_and_PackStreams())
203     return false;
204 
205   CBondsChecks bc;
206   bc.BindInfo = this;
207   return bc.Check();
208 }
209 
210 
SetCoderInfo(const UInt64 * unpackSize,const UInt64 * const * packSizes,bool finish)211 void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
212 {
213   Finish = finish;
214 
215   if (unpackSize)
216   {
217     UnpackSize = *unpackSize;
218     UnpackSizePointer = &UnpackSize;
219   }
220   else
221   {
222     UnpackSize = 0;
223     UnpackSizePointer = NULL;
224   }
225 
226   PackSizes.ClearAndSetSize((unsigned)NumStreams);
227   PackSizePointers.ClearAndSetSize((unsigned)NumStreams);
228 
229   for (unsigned i = 0; i < NumStreams; i++)
230   {
231     if (packSizes && packSizes[i])
232     {
233       PackSizes[i] = *(packSizes[i]);
234       PackSizePointers[i] = &PackSizes[i];
235     }
236     else
237     {
238       PackSizes[i] = 0;
239       PackSizePointers[i] = NULL;
240     }
241   }
242 }
243 
Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex)244 bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex)
245 {
246   if (coderIndex == _bi.UnpackCoder)
247     return true;
248 
249   const int bond = _bi.FindBond_for_UnpackStream(coderIndex);
250   if (bond < 0)
251     throw 20150213;
252 
253   /*
254   UInt32 coderIndex, coderStreamIndex;
255   _bi.GetCoder_for_Stream(_bi.Bonds[(unsigned)bond].PackIndex, coderIndex, coderStreamIndex);
256   */
257   const UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[(unsigned)bond].PackIndex];
258 
259   if (!IsFilter_Vector[nextCoder])
260     return false;
261 
262   return Is_UnpackSize_Correct_for_Coder(nextCoder);
263 }
264 
Is_PackSize_Correct_for_Stream(UInt32 streamIndex)265 bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex)
266 {
267   if (_bi.IsStream_in_PackStreams(streamIndex))
268     return true;
269 
270   const int bond = _bi.FindBond_for_PackStream(streamIndex);
271   if (bond < 0)
272     throw 20150213;
273 
274   const UInt32 nextCoder = _bi.Bonds[(unsigned)bond].UnpackIndex;
275 
276   if (!IsFilter_Vector[nextCoder])
277     return false;
278 
279   return Is_PackSize_Correct_for_Coder(nextCoder);
280 }
281 
Is_PackSize_Correct_for_Coder(UInt32 coderIndex)282 bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex)
283 {
284   const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
285   const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
286   for (UInt32 i = 0; i < numStreams; i++)
287     if (!Is_PackSize_Correct_for_Stream(startIndex + i))
288       return false;
289   return true;
290 }
291 
IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex)292 bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex)
293 {
294   if (IsExternal_Vector[coderIndex])
295     return true;
296   const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
297   const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
298   for (UInt32 i = 0; i < numStreams; i++)
299   {
300     const UInt32 si = startIndex + i;
301     if (_bi.IsStream_in_PackStreams(si))
302       continue;
303 
304     const int bond = _bi.FindBond_for_PackStream(si);
305     if (bond < 0)
306       throw 20150213;
307 
308     if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[(unsigned)bond].UnpackIndex))
309       return true;
310   }
311   return false;
312 }
313 
314 
315 
316 
317 #ifdef USE_MIXER_ST
318 
CMixerST(bool encodeMode)319 CMixerST::CMixerST(bool encodeMode):
320     CMixer(encodeMode)
321     {}
322 
~CMixerST()323 CMixerST::~CMixerST() {}
324 
AddCoder(const CCreatedCoder & cod)325 void CMixerST::AddCoder(const CCreatedCoder &cod)
326 {
327   IsFilter_Vector.Add(cod.IsFilter);
328   IsExternal_Vector.Add(cod.IsExternal);
329   // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
330   CCoderST &c2 = _coders.AddNew();
331   c2.NumStreams = cod.NumStreams;
332   c2.Coder = cod.Coder;
333   c2.Coder2 = cod.Coder2;
334 
335   /*
336   if (isFilter)
337   {
338     c2.CanRead = true;
339     c2.CanWrite = true;
340   }
341   else
342   */
343   {
344     IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2);
345     {
346       Z7_DECL_CMyComPtr_QI_FROM(ISequentialInStream, s, unk)
347       c2.CanRead = (s != NULL);
348     }
349     {
350       Z7_DECL_CMyComPtr_QI_FROM(ISequentialOutStream, s, unk)
351       c2.CanWrite = (s != NULL);
352     }
353   }
354 }
355 
GetCoder(unsigned index)356 CCoder &CMixerST::GetCoder(unsigned index)
357 {
358   return _coders[index];
359 }
360 
ReInit2()361 HRESULT CMixerST::ReInit2() { return S_OK; }
362 
GetInStream2(ISequentialInStream * const * inStreams,UInt32 outStreamIndex,ISequentialInStream ** inStreamRes)363 HRESULT CMixerST::GetInStream2(
364     ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
365     UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
366 {
367   UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
368 
369   if (EncodeMode)
370   {
371     _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
372     if (coderStreamIndex != 0)
373       return E_NOTIMPL;
374   }
375 
376   const CCoder &coder = _coders[coderIndex];
377 
378   CMyComPtr<ISequentialInStream> seqInStream;
379   coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
380   if (!seqInStream)
381     return E_NOTIMPL;
382 
383   const UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
384   const UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
385 
386   bool isSet = false;
387 
388   if (numInStreams == 1)
389   {
390     CMyComPtr<ICompressSetInStream> setStream;
391     coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
392     if (setStream)
393     {
394       CMyComPtr<ISequentialInStream> seqInStream2;
395       RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2))
396       RINOK(setStream->SetInStream(seqInStream2))
397       isSet = true;
398     }
399   }
400 
401   if (!isSet && numInStreams != 0)
402   {
403     CMyComPtr<ICompressSetInStream2> setStream2;
404     coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
405     if (!setStream2)
406       return E_NOTIMPL;
407 
408     for (UInt32 i = 0; i < numInStreams; i++)
409     {
410       CMyComPtr<ISequentialInStream> seqInStream2;
411       RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2))
412       RINOK(setStream2->SetInStream2(i, seqInStream2))
413     }
414   }
415 
416   *inStreamRes = seqInStream.Detach();
417   return S_OK;
418 }
419 
420 
GetInStream(ISequentialInStream * const * inStreams,UInt32 inStreamIndex,ISequentialInStream ** inStreamRes)421 HRESULT CMixerST::GetInStream(
422     ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
423     UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
424 {
425   CMyComPtr<ISequentialInStream> seqInStream;
426 
427   {
428     int index = -1;
429     if (EncodeMode)
430     {
431       if (_bi.UnpackCoder == inStreamIndex)
432         index = 0;
433     }
434     else
435       index = _bi.FindStream_in_PackStreams(inStreamIndex);
436 
437     if (index >= 0)
438     {
439       seqInStream = inStreams[(unsigned)index];
440       *inStreamRes = seqInStream.Detach();
441       return S_OK;
442     }
443   }
444 
445   const int bond = FindBond_for_Stream(
446       true, // forInputStream
447       inStreamIndex);
448   if (bond < 0)
449     return E_INVALIDARG;
450 
451   RINOK(GetInStream2(inStreams, /* inSizes, */
452       _bi.Bonds[(unsigned)bond].Get_OutIndex(EncodeMode), &seqInStream))
453 
454   while (_binderStreams.Size() <= (unsigned)bond)
455     _binderStreams.AddNew();
456   CStBinderStream &bs = _binderStreams[(unsigned)bond];
457 
458   if (bs.StreamRef || bs.InStreamSpec)
459     return E_NOTIMPL;
460 
461   CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
462   bs.StreamRef = spec;
463   bs.InStreamSpec = spec;
464 
465   spec->SetStream(seqInStream);
466   spec->Init();
467 
468   seqInStream = bs.InStreamSpec;
469 
470   *inStreamRes = seqInStream.Detach();
471   return S_OK;
472 }
473 
474 
GetOutStream(ISequentialOutStream * const * outStreams,UInt32 outStreamIndex,ISequentialOutStream ** outStreamRes)475 HRESULT CMixerST::GetOutStream(
476     ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
477     UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
478 {
479   CMyComPtr<ISequentialOutStream> seqOutStream;
480 
481   {
482     int index = -1;
483     if (!EncodeMode)
484     {
485       if (_bi.UnpackCoder == outStreamIndex)
486         index = 0;
487     }
488     else
489       index = _bi.FindStream_in_PackStreams(outStreamIndex);
490 
491     if (index >= 0)
492     {
493       seqOutStream = outStreams[(unsigned)index];
494       *outStreamRes = seqOutStream.Detach();
495       return S_OK;
496     }
497   }
498 
499   const int bond = FindBond_for_Stream(
500       false, // forInputStream
501       outStreamIndex);
502   if (bond < 0)
503     return E_INVALIDARG;
504 
505   const UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode);
506 
507   UInt32 coderIndex = inStreamIndex;
508   UInt32 coderStreamIndex = 0;
509 
510   if (!EncodeMode)
511     _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
512 
513   CCoder &coder = _coders[coderIndex];
514 
515   /*
516   if (!coder.Coder)
517     return E_NOTIMPL;
518   */
519 
520   coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
521   if (!seqOutStream)
522     return E_NOTIMPL;
523 
524   const UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
525   const UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
526 
527   bool isSet = false;
528 
529   if (numOutStreams == 1)
530   {
531     CMyComPtr<ICompressSetOutStream> setOutStream;
532     coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
533     if (setOutStream)
534     {
535       CMyComPtr<ISequentialOutStream> seqOutStream2;
536       RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2))
537       RINOK(setOutStream->SetOutStream(seqOutStream2))
538       isSet = true;
539     }
540   }
541 
542   if (!isSet && numOutStreams != 0)
543   {
544     return E_NOTIMPL;
545     /*
546     CMyComPtr<ICompressSetOutStream2> setStream2;
547     coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
548     if (!setStream2)
549       return E_NOTIMPL;
550     for (UInt32 i = 0; i < numOutStreams; i++)
551     {
552       CMyComPtr<ISequentialOutStream> seqOutStream2;
553       RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2))
554       RINOK(setStream2->SetOutStream2(i, seqOutStream2))
555     }
556     */
557   }
558 
559   while (_binderStreams.Size() <= (unsigned)bond)
560     _binderStreams.AddNew();
561   CStBinderStream &bs = _binderStreams[(unsigned)bond];
562 
563   if (bs.StreamRef || bs.OutStreamSpec)
564     return E_NOTIMPL;
565 
566   COutStreamCalcSize *spec = new COutStreamCalcSize;
567   bs.StreamRef = (ISequentialOutStream *)spec;
568   bs.OutStreamSpec = spec;
569 
570   spec->SetStream(seqOutStream);
571   spec->Init();
572 
573   seqOutStream = bs.OutStreamSpec;
574 
575   *outStreamRes = seqOutStream.Detach();
576   return S_OK;
577 }
578 
579 
GetError(HRESULT res,HRESULT res2)580 static HRESULT GetError(HRESULT res, HRESULT res2)
581 {
582   if (res == res2)
583     return res;
584   if (res == S_OK)
585     return res2;
586   if (res == k_My_HRESULT_WritingWasCut)
587   {
588     if (res2 != S_OK)
589       return res2;
590   }
591   return res;
592 }
593 
594 
FinishStream(UInt32 streamIndex)595 HRESULT CMixerST::FinishStream(UInt32 streamIndex)
596 {
597   {
598     int index = -1;
599     if (!EncodeMode)
600     {
601       if (_bi.UnpackCoder == streamIndex)
602         index = 0;
603     }
604     else
605       index = _bi.FindStream_in_PackStreams(streamIndex);
606 
607     if (index >= 0)
608       return S_OK;
609   }
610 
611   const int bond = FindBond_for_Stream(
612       false, // forInputStream
613       streamIndex);
614   if (bond < 0)
615     return E_INVALIDARG;
616 
617   const UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode);
618 
619   UInt32 coderIndex = inStreamIndex;
620   UInt32 coderStreamIndex = 0;
621   if (!EncodeMode)
622     _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
623 
624   CCoder &coder = _coders[coderIndex];
625   CMyComPtr<IOutStreamFinish> finish;
626   coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish);
627   HRESULT res = S_OK;
628   if (finish)
629   {
630     res = finish->OutStreamFinish();
631   }
632   return GetError(res, FinishCoder(coderIndex));
633 }
634 
635 
FinishCoder(UInt32 coderIndex)636 HRESULT CMixerST::FinishCoder(UInt32 coderIndex)
637 {
638   CCoder &coder = _coders[coderIndex];
639 
640   const UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
641   const UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
642 
643   HRESULT res = S_OK;
644   for (unsigned i = 0; i < numOutStreams; i++)
645     res = GetError(res, FinishStream(startIndex + i));
646   return res;
647 }
648 
649 
SelectMainCoder(bool useFirst)650 void CMixerST::SelectMainCoder(bool useFirst)
651 {
652   unsigned ci = _bi.UnpackCoder;
653 
654   int firstNonFilter = -1;
655   unsigned firstAllowed = ci;
656 
657   for (;;)
658   {
659     const CCoderST &coder = _coders[ci];
660     // break;
661 
662     if (ci != _bi.UnpackCoder)
663       if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
664       {
665         firstAllowed = ci;
666         firstNonFilter = -2;
667       }
668 
669     if (coder.NumStreams != 1)
670       break;
671 
672     const UInt32 st = _bi.Coder_to_Stream[ci];
673     if (_bi.IsStream_in_PackStreams(st))
674       break;
675     const int bond = _bi.FindBond_for_PackStream(st);
676     if (bond < 0)
677       throw 20150213;
678 
679     if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
680       break;
681 
682     if (firstNonFilter == -1 && !IsFilter_Vector[ci])
683       firstNonFilter = (int)ci;
684 
685     ci = _bi.Bonds[(unsigned)bond].UnpackIndex;
686   }
687 
688   if (useFirst)
689     ci = firstAllowed;
690   else if (firstNonFilter >= 0)
691     ci = (unsigned)firstNonFilter;
692 
693   MainCoderIndex = ci;
694 }
695 
696 
Code(ISequentialInStream * const * inStreams,ISequentialOutStream * const * outStreams,ICompressProgressInfo * progress,bool & dataAfterEnd_Error)697 HRESULT CMixerST::Code(
698     ISequentialInStream * const *inStreams,
699     ISequentialOutStream * const *outStreams,
700     ICompressProgressInfo *progress,
701     bool &dataAfterEnd_Error)
702 {
703   // InternalPackSizeError = false;
704   dataAfterEnd_Error = false;
705 
706   _binderStreams.Clear();
707   const unsigned ci = MainCoderIndex;
708 
709   const CCoder &mainCoder = _coders[MainCoderIndex];
710 
711   CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
712   CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
713 
714   const UInt32 numInStreams  =  EncodeMode ? 1 : mainCoder.NumStreams;
715   const UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
716 
717   const UInt32 startInIndex  =  EncodeMode ? ci : _bi.Coder_to_Stream[ci];
718   const UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
719 
720   UInt32 i;
721 
722   for (i = 0; i < numInStreams; i++)
723   {
724     CMyComPtr<ISequentialInStream> seqInStream;
725     RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream))
726     seqInStreams.Add(seqInStream);
727   }
728 
729   for (i = 0; i < numOutStreams; i++)
730   {
731     CMyComPtr<ISequentialOutStream> seqOutStream;
732     RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream))
733     seqOutStreams.Add(seqOutStream);
734   }
735 
736   CRecordVector< ISequentialInStream * > seqInStreamsSpec;
737   CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
738 
739   for (i = 0; i < numInStreams; i++)
740     seqInStreamsSpec.Add(seqInStreams[i]);
741   for (i = 0; i < numOutStreams; i++)
742     seqOutStreamsSpec.Add(seqOutStreams[i]);
743 
744   for (i = 0; i < _coders.Size(); i++)
745   {
746     if (i == ci)
747       continue;
748 
749     CCoder &coder = _coders[i];
750 
751     if (EncodeMode)
752     {
753       CMyComPtr<ICompressInitEncoder> initEncoder;
754       coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder);
755       if (initEncoder)
756       {
757         RINOK(initEncoder->InitEncoder())
758       }
759     }
760     else
761     {
762       CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
763       coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
764       if (setOutStreamSize)
765       {
766         RINOK(setOutStreamSize->SetOutStreamSize(
767             EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer))
768       }
769     }
770   }
771 
772   const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : mainCoder.PackSizePointers.ConstData();
773   const UInt64 * const *outSizes2 = EncodeMode ? mainCoder.PackSizePointers.ConstData() : &mainCoder.UnpackSizePointer;
774 
775   HRESULT res;
776   if (mainCoder.Coder)
777   {
778     res = mainCoder.Coder->Code(
779         seqInStreamsSpec[0], seqOutStreamsSpec[0],
780         isSizes2[0], outSizes2[0],
781         progress);
782   }
783   else
784   {
785     res = mainCoder.Coder2->Code(
786         seqInStreamsSpec.ConstData(), isSizes2, numInStreams,
787         seqOutStreamsSpec.ConstData(), outSizes2, numOutStreams,
788         progress);
789   }
790 
791   if (res == k_My_HRESULT_WritingWasCut)
792     res = S_OK;
793 
794   if (res == S_OK || res == S_FALSE)
795   {
796     res = GetError(res, FinishCoder(ci));
797   }
798 
799   for (i = 0; i < _binderStreams.Size(); i++)
800   {
801     const CStBinderStream &bs = _binderStreams[i];
802     if (bs.InStreamSpec)
803       bs.InStreamSpec->ReleaseStream();
804     else
805       bs.OutStreamSpec->ReleaseStream();
806   }
807 
808   if (res == k_My_HRESULT_WritingWasCut)
809     res = S_OK;
810 
811   if (res != S_OK)
812     return res;
813 
814   for (i = 0; i < _coders.Size(); i++)
815   {
816     RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */))
817   }
818 
819   return S_OK;
820 }
821 
822 
GetMainUnpackStream(ISequentialInStream * const * inStreams,ISequentialInStream ** inStreamRes)823 HRESULT CMixerST::GetMainUnpackStream(
824     ISequentialInStream * const *inStreams,
825     ISequentialInStream **inStreamRes)
826 {
827   CMyComPtr<ISequentialInStream> seqInStream;
828 
829   RINOK(GetInStream2(inStreams, /* inSizes, */
830       _bi.UnpackCoder, &seqInStream))
831 
832   FOR_VECTOR (i, _coders)
833   {
834     CCoder &coder = _coders[i];
835     CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
836     coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
837     if (setOutStreamSize)
838     {
839       RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer))
840     }
841   }
842 
843   *inStreamRes = seqInStream.Detach();
844   return S_OK;
845 }
846 
847 
GetBondStreamSize(unsigned bondIndex) const848 UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
849 {
850   const CStBinderStream &bs = _binderStreams[bondIndex];
851   if (bs.InStreamSpec)
852     return bs.InStreamSpec->GetSize();
853   return bs.OutStreamSpec->GetSize();
854 }
855 
856 #endif
857 
858 
859 
860 
861 
862 
863 #ifdef USE_MIXER_MT
864 
865 
Execute()866 void CCoderMT::Execute()
867 {
868   try
869   {
870     Code(NULL);
871   }
872   catch(...)
873   {
874     Result = E_FAIL;
875   }
876 }
877 
Code(ICompressProgressInfo * progress)878 void CCoderMT::Code(ICompressProgressInfo *progress)
879 {
880   unsigned numInStreams = EncodeMode ? 1 : NumStreams;
881   unsigned numOutStreams = EncodeMode ? NumStreams : 1;
882 
883   InStreamPointers.ClearAndReserve(numInStreams);
884   OutStreamPointers.ClearAndReserve(numOutStreams);
885 
886   unsigned i;
887 
888   for (i = 0; i < numInStreams; i++)
889     InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
890 
891   for (i = 0; i < numOutStreams; i++)
892     OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
893 
894   // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
895   /*
896   if (UnpackSizePointer)
897     UnpackSizePointer = &UnpackSize;
898   for (i = 0; i < NumStreams; i++)
899     if (PackSizePointers[i])
900       PackSizePointers[i] = &PackSizes[i];
901   */
902 
903   CReleaser releaser(*this);
904 
905   if (Coder)
906     Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
907         EncodeMode ? UnpackSizePointer : PackSizePointers[0],
908         EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
909         progress);
910   else
911     Result = Coder2->Code(
912         InStreamPointers.ConstData(),  EncodeMode ? &UnpackSizePointer : PackSizePointers.ConstData(), numInStreams,
913         OutStreamPointers.ConstData(), EncodeMode ? PackSizePointers.ConstData(): &UnpackSizePointer, numOutStreams,
914         progress);
915 }
916 
SetBindInfo(const CBindInfo & bindInfo)917 HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
918 {
919   CMixer::SetBindInfo(bindInfo);
920 
921   _streamBinders.Clear();
922   FOR_VECTOR (i, _bi.Bonds)
923   {
924     // RINOK(_streamBinders.AddNew().CreateEvents())
925     _streamBinders.AddNew();
926   }
927   return S_OK;
928 }
929 
AddCoder(const CCreatedCoder & cod)930 void CMixerMT::AddCoder(const CCreatedCoder &cod)
931 {
932   IsFilter_Vector.Add(cod.IsFilter);
933   IsExternal_Vector.Add(cod.IsExternal);
934   // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
935   CCoderMT &c2 = _coders.AddNew();
936   c2.NumStreams = cod.NumStreams;
937   c2.Coder = cod.Coder;
938   c2.Coder2 = cod.Coder2;
939   c2.EncodeMode = EncodeMode;
940 }
941 
GetCoder(unsigned index)942 CCoder &CMixerMT::GetCoder(unsigned index)
943 {
944   return _coders[index];
945 }
946 
ReInit2()947 HRESULT CMixerMT::ReInit2()
948 {
949   FOR_VECTOR (i, _streamBinders)
950   {
951     RINOK(_streamBinders[i].Create_ReInit())
952   }
953   return S_OK;
954 }
955 
SelectMainCoder(bool useFirst)956 void CMixerMT::SelectMainCoder(bool useFirst)
957 {
958   unsigned ci = _bi.UnpackCoder;
959 
960   if (!useFirst)
961   for (;;)
962   {
963     if (_coders[ci].NumStreams != 1)
964       break;
965     if (!IsFilter_Vector[ci])
966       break;
967 
968     UInt32 st = _bi.Coder_to_Stream[ci];
969     if (_bi.IsStream_in_PackStreams(st))
970       break;
971     const int bond = _bi.FindBond_for_PackStream(st);
972     if (bond < 0)
973       throw 20150213;
974     ci = _bi.Bonds[(unsigned)bond].UnpackIndex;
975   }
976 
977   MainCoderIndex = ci;
978 }
979 
Init(ISequentialInStream * const * inStreams,ISequentialOutStream * const * outStreams)980 HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
981 {
982   unsigned i;
983 
984   for (i = 0; i < _coders.Size(); i++)
985   {
986     CCoderMT &coderInfo = _coders[i];
987     const CCoderStreamsInfo &csi = _bi.Coders[i];
988 
989     UInt32 j;
990 
991     const unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
992     const unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
993 
994     coderInfo.InStreams.Clear();
995     for (j = 0; j < numInStreams; j++)
996       coderInfo.InStreams.AddNew();
997 
998     coderInfo.OutStreams.Clear();
999     for (j = 0; j < numOutStreams; j++)
1000       coderInfo.OutStreams.AddNew();
1001   }
1002 
1003   for (i = 0; i < _bi.Bonds.Size(); i++)
1004   {
1005     const CBond &bond = _bi.Bonds[i];
1006 
1007     UInt32 inCoderIndex, inCoderStreamIndex;
1008     UInt32 outCoderIndex, outCoderStreamIndex;
1009 
1010     {
1011       UInt32 coderIndex, coderStreamIndex;
1012       _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
1013 
1014       inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
1015       outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
1016 
1017       inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
1018       outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
1019     }
1020 
1021     _streamBinders[i].CreateStreams2(
1022         _coders[inCoderIndex].InStreams[inCoderStreamIndex],
1023         _coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
1024 
1025     CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
1026     _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
1027     _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
1028     if (inSetSize && outSetSize)
1029     {
1030       const UInt32 kBufSize = 1 << 19;
1031       inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
1032       outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
1033     }
1034   }
1035 
1036   {
1037     CCoderMT &cod = _coders[_bi.UnpackCoder];
1038     if (EncodeMode)
1039       cod.InStreams[0] = inStreams[0];
1040     else
1041       cod.OutStreams[0] = outStreams[0];
1042   }
1043 
1044   for (i = 0; i < _bi.PackStreams.Size(); i++)
1045   {
1046     UInt32 coderIndex, coderStreamIndex;
1047     _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
1048     CCoderMT &cod = _coders[coderIndex];
1049     if (EncodeMode)
1050       cod.OutStreams[coderStreamIndex] = outStreams[i];
1051     else
1052       cod.InStreams[coderStreamIndex] = inStreams[i];
1053   }
1054 
1055   return S_OK;
1056 }
1057 
ReturnIfError(HRESULT code)1058 HRESULT CMixerMT::ReturnIfError(HRESULT code)
1059 {
1060   FOR_VECTOR (i, _coders)
1061     if (_coders[i].Result == code)
1062       return code;
1063   return S_OK;
1064 }
1065 
Code(ISequentialInStream * const * inStreams,ISequentialOutStream * const * outStreams,ICompressProgressInfo * progress,bool & dataAfterEnd_Error)1066 HRESULT CMixerMT::Code(
1067     ISequentialInStream * const *inStreams,
1068     ISequentialOutStream * const *outStreams,
1069     ICompressProgressInfo *progress,
1070     bool &dataAfterEnd_Error)
1071 {
1072   // InternalPackSizeError = false;
1073   dataAfterEnd_Error = false;
1074 
1075   Init(inStreams, outStreams);
1076 
1077   unsigned i;
1078   for (i = 0; i < _coders.Size(); i++)
1079     if (i != MainCoderIndex)
1080     {
1081       const WRes wres = _coders[i].Create();
1082       if (wres != 0)
1083         return HRESULT_FROM_WIN32(wres);
1084     }
1085 
1086   for (i = 0; i < _coders.Size(); i++)
1087     if (i != MainCoderIndex)
1088     {
1089       const WRes wres = _coders[i].Start();
1090       if (wres != 0)
1091         return HRESULT_FROM_WIN32(wres);
1092     }
1093 
1094   _coders[MainCoderIndex].Code(progress);
1095 
1096   WRes wres = 0;
1097   for (i = 0; i < _coders.Size(); i++)
1098     if (i != MainCoderIndex)
1099     {
1100       WRes wres2 = _coders[i].WaitExecuteFinish();
1101       if (wres == 0)
1102         wres = wres2;
1103     }
1104   if (wres != 0)
1105     return HRESULT_FROM_WIN32(wres);
1106 
1107   RINOK(ReturnIfError(E_ABORT))
1108   RINOK(ReturnIfError(E_OUTOFMEMORY))
1109 
1110   for (i = 0; i < _coders.Size(); i++)
1111   {
1112     HRESULT result = _coders[i].Result;
1113     if (result != S_OK
1114         && result != k_My_HRESULT_WritingWasCut
1115         && result != S_FALSE
1116         && result != E_FAIL)
1117       return result;
1118   }
1119 
1120   RINOK(ReturnIfError(S_FALSE))
1121 
1122   for (i = 0; i < _coders.Size(); i++)
1123   {
1124     HRESULT result = _coders[i].Result;
1125     if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
1126       return result;
1127   }
1128 
1129   for (i = 0; i < _coders.Size(); i++)
1130   {
1131     RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */))
1132   }
1133 
1134   return S_OK;
1135 }
1136 
GetBondStreamSize(unsigned bondIndex) const1137 UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
1138 {
1139   return _streamBinders[bondIndex].ProcessedSize;
1140 }
1141 
1142 #endif
1143 
1144 }
1145