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