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 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 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
ReInit2()363 HRESULT CMixerST::ReInit2() { return S_OK; }
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 const 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[(unsigned)bond].Get_OutIndex(EncodeMode), &seqInStream));
455
456 while (_binderStreams.Size() <= (unsigned)bond)
457 _binderStreams.AddNew();
458 CStBinderStream &bs = _binderStreams[(unsigned)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 const int bond = FindBond_for_Stream(
502 false, // forInputStream
503 outStreamIndex);
504 if (bond < 0)
505 return E_INVALIDARG;
506
507 UInt32 inStreamIndex = _bi.Bonds[(unsigned)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[(unsigned)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 const int bond = FindBond_for_Stream(
614 false, // forInputStream
615 streamIndex);
616 if (bond < 0)
617 return E_INVALIDARG;
618
619 UInt32 inStreamIndex = _bi.Bonds[(unsigned)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 unsigned 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 const 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 = (int)ci;
686
687 ci = _bi.Bonds[(unsigned)bond].UnpackIndex;
688 }
689
690 if (useFirst)
691 ci = firstAllowed;
692 else if (firstNonFilter >= 0)
693 ci = (unsigned)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 _streamBinders.AddNew();
924 }
925 return S_OK;
926 }
927
AddCoder(const CCreatedCoder & cod)928 void CMixerMT::AddCoder(const CCreatedCoder &cod)
929 {
930 IsFilter_Vector.Add(cod.IsFilter);
931 IsExternal_Vector.Add(cod.IsExternal);
932 // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];
933 CCoderMT &c2 = _coders.AddNew();
934 c2.NumStreams = cod.NumStreams;
935 c2.Coder = cod.Coder;
936 c2.Coder2 = cod.Coder2;
937 c2.EncodeMode = EncodeMode;
938 }
939
GetCoder(unsigned index)940 CCoder &CMixerMT::GetCoder(unsigned index)
941 {
942 return _coders[index];
943 }
944
ReInit2()945 HRESULT CMixerMT::ReInit2()
946 {
947 FOR_VECTOR (i, _streamBinders)
948 {
949 RINOK(_streamBinders[i].Create_ReInit());
950 }
951 return S_OK;
952 }
953
SelectMainCoder(bool useFirst)954 void CMixerMT::SelectMainCoder(bool useFirst)
955 {
956 unsigned ci = _bi.UnpackCoder;
957
958 if (!useFirst)
959 for (;;)
960 {
961 if (_coders[ci].NumStreams != 1)
962 break;
963 if (!IsFilter_Vector[ci])
964 break;
965
966 UInt32 st = _bi.Coder_to_Stream[ci];
967 if (_bi.IsStream_in_PackStreams(st))
968 break;
969 const int bond = _bi.FindBond_for_PackStream(st);
970 if (bond < 0)
971 throw 20150213;
972 ci = _bi.Bonds[(unsigned)bond].UnpackIndex;
973 }
974
975 MainCoderIndex = ci;
976 }
977
Init(ISequentialInStream * const * inStreams,ISequentialOutStream * const * outStreams)978 HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)
979 {
980 unsigned i;
981
982 for (i = 0; i < _coders.Size(); i++)
983 {
984 CCoderMT &coderInfo = _coders[i];
985 const CCoderStreamsInfo &csi = _bi.Coders[i];
986
987 UInt32 j;
988
989 unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;
990 unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;
991
992 coderInfo.InStreams.Clear();
993 for (j = 0; j < numInStreams; j++)
994 coderInfo.InStreams.AddNew();
995
996 coderInfo.OutStreams.Clear();
997 for (j = 0; j < numOutStreams; j++)
998 coderInfo.OutStreams.AddNew();
999 }
1000
1001 for (i = 0; i < _bi.Bonds.Size(); i++)
1002 {
1003 const CBond &bond = _bi.Bonds[i];
1004
1005 UInt32 inCoderIndex, inCoderStreamIndex;
1006 UInt32 outCoderIndex, outCoderStreamIndex;
1007
1008 {
1009 UInt32 coderIndex, coderStreamIndex;
1010 _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);
1011
1012 inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;
1013 outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;
1014
1015 inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;
1016 outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;
1017 }
1018
1019 _streamBinders[i].CreateStreams2(
1020 _coders[inCoderIndex].InStreams[inCoderStreamIndex],
1021 _coders[outCoderIndex].OutStreams[outCoderStreamIndex]);
1022
1023 CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;
1024 _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);
1025 _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);
1026 if (inSetSize && outSetSize)
1027 {
1028 const UInt32 kBufSize = 1 << 19;
1029 inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);
1030 outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);
1031 }
1032 }
1033
1034 {
1035 CCoderMT &cod = _coders[_bi.UnpackCoder];
1036 if (EncodeMode)
1037 cod.InStreams[0] = inStreams[0];
1038 else
1039 cod.OutStreams[0] = outStreams[0];
1040 }
1041
1042 for (i = 0; i < _bi.PackStreams.Size(); i++)
1043 {
1044 UInt32 coderIndex, coderStreamIndex;
1045 _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);
1046 CCoderMT &cod = _coders[coderIndex];
1047 if (EncodeMode)
1048 cod.OutStreams[coderStreamIndex] = outStreams[i];
1049 else
1050 cod.InStreams[coderStreamIndex] = inStreams[i];
1051 }
1052
1053 return S_OK;
1054 }
1055
ReturnIfError(HRESULT code)1056 HRESULT CMixerMT::ReturnIfError(HRESULT code)
1057 {
1058 FOR_VECTOR (i, _coders)
1059 if (_coders[i].Result == code)
1060 return code;
1061 return S_OK;
1062 }
1063
Code(ISequentialInStream * const * inStreams,ISequentialOutStream * const * outStreams,ICompressProgressInfo * progress,bool & dataAfterEnd_Error)1064 HRESULT CMixerMT::Code(
1065 ISequentialInStream * const *inStreams,
1066 ISequentialOutStream * const *outStreams,
1067 ICompressProgressInfo *progress,
1068 bool &dataAfterEnd_Error)
1069 {
1070 // InternalPackSizeError = false;
1071 dataAfterEnd_Error = false;
1072
1073 Init(inStreams, outStreams);
1074
1075 unsigned i;
1076 for (i = 0; i < _coders.Size(); i++)
1077 if (i != MainCoderIndex)
1078 {
1079 const WRes wres = _coders[i].Create();
1080 if (wres != 0)
1081 return HRESULT_FROM_WIN32(wres);
1082 }
1083
1084 for (i = 0; i < _coders.Size(); i++)
1085 if (i != MainCoderIndex)
1086 {
1087 const WRes wres = _coders[i].Start();
1088 if (wres != 0)
1089 return HRESULT_FROM_WIN32(wres);
1090 }
1091
1092 _coders[MainCoderIndex].Code(progress);
1093
1094 WRes wres = 0;
1095 for (i = 0; i < _coders.Size(); i++)
1096 if (i != MainCoderIndex)
1097 {
1098 WRes wres2 = _coders[i].WaitExecuteFinish();
1099 if (wres == 0)
1100 wres = wres2;
1101 }
1102 if (wres != 0)
1103 return HRESULT_FROM_WIN32(wres);
1104
1105 RINOK(ReturnIfError(E_ABORT));
1106 RINOK(ReturnIfError(E_OUTOFMEMORY));
1107
1108 for (i = 0; i < _coders.Size(); i++)
1109 {
1110 HRESULT result = _coders[i].Result;
1111 if (result != S_OK
1112 && result != k_My_HRESULT_WritingWasCut
1113 && result != S_FALSE
1114 && result != E_FAIL)
1115 return result;
1116 }
1117
1118 RINOK(ReturnIfError(S_FALSE));
1119
1120 for (i = 0; i < _coders.Size(); i++)
1121 {
1122 HRESULT result = _coders[i].Result;
1123 if (result != S_OK && result != k_My_HRESULT_WritingWasCut)
1124 return result;
1125 }
1126
1127 for (i = 0; i < _coders.Size(); i++)
1128 {
1129 RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */));
1130 }
1131
1132 return S_OK;
1133 }
1134
GetBondStreamSize(unsigned bondIndex) const1135 UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const
1136 {
1137 return _streamBinders[bondIndex].ProcessedSize;
1138 }
1139
1140 #endif
1141
1142 }
1143