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