• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 kNumCodecsMax = 64;
14 extern
15 unsigned g_NumCodecs;
16 unsigned g_NumCodecs = 0;
17 extern
18 const CCodecInfo *g_Codecs[];
19 const CCodecInfo *g_Codecs[kNumCodecsMax];
20 
21 // We use g_ExternalCodecs in other stages.
22 #ifdef Z7_EXTERNAL_CODECS
23 /*
24 extern CExternalCodecs g_ExternalCodecs;
25 #define CHECK_GLOBAL_CODECS \
26     if (!_externalCodecs || !_externalCodecs->IsSet()) _externalCodecs = &g_ExternalCodecs;
27 */
28 #define CHECK_GLOBAL_CODECS
29 #endif
30 
31 
RegisterCodec(const CCodecInfo * codecInfo)32 void RegisterCodec(const CCodecInfo *codecInfo) throw()
33 {
34   if (g_NumCodecs < kNumCodecsMax)
35     g_Codecs[g_NumCodecs++] = codecInfo;
36 }
37 
38 static const unsigned kNumHashersMax = 16;
39 extern
40 unsigned g_NumHashers;
41 unsigned g_NumHashers = 0;
42 extern
43 const CHasherInfo *g_Hashers[];
44 const CHasherInfo *g_Hashers[kNumHashersMax];
45 
RegisterHasher(const CHasherInfo * hashInfo)46 void RegisterHasher(const CHasherInfo *hashInfo) throw()
47 {
48   if (g_NumHashers < kNumHashersMax)
49     g_Hashers[g_NumHashers++] = hashInfo;
50 }
51 
52 
53 #ifdef Z7_EXTERNAL_CODECS
54 
ReadNumberOfStreams(ICompressCodecsInfo * codecsInfo,UInt32 index,PROPID propID,UInt32 & res)55 static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)
56 {
57   NWindows::NCOM::CPropVariant prop;
58   RINOK(codecsInfo->GetProperty(index, propID, &prop))
59   if (prop.vt == VT_EMPTY)
60     res = 1;
61   else if (prop.vt == VT_UI4)
62     res = prop.ulVal;
63   else
64     return E_INVALIDARG;
65   return S_OK;
66 }
67 
ReadIsAssignedProp(ICompressCodecsInfo * codecsInfo,UInt32 index,PROPID propID,bool & res)68 static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)
69 {
70   NWindows::NCOM::CPropVariant prop;
71   RINOK(codecsInfo->GetProperty(index, propID, &prop))
72   if (prop.vt == VT_EMPTY)
73     res = true;
74   else if (prop.vt == VT_BOOL)
75     res = VARIANT_BOOLToBool(prop.boolVal);
76   else
77     return E_INVALIDARG;
78   return S_OK;
79 }
80 
Load()81 HRESULT CExternalCodecs::Load()
82 {
83   Codecs.Clear();
84   Hashers.Clear();
85 
86   if (GetCodecs)
87   {
88     CCodecInfoEx info;
89 
90     UString s;
91     UInt32 num;
92     RINOK(GetCodecs->GetNumMethods(&num))
93 
94     for (UInt32 i = 0; i < num; i++)
95     {
96       NWindows::NCOM::CPropVariant prop;
97 
98       RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop))
99       if (prop.vt != VT_UI8)
100         continue; // old Interface
101       info.Id = prop.uhVal.QuadPart;
102 
103       prop.Clear();
104 
105       info.Name.Empty();
106       RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop))
107       if (prop.vt == VT_BSTR)
108         info.Name.SetFromWStr_if_Ascii(prop.bstrVal);
109       else if (prop.vt != VT_EMPTY)
110         continue;
111 
112       RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams))
113       {
114         UInt32 numUnpackStreams = 1;
115         RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams))
116         if (numUnpackStreams != 1)
117           continue;
118       }
119       RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned))
120       RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned))
121       RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kIsFilter, info.IsFilter))
122 
123       Codecs.Add(info);
124     }
125   }
126 
127   if (GetHashers)
128   {
129     UInt32 num = GetHashers->GetNumHashers();
130     CHasherInfoEx info;
131 
132     for (UInt32 i = 0; i < num; i++)
133     {
134       NWindows::NCOM::CPropVariant prop;
135 
136       RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop))
137       if (prop.vt != VT_UI8)
138         continue;
139       info.Id = prop.uhVal.QuadPart;
140 
141       prop.Clear();
142 
143       info.Name.Empty();
144       RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop))
145       if (prop.vt == VT_BSTR)
146         info.Name.SetFromWStr_if_Ascii(prop.bstrVal);
147       else if (prop.vt != VT_EMPTY)
148         continue;
149 
150       Hashers.Add(info);
151     }
152   }
153 
154   return S_OK;
155 }
156 
157 #endif
158 
159 
FindMethod_Index(DECL_EXTERNAL_CODECS_LOC_VARS const AString & name,bool encode,CMethodId & methodId,UInt32 & numStreams,bool & isFilter)160 int FindMethod_Index(
161     DECL_EXTERNAL_CODECS_LOC_VARS
162     const AString &name,
163     bool encode,
164     CMethodId &methodId,
165     UInt32 &numStreams,
166     bool &isFilter)
167 {
168   unsigned i;
169   for (i = 0; i < g_NumCodecs; i++)
170   {
171     const CCodecInfo &codec = *g_Codecs[i];
172     if ((encode ? codec.CreateEncoder : codec.CreateDecoder)
173         && StringsAreEqualNoCase_Ascii(name, codec.Name))
174     {
175       methodId = codec.Id;
176       numStreams = codec.NumStreams;
177       isFilter = codec.IsFilter;
178       return (int)i;
179     }
180   }
181 
182   #ifdef Z7_EXTERNAL_CODECS
183 
184   CHECK_GLOBAL_CODECS
185 
186   if (_externalCodecs)
187     for (i = 0; i < _externalCodecs->Codecs.Size(); i++)
188     {
189       const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
190       if ((encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)
191           && StringsAreEqualNoCase_Ascii(name, codec.Name))
192       {
193         methodId = codec.Id;
194         numStreams = codec.NumStreams;
195         isFilter = codec.IsFilter;
196         return (int)(g_NumCodecs + i);
197       }
198     }
199 
200   #endif
201 
202   return -1;
203 }
204 
205 
FindMethod_Index(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,bool encode)206 static int FindMethod_Index(
207     DECL_EXTERNAL_CODECS_LOC_VARS
208     CMethodId methodId, bool encode)
209 {
210   unsigned i;
211   for (i = 0; i < g_NumCodecs; i++)
212   {
213     const CCodecInfo &codec = *g_Codecs[i];
214     if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder))
215       return (int)i;
216   }
217 
218   #ifdef Z7_EXTERNAL_CODECS
219 
220   CHECK_GLOBAL_CODECS
221 
222   if (_externalCodecs)
223     for (i = 0; i < _externalCodecs->Codecs.Size(); i++)
224     {
225       const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
226       if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned))
227         return (int)(g_NumCodecs + i);
228     }
229 
230   #endif
231 
232   return -1;
233 }
234 
235 
FindMethod(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,AString & name)236 bool FindMethod(
237     DECL_EXTERNAL_CODECS_LOC_VARS
238     CMethodId methodId,
239     AString &name)
240 {
241   name.Empty();
242 
243   unsigned i;
244   for (i = 0; i < g_NumCodecs; i++)
245   {
246     const CCodecInfo &codec = *g_Codecs[i];
247     if (methodId == codec.Id)
248     {
249       name = codec.Name;
250       return true;
251     }
252   }
253 
254   #ifdef Z7_EXTERNAL_CODECS
255 
256   CHECK_GLOBAL_CODECS
257 
258   if (_externalCodecs)
259     for (i = 0; i < _externalCodecs->Codecs.Size(); i++)
260     {
261       const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
262       if (methodId == codec.Id)
263       {
264         name = codec.Name;
265         return true;
266       }
267     }
268 
269   #endif
270 
271   return false;
272 }
273 
FindHashMethod(DECL_EXTERNAL_CODECS_LOC_VARS const AString & name,CMethodId & methodId)274 bool FindHashMethod(
275     DECL_EXTERNAL_CODECS_LOC_VARS
276     const AString &name,
277     CMethodId &methodId)
278 {
279   unsigned i;
280   for (i = 0; i < g_NumHashers; i++)
281   {
282     const CHasherInfo &codec = *g_Hashers[i];
283     if (StringsAreEqualNoCase_Ascii(name, codec.Name))
284     {
285       methodId = codec.Id;
286       return true;
287     }
288   }
289 
290   #ifdef Z7_EXTERNAL_CODECS
291 
292   CHECK_GLOBAL_CODECS
293 
294   if (_externalCodecs)
295     for (i = 0; i < _externalCodecs->Hashers.Size(); i++)
296     {
297       const CHasherInfoEx &codec = _externalCodecs->Hashers[i];
298       if (StringsAreEqualNoCase_Ascii(name, codec.Name))
299       {
300         methodId = codec.Id;
301         return true;
302       }
303     }
304 
305   #endif
306 
307   return false;
308 }
309 
GetHashMethods(DECL_EXTERNAL_CODECS_LOC_VARS CRecordVector<CMethodId> & methods)310 void GetHashMethods(
311     DECL_EXTERNAL_CODECS_LOC_VARS
312     CRecordVector<CMethodId> &methods)
313 {
314   methods.ClearAndSetSize(g_NumHashers);
315   unsigned i;
316   for (i = 0; i < g_NumHashers; i++)
317     methods[i] = (*g_Hashers[i]).Id;
318 
319   #ifdef Z7_EXTERNAL_CODECS
320 
321   CHECK_GLOBAL_CODECS
322 
323   if (_externalCodecs)
324     for (i = 0; i < _externalCodecs->Hashers.Size(); i++)
325       methods.Add(_externalCodecs->Hashers[i].Id);
326 
327   #endif
328 }
329 
330 
331 
CreateCoder_Index(DECL_EXTERNAL_CODECS_LOC_VARS unsigned i,bool encode,CMyComPtr<ICompressFilter> & filter,CCreatedCoder & cod)332 HRESULT CreateCoder_Index(
333     DECL_EXTERNAL_CODECS_LOC_VARS
334     unsigned i, bool encode,
335     CMyComPtr<ICompressFilter> &filter,
336     CCreatedCoder &cod)
337 {
338   cod.IsExternal = false;
339   cod.IsFilter = false;
340   cod.NumStreams = 1;
341 
342   if (i < g_NumCodecs)
343   {
344     const CCodecInfo &codec = *g_Codecs[i];
345     // if (codec.Id == methodId)
346     {
347       if (encode)
348       {
349         if (codec.CreateEncoder)
350         {
351           void *p = codec.CreateEncoder();
352           if (codec.IsFilter) filter = (ICompressFilter *)p;
353           else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;
354           else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }
355           return S_OK;
356         }
357       }
358       else
359         if (codec.CreateDecoder)
360         {
361           void *p = codec.CreateDecoder();
362           if (codec.IsFilter) filter = (ICompressFilter *)p;
363           else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;
364           else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }
365           return S_OK;
366         }
367     }
368   }
369 
370   #ifdef Z7_EXTERNAL_CODECS
371 
372   CHECK_GLOBAL_CODECS
373 
374   if (_externalCodecs)
375   {
376     i -= g_NumCodecs;
377     cod.IsExternal = true;
378     if (i < _externalCodecs->Codecs.Size())
379     {
380       const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
381       // if (codec.Id == methodId)
382       {
383         if (encode)
384         {
385           if (codec.EncoderIsAssigned)
386           {
387             if (codec.NumStreams == 1)
388             {
389               const HRESULT res = _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
390               if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)
391                 return res;
392               if (cod.Coder)
393                 return res;
394               return _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter);
395             }
396             cod.NumStreams = codec.NumStreams;
397             return _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
398           }
399         }
400         else
401           if (codec.DecoderIsAssigned)
402           {
403             if (codec.NumStreams == 1)
404             {
405               const HRESULT res = _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
406               if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)
407                 return res;
408               if (cod.Coder)
409                 return res;
410               return _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter);
411             }
412             cod.NumStreams = codec.NumStreams;
413             return _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
414           }
415       }
416     }
417   }
418   #endif
419 
420   return S_OK;
421 }
422 
423 
CreateCoder_Index(DECL_EXTERNAL_CODECS_LOC_VARS unsigned index,bool encode,CCreatedCoder & cod)424 HRESULT CreateCoder_Index(
425     DECL_EXTERNAL_CODECS_LOC_VARS
426     unsigned index, bool encode,
427     CCreatedCoder &cod)
428 {
429   CMyComPtr<ICompressFilter> filter;
430   const HRESULT res = CreateCoder_Index(
431       EXTERNAL_CODECS_LOC_VARS
432       index, encode,
433       filter, cod);
434 
435   if (filter)
436   {
437     cod.IsFilter = true;
438     CFilterCoder *coderSpec = new CFilterCoder(encode);
439     cod.Coder = coderSpec;
440     coderSpec->Filter = filter;
441   }
442 
443   return res;
444 }
445 
446 
CreateCoder_Id(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,bool encode,CMyComPtr<ICompressFilter> & filter,CCreatedCoder & cod)447 HRESULT CreateCoder_Id(
448     DECL_EXTERNAL_CODECS_LOC_VARS
449     CMethodId methodId, bool encode,
450     CMyComPtr<ICompressFilter> &filter,
451     CCreatedCoder &cod)
452 {
453   const int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode);
454   if (index < 0)
455     return S_OK;
456   return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)index, encode, filter, cod);
457 }
458 
459 
CreateCoder_Id(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,bool encode,CCreatedCoder & cod)460 HRESULT CreateCoder_Id(
461     DECL_EXTERNAL_CODECS_LOC_VARS
462     CMethodId methodId, bool encode,
463     CCreatedCoder &cod)
464 {
465   CMyComPtr<ICompressFilter> filter;
466   const HRESULT res = CreateCoder_Id(
467       EXTERNAL_CODECS_LOC_VARS
468       methodId, encode,
469       filter, cod);
470 
471   if (filter)
472   {
473     cod.IsFilter = true;
474     CFilterCoder *coderSpec = new CFilterCoder(encode);
475     cod.Coder = coderSpec;
476     coderSpec->Filter = filter;
477   }
478 
479   return res;
480 }
481 
482 
CreateCoder_Id(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,bool encode,CMyComPtr<ICompressCoder> & coder)483 HRESULT CreateCoder_Id(
484     DECL_EXTERNAL_CODECS_LOC_VARS
485     CMethodId methodId, bool encode,
486     CMyComPtr<ICompressCoder> &coder)
487 {
488   CCreatedCoder cod;
489   const HRESULT res = CreateCoder_Id(
490       EXTERNAL_CODECS_LOC_VARS
491       methodId, encode,
492       cod);
493   coder = cod.Coder;
494   return res;
495 }
496 
CreateFilter(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,bool encode,CMyComPtr<ICompressFilter> & filter)497 HRESULT CreateFilter(
498     DECL_EXTERNAL_CODECS_LOC_VARS
499     CMethodId methodId, bool encode,
500     CMyComPtr<ICompressFilter> &filter)
501 {
502   CCreatedCoder cod;
503   return CreateCoder_Id(
504       EXTERNAL_CODECS_LOC_VARS
505       methodId, encode,
506       filter, cod);
507 }
508 
509 
CreateHasher(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,AString & name,CMyComPtr<IHasher> & hasher)510 HRESULT CreateHasher(
511     DECL_EXTERNAL_CODECS_LOC_VARS
512     CMethodId methodId,
513     AString &name,
514     CMyComPtr<IHasher> &hasher)
515 {
516   name.Empty();
517 
518   unsigned i;
519   for (i = 0; i < g_NumHashers; i++)
520   {
521     const CHasherInfo &codec = *g_Hashers[i];
522     if (codec.Id == methodId)
523     {
524       hasher = codec.CreateHasher();
525       name = codec.Name;
526       break;
527     }
528   }
529 
530   #ifdef Z7_EXTERNAL_CODECS
531 
532   CHECK_GLOBAL_CODECS
533 
534   if (!hasher && _externalCodecs)
535     for (i = 0; i < _externalCodecs->Hashers.Size(); i++)
536     {
537       const CHasherInfoEx &codec = _externalCodecs->Hashers[i];
538       if (codec.Id == methodId)
539       {
540         name = codec.Name;
541         return _externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher);
542       }
543     }
544 
545   #endif
546 
547   return S_OK;
548 }
549