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)
     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