Home | History | Annotate | Download | only in Common
      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) 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];
     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
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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