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     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   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     int bond = BindInfo->FindBond_for_PackStream(ind);
150     if (bond < 0)
151       return false;
152     if (!CheckCoder(BindInfo->Bonds[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   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[bond].PackIndex, coderIndex, coderStreamIndex);
256   */
257   UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[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   int bond = _bi.FindBond_for_PackStream(streamIndex);
271   if (bond < 0)
272     throw 20150213;
273 
274   UInt32 nextCoder = _bi.Bonds[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   UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
285   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   UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];
297   UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;
298   for (UInt32 i = 0; i < numStreams; i++)
299   {
300     UInt32 si = startIndex + i;
301     if (_bi.IsStream_in_PackStreams(si))
302       continue;
303 
304     int bond = _bi.FindBond_for_PackStream(si);
305     if (bond < 0)
306       throw 20150213;
307 
308     if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[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       CMyComPtr<ISequentialInStream> s;
347       unk->QueryInterface(IID_ISequentialInStream, (void**)&s);
348       c2.CanRead = (s != NULL);
349     }
350     {
351       CMyComPtr<ISequentialOutStream> s;
352       unk->QueryInterface(IID_ISequentialOutStream, (void**)&s);
353       c2.CanWrite = (s != NULL);
354     }
355   }
356 }
357 
GetCoder(unsigned index)358 CCoder &CMixerST::GetCoder(unsigned index)
359 {
360   return _coders[index];
361 }
362 
ReInit()363 void CMixerST::ReInit() {}
364 
GetInStream2(ISequentialInStream * const * inStreams,UInt32 outStreamIndex,ISequentialInStream ** inStreamRes)365 HRESULT CMixerST::GetInStream2(
366     ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
367     UInt32 outStreamIndex, ISequentialInStream **inStreamRes)
368 {
369   UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;
370 
371   if (EncodeMode)
372   {
373     _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);
374     if (coderStreamIndex != 0)
375       return E_NOTIMPL;
376   }
377 
378   const CCoder &coder = _coders[coderIndex];
379 
380   CMyComPtr<ISequentialInStream> seqInStream;
381   coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);
382   if (!seqInStream)
383     return E_NOTIMPL;
384 
385   UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;
386   UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];
387 
388   bool isSet = false;
389 
390   if (numInStreams == 1)
391   {
392     CMyComPtr<ICompressSetInStream> setStream;
393     coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);
394     if (setStream)
395     {
396       CMyComPtr<ISequentialInStream> seqInStream2;
397       RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2));
398       RINOK(setStream->SetInStream(seqInStream2));
399       isSet = true;
400     }
401   }
402 
403   if (!isSet && numInStreams != 0)
404   {
405     CMyComPtr<ICompressSetInStream2> setStream2;
406     coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);
407     if (!setStream2)
408       return E_NOTIMPL;
409 
410     for (UInt32 i = 0; i < numInStreams; i++)
411     {
412       CMyComPtr<ISequentialInStream> seqInStream2;
413       RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2));
414       RINOK(setStream2->SetInStream2(i, seqInStream2));
415     }
416   }
417 
418   *inStreamRes = seqInStream.Detach();
419   return S_OK;
420 }
421 
422 
GetInStream(ISequentialInStream * const * inStreams,UInt32 inStreamIndex,ISequentialInStream ** inStreamRes)423 HRESULT CMixerST::GetInStream(
424     ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */
425     UInt32 inStreamIndex, ISequentialInStream **inStreamRes)
426 {
427   CMyComPtr<ISequentialInStream> seqInStream;
428 
429   {
430     int index = -1;
431     if (EncodeMode)
432     {
433       if (_bi.UnpackCoder == inStreamIndex)
434         index = 0;
435     }
436     else
437       index = _bi.FindStream_in_PackStreams(inStreamIndex);
438 
439     if (index >= 0)
440     {
441       seqInStream = inStreams[(unsigned)index];
442       *inStreamRes = seqInStream.Detach();
443       return S_OK;
444     }
445   }
446 
447   int bond = FindBond_for_Stream(
448       true, // forInputStream
449       inStreamIndex);
450   if (bond < 0)
451     return E_INVALIDARG;
452 
453   RINOK(GetInStream2(inStreams, /* inSizes, */
454       _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream));
455 
456   while (_binderStreams.Size() <= (unsigned)bond)
457     _binderStreams.AddNew();
458   CStBinderStream &bs = _binderStreams[bond];
459 
460   if (bs.StreamRef || bs.InStreamSpec)
461     return E_NOTIMPL;
462 
463   CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;
464   bs.StreamRef = spec;
465   bs.InStreamSpec = spec;
466 
467   spec->SetStream(seqInStream);
468   spec->Init();
469 
470   seqInStream = bs.InStreamSpec;
471 
472   *inStreamRes = seqInStream.Detach();
473   return S_OK;
474 }
475 
476 
GetOutStream(ISequentialOutStream * const * outStreams,UInt32 outStreamIndex,ISequentialOutStream ** outStreamRes)477 HRESULT CMixerST::GetOutStream(
478     ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */
479     UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)
480 {
481   CMyComPtr<ISequentialOutStream> seqOutStream;
482 
483   {
484     int index = -1;
485     if (!EncodeMode)
486     {
487       if (_bi.UnpackCoder == outStreamIndex)
488         index = 0;
489     }
490     else
491       index = _bi.FindStream_in_PackStreams(outStreamIndex);
492 
493     if (index >= 0)
494     {
495       seqOutStream = outStreams[(unsigned)index];
496       *outStreamRes = seqOutStream.Detach();
497       return S_OK;
498     }
499   }
500 
501   int bond = FindBond_for_Stream(
502       false, // forInputStream
503       outStreamIndex);
504   if (bond < 0)
505     return E_INVALIDARG;
506 
507   UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
508 
509   UInt32 coderIndex = inStreamIndex;
510   UInt32 coderStreamIndex = 0;
511 
512   if (!EncodeMode)
513     _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
514 
515   CCoder &coder = _coders[coderIndex];
516 
517   /*
518   if (!coder.Coder)
519     return E_NOTIMPL;
520   */
521 
522   coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);
523   if (!seqOutStream)
524     return E_NOTIMPL;
525 
526   UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
527   UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
528 
529   bool isSet = false;
530 
531   if (numOutStreams == 1)
532   {
533     CMyComPtr<ICompressSetOutStream> setOutStream;
534     coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
535     if (setOutStream)
536     {
537       CMyComPtr<ISequentialOutStream> seqOutStream2;
538       RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2));
539       RINOK(setOutStream->SetOutStream(seqOutStream2));
540       isSet = true;
541     }
542   }
543 
544   if (!isSet && numOutStreams != 0)
545   {
546     return E_NOTIMPL;
547     /*
548     CMyComPtr<ICompressSetOutStream2> setStream2;
549     coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);
550     if (!setStream2)
551       return E_NOTIMPL;
552     for (UInt32 i = 0; i < numOutStreams; i++)
553     {
554       CMyComPtr<ISequentialOutStream> seqOutStream2;
555       RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2));
556       RINOK(setStream2->SetOutStream2(i, seqOutStream2));
557     }
558     */
559   }
560 
561   while (_binderStreams.Size() <= (unsigned)bond)
562     _binderStreams.AddNew();
563   CStBinderStream &bs = _binderStreams[bond];
564 
565   if (bs.StreamRef || bs.OutStreamSpec)
566     return E_NOTIMPL;
567 
568   COutStreamCalcSize *spec = new COutStreamCalcSize;
569   bs.StreamRef = (ISequentialOutStream *)spec;
570   bs.OutStreamSpec = spec;
571 
572   spec->SetStream(seqOutStream);
573   spec->Init();
574 
575   seqOutStream = bs.OutStreamSpec;
576 
577   *outStreamRes = seqOutStream.Detach();
578   return S_OK;
579 }
580 
581 
GetError(HRESULT res,HRESULT res2)582 static HRESULT GetError(HRESULT res, HRESULT res2)
583 {
584   if (res == res2)
585     return res;
586   if (res == S_OK)
587     return res2;
588   if (res == k_My_HRESULT_WritingWasCut)
589   {
590     if (res2 != S_OK)
591       return res2;
592   }
593   return res;
594 }
595 
596 
FinishStream(UInt32 streamIndex)597 HRESULT CMixerST::FinishStream(UInt32 streamIndex)
598 {
599   {
600     int index = -1;
601     if (!EncodeMode)
602     {
603       if (_bi.UnpackCoder == streamIndex)
604         index = 0;
605     }
606     else
607       index = _bi.FindStream_in_PackStreams(streamIndex);
608 
609     if (index >= 0)
610       return S_OK;
611   }
612 
613   int bond = FindBond_for_Stream(
614       false, // forInputStream
615       streamIndex);
616   if (bond < 0)
617     return E_INVALIDARG;
618 
619   UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode);
620 
621   UInt32 coderIndex = inStreamIndex;
622   UInt32 coderStreamIndex = 0;
623   if (!EncodeMode)
624     _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);
625 
626   CCoder &coder = _coders[coderIndex];
627   CMyComPtr<IOutStreamFinish> finish;
628   coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish);
629   HRESULT res = S_OK;
630   if (finish)
631   {
632     res = finish->OutStreamFinish();
633   }
634   return GetError(res, FinishCoder(coderIndex));
635 }
636 
637 
FinishCoder(UInt32 coderIndex)638 HRESULT CMixerST::FinishCoder(UInt32 coderIndex)
639 {
640   CCoder &coder = _coders[coderIndex];
641 
642   UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;
643   UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;
644 
645   HRESULT res = S_OK;
646   for (unsigned i = 0; i < numOutStreams; i++)
647     res = GetError(res, FinishStream(startIndex + i));
648   return res;
649 }
650 
651 
SelectMainCoder(bool useFirst)652 void CMixerST::SelectMainCoder(bool useFirst)
653 {
654   unsigned ci = _bi.UnpackCoder;
655 
656   int firstNonFilter = -1;
657   int firstAllowed = ci;
658 
659   for (;;)
660   {
661     const CCoderST &coder = _coders[ci];
662     // break;
663 
664     if (ci != _bi.UnpackCoder)
665       if (EncodeMode ? !coder.CanWrite : !coder.CanRead)
666       {
667         firstAllowed = ci;
668         firstNonFilter = -2;
669       }
670 
671     if (coder.NumStreams != 1)
672       break;
673 
674     UInt32 st = _bi.Coder_to_Stream[ci];
675     if (_bi.IsStream_in_PackStreams(st))
676       break;
677     int bond = _bi.FindBond_for_PackStream(st);
678     if (bond < 0)
679       throw 20150213;
680 
681     if (EncodeMode ? !coder.CanRead : !coder.CanWrite)
682       break;
683 
684     if (firstNonFilter == -1 && !IsFilter_Vector[ci])
685       firstNonFilter = ci;
686 
687     ci = _bi.Bonds[bond].UnpackIndex;
688   }
689 
690   if (useFirst)
691     ci = firstAllowed;
692   else if (firstNonFilter >= 0)
693     ci = firstNonFilter;
694 
695   MainCoderIndex = ci;
696 }
697 
698 
Code(ISequentialInStream * const * inStreams,ISequentialOutStream * const * outStreams,ICompressProgressInfo * progress,bool & dataAfterEnd_Error)699 HRESULT CMixerST::Code(
700     ISequentialInStream * const *inStreams,
701     ISequentialOutStream * const *outStreams,
702     ICompressProgressInfo *progress,
703     bool &dataAfterEnd_Error)
704 {
705   // InternalPackSizeError = false;
706   dataAfterEnd_Error = false;
707 
708   _binderStreams.Clear();
709   unsigned ci = MainCoderIndex;
710 
711   const CCoder &mainCoder = _coders[MainCoderIndex];
712 
713   CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
714   CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
715 
716   UInt32 numInStreams  =  EncodeMode ? 1 : mainCoder.NumStreams;
717   UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;
718 
719   UInt32 startInIndex  =  EncodeMode ? ci : _bi.Coder_to_Stream[ci];
720   UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];
721 
722   UInt32 i;
723 
724   for (i = 0; i < numInStreams; i++)
725   {
726     CMyComPtr<ISequentialInStream> seqInStream;
727     RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream));
728     seqInStreams.Add(seqInStream);
729   }
730 
731   for (i = 0; i < numOutStreams; i++)
732   {
733     CMyComPtr<ISequentialOutStream> seqOutStream;
734     RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream));
735     seqOutStreams.Add(seqOutStream);
736   }
737 
738   CRecordVector< ISequentialInStream * > seqInStreamsSpec;
739   CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
740 
741   for (i = 0; i < numInStreams; i++)
742     seqInStreamsSpec.Add(seqInStreams[i]);
743   for (i = 0; i < numOutStreams; i++)
744     seqOutStreamsSpec.Add(seqOutStreams[i]);
745 
746   for (i = 0; i < _coders.Size(); i++)
747   {
748     if (i == ci)
749       continue;
750 
751     CCoder &coder = _coders[i];
752 
753     if (EncodeMode)
754     {
755       CMyComPtr<ICompressInitEncoder> initEncoder;
756       coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder);
757       if (initEncoder)
758         RINOK(initEncoder->InitEncoder());
759     }
760     else
761     {
762       CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
763       coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
764       if (setOutStreamSize)
765         RINOK(setOutStreamSize->SetOutStreamSize(
766             EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer));
767     }
768   }
769 
770   const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front();
771   const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer;
772 
773   HRESULT res;
774   if (mainCoder.Coder)
775   {
776     res = mainCoder.Coder->Code(
777         seqInStreamsSpec[0], seqOutStreamsSpec[0],
778         isSizes2[0], outSizes2[0],
779         progress);
780   }
781   else
782   {
783     res = mainCoder.Coder2->Code(
784         &seqInStreamsSpec.Front(), isSizes2, numInStreams,
785         &seqOutStreamsSpec.Front(), outSizes2, numOutStreams,
786         progress);
787   }
788 
789   if (res == k_My_HRESULT_WritingWasCut)
790     res = S_OK;
791 
792   if (res == S_OK || res == S_FALSE)
793   {
794     res = GetError(res, FinishCoder(ci));
795   }
796 
797   for (i = 0; i < _binderStreams.Size(); i++)
798   {
799     const CStBinderStream &bs = _binderStreams[i];
800     if (bs.InStreamSpec)
801       bs.InStreamSpec->ReleaseStream();
802     else
803       bs.OutStreamSpec->ReleaseStream();
804   }
805 
806   if (res == k_My_HRESULT_WritingWasCut)
807     res = S_OK;
808 
809   if (res != S_OK)
810     return res;
811 
812   for (i = 0; i < _coders.Size(); i++)
813   {
814     RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */));
815   }
816 
817   return S_OK;
818 }
819 
820 
GetMainUnpackStream(ISequentialInStream * const * inStreams,ISequentialInStream ** inStreamRes)821 HRESULT CMixerST::GetMainUnpackStream(
822     ISequentialInStream * const *inStreams,
823     ISequentialInStream **inStreamRes)
824 {
825   CMyComPtr<ISequentialInStream> seqInStream;
826 
827   RINOK(GetInStream2(inStreams, /* inSizes, */
828       _bi.UnpackCoder, &seqInStream))
829 
830   FOR_VECTOR (i, _coders)
831   {
832     CCoder &coder = _coders[i];
833     CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
834     coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);
835     if (setOutStreamSize)
836     {
837       RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer));
838     }
839   }
840 
841   *inStreamRes = seqInStream.Detach();
842   return S_OK;
843 }
844 
845 
GetBondStreamSize(unsigned bondIndex) const846 UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const
847 {
848   const CStBinderStream &bs = _binderStreams[bondIndex];
849   if (bs.InStreamSpec)
850     return bs.InStreamSpec->GetSize();
851   return bs.OutStreamSpec->GetSize();
852 }
853 
854 #endif
855 
856 
857 
858 
859 
860 
861 #ifdef USE_MIXER_MT
862 
863 
Execute()864 void CCoderMT::Execute()
865 {
866   try
867   {
868     Code(NULL);
869   }
870   catch(...)
871   {
872     Result = E_FAIL;
873   }
874 }
875 
Code(ICompressProgressInfo * progress)876 void CCoderMT::Code(ICompressProgressInfo *progress)
877 {
878   unsigned numInStreams = EncodeMode ? 1 : NumStreams;
879   unsigned numOutStreams = EncodeMode ? NumStreams : 1;
880 
881   InStreamPointers.ClearAndReserve(numInStreams);
882   OutStreamPointers.ClearAndReserve(numOutStreams);
883 
884   unsigned i;
885 
886   for (i = 0; i < numInStreams; i++)
887     InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);
888 
889   for (i = 0; i < numOutStreams; i++)
890     OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);
891 
892   // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.
893   /*
894   if (UnpackSizePointer)
895     UnpackSizePointer = &UnpackSize;
896   for (i = 0; i < NumStreams; i++)
897     if (PackSizePointers[i])
898       PackSizePointers[i] = &PackSizes[i];
899   */
900 
901   CReleaser releaser(*this);
902 
903   if (Coder)
904     Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],
905         EncodeMode ? UnpackSizePointer : PackSizePointers[0],
906         EncodeMode ? PackSizePointers[0] : UnpackSizePointer,
907         progress);
908   else
909     Result = Coder2->Code(
910         &InStreamPointers.Front(),  EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams,
911         &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams,
912         progress);
913 }
914 
SetBindInfo(const CBindInfo & bindInfo)915 HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)
916 {
917   CMixer::SetBindInfo(bindInfo);
918 
919   _streamBinders.Clear();
920   FOR_VECTOR (i, _bi.Bonds)
921   {
922     RINOK(_streamBinders.AddNew().CreateEvents());
923   }
924   return S_OK;
925 }
926 
AddCoder(const CCreatedCoder & cod)927 void CMixerMT::AddCoder(const CCreatedCoder &cod)
928 {
929   IsFilter_Vector.Add(cod.IsFilter);
930   IsExternal_Vector.Add(cod.IsExternal);
931   // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
932   CCoderMT &c2 = _coders.AddNew();
933   c2.NumStreams = cod.NumStreams;
934   c2.Coder = cod.Coder;
935   c2.Coder2 = cod.Coder2;
936   c2.EncodeMode = EncodeMode;
937 }
938 
GetCoder(unsigned index)939 CCoder &CMixerMT::GetCoder(unsigned index)
940 {
941   return _coders[index];
942 }
943 
ReInit()944 void CMixerMT::ReInit()
945 {
946   FOR_VECTOR (i, _streamBinders)
947     _streamBinders[i].ReInit();
948 }
949 
SelectMainCoder(bool useFirst)950 void CMixerMT::SelectMainCoder(bool useFirst)
951 {
952   unsigned ci = _bi.UnpackCoder;
953 
954   if (!useFirst)
955   for (;;)
956   {
957     if (_coders[ci].NumStreams != 1)
958       break;
959     if (!IsFilter_Vector[ci])
960       break;
961 
962     UInt32 st = _bi.Coder_to_Stream[ci];
963     if (_bi.IsStream_in_PackStreams(st))
964       break;
965     int bond = _bi.FindBond_for_PackStream(st);
966     if (bond < 0)
967       throw 20150213;
968     ci = _bi.Bonds[bond].UnpackIndex;
969   }
970 
971   MainCoderIndex = ci;
972 }
973 
Init(ISequentialInStream * const * inStreams,ISequentialOutStream * const * outStreams)974 HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
975 {
976   unsigned i;
977 
978   for (i = 0; i < _coders.Size(); i++)
979   {
980     CCoderMT &coderInfo = _coders[i];
981     const CCoderStreamsInfo &csi = _bi.Coders[i];
982 
983     UInt32 j;
984 
985     unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
986     unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
987 
988     coderInfo.InStreams.Clear();
989     for (j = 0; j < numInStreams; j++)
990       coderInfo.InStreams.AddNew();
991 
992     coderInfo.OutStreams.Clear();
993     for (j = 0; j < numOutStreams; j++)
994       coderInfo.OutStreams.AddNew();
995   }
996 
997   for (i = 0; i < _bi.Bonds.Size(); i++)
998   {
999     const CBond &bond = _bi.Bonds[i];
1000 
1001     UInt32 inCoderIndex, inCoderStreamIndex;
1002     UInt32 outCoderIndex, outCoderStreamIndex;
1003 
1004     {
1005       UInt32 coderIndex, coderStreamIndex;
1006       _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
1007 
1008       inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
1009       outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
1010 
1011       inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
1012       outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
1013     }
1014 
1015     _streamBinders[i].CreateStreams(
1016         &_coders[inCoderIndex].InStreams[inCoderStreamIndex],
1017         &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
1018 
1019     CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
1020     _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
1021     _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
1022     if (inSetSize && outSetSize)
1023     {
1024       const UInt32 kBufSize = 1 << 19;
1025       inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
1026       outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
1027     }
1028   }
1029 
1030   {
1031     CCoderMT &cod = _coders[_bi.UnpackCoder];
1032     if (EncodeMode)
1033       cod.InStreams[0] = inStreams[0];
1034     else
1035       cod.OutStreams[0] = outStreams[0];
1036   }
1037 
1038   for (i = 0; i < _bi.PackStreams.Size(); i++)
1039   {
1040     UInt32 coderIndex, coderStreamIndex;
1041     _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
1042     CCoderMT &cod = _coders[coderIndex];
1043     if (EncodeMode)
1044       cod.OutStreams[coderStreamIndex] = outStreams[i];
1045     else
1046       cod.InStreams[coderStreamIndex] = inStreams[i];
1047   }
1048 
1049   return S_OK;
1050 }
1051 
ReturnIfError(HRESULT code)1052 HRESULT CMixerMT::ReturnIfError(HRESULT code)
1053 {
1054   FOR_VECTOR (i, _coders)
1055     if (_coders[i].Result == code)
1056       return code;
1057   return S_OK;
1058 }
1059 
Code(ISequentialInStream * const * inStreams,ISequentialOutStream * const * outStreams,ICompressProgressInfo * progress,bool & dataAfterEnd_Error)1060 HRESULT CMixerMT::Code(
1061     ISequentialInStream * const *inStreams,
1062     ISequentialOutStream * const *outStreams,
1063     ICompressProgressInfo *progress,
1064     bool &dataAfterEnd_Error)
1065 {
1066   // InternalPackSizeError = false;
1067   dataAfterEnd_Error = false;
1068 
1069   Init(inStreams, outStreams);
1070 
1071   unsigned i;
1072   for (i = 0; i < _coders.Size(); i++)
1073     if (i != MainCoderIndex)
1074     {
1075       RINOK(_coders[i].Create());
1076     }
1077 
1078   for (i = 0; i < _coders.Size(); i++)
1079     if (i != MainCoderIndex)
1080       _coders[i].Start();
1081 
1082   _coders[MainCoderIndex].Code(progress);
1083 
1084   for (i = 0; i < _coders.Size(); i++)
1085     if (i != MainCoderIndex)
1086       _coders[i].WaitExecuteFinish();
1087 
1088   RINOK(ReturnIfError(E_ABORT));
1089   RINOK(ReturnIfError(E_OUTOFMEMORY));
1090 
1091   for (i = 0; i < _coders.Size(); i++)
1092   {
1093     HRESULT result = _coders[i].Result;
1094     if (result != S_OK
1095         && result != k_My_HRESULT_WritingWasCut
1096         && result != S_FALSE
1097         && result != E_FAIL)
1098       return result;
1099   }
1100 
1101   RINOK(ReturnIfError(S_FALSE));
1102 
1103   for (i = 0; i < _coders.Size(); i++)
1104   {
1105     HRESULT result = _coders[i].Result;
1106     if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
1107       return result;
1108   }
1109 
1110   for (i = 0; i < _coders.Size(); i++)
1111   {
1112     RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */));
1113   }
1114 
1115   return S_OK;
1116 }
1117 
GetBondStreamSize(unsigned bondIndex) const1118 UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
1119 {
1120   return _streamBinders[bondIndex].ProcessedSize;
1121 }
1122 
1123 #endif
1124 
1125 }
1126