1// CreateCoder.cpp 2 3#include "StdAfx.h" 4 5#include "../../Windows/Defs.h" 6#include "../../Windows/PropVariant.h" 7 8#include "CreateCoder.h" 9 10#include "FilterCoder.h" 11#include "RegisterCodec.h" 12 13static const unsigned int kNumCodecsMax = 64; 14unsigned int g_NumCodecs = 0; 15const CCodecInfo *g_Codecs[kNumCodecsMax]; 16void RegisterCodec(const CCodecInfo *codecInfo) throw() 17{ 18 if (g_NumCodecs < kNumCodecsMax) 19 g_Codecs[g_NumCodecs++] = codecInfo; 20} 21 22static const unsigned int kNumHashersMax = 16; 23unsigned int g_NumHashers = 0; 24const CHasherInfo *g_Hashers[kNumHashersMax]; 25void RegisterHasher(const CHasherInfo *hashInfo) throw() 26{ 27 if (g_NumHashers < kNumHashersMax) 28 g_Hashers[g_NumHashers++] = hashInfo; 29} 30 31#ifdef EXTERNAL_CODECS 32static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) 33{ 34 NWindows::NCOM::CPropVariant prop; 35 RINOK(codecsInfo->GetProperty(index, propID, &prop)); 36 if (prop.vt == VT_EMPTY) 37 res = 1; 38 else if (prop.vt == VT_UI4) 39 res = prop.ulVal; 40 else 41 return E_INVALIDARG; 42 return S_OK; 43} 44 45static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) 46{ 47 NWindows::NCOM::CPropVariant prop; 48 RINOK(codecsInfo->GetProperty(index, propID, &prop)); 49 if (prop.vt == VT_EMPTY) 50 res = true; 51 else if (prop.vt == VT_BOOL) 52 res = VARIANT_BOOLToBool(prop.boolVal); 53 else 54 return E_INVALIDARG; 55 return S_OK; 56} 57 58HRESULT CExternalCodecs::LoadCodecs() 59{ 60 if (GetCodecs) 61 { 62 UInt32 num; 63 RINOK(GetCodecs->GetNumberOfMethods(&num)); 64 for (UInt32 i = 0; i < num; i++) 65 { 66 CCodecInfoEx info; 67 NWindows::NCOM::CPropVariant prop; 68 RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop)); 69 // if (prop.vt != VT_BSTR) 70 // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); 71 // memcpy(info.Id.ID, prop.bstrVal, info.Id.IDSize); 72 if (prop.vt != VT_UI8) 73 continue; // old Interface 74 info.Id = prop.uhVal.QuadPart; 75 prop.Clear(); 76 77 RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop)); 78 if (prop.vt == VT_BSTR) 79 info.Name = prop.bstrVal; 80 else if (prop.vt != VT_EMPTY) 81 return E_INVALIDARG; 82 83 RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kInStreams, info.NumInStreams)); 84 RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kOutStreams, info.NumOutStreams)); 85 RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); 86 RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); 87 88 Codecs.Add(info); 89 } 90 } 91 if (GetHashers) 92 { 93 UInt32 num = GetHashers->GetNumHashers(); 94 for (UInt32 i = 0; i < num; i++) 95 { 96 CHasherInfoEx info; 97 NWindows::NCOM::CPropVariant prop; 98 RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop)); 99 if (prop.vt != VT_UI8) 100 continue; 101 info.Id = prop.uhVal.QuadPart; 102 prop.Clear(); 103 104 RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop)); 105 if (prop.vt == VT_BSTR) 106 info.Name = prop.bstrVal; 107 else if (prop.vt != VT_EMPTY) 108 return E_INVALIDARG; 109 110 Hashers.Add(info); 111 } 112 } 113 return S_OK; 114} 115 116#endif 117 118bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS 119 const UString &name, CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) 120{ 121 UInt32 i; 122 for (i = 0; i < g_NumCodecs; i++) 123 { 124 const CCodecInfo &codec = *g_Codecs[i]; 125 if (name.IsEqualToNoCase(codec.Name)) 126 { 127 methodId = codec.Id; 128 numInStreams = codec.NumInStreams; 129 numOutStreams = 1; 130 return true; 131 } 132 } 133 #ifdef EXTERNAL_CODECS 134 if (__externalCodecs) 135 for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) 136 { 137 const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; 138 if (codec.Name.IsEqualToNoCase(name)) 139 { 140 methodId = codec.Id; 141 numInStreams = codec.NumInStreams; 142 numOutStreams = codec.NumOutStreams; 143 return true; 144 } 145 } 146 #endif 147 return false; 148} 149 150bool FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS 151 CMethodId methodId, UString &name) 152{ 153 UInt32 i; 154 for (i = 0; i < g_NumCodecs; i++) 155 { 156 const CCodecInfo &codec = *g_Codecs[i]; 157 if (methodId == codec.Id) 158 { 159 name = codec.Name; 160 return true; 161 } 162 } 163 #ifdef EXTERNAL_CODECS 164 if (__externalCodecs) 165 for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) 166 { 167 const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; 168 if (methodId == codec.Id) 169 { 170 name = codec.Name; 171 return true; 172 } 173 } 174 #endif 175 return false; 176} 177 178bool FindHashMethod(DECL_EXTERNAL_CODECS_LOC_VARS 179 const UString &name, 180 CMethodId &methodId) 181{ 182 UInt32 i; 183 for (i = 0; i < g_NumHashers; i++) 184 { 185 const CHasherInfo &codec = *g_Hashers[i]; 186 if (name.IsEqualToNoCase(codec.Name)) 187 { 188 methodId = codec.Id; 189 return true; 190 } 191 } 192 #ifdef EXTERNAL_CODECS 193 if (__externalCodecs) 194 for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) 195 { 196 const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; 197 if (codec.Name.IsEqualToNoCase(name)) 198 { 199 methodId = codec.Id; 200 return true; 201 } 202 } 203 #endif 204 return false; 205} 206 207void GetHashMethods(DECL_EXTERNAL_CODECS_LOC_VARS 208 CRecordVector<CMethodId> &methods) 209{ 210 methods.ClearAndSetSize(g_NumHashers); 211 UInt32 i; 212 for (i = 0; i < g_NumHashers; i++) 213 methods[i] = (*g_Hashers[i]).Id; 214 #ifdef EXTERNAL_CODECS 215 if (__externalCodecs) 216 for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) 217 methods.Add(__externalCodecs->Hashers[i].Id); 218 #endif 219} 220 221HRESULT CreateCoder( 222 DECL_EXTERNAL_CODECS_LOC_VARS 223 CMethodId methodId, 224 CMyComPtr<ICompressFilter> &filter, 225 CMyComPtr<ICompressCoder> &coder, 226 CMyComPtr<ICompressCoder2> &coder2, 227 bool encode, bool onlyCoder) 228{ 229 UInt32 i; 230 for (i = 0; i < g_NumCodecs; i++) 231 { 232 const CCodecInfo &codec = *g_Codecs[i]; 233 if (codec.Id == methodId) 234 { 235 if (encode) 236 { 237 if (codec.CreateEncoder) 238 { 239 void *p = codec.CreateEncoder(); 240 if (codec.IsFilter) filter = (ICompressFilter *)p; 241 else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; 242 else coder2 = (ICompressCoder2 *)p; 243 break; 244 } 245 } 246 else 247 if (codec.CreateDecoder) 248 { 249 void *p = codec.CreateDecoder(); 250 if (codec.IsFilter) filter = (ICompressFilter *)p; 251 else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; 252 else coder2 = (ICompressCoder2 *)p; 253 break; 254 } 255 } 256 } 257 258 #ifdef EXTERNAL_CODECS 259 if (!filter && !coder && !coder2 && __externalCodecs) 260 for (i = 0; i < (UInt32)__externalCodecs->Codecs.Size(); i++) 261 { 262 const CCodecInfoEx &codec = __externalCodecs->Codecs[i]; 263 if (codec.Id == methodId) 264 { 265 if (encode) 266 { 267 if (codec.EncoderIsAssigned) 268 { 269 if (codec.IsSimpleCodec()) 270 { 271 HRESULT result = __externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); 272 if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) 273 return result; 274 if (!coder) 275 { 276 RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); 277 } 278 } 279 else 280 { 281 RINOK(__externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); 282 } 283 break; 284 } 285 } 286 else 287 if (codec.DecoderIsAssigned) 288 { 289 if (codec.IsSimpleCodec()) 290 { 291 HRESULT result = __externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); 292 if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) 293 return result; 294 if (!coder) 295 { 296 RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); 297 } 298 } 299 else 300 { 301 RINOK(__externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); 302 } 303 break; 304 } 305 } 306 } 307 #endif 308 309 if (onlyCoder && filter) 310 { 311 CFilterCoder *coderSpec = new CFilterCoder; 312 coder = coderSpec; 313 coderSpec->Filter = filter; 314 } 315 return S_OK; 316} 317 318HRESULT CreateCoder( 319 DECL_EXTERNAL_CODECS_LOC_VARS 320 CMethodId methodId, 321 CMyComPtr<ICompressCoder> &coder, 322 CMyComPtr<ICompressCoder2> &coder2, 323 bool encode) 324{ 325 CMyComPtr<ICompressFilter> filter; 326 return CreateCoder( 327 EXTERNAL_CODECS_LOC_VARS 328 methodId, 329 filter, coder, coder2, encode, true); 330} 331 332HRESULT CreateCoder( 333 DECL_EXTERNAL_CODECS_LOC_VARS 334 CMethodId methodId, 335 CMyComPtr<ICompressCoder> &coder, bool encode) 336{ 337 CMyComPtr<ICompressFilter> filter; 338 CMyComPtr<ICompressCoder2> coder2; 339 return CreateCoder( 340 EXTERNAL_CODECS_LOC_VARS 341 methodId, 342 coder, coder2, encode); 343} 344 345HRESULT CreateFilter( 346 DECL_EXTERNAL_CODECS_LOC_VARS 347 CMethodId methodId, 348 CMyComPtr<ICompressFilter> &filter, 349 bool encode) 350{ 351 CMyComPtr<ICompressCoder> coder; 352 CMyComPtr<ICompressCoder2> coder2; 353 return CreateCoder( 354 EXTERNAL_CODECS_LOC_VARS 355 methodId, 356 filter, coder, coder2, encode, false); 357} 358 359HRESULT CreateHasher( 360 DECL_EXTERNAL_CODECS_LOC_VARS 361 CMethodId methodId, 362 UString &name, 363 CMyComPtr<IHasher> &hasher) 364{ 365 UInt32 i; 366 for (i = 0; i < g_NumHashers; i++) 367 { 368 const CHasherInfo &codec = *g_Hashers[i]; 369 if (codec.Id == methodId) 370 { 371 hasher = (IHasher *)codec.CreateHasher(); 372 name = codec.Name; 373 break; 374 } 375 } 376 377 #ifdef EXTERNAL_CODECS 378 if (!hasher && __externalCodecs) 379 for (i = 0; i < (UInt32)__externalCodecs->Hashers.Size(); i++) 380 { 381 const CHasherInfoEx &codec = __externalCodecs->Hashers[i]; 382 if (codec.Id == methodId) 383 { 384 name = codec.Name; 385 return __externalCodecs->GetHashers->CreateHasher(i, &hasher); 386 } 387 } 388 #endif 389 390 return S_OK; 391} 392