1370b324cSopenharmony_ci// CreateCoder.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../Windows/Defs.h"
6370b324cSopenharmony_ci#include "../../Windows/PropVariant.h"
7370b324cSopenharmony_ci
8370b324cSopenharmony_ci#include "CreateCoder.h"
9370b324cSopenharmony_ci
10370b324cSopenharmony_ci#include "FilterCoder.h"
11370b324cSopenharmony_ci#include "RegisterCodec.h"
12370b324cSopenharmony_ci
13370b324cSopenharmony_cistatic const unsigned kNumCodecsMax = 64;
14370b324cSopenharmony_ciextern
15370b324cSopenharmony_ciunsigned g_NumCodecs;
16370b324cSopenharmony_ciunsigned g_NumCodecs = 0;
17370b324cSopenharmony_ciextern
18370b324cSopenharmony_ciconst CCodecInfo *g_Codecs[];
19370b324cSopenharmony_ciconst CCodecInfo *g_Codecs[kNumCodecsMax];
20370b324cSopenharmony_ci
21370b324cSopenharmony_ci// We use g_ExternalCodecs in other stages.
22370b324cSopenharmony_ci#ifdef Z7_EXTERNAL_CODECS
23370b324cSopenharmony_ci/*
24370b324cSopenharmony_ciextern CExternalCodecs g_ExternalCodecs;
25370b324cSopenharmony_ci#define CHECK_GLOBAL_CODECS \
26370b324cSopenharmony_ci    if (!_externalCodecs || !_externalCodecs->IsSet()) _externalCodecs = &g_ExternalCodecs;
27370b324cSopenharmony_ci*/
28370b324cSopenharmony_ci#define CHECK_GLOBAL_CODECS
29370b324cSopenharmony_ci#endif
30370b324cSopenharmony_ci
31370b324cSopenharmony_ci
32370b324cSopenharmony_civoid RegisterCodec(const CCodecInfo *codecInfo) throw()
33370b324cSopenharmony_ci{
34370b324cSopenharmony_ci  if (g_NumCodecs < kNumCodecsMax)
35370b324cSopenharmony_ci    g_Codecs[g_NumCodecs++] = codecInfo;
36370b324cSopenharmony_ci}
37370b324cSopenharmony_ci
38370b324cSopenharmony_cistatic const unsigned kNumHashersMax = 16;
39370b324cSopenharmony_ciextern
40370b324cSopenharmony_ciunsigned g_NumHashers;
41370b324cSopenharmony_ciunsigned g_NumHashers = 0;
42370b324cSopenharmony_ciextern
43370b324cSopenharmony_ciconst CHasherInfo *g_Hashers[];
44370b324cSopenharmony_ciconst CHasherInfo *g_Hashers[kNumHashersMax];
45370b324cSopenharmony_ci
46370b324cSopenharmony_civoid RegisterHasher(const CHasherInfo *hashInfo) throw()
47370b324cSopenharmony_ci{
48370b324cSopenharmony_ci  if (g_NumHashers < kNumHashersMax)
49370b324cSopenharmony_ci    g_Hashers[g_NumHashers++] = hashInfo;
50370b324cSopenharmony_ci}
51370b324cSopenharmony_ci
52370b324cSopenharmony_ci
53370b324cSopenharmony_ci#ifdef Z7_EXTERNAL_CODECS
54370b324cSopenharmony_ci
55370b324cSopenharmony_cistatic HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)
56370b324cSopenharmony_ci{
57370b324cSopenharmony_ci  NWindows::NCOM::CPropVariant prop;
58370b324cSopenharmony_ci  RINOK(codecsInfo->GetProperty(index, propID, &prop))
59370b324cSopenharmony_ci  if (prop.vt == VT_EMPTY)
60370b324cSopenharmony_ci    res = 1;
61370b324cSopenharmony_ci  else if (prop.vt == VT_UI4)
62370b324cSopenharmony_ci    res = prop.ulVal;
63370b324cSopenharmony_ci  else
64370b324cSopenharmony_ci    return E_INVALIDARG;
65370b324cSopenharmony_ci  return S_OK;
66370b324cSopenharmony_ci}
67370b324cSopenharmony_ci
68370b324cSopenharmony_cistatic HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)
69370b324cSopenharmony_ci{
70370b324cSopenharmony_ci  NWindows::NCOM::CPropVariant prop;
71370b324cSopenharmony_ci  RINOK(codecsInfo->GetProperty(index, propID, &prop))
72370b324cSopenharmony_ci  if (prop.vt == VT_EMPTY)
73370b324cSopenharmony_ci    res = true;
74370b324cSopenharmony_ci  else if (prop.vt == VT_BOOL)
75370b324cSopenharmony_ci    res = VARIANT_BOOLToBool(prop.boolVal);
76370b324cSopenharmony_ci  else
77370b324cSopenharmony_ci    return E_INVALIDARG;
78370b324cSopenharmony_ci  return S_OK;
79370b324cSopenharmony_ci}
80370b324cSopenharmony_ci
81370b324cSopenharmony_ciHRESULT CExternalCodecs::Load()
82370b324cSopenharmony_ci{
83370b324cSopenharmony_ci  Codecs.Clear();
84370b324cSopenharmony_ci  Hashers.Clear();
85370b324cSopenharmony_ci
86370b324cSopenharmony_ci  if (GetCodecs)
87370b324cSopenharmony_ci  {
88370b324cSopenharmony_ci    CCodecInfoEx info;
89370b324cSopenharmony_ci
90370b324cSopenharmony_ci    UString s;
91370b324cSopenharmony_ci    UInt32 num;
92370b324cSopenharmony_ci    RINOK(GetCodecs->GetNumMethods(&num))
93370b324cSopenharmony_ci
94370b324cSopenharmony_ci    for (UInt32 i = 0; i < num; i++)
95370b324cSopenharmony_ci    {
96370b324cSopenharmony_ci      NWindows::NCOM::CPropVariant prop;
97370b324cSopenharmony_ci
98370b324cSopenharmony_ci      RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop))
99370b324cSopenharmony_ci      if (prop.vt != VT_UI8)
100370b324cSopenharmony_ci        continue; // old Interface
101370b324cSopenharmony_ci      info.Id = prop.uhVal.QuadPart;
102370b324cSopenharmony_ci
103370b324cSopenharmony_ci      prop.Clear();
104370b324cSopenharmony_ci
105370b324cSopenharmony_ci      info.Name.Empty();
106370b324cSopenharmony_ci      RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop))
107370b324cSopenharmony_ci      if (prop.vt == VT_BSTR)
108370b324cSopenharmony_ci        info.Name.SetFromWStr_if_Ascii(prop.bstrVal);
109370b324cSopenharmony_ci      else if (prop.vt != VT_EMPTY)
110370b324cSopenharmony_ci        continue;
111370b324cSopenharmony_ci
112370b324cSopenharmony_ci      RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams))
113370b324cSopenharmony_ci      {
114370b324cSopenharmony_ci        UInt32 numUnpackStreams = 1;
115370b324cSopenharmony_ci        RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams))
116370b324cSopenharmony_ci        if (numUnpackStreams != 1)
117370b324cSopenharmony_ci          continue;
118370b324cSopenharmony_ci      }
119370b324cSopenharmony_ci      RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned))
120370b324cSopenharmony_ci      RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned))
121370b324cSopenharmony_ci      RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kIsFilter, info.IsFilter))
122370b324cSopenharmony_ci
123370b324cSopenharmony_ci      Codecs.Add(info);
124370b324cSopenharmony_ci    }
125370b324cSopenharmony_ci  }
126370b324cSopenharmony_ci
127370b324cSopenharmony_ci  if (GetHashers)
128370b324cSopenharmony_ci  {
129370b324cSopenharmony_ci    UInt32 num = GetHashers->GetNumHashers();
130370b324cSopenharmony_ci    CHasherInfoEx info;
131370b324cSopenharmony_ci
132370b324cSopenharmony_ci    for (UInt32 i = 0; i < num; i++)
133370b324cSopenharmony_ci    {
134370b324cSopenharmony_ci      NWindows::NCOM::CPropVariant prop;
135370b324cSopenharmony_ci
136370b324cSopenharmony_ci      RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop))
137370b324cSopenharmony_ci      if (prop.vt != VT_UI8)
138370b324cSopenharmony_ci        continue;
139370b324cSopenharmony_ci      info.Id = prop.uhVal.QuadPart;
140370b324cSopenharmony_ci
141370b324cSopenharmony_ci      prop.Clear();
142370b324cSopenharmony_ci
143370b324cSopenharmony_ci      info.Name.Empty();
144370b324cSopenharmony_ci      RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop))
145370b324cSopenharmony_ci      if (prop.vt == VT_BSTR)
146370b324cSopenharmony_ci        info.Name.SetFromWStr_if_Ascii(prop.bstrVal);
147370b324cSopenharmony_ci      else if (prop.vt != VT_EMPTY)
148370b324cSopenharmony_ci        continue;
149370b324cSopenharmony_ci
150370b324cSopenharmony_ci      Hashers.Add(info);
151370b324cSopenharmony_ci    }
152370b324cSopenharmony_ci  }
153370b324cSopenharmony_ci
154370b324cSopenharmony_ci  return S_OK;
155370b324cSopenharmony_ci}
156370b324cSopenharmony_ci
157370b324cSopenharmony_ci#endif
158370b324cSopenharmony_ci
159370b324cSopenharmony_ci
160370b324cSopenharmony_ciint FindMethod_Index(
161370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
162370b324cSopenharmony_ci    const AString &name,
163370b324cSopenharmony_ci    bool encode,
164370b324cSopenharmony_ci    CMethodId &methodId,
165370b324cSopenharmony_ci    UInt32 &numStreams,
166370b324cSopenharmony_ci    bool &isFilter)
167370b324cSopenharmony_ci{
168370b324cSopenharmony_ci  unsigned i;
169370b324cSopenharmony_ci  for (i = 0; i < g_NumCodecs; i++)
170370b324cSopenharmony_ci  {
171370b324cSopenharmony_ci    const CCodecInfo &codec = *g_Codecs[i];
172370b324cSopenharmony_ci    if ((encode ? codec.CreateEncoder : codec.CreateDecoder)
173370b324cSopenharmony_ci        && StringsAreEqualNoCase_Ascii(name, codec.Name))
174370b324cSopenharmony_ci    {
175370b324cSopenharmony_ci      methodId = codec.Id;
176370b324cSopenharmony_ci      numStreams = codec.NumStreams;
177370b324cSopenharmony_ci      isFilter = codec.IsFilter;
178370b324cSopenharmony_ci      return (int)i;
179370b324cSopenharmony_ci    }
180370b324cSopenharmony_ci  }
181370b324cSopenharmony_ci
182370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
183370b324cSopenharmony_ci
184370b324cSopenharmony_ci  CHECK_GLOBAL_CODECS
185370b324cSopenharmony_ci
186370b324cSopenharmony_ci  if (_externalCodecs)
187370b324cSopenharmony_ci    for (i = 0; i < _externalCodecs->Codecs.Size(); i++)
188370b324cSopenharmony_ci    {
189370b324cSopenharmony_ci      const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
190370b324cSopenharmony_ci      if ((encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)
191370b324cSopenharmony_ci          && StringsAreEqualNoCase_Ascii(name, codec.Name))
192370b324cSopenharmony_ci      {
193370b324cSopenharmony_ci        methodId = codec.Id;
194370b324cSopenharmony_ci        numStreams = codec.NumStreams;
195370b324cSopenharmony_ci        isFilter = codec.IsFilter;
196370b324cSopenharmony_ci        return (int)(g_NumCodecs + i);
197370b324cSopenharmony_ci      }
198370b324cSopenharmony_ci    }
199370b324cSopenharmony_ci
200370b324cSopenharmony_ci  #endif
201370b324cSopenharmony_ci
202370b324cSopenharmony_ci  return -1;
203370b324cSopenharmony_ci}
204370b324cSopenharmony_ci
205370b324cSopenharmony_ci
206370b324cSopenharmony_cistatic int FindMethod_Index(
207370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
208370b324cSopenharmony_ci    CMethodId methodId, bool encode)
209370b324cSopenharmony_ci{
210370b324cSopenharmony_ci  unsigned i;
211370b324cSopenharmony_ci  for (i = 0; i < g_NumCodecs; i++)
212370b324cSopenharmony_ci  {
213370b324cSopenharmony_ci    const CCodecInfo &codec = *g_Codecs[i];
214370b324cSopenharmony_ci    if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder))
215370b324cSopenharmony_ci      return (int)i;
216370b324cSopenharmony_ci  }
217370b324cSopenharmony_ci
218370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
219370b324cSopenharmony_ci
220370b324cSopenharmony_ci  CHECK_GLOBAL_CODECS
221370b324cSopenharmony_ci
222370b324cSopenharmony_ci  if (_externalCodecs)
223370b324cSopenharmony_ci    for (i = 0; i < _externalCodecs->Codecs.Size(); i++)
224370b324cSopenharmony_ci    {
225370b324cSopenharmony_ci      const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
226370b324cSopenharmony_ci      if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned))
227370b324cSopenharmony_ci        return (int)(g_NumCodecs + i);
228370b324cSopenharmony_ci    }
229370b324cSopenharmony_ci
230370b324cSopenharmony_ci  #endif
231370b324cSopenharmony_ci
232370b324cSopenharmony_ci  return -1;
233370b324cSopenharmony_ci}
234370b324cSopenharmony_ci
235370b324cSopenharmony_ci
236370b324cSopenharmony_cibool FindMethod(
237370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
238370b324cSopenharmony_ci    CMethodId methodId,
239370b324cSopenharmony_ci    AString &name)
240370b324cSopenharmony_ci{
241370b324cSopenharmony_ci  name.Empty();
242370b324cSopenharmony_ci
243370b324cSopenharmony_ci  unsigned i;
244370b324cSopenharmony_ci  for (i = 0; i < g_NumCodecs; i++)
245370b324cSopenharmony_ci  {
246370b324cSopenharmony_ci    const CCodecInfo &codec = *g_Codecs[i];
247370b324cSopenharmony_ci    if (methodId == codec.Id)
248370b324cSopenharmony_ci    {
249370b324cSopenharmony_ci      name = codec.Name;
250370b324cSopenharmony_ci      return true;
251370b324cSopenharmony_ci    }
252370b324cSopenharmony_ci  }
253370b324cSopenharmony_ci
254370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
255370b324cSopenharmony_ci
256370b324cSopenharmony_ci  CHECK_GLOBAL_CODECS
257370b324cSopenharmony_ci
258370b324cSopenharmony_ci  if (_externalCodecs)
259370b324cSopenharmony_ci    for (i = 0; i < _externalCodecs->Codecs.Size(); i++)
260370b324cSopenharmony_ci    {
261370b324cSopenharmony_ci      const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
262370b324cSopenharmony_ci      if (methodId == codec.Id)
263370b324cSopenharmony_ci      {
264370b324cSopenharmony_ci        name = codec.Name;
265370b324cSopenharmony_ci        return true;
266370b324cSopenharmony_ci      }
267370b324cSopenharmony_ci    }
268370b324cSopenharmony_ci
269370b324cSopenharmony_ci  #endif
270370b324cSopenharmony_ci
271370b324cSopenharmony_ci  return false;
272370b324cSopenharmony_ci}
273370b324cSopenharmony_ci
274370b324cSopenharmony_cibool FindHashMethod(
275370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
276370b324cSopenharmony_ci    const AString &name,
277370b324cSopenharmony_ci    CMethodId &methodId)
278370b324cSopenharmony_ci{
279370b324cSopenharmony_ci  unsigned i;
280370b324cSopenharmony_ci  for (i = 0; i < g_NumHashers; i++)
281370b324cSopenharmony_ci  {
282370b324cSopenharmony_ci    const CHasherInfo &codec = *g_Hashers[i];
283370b324cSopenharmony_ci    if (StringsAreEqualNoCase_Ascii(name, codec.Name))
284370b324cSopenharmony_ci    {
285370b324cSopenharmony_ci      methodId = codec.Id;
286370b324cSopenharmony_ci      return true;
287370b324cSopenharmony_ci    }
288370b324cSopenharmony_ci  }
289370b324cSopenharmony_ci
290370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
291370b324cSopenharmony_ci
292370b324cSopenharmony_ci  CHECK_GLOBAL_CODECS
293370b324cSopenharmony_ci
294370b324cSopenharmony_ci  if (_externalCodecs)
295370b324cSopenharmony_ci    for (i = 0; i < _externalCodecs->Hashers.Size(); i++)
296370b324cSopenharmony_ci    {
297370b324cSopenharmony_ci      const CHasherInfoEx &codec = _externalCodecs->Hashers[i];
298370b324cSopenharmony_ci      if (StringsAreEqualNoCase_Ascii(name, codec.Name))
299370b324cSopenharmony_ci      {
300370b324cSopenharmony_ci        methodId = codec.Id;
301370b324cSopenharmony_ci        return true;
302370b324cSopenharmony_ci      }
303370b324cSopenharmony_ci    }
304370b324cSopenharmony_ci
305370b324cSopenharmony_ci  #endif
306370b324cSopenharmony_ci
307370b324cSopenharmony_ci  return false;
308370b324cSopenharmony_ci}
309370b324cSopenharmony_ci
310370b324cSopenharmony_civoid GetHashMethods(
311370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
312370b324cSopenharmony_ci    CRecordVector<CMethodId> &methods)
313370b324cSopenharmony_ci{
314370b324cSopenharmony_ci  methods.ClearAndSetSize(g_NumHashers);
315370b324cSopenharmony_ci  unsigned i;
316370b324cSopenharmony_ci  for (i = 0; i < g_NumHashers; i++)
317370b324cSopenharmony_ci    methods[i] = (*g_Hashers[i]).Id;
318370b324cSopenharmony_ci
319370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
320370b324cSopenharmony_ci
321370b324cSopenharmony_ci  CHECK_GLOBAL_CODECS
322370b324cSopenharmony_ci
323370b324cSopenharmony_ci  if (_externalCodecs)
324370b324cSopenharmony_ci    for (i = 0; i < _externalCodecs->Hashers.Size(); i++)
325370b324cSopenharmony_ci      methods.Add(_externalCodecs->Hashers[i].Id);
326370b324cSopenharmony_ci
327370b324cSopenharmony_ci  #endif
328370b324cSopenharmony_ci}
329370b324cSopenharmony_ci
330370b324cSopenharmony_ci
331370b324cSopenharmony_ci
332370b324cSopenharmony_ciHRESULT CreateCoder_Index(
333370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
334370b324cSopenharmony_ci    unsigned i, bool encode,
335370b324cSopenharmony_ci    CMyComPtr<ICompressFilter> &filter,
336370b324cSopenharmony_ci    CCreatedCoder &cod)
337370b324cSopenharmony_ci{
338370b324cSopenharmony_ci  cod.IsExternal = false;
339370b324cSopenharmony_ci  cod.IsFilter = false;
340370b324cSopenharmony_ci  cod.NumStreams = 1;
341370b324cSopenharmony_ci
342370b324cSopenharmony_ci  if (i < g_NumCodecs)
343370b324cSopenharmony_ci  {
344370b324cSopenharmony_ci    const CCodecInfo &codec = *g_Codecs[i];
345370b324cSopenharmony_ci    // if (codec.Id == methodId)
346370b324cSopenharmony_ci    {
347370b324cSopenharmony_ci      if (encode)
348370b324cSopenharmony_ci      {
349370b324cSopenharmony_ci        if (codec.CreateEncoder)
350370b324cSopenharmony_ci        {
351370b324cSopenharmony_ci          void *p = codec.CreateEncoder();
352370b324cSopenharmony_ci          if (codec.IsFilter) filter = (ICompressFilter *)p;
353370b324cSopenharmony_ci          else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;
354370b324cSopenharmony_ci          else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }
355370b324cSopenharmony_ci          return S_OK;
356370b324cSopenharmony_ci        }
357370b324cSopenharmony_ci      }
358370b324cSopenharmony_ci      else
359370b324cSopenharmony_ci        if (codec.CreateDecoder)
360370b324cSopenharmony_ci        {
361370b324cSopenharmony_ci          void *p = codec.CreateDecoder();
362370b324cSopenharmony_ci          if (codec.IsFilter) filter = (ICompressFilter *)p;
363370b324cSopenharmony_ci          else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;
364370b324cSopenharmony_ci          else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }
365370b324cSopenharmony_ci          return S_OK;
366370b324cSopenharmony_ci        }
367370b324cSopenharmony_ci    }
368370b324cSopenharmony_ci  }
369370b324cSopenharmony_ci
370370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
371370b324cSopenharmony_ci
372370b324cSopenharmony_ci  CHECK_GLOBAL_CODECS
373370b324cSopenharmony_ci
374370b324cSopenharmony_ci  if (_externalCodecs)
375370b324cSopenharmony_ci  {
376370b324cSopenharmony_ci    i -= g_NumCodecs;
377370b324cSopenharmony_ci    cod.IsExternal = true;
378370b324cSopenharmony_ci    if (i < _externalCodecs->Codecs.Size())
379370b324cSopenharmony_ci    {
380370b324cSopenharmony_ci      const CCodecInfoEx &codec = _externalCodecs->Codecs[i];
381370b324cSopenharmony_ci      // if (codec.Id == methodId)
382370b324cSopenharmony_ci      {
383370b324cSopenharmony_ci        if (encode)
384370b324cSopenharmony_ci        {
385370b324cSopenharmony_ci          if (codec.EncoderIsAssigned)
386370b324cSopenharmony_ci          {
387370b324cSopenharmony_ci            if (codec.NumStreams == 1)
388370b324cSopenharmony_ci            {
389370b324cSopenharmony_ci              const HRESULT res = _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
390370b324cSopenharmony_ci              if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)
391370b324cSopenharmony_ci                return res;
392370b324cSopenharmony_ci              if (cod.Coder)
393370b324cSopenharmony_ci                return res;
394370b324cSopenharmony_ci              return _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter);
395370b324cSopenharmony_ci            }
396370b324cSopenharmony_ci            cod.NumStreams = codec.NumStreams;
397370b324cSopenharmony_ci            return _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
398370b324cSopenharmony_ci          }
399370b324cSopenharmony_ci        }
400370b324cSopenharmony_ci        else
401370b324cSopenharmony_ci          if (codec.DecoderIsAssigned)
402370b324cSopenharmony_ci          {
403370b324cSopenharmony_ci            if (codec.NumStreams == 1)
404370b324cSopenharmony_ci            {
405370b324cSopenharmony_ci              const HRESULT res = _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder);
406370b324cSopenharmony_ci              if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)
407370b324cSopenharmony_ci                return res;
408370b324cSopenharmony_ci              if (cod.Coder)
409370b324cSopenharmony_ci                return res;
410370b324cSopenharmony_ci              return _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter);
411370b324cSopenharmony_ci            }
412370b324cSopenharmony_ci            cod.NumStreams = codec.NumStreams;
413370b324cSopenharmony_ci            return _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);
414370b324cSopenharmony_ci          }
415370b324cSopenharmony_ci      }
416370b324cSopenharmony_ci    }
417370b324cSopenharmony_ci  }
418370b324cSopenharmony_ci  #endif
419370b324cSopenharmony_ci
420370b324cSopenharmony_ci  return S_OK;
421370b324cSopenharmony_ci}
422370b324cSopenharmony_ci
423370b324cSopenharmony_ci
424370b324cSopenharmony_ciHRESULT CreateCoder_Index(
425370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
426370b324cSopenharmony_ci    unsigned index, bool encode,
427370b324cSopenharmony_ci    CCreatedCoder &cod)
428370b324cSopenharmony_ci{
429370b324cSopenharmony_ci  CMyComPtr<ICompressFilter> filter;
430370b324cSopenharmony_ci  const HRESULT res = CreateCoder_Index(
431370b324cSopenharmony_ci      EXTERNAL_CODECS_LOC_VARS
432370b324cSopenharmony_ci      index, encode,
433370b324cSopenharmony_ci      filter, cod);
434370b324cSopenharmony_ci
435370b324cSopenharmony_ci  if (filter)
436370b324cSopenharmony_ci  {
437370b324cSopenharmony_ci    cod.IsFilter = true;
438370b324cSopenharmony_ci    CFilterCoder *coderSpec = new CFilterCoder(encode);
439370b324cSopenharmony_ci    cod.Coder = coderSpec;
440370b324cSopenharmony_ci    coderSpec->Filter = filter;
441370b324cSopenharmony_ci  }
442370b324cSopenharmony_ci
443370b324cSopenharmony_ci  return res;
444370b324cSopenharmony_ci}
445370b324cSopenharmony_ci
446370b324cSopenharmony_ci
447370b324cSopenharmony_ciHRESULT CreateCoder_Id(
448370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
449370b324cSopenharmony_ci    CMethodId methodId, bool encode,
450370b324cSopenharmony_ci    CMyComPtr<ICompressFilter> &filter,
451370b324cSopenharmony_ci    CCreatedCoder &cod)
452370b324cSopenharmony_ci{
453370b324cSopenharmony_ci  const int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode);
454370b324cSopenharmony_ci  if (index < 0)
455370b324cSopenharmony_ci    return S_OK;
456370b324cSopenharmony_ci  return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)index, encode, filter, cod);
457370b324cSopenharmony_ci}
458370b324cSopenharmony_ci
459370b324cSopenharmony_ci
460370b324cSopenharmony_ciHRESULT CreateCoder_Id(
461370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
462370b324cSopenharmony_ci    CMethodId methodId, bool encode,
463370b324cSopenharmony_ci    CCreatedCoder &cod)
464370b324cSopenharmony_ci{
465370b324cSopenharmony_ci  CMyComPtr<ICompressFilter> filter;
466370b324cSopenharmony_ci  const HRESULT res = CreateCoder_Id(
467370b324cSopenharmony_ci      EXTERNAL_CODECS_LOC_VARS
468370b324cSopenharmony_ci      methodId, encode,
469370b324cSopenharmony_ci      filter, cod);
470370b324cSopenharmony_ci
471370b324cSopenharmony_ci  if (filter)
472370b324cSopenharmony_ci  {
473370b324cSopenharmony_ci    cod.IsFilter = true;
474370b324cSopenharmony_ci    CFilterCoder *coderSpec = new CFilterCoder(encode);
475370b324cSopenharmony_ci    cod.Coder = coderSpec;
476370b324cSopenharmony_ci    coderSpec->Filter = filter;
477370b324cSopenharmony_ci  }
478370b324cSopenharmony_ci
479370b324cSopenharmony_ci  return res;
480370b324cSopenharmony_ci}
481370b324cSopenharmony_ci
482370b324cSopenharmony_ci
483370b324cSopenharmony_ciHRESULT CreateCoder_Id(
484370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
485370b324cSopenharmony_ci    CMethodId methodId, bool encode,
486370b324cSopenharmony_ci    CMyComPtr<ICompressCoder> &coder)
487370b324cSopenharmony_ci{
488370b324cSopenharmony_ci  CCreatedCoder cod;
489370b324cSopenharmony_ci  const HRESULT res = CreateCoder_Id(
490370b324cSopenharmony_ci      EXTERNAL_CODECS_LOC_VARS
491370b324cSopenharmony_ci      methodId, encode,
492370b324cSopenharmony_ci      cod);
493370b324cSopenharmony_ci  coder = cod.Coder;
494370b324cSopenharmony_ci  return res;
495370b324cSopenharmony_ci}
496370b324cSopenharmony_ci
497370b324cSopenharmony_ciHRESULT CreateFilter(
498370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
499370b324cSopenharmony_ci    CMethodId methodId, bool encode,
500370b324cSopenharmony_ci    CMyComPtr<ICompressFilter> &filter)
501370b324cSopenharmony_ci{
502370b324cSopenharmony_ci  CCreatedCoder cod;
503370b324cSopenharmony_ci  return CreateCoder_Id(
504370b324cSopenharmony_ci      EXTERNAL_CODECS_LOC_VARS
505370b324cSopenharmony_ci      methodId, encode,
506370b324cSopenharmony_ci      filter, cod);
507370b324cSopenharmony_ci}
508370b324cSopenharmony_ci
509370b324cSopenharmony_ci
510370b324cSopenharmony_ciHRESULT CreateHasher(
511370b324cSopenharmony_ci    DECL_EXTERNAL_CODECS_LOC_VARS
512370b324cSopenharmony_ci    CMethodId methodId,
513370b324cSopenharmony_ci    AString &name,
514370b324cSopenharmony_ci    CMyComPtr<IHasher> &hasher)
515370b324cSopenharmony_ci{
516370b324cSopenharmony_ci  name.Empty();
517370b324cSopenharmony_ci
518370b324cSopenharmony_ci  unsigned i;
519370b324cSopenharmony_ci  for (i = 0; i < g_NumHashers; i++)
520370b324cSopenharmony_ci  {
521370b324cSopenharmony_ci    const CHasherInfo &codec = *g_Hashers[i];
522370b324cSopenharmony_ci    if (codec.Id == methodId)
523370b324cSopenharmony_ci    {
524370b324cSopenharmony_ci      hasher = codec.CreateHasher();
525370b324cSopenharmony_ci      name = codec.Name;
526370b324cSopenharmony_ci      break;
527370b324cSopenharmony_ci    }
528370b324cSopenharmony_ci  }
529370b324cSopenharmony_ci
530370b324cSopenharmony_ci  #ifdef Z7_EXTERNAL_CODECS
531370b324cSopenharmony_ci
532370b324cSopenharmony_ci  CHECK_GLOBAL_CODECS
533370b324cSopenharmony_ci
534370b324cSopenharmony_ci  if (!hasher && _externalCodecs)
535370b324cSopenharmony_ci    for (i = 0; i < _externalCodecs->Hashers.Size(); i++)
536370b324cSopenharmony_ci    {
537370b324cSopenharmony_ci      const CHasherInfoEx &codec = _externalCodecs->Hashers[i];
538370b324cSopenharmony_ci      if (codec.Id == methodId)
539370b324cSopenharmony_ci      {
540370b324cSopenharmony_ci        name = codec.Name;
541370b324cSopenharmony_ci        return _externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher);
542370b324cSopenharmony_ci      }
543370b324cSopenharmony_ci    }
544370b324cSopenharmony_ci
545370b324cSopenharmony_ci  #endif
546370b324cSopenharmony_ci
547370b324cSopenharmony_ci  return S_OK;
548370b324cSopenharmony_ci}
549