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