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 64 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 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 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 173 void CBindInfo::ClearMaps() 174 { 175 Coder_to_Stream.Clear(); 176 Stream_to_Coder.Clear(); 177 } 178 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 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 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 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 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 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 319 CMixerST::CMixerST(bool encodeMode): 320 CMixer(encodeMode) 321 {} 322 323 CMixerST::~CMixerST() {} 324 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 358 CCoder &CMixerST::GetCoder(unsigned index) 359 { 360 return _coders[index]; 361 } 362 363 void CMixerST::ReInit() {} 364 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 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 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 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 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 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 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 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 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 846 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 864 void CCoderMT::Execute() 865 { 866 try 867 { 868 Code(NULL); 869 } 870 catch(...) 871 { 872 Result = E_FAIL; 873 } 874 } 875 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 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 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 939 CCoder &CMixerMT::GetCoder(unsigned index) 940 { 941 return _coders[index]; 942 } 943 944 void CMixerMT::ReInit() 945 { 946 FOR_VECTOR (i, _streamBinders) 947 _streamBinders[i].ReInit(); 948 } 949 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 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 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 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 1118 UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const 1119 { 1120 return _streamBinders[bondIndex].ProcessedSize; 1121 } 1122 1123 #endif 1124 1125 } 1126