misc/libphysfs/lzma/CPP/7zip/Common/CreateCoder.cpp
changeset 13904 99b265e0d1d0
parent 13903 5f819b90d479
child 13905 b172a5d40eee
equal deleted inserted replaced
13903:5f819b90d479 13904:99b265e0d1d0
     1 // CreateCoder.cpp
       
     2 
       
     3 #include "StdAfx.h"
       
     4 
       
     5 #include "CreateCoder.h"
       
     6 
       
     7 #include "../../Windows/PropVariant.h"
       
     8 #include "../../Windows/Defs.h"
       
     9 #include "FilterCoder.h"
       
    10 #include "RegisterCodec.h"
       
    11 
       
    12 static const unsigned int kNumCodecsMax = 64;
       
    13 unsigned int g_NumCodecs = 0;
       
    14 const CCodecInfo *g_Codecs[kNumCodecsMax]; 
       
    15 void RegisterCodec(const CCodecInfo *codecInfo) 
       
    16 { 
       
    17   if (g_NumCodecs < kNumCodecsMax)
       
    18     g_Codecs[g_NumCodecs++] = codecInfo; 
       
    19 }
       
    20 
       
    21 #ifdef EXTERNAL_CODECS
       
    22 static HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)
       
    23 {
       
    24   NWindows::NCOM::CPropVariant prop;
       
    25   RINOK(codecsInfo->GetProperty(index, propID, &prop));
       
    26   if (prop.vt == VT_EMPTY)
       
    27     res = 1;
       
    28   else if (prop.vt == VT_UI4)
       
    29     res = prop.ulVal;
       
    30   else
       
    31     return E_INVALIDARG;
       
    32   return S_OK;
       
    33 }
       
    34 
       
    35 static HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)
       
    36 {
       
    37   NWindows::NCOM::CPropVariant prop;
       
    38   RINOK(codecsInfo->GetProperty(index, propID, &prop));
       
    39   if (prop.vt == VT_EMPTY)
       
    40     res = true;
       
    41   else if (prop.vt == VT_BOOL)
       
    42     res = VARIANT_BOOLToBool(prop.boolVal);
       
    43   else
       
    44     return E_INVALIDARG;
       
    45   return S_OK;
       
    46 }
       
    47 
       
    48 HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, CObjectVector<CCodecInfoEx> &externalCodecs)
       
    49 {
       
    50   UInt32 num;
       
    51   RINOK(codecsInfo->GetNumberOfMethods(&num));
       
    52   for (UInt32 i = 0; i < num; i++)
       
    53   {
       
    54     CCodecInfoEx info;
       
    55     NWindows::NCOM::CPropVariant prop;
       
    56     RINOK(codecsInfo->GetProperty(i, NMethodPropID::kID, &prop));
       
    57     // if (prop.vt != VT_BSTR)
       
    58     // info.Id.IDSize = (Byte)SysStringByteLen(prop.bstrVal);
       
    59     // memmove(info.Id.ID, prop.bstrVal, info.Id.IDSize);
       
    60     if (prop.vt != VT_UI8)
       
    61     {
       
    62       continue; // old Interface 
       
    63       // return E_INVALIDARG;
       
    64     }
       
    65     info.Id = prop.uhVal.QuadPart;
       
    66     prop.Clear();
       
    67     
       
    68     RINOK(codecsInfo->GetProperty(i, NMethodPropID::kName, &prop));
       
    69     if (prop.vt == VT_BSTR)
       
    70       info.Name = prop.bstrVal;
       
    71     else if (prop.vt != VT_EMPTY)
       
    72       return E_INVALIDARG;;
       
    73     
       
    74     RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kInStreams, info.NumInStreams));
       
    75     RINOK(ReadNumberOfStreams(codecsInfo, i, NMethodPropID::kOutStreams, info.NumOutStreams));
       
    76     RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned));
       
    77     RINOK(ReadIsAssignedProp(codecsInfo, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned));
       
    78     
       
    79     externalCodecs.Add(info);
       
    80   }
       
    81   return S_OK;
       
    82 }
       
    83 
       
    84 #endif
       
    85 
       
    86 bool FindMethod(
       
    87   #ifdef EXTERNAL_CODECS
       
    88   ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,
       
    89   #endif
       
    90   const UString &name,
       
    91   CMethodId &methodId, UInt32 &numInStreams, UInt32 &numOutStreams)
       
    92 {
       
    93   UInt32 i;
       
    94   for (i = 0; i < g_NumCodecs; i++)
       
    95   {
       
    96     const CCodecInfo &codec = *g_Codecs[i]; 
       
    97     if (name.CompareNoCase(codec.Name) == 0)
       
    98     {
       
    99       methodId = codec.Id;
       
   100       numInStreams = codec.NumInStreams;
       
   101       numOutStreams = 1;
       
   102       return true;
       
   103     }
       
   104   }
       
   105   #ifdef EXTERNAL_CODECS
       
   106   if (externalCodecs)
       
   107     for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
       
   108     {
       
   109       const CCodecInfoEx &codec = (*externalCodecs)[i]; 
       
   110       if (codec.Name.CompareNoCase(name) == 0)
       
   111       {
       
   112         methodId = codec.Id;
       
   113         numInStreams = codec.NumInStreams;
       
   114         numOutStreams = codec.NumOutStreams;
       
   115         return true;
       
   116       }
       
   117     }
       
   118   #endif
       
   119   return false;
       
   120 }
       
   121 
       
   122 bool FindMethod(
       
   123   #ifdef EXTERNAL_CODECS
       
   124   ICompressCodecsInfo * /* codecsInfo */, const CObjectVector<CCodecInfoEx> *externalCodecs,
       
   125   #endif
       
   126   CMethodId methodId, UString &name)
       
   127 {
       
   128   UInt32 i;
       
   129   for (i = 0; i < g_NumCodecs; i++)
       
   130   {
       
   131     const CCodecInfo &codec = *g_Codecs[i]; 
       
   132     if (methodId == codec.Id)
       
   133     {
       
   134       name = codec.Name;
       
   135       return true;
       
   136     }
       
   137   }
       
   138   #ifdef EXTERNAL_CODECS
       
   139   if (externalCodecs)
       
   140     for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
       
   141     {
       
   142       const CCodecInfoEx &codec = (*externalCodecs)[i]; 
       
   143       if (methodId == codec.Id)
       
   144       {
       
   145         name = codec.Name;
       
   146         return true;
       
   147       }
       
   148     }
       
   149   #endif
       
   150   return false;
       
   151 }
       
   152 
       
   153 HRESULT CreateCoder(
       
   154   DECL_EXTERNAL_CODECS_LOC_VARS
       
   155   CMethodId methodId,
       
   156   CMyComPtr<ICompressFilter> &filter,
       
   157   CMyComPtr<ICompressCoder> &coder,
       
   158   CMyComPtr<ICompressCoder2> &coder2,
       
   159   bool encode, bool onlyCoder)
       
   160 {
       
   161   bool created = false;
       
   162   UInt32 i;
       
   163   for (i = 0; i < g_NumCodecs; i++)
       
   164   {
       
   165     const CCodecInfo &codec = *g_Codecs[i]; 
       
   166     if (codec.Id == methodId)
       
   167     {
       
   168       if (encode)
       
   169       {
       
   170         if (codec.CreateEncoder)
       
   171         {
       
   172           void *p = codec.CreateEncoder();
       
   173           if (codec.IsFilter) filter = (ICompressFilter *)p;
       
   174           else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;
       
   175           else coder2 = (ICompressCoder2 *)p;
       
   176           created = (p != 0);
       
   177           break;
       
   178         }
       
   179       }
       
   180       else
       
   181         if (codec.CreateDecoder)
       
   182         {
       
   183           void *p = codec.CreateDecoder();
       
   184           if (codec.IsFilter) filter = (ICompressFilter *)p;
       
   185           else if (codec.NumInStreams == 1) coder = (ICompressCoder *)p;
       
   186           else coder2 = (ICompressCoder2 *)p;
       
   187           created = (p != 0);
       
   188           break;
       
   189         }
       
   190     }
       
   191   }
       
   192 
       
   193   #ifdef EXTERNAL_CODECS
       
   194   if (!created && externalCodecs)
       
   195     for (i = 0; i < (UInt32)externalCodecs->Size(); i++)
       
   196     {
       
   197       const CCodecInfoEx &codec = (*externalCodecs)[i]; 
       
   198       if (codec.Id == methodId)
       
   199       {
       
   200         if (encode)
       
   201         {
       
   202           if (codec.EncoderIsAssigned)
       
   203           {
       
   204             if (codec.IsSimpleCodec())
       
   205             {
       
   206               HRESULT result = codecsInfo->CreateEncoder(i, &IID_ICompressCoder, (void **)&coder);
       
   207               if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) 
       
   208                 return result;
       
   209               if (!coder)
       
   210               {
       
   211                 RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter));
       
   212               }
       
   213             }
       
   214             else
       
   215             {
       
   216               RINOK(codecsInfo->CreateEncoder(i, &IID_ICompressCoder2, (void **)&coder2));
       
   217             }
       
   218             break;
       
   219           }
       
   220         }
       
   221         else
       
   222           if (codec.DecoderIsAssigned)
       
   223           {
       
   224             if (codec.IsSimpleCodec())
       
   225             {
       
   226               HRESULT result = codecsInfo->CreateDecoder(i, &IID_ICompressCoder, (void **)&coder);
       
   227               if (result != S_OK && result != E_NOINTERFACE && result != CLASS_E_CLASSNOTAVAILABLE) 
       
   228                 return result;
       
   229               if (!coder)
       
   230               {
       
   231                 RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter));
       
   232               }
       
   233             }
       
   234             else
       
   235             {
       
   236               RINOK(codecsInfo->CreateDecoder(i, &IID_ICompressCoder2, (void **)&coder2));
       
   237             }
       
   238             break;
       
   239           }
       
   240       }
       
   241     }
       
   242   #endif
       
   243 
       
   244   if (onlyCoder && filter)
       
   245   {
       
   246     CFilterCoder *coderSpec = new CFilterCoder;
       
   247     coder = coderSpec;
       
   248     coderSpec->Filter = filter;
       
   249   }
       
   250   return S_OK;
       
   251 }
       
   252 
       
   253 HRESULT CreateCoder(
       
   254   DECL_EXTERNAL_CODECS_LOC_VARS
       
   255   CMethodId methodId,
       
   256   CMyComPtr<ICompressCoder> &coder, 
       
   257   CMyComPtr<ICompressCoder2> &coder2,
       
   258   bool encode)
       
   259 {
       
   260   CMyComPtr<ICompressFilter> filter;
       
   261   return CreateCoder(
       
   262     EXTERNAL_CODECS_LOC_VARS
       
   263     methodId,
       
   264     filter, coder, coder2, encode, true);
       
   265 }
       
   266 
       
   267 HRESULT CreateCoder(
       
   268   DECL_EXTERNAL_CODECS_LOC_VARS
       
   269   CMethodId methodId,
       
   270   CMyComPtr<ICompressCoder> &coder, bool encode)
       
   271 {
       
   272   CMyComPtr<ICompressFilter> filter;
       
   273   CMyComPtr<ICompressCoder2> coder2;
       
   274   return CreateCoder(
       
   275     EXTERNAL_CODECS_LOC_VARS
       
   276     methodId,
       
   277     coder, coder2, encode);
       
   278 }
       
   279 
       
   280 HRESULT CreateFilter(
       
   281   DECL_EXTERNAL_CODECS_LOC_VARS
       
   282   CMethodId methodId,
       
   283   CMyComPtr<ICompressFilter> &filter,
       
   284   bool encode)
       
   285 {
       
   286   CMyComPtr<ICompressCoder> coder;
       
   287   CMyComPtr<ICompressCoder2> coder2;
       
   288   return CreateCoder(
       
   289     EXTERNAL_CODECS_LOC_VARS
       
   290     methodId,
       
   291     filter, coder, coder2, encode, false);
       
   292 }