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];
RegisterCodec(const CCodecInfo * codecInfo)16 void RegisterCodec(const CCodecInfo *codecInfo)
17 {
18 if (g_NumCodecs < kNumCodecsMax)
19 g_Codecs[g_NumCodecs++] = codecInfo;
20 }
21
22 #ifdef EXTERNAL_CODECS
ReadNumberOfStreams(ICompressCodecsInfo * codecsInfo,UInt32 index,PROPID propID,UInt32 & res)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
ReadIsAssignedProp(ICompressCodecsInfo * codecsInfo,UInt32 index,PROPID propID,bool & res)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
LoadExternalCodecs(ICompressCodecsInfo * codecsInfo,CObjectVector<CCodecInfoEx> & externalCodecs)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
FindMethod(ICompressCodecsInfo *,const CObjectVector<CCodecInfoEx> * externalCodecs,const UString & name,CMethodId & methodId,UInt32 & numInStreams,UInt32 & numOutStreams)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
FindMethod(ICompressCodecsInfo *,const CObjectVector<CCodecInfoEx> * externalCodecs,CMethodId methodId,UString & name)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
CreateCoder(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,CMyComPtr<ICompressFilter> & filter,CMyComPtr<ICompressCoder> & coder,CMyComPtr<ICompressCoder2> & coder2,bool encode,bool onlyCoder)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
CreateCoder(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,CMyComPtr<ICompressCoder> & coder,CMyComPtr<ICompressCoder2> & coder2,bool encode)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
CreateCoder(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,CMyComPtr<ICompressCoder> & coder,bool encode)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
CreateFilter(DECL_EXTERNAL_CODECS_LOC_VARS CMethodId methodId,CMyComPtr<ICompressFilter> & filter,bool encode)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