1 // CoderMixer2.cpp 2 3 #include "StdAfx.h" 4 5 #include "CoderMixer2.h" 6 7 #ifdef USE_MIXER_ST 8 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 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 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 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 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 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 116 void CBindInfo::ClearMaps() 117 { 118 Coder_to_Stream.Clear(); 119 Stream_to_Coder.Clear(); 120 } 121 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 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 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 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 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 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 260 CMixerST::CMixerST(bool encodeMode): 261 CMixer(encodeMode) 262 {} 263 264 CMixerST::~CMixerST() {} 265 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 299 CCoder &CMixerST::GetCoder(unsigned index) 300 { 301 return _coders[index]; 302 } 303 304 void CMixerST::ReInit() {} 305 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 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 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 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 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 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 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 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 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 774 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 792 void CCoderMT::Execute() 793 { 794 try 795 { 796 Code(NULL); 797 } 798 catch(...) 799 { 800 Result = E_FAIL; 801 } 802 } 803 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 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 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 867 CCoder &CMixerMT::GetCoder(unsigned index) 868 { 869 return _coders[index]; 870 } 871 872 void CMixerMT::ReInit() 873 { 874 FOR_VECTOR (i, _streamBinders) 875 _streamBinders[i].ReInit(); 876 } 877 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 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 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 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 1037 UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const 1038 { 1039 return _streamBinders[bondIndex].ProcessedSize; 1040 } 1041 1042 #endif 1043 1044 } 1045