1// CreateCoder.cpp 2 3#include "StdAfx.h" 4 5#include "CreateCoder.h" 6 7#include "../../Windows/PropVariant.h" 8#include "../../Windows/Defs.h" 9#include "FilterCoder.h" 10#include "RegisterCodec.h" 11 12static const unsigned int kNumCodecsMax = 64; 13unsigned int g_NumCodecs = 0; 14const CCodecInfo *g_Codecs[kNumCodecsMax]; 15void RegisterCodec(const CCodecInfo *codecInfo) 16{ 17 if (g_NumCodecs < kNumCodecsMax) 18 g_Codecs[g_NumCodecs++] = codecInfo; 19} 20 21#ifdef EXTERNAL_CODECS 22static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res) 23{ 24 NWindows::NCOM::CPropVariant prop; 25 RINOK(codecsInfo->GetProperty(index, propID, &prop)); 26 if (prop.vt == VT_EMPTY) 27 res = 1; 28 else if (prop.vt == VT_UI4) 29 res = prop.ulVal; 30 else 31 return E_INVALIDARG; 32 return S_OK; 33} 34 35static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res) 36{ 37 NWindows::NCOM::CPropVariant prop; 38 RINOK(codecsInfo->GetProperty(index, propID, &prop)); 39 if (prop.vt == VT_EMPTY) 40 res = true; 41 else if (prop.vt == VT_BOOL) 42 res = VARIANT_BOOLToBool(prop.boolVal); 43 else 44 return E_INVALIDARG; 45 return S_OK; 46} 47 48HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs) 49{ 50 UInt32 num; 51 RINOK(codecsInfo->GetNumberOfMethods(&num)); 52 for (UInt32 i = 0; i < num; i++) 53 { 54 CCodecInfoEx info; 55 NWindows::NCOM::CPropVariant prop; 56 RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop)); 57 // if (prop.vt != VT_BSTR) 58 // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal); 59 // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize); 60 if (prop.vt != VT_UI8) 61 { 62 continue; // old Interface 63 // return E_INVALIDARG; 64 } 65 info.Id = prop.uhVal.QuadPart; 66 prop.Clear(); 67 68 RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop)); 69 if (prop.vt == VT_BSTR) 70 info.Name = prop.bstrVal; 71 else if (prop.vt != VT_EMPTY) 72 return E_INVALIDARG;; 73 74 RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams)); 75 RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams)); 76 RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned)); 77 RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned)); 78 79 externalCodecs.Add(info); 80 } 81 return S_OK; 82} 83 84#endif 85 86bool FindMethod( 87 #ifdef EXTERNAL_CODECS 88 ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, 89 #endif 90 const UString &name, 91 CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams) 92{ 93 UInt32 i; 94 for (i = 0; i < g_NumCodecs; i++) 95 { 96 const CCodecInfo &codec = *g_Codecs[i]; 97 if (name.CompareNoCase(codec.Name) == 0) 98 { 99 methodId = codec.Id; 100 numInStreams = codec.NumInStreams; 101 numOutStreams = 1; 102 return true; 103 } 104 } 105 #ifdef EXTERNAL_CODECS 106 if (externalCodecs) 107 for (i = 0; i < (UInt32)externalCodecs->Size(); i++) 108 { 109 const CCodecInfoEx &codec = (*externalCodecs)[i]; 110 if (codec.Name.CompareNoCase(name) == 0) 111 { 112 methodId = codec.Id; 113 numInStreams = codec.NumInStreams; 114 numOutStreams = codec.NumOutStreams; 115 return true; 116 } 117 } 118 #endif 119 return false; 120} 121 122bool FindMethod( 123 #ifdef EXTERNAL_CODECS 124 ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs, 125 #endif 126 CMethodId methodId, UString &name) 127{ 128 UInt32 i; 129 for (i = 0; i < g_NumCodecs; i++) 130 { 131 const CCodecInfo &codec = *g_Codecs[i]; 132 if (methodId == codec.Id) 133 { 134 name = codec.Name; 135 return true; 136 } 137 } 138 #ifdef EXTERNAL_CODECS 139 if (externalCodecs) 140 for (i = 0; i < (UInt32)externalCodecs->Size(); i++) 141 { 142 const CCodecInfoEx &codec = (*externalCodecs)[i]; 143 if (methodId == codec.Id) 144 { 145 name = codec.Name; 146 return true; 147 } 148 } 149 #endif 150 return false; 151} 152 153HRESULT CreateCoder( 154 DECL_EXTERNAL_CODECS_LOC_VARS 155 CMethodId methodId, 156 CMyComPtr<ICompressFilter> &filter, 157 CMyComPtr<ICompressCoder> &coder, 158 CMyComPtr<ICompressCoder2> &coder2, 159 bool encode, bool onlyCoder) 160{ 161 bool created = false; 162 UInt32 i; 163 for (i = 0; i < g_NumCodecs; i++) 164 { 165 const CCodecInfo &codec = *g_Codecs[i]; 166 if (codec.Id == methodId) 167 { 168 if (encode) 169 { 170 if (codec.CreateEncoder) 171 { 172 void *p = codec.CreateEncoder(); 173 if (codec.IsFilter) filter = (ICompressFilter *)p; 174 else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; 175 else coder2 = (ICompressCoder2 *)p; 176 created = (p != 0); 177 break; 178 } 179 } 180 else 181 if (codec.CreateDecoder) 182 { 183 void *p = codec.CreateDecoder(); 184 if (codec.IsFilter) filter = (ICompressFilter *)p; 185 else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p; 186 else coder2 = (ICompressCoder2 *)p; 187 created = (p != 0); 188 break; 189 } 190 } 191 } 192 193 #ifdef EXTERNAL_CODECS 194 if (!created && externalCodecs) 195 for (i = 0; i < (UInt32)externalCodecs->Size(); i++) 196 { 197 const CCodecInfoEx &codec = (*externalCodecs)[i]; 198 if (codec.Id == methodId) 199 { 200 if (encode) 201 { 202 if (codec.EncoderIsAssigned) 203 { 204 if (codec.IsSimpleCodec()) 205 { 206 HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder); 207 if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) 208 return result; 209 if (!coder) 210 { 211 RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter)); 212 } 213 } 214 else 215 { 216 RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2)); 217 } 218 break; 219 } 220 } 221 else 222 if (codec.DecoderIsAssigned) 223 { 224 if (codec.IsSimpleCodec()) 225 { 226 HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder); 227 if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) 228 return result; 229 if (!coder) 230 { 231 RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter)); 232 } 233 } 234 else 235 { 236 RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2)); 237 } 238 break; 239 } 240 } 241 } 242 #endif 243 244 if (onlyCoder && filter) 245 { 246 CFilterCoder *coderSpec = new CFilterCoder; 247 coder = coderSpec; 248 coderSpec->Filter = filter; 249 } 250 return S_OK; 251} 252 253HRESULT CreateCoder( 254 DECL_EXTERNAL_CODECS_LOC_VARS 255 CMethodId methodId, 256 CMyComPtr<ICompressCoder> &coder, 257 CMyComPtr<ICompressCoder2> &coder2, 258 bool encode) 259{ 260 CMyComPtr<ICompressFilter> filter; 261 return CreateCoder( 262 EXTERNAL_CODECS_LOC_VARS 263 methodId, 264 filter, coder, coder2, encode, true); 265} 266 267HRESULT CreateCoder( 268 DECL_EXTERNAL_CODECS_LOC_VARS 269 CMethodId methodId, 270 CMyComPtr<ICompressCoder> &coder, bool encode) 271{ 272 CMyComPtr<ICompressFilter> filter; 273 CMyComPtr<ICompressCoder2> coder2; 274 return CreateCoder( 275 EXTERNAL_CODECS_LOC_VARS 276 methodId, 277 coder, coder2, encode); 278} 279 280HRESULT CreateFilter( 281 DECL_EXTERNAL_CODECS_LOC_VARS 282 CMethodId methodId, 283 CMyComPtr<ICompressFilter> &filter, 284 bool encode) 285{ 286 CMyComPtr<ICompressCoder> coder; 287 CMyComPtr<ICompressCoder2> coder2; 288 return CreateCoder( 289 EXTERNAL_CODECS_LOC_VARS 290 methodId, 291 filter, coder, coder2, encode, false); 292} 293