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];
RegisterCodec(const CCodecInfo * codecInfo)16 void RegisterCodec(const CCodecInfo *codecInfo) throw()
17 {
18 if (g_NumCodecs < kNumCodecsMax)
19 g_Codecs[g_NumCodecs++] = codecInfo;
20 }
21
22 static const unsigned int kNumHashersMax = 16;
23 unsigned int g_NumHashers = 0;
24 const CHasherInfo *g_Hashers[kNumHashersMax];
RegisterHasher(const CHasherInfo * hashInfo)25 void RegisterHasher(const CHasherInfo *hashInfo) throw()
26 {
27 if (g_NumHashers < kNumHashersMax)
28 g_Hashers[g_NumHashers++] = hashInfo;
29 }
30
31 #ifdef EXTERNAL_CODECS
ReadNumberOfStreams(ICompressCodecsInfo * codecsInfo,UInt32 index,PROPID propID,UInt32 & res)32 static 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
ReadIsAssignedProp(ICompressCodecsInfo * codecsInfo,UInt32 index,PROPID propID,bool & res)45 static 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
LoadCodecs()58 HRESULT 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
FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS const UString & name,CMethodId & methodId,UInt32 & numInStreams,UInt32 & numOutStreams)118 bool 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
FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,UString & name)150 bool 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
FindHashMethod(DECL_EXTERNAL_CODECS_LOC_VARS const UString & name,CMethodId & methodId)178 bool 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
GetHashMethods(DECL_EXTERNAL_CODECS_LOC_VARS CRecordVector<CMethodId> & methods)207 void 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
CreateCoder(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,CMyComPtr<ICompressFilter> & filter,CMyComPtr<ICompressCoder> & coder,CMyComPtr<ICompressCoder2> & coder2,bool encode,bool onlyCoder)221 HRESULT 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
CreateCoder(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,CMyComPtr<ICompressCoder> & coder,CMyComPtr<ICompressCoder2> & coder2,bool encode)318 HRESULT 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
CreateCoder(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,CMyComPtr<ICompressCoder> & coder,bool encode)332 HRESULT 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
CreateFilter(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,CMyComPtr<ICompressFilter> & filter,bool encode)345 HRESULT 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
CreateHasher(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,UString & name,CMyComPtr<IHasher> & hasher)359 HRESULT 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