1 // CoderMixer2MT.cpp 2 3 #include "StdAfx.h" 4 5 #include "CoderMixer2MT.h" 6 7 namespace NCoderMixer { 8 9 CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): 10 CCoderInfo2(numInStreams, numOutStreams) 11 { 12 InStreams.Reserve(NumInStreams); 13 InStreamPointers.Reserve(NumInStreams); 14 OutStreams.Reserve(NumOutStreams); 15 OutStreamPointers.Reserve(NumOutStreams); 16 } 17 18 void CCoder2::Execute() { Code(NULL); } 19 20 void CCoder2::Code(ICompressProgressInfo *progress) 21 { 22 InStreamPointers.Clear(); 23 OutStreamPointers.Clear(); 24 UInt32 i; 25 for (i = 0; i < NumInStreams; i++) 26 { 27 if (InSizePointers[i] != NULL) 28 InSizePointers[i] = &InSizes[i]; 29 InStreamPointers.Add((ISequentialInStream *)InStreams[i]); 30 } 31 for (i = 0; i < NumOutStreams; i++) 32 { 33 if (OutSizePointers[i] != NULL) 34 OutSizePointers[i] = &OutSizes[i]; 35 OutStreamPointers.Add((ISequentialOutStream *)OutStreams[i]); 36 } 37 if (Coder) 38 Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], 39 InSizePointers[0], OutSizePointers[0], progress); 40 else 41 Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, 42 &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); 43 { 44 int i; 45 for (i = 0; i < InStreams.Size(); i++) 46 InStreams[i].Release(); 47 for (i = 0; i < OutStreams.Size(); i++) 48 OutStreams[i].Release(); 49 } 50 } 51 52 static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, 53 CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) 54 { 55 sizes.Clear(); 56 sizePointers.Clear(); 57 for (UInt32 i = 0; i < numItems; i++) 58 { 59 if (srcSizes == 0 || srcSizes[i] == NULL) 60 { 61 sizes.Add(0); 62 sizePointers.Add(NULL); 63 } 64 else 65 { 66 sizes.Add(*srcSizes[i]); 67 sizePointers.Add(&sizes.Back()); 68 } 69 } 70 } 71 72 73 void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) 74 { 75 SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); 76 SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); 77 } 78 79 ////////////////////////////////////// 80 // CCoderMixer2MT 81 82 HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) 83 { 84 _bindInfo = bindInfo; 85 _streamBinders.Clear(); 86 for (int i = 0; i < _bindInfo.BindPairs.Size(); i++) 87 { 88 _streamBinders.Add(CStreamBinder()); 89 RINOK(_streamBinders.Back().CreateEvents()); 90 } 91 return S_OK; 92 } 93 94 void CCoderMixer2MT::AddCoderCommon() 95 { 96 const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; 97 CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); 98 _coders.Add(threadCoderInfo); 99 } 100 101 void CCoderMixer2MT::AddCoder(ICompressCoder *coder) 102 { 103 AddCoderCommon(); 104 _coders.Back().Coder = coder; 105 } 106 107 void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) 108 { 109 AddCoderCommon(); 110 _coders.Back().Coder2 = coder; 111 } 112 113 114 void CCoderMixer2MT::ReInit() 115 { 116 for (int i = 0; i < _streamBinders.Size(); i++) 117 _streamBinders[i].ReInit(); 118 } 119 120 121 HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) 122 { 123 /* 124 if (_coders.Size() != _bindInfo.Coders.Size()) 125 throw 0; 126 */ 127 int i; 128 for (i = 0; i < _coders.Size(); i++) 129 { 130 CCoder2 &coderInfo = _coders[i]; 131 const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; 132 coderInfo.InStreams.Clear(); 133 UInt32 j; 134 for (j = 0; j < coderStreamsInfo.NumInStreams; j++) 135 coderInfo.InStreams.Add(NULL); 136 coderInfo.OutStreams.Clear(); 137 for (j = 0; j < coderStreamsInfo.NumOutStreams; j++) 138 coderInfo.OutStreams.Add(NULL); 139 } 140 141 for (i = 0; i < _bindInfo.BindPairs.Size(); i++) 142 { 143 const CBindPair &bindPair = _bindInfo.BindPairs[i]; 144 UInt32 inCoderIndex, inCoderStreamIndex; 145 UInt32 outCoderIndex, outCoderStreamIndex; 146 _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); 147 _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); 148 149 _streamBinders[i].CreateStreams( 150 &_coders[inCoderIndex].InStreams[inCoderStreamIndex], 151 &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); 152 153 CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize; 154 _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize); 155 _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize); 156 if (inSetSize && outSetSize) 157 { 158 const UInt32 kBufSize = 1 << 19; 159 inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize); 160 outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize); 161 } 162 } 163 164 for (i = 0; i < _bindInfo.InStreams.Size(); i++) 165 { 166 UInt32 inCoderIndex, inCoderStreamIndex; 167 _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); 168 _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; 169 } 170 171 for (i = 0; i < _bindInfo.OutStreams.Size(); i++) 172 { 173 UInt32 outCoderIndex, outCoderStreamIndex; 174 _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); 175 _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; 176 } 177 return S_OK; 178 } 179 180 HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) 181 { 182 for (int i = 0; i < _coders.Size(); i++) 183 if (_coders[i].Result == code) 184 return code; 185 return S_OK; 186 } 187 188 STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, 189 const UInt64 ** /* inSizes */, 190 UInt32 numInStreams, 191 ISequentialOutStream **outStreams, 192 const UInt64 ** /* outSizes */, 193 UInt32 numOutStreams, 194 ICompressProgressInfo *progress) 195 { 196 if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || 197 numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) 198 return E_INVALIDARG; 199 200 Init(inStreams, outStreams); 201 202 int i; 203 for (i = 0; i < _coders.Size(); i++) 204 if (i != _progressCoderIndex) 205 { 206 RINOK(_coders[i].Create()); 207 } 208 209 for (i = 0; i < _coders.Size(); i++) 210 if (i != _progressCoderIndex) 211 _coders[i].Start(); 212 213 _coders[_progressCoderIndex].Code(progress); 214 215 for (i = 0; i < _coders.Size(); i++) 216 if (i != _progressCoderIndex) 217 _coders[i].WaitFinish(); 218 219 RINOK(ReturnIfError(E_ABORT)); 220 RINOK(ReturnIfError(E_OUTOFMEMORY)); 221 222 for (i = 0; i < _coders.Size(); i++) 223 { 224 HRESULT result = _coders[i].Result; 225 if (result != S_OK && result != E_FAIL && result != S_FALSE) 226 return result; 227 } 228 229 RINOK(ReturnIfError(S_FALSE)); 230 231 for (i = 0; i < _coders.Size(); i++) 232 { 233 HRESULT result = _coders[i].Result; 234 if (result != S_OK) 235 return result; 236 } 237 return S_OK; 238 } 239 240 } 241