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