CreateCoder.cpp 7.7 KB

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