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