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