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