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