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