Home | History | Annotate | Download | only in Compress
      1 // CodecExports.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../Common/ComTry.h"
      6 
      7 #include "../../Windows/PropVariant.h"
      8 
      9 #include "../ICoder.h"
     10 
     11 #include "../Common/RegisterCodec.h"
     12 
     13 extern unsigned int g_NumCodecs;
     14 extern const CCodecInfo *g_Codecs[];
     15 
     16 static const UInt16 kDecodeId = 0x2790;
     17 
     18 DEFINE_GUID(CLSID_CCodec,
     19 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
     20 
     21 static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)
     22 {
     23   if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
     24     value->vt = VT_BSTR;
     25   return S_OK;
     26 }
     27 
     28 static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
     29 {
     30   return SetPropString((const char *)&guid, sizeof(GUID), value);
     31 }
     32 
     33 static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value)
     34 {
     35   GUID clsId = CLSID_CCodec;
     36   for (int i = 0; i < sizeof(id); i++, id >>= 8)
     37     clsId.Data4[i] = (Byte)(id & 0xFF);
     38   if (encode)
     39     clsId.Data3++;
     40   return SetPropGUID(clsId, value);
     41 }
     42 
     43 static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index)
     44 {
     45   index = -1;
     46   if (clsID->Data1 != CLSID_CCodec.Data1 ||
     47       clsID->Data2 != CLSID_CCodec.Data2 ||
     48       (clsID->Data3 & ~1) != kDecodeId)
     49     return S_OK;
     50   encode = (clsID->Data3 != kDecodeId);
     51   UInt64 id = 0;
     52   for (int j = 0; j < 8; j++)
     53     id |= ((UInt64)clsID->Data4[j]) << (8 * j);
     54   for (unsigned i = 0; i < g_NumCodecs; i++)
     55   {
     56     const CCodecInfo &codec = *g_Codecs[i];
     57     if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder)
     58       continue;
     59     if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||
     60         codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)
     61       return E_NOINTERFACE;
     62     index = i;
     63     return S_OK;
     64   }
     65   return S_OK;
     66 }
     67 
     68 STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)
     69 {
     70   COM_TRY_BEGIN
     71   *outObject = 0;
     72   bool isCoder = (*iid == IID_ICompressCoder) != 0;
     73   bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;
     74   bool isFilter = (*iid == IID_ICompressFilter) != 0;
     75   const CCodecInfo &codec = *g_Codecs[index];
     76   if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||
     77       codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)
     78     return E_NOINTERFACE;
     79   if (encode)
     80   {
     81     if (!codec.CreateEncoder)
     82       return CLASS_E_CLASSNOTAVAILABLE;
     83     *outObject = codec.CreateEncoder();
     84   }
     85   else
     86   {
     87     if (!codec.CreateDecoder)
     88       return CLASS_E_CLASSNOTAVAILABLE;
     89     *outObject = codec.CreateDecoder();
     90   }
     91   if (isCoder)
     92     ((ICompressCoder *)*outObject)->AddRef();
     93   else if (isCoder2)
     94     ((ICompressCoder2 *)*outObject)->AddRef();
     95   else
     96     ((ICompressFilter *)*outObject)->AddRef();
     97   return S_OK;
     98   COM_TRY_END
     99 }
    100 
    101 STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)
    102 {
    103   *outObject = 0;
    104   bool isCoder = (*iid == IID_ICompressCoder) != 0;
    105   bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;
    106   bool isFilter = (*iid == IID_ICompressFilter) != 0;
    107   if (!isCoder && !isCoder2 && !isFilter)
    108     return E_NOINTERFACE;
    109   bool encode;
    110   int codecIndex;
    111   HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);
    112   if (res != S_OK)
    113     return res;
    114   if (codecIndex < 0)
    115     return CLASS_E_CLASSNOTAVAILABLE;
    116   return CreateCoder2(encode, codecIndex, iid, outObject);
    117 }
    118 
    119 STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
    120 {
    121   ::VariantClear((VARIANTARG *)value);
    122   const CCodecInfo &codec = *g_Codecs[codecIndex];
    123   switch(propID)
    124   {
    125     case NMethodPropID::kID:
    126     {
    127       value->uhVal.QuadPart = (UInt64)codec.Id;
    128       value->vt = VT_UI8;
    129       break;
    130     }
    131     case NMethodPropID::kName:
    132       if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)
    133         value->vt = VT_BSTR;
    134       break;
    135     case NMethodPropID::kDecoder:
    136       if (codec.CreateDecoder)
    137         return SetClassID(codec.Id, false, value);
    138       break;
    139     case NMethodPropID::kEncoder:
    140       if (codec.CreateEncoder)
    141         return SetClassID(codec.Id, true, value);
    142       break;
    143     case NMethodPropID::kInStreams:
    144     {
    145       if (codec.NumInStreams != 1)
    146       {
    147         value->vt = VT_UI4;
    148         value->ulVal = (ULONG)codec.NumInStreams;
    149       }
    150       break;
    151     }
    152   }
    153   return S_OK;
    154 }
    155 
    156 STDAPI GetNumberOfMethods(UINT32 *numCodecs)
    157 {
    158   *numCodecs = g_NumCodecs;
    159   return S_OK;
    160 }
    161