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