• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SetPropString(const char * s,unsigned int size,PROPVARIANT * value)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 
SetPropGUID(const GUID & guid,PROPVARIANT * value)28 static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
29 {
30   return SetPropString((const char *)&guid, sizeof(GUID), value);
31 }
32 
SetClassID(CMethodId id,bool encode,PROPVARIANT * value)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 
FindCodecClassId(const GUID * clsID,UInt32 isCoder2,bool isFilter,bool & encode,int & index)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 
CreateCoder2(bool encode,UInt32 index,const GUID * iid,void ** outObject)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 
CreateCoder(const GUID * clsid,const GUID * iid,void ** outObject)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 
GetMethodProperty(UInt32 codecIndex,PROPID propID,PROPVARIANT * value)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 
GetNumberOfMethods(UINT32 * numCodecs)156 STDAPI GetNumberOfMethods(UINT32 *numCodecs)
157 {
158   *numCodecs = g_NumCodecs;
159   return S_OK;
160 }
161