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