CodecExports.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // CodecExports.cpp
  2. #include "StdAfx.h"
  3. #include "../../Common/ComTry.h"
  4. #include "../../Windows/PropVariant.h"
  5. #include "../Common/RegisterCodec.h"
  6. #include "../ICoder.h"
  7. extern unsigned int g_NumCodecs;
  8. extern const CCodecInfo *g_Codecs[];
  9. static const UInt16 kDecodeId = 0x2790;
  10. DEFINE_GUID(CLSID_CCodec,
  11. 0x23170F69, 0x40C1, kDecodeId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
  12. static inline HRESULT SetPropString(const char *s, unsigned int size, PROPVARIANT *value)
  13. {
  14. if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != 0)
  15. value->vt = VT_BSTR;
  16. return S_OK;
  17. }
  18. static inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)
  19. {
  20. return SetPropString((const char *)&guid, sizeof(GUID), value);
  21. }
  22. static HRESULT SetClassID(CMethodId id, bool encode, PROPVARIANT *value)
  23. {
  24. GUID clsId = CLSID_CCodec;
  25. for (int i = 0; i < sizeof(id); i++, id >>= 8)
  26. clsId.Data4[i] = (Byte)(id & 0xFF);
  27. if (encode)
  28. clsId.Data3++;
  29. return SetPropGUID(clsId, value);
  30. }
  31. static HRESULT FindCodecClassId(const GUID *clsID, UInt32 isCoder2, bool isFilter, bool &encode, int &index)
  32. {
  33. index = -1;
  34. if (clsID->Data1 != CLSID_CCodec.Data1 ||
  35. clsID->Data2 != CLSID_CCodec.Data2 ||
  36. (clsID->Data3 & ~1) != kDecodeId)
  37. return S_OK;
  38. encode = (clsID->Data3 != kDecodeId);
  39. UInt64 id = 0;
  40. for (int j = 0; j < 8; j++)
  41. id |= ((UInt64)clsID->Data4[j]) << (8 * j);
  42. for (UInt32 i = 0; i < g_NumCodecs; i++)
  43. {
  44. const CCodecInfo &codec = *g_Codecs[i];
  45. if (id != codec.Id || encode && !codec.CreateEncoder || !encode && !codec.CreateDecoder)
  46. continue;
  47. if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||
  48. codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)
  49. return E_NOINTERFACE;
  50. index = i;
  51. return S_OK;
  52. }
  53. return S_OK;
  54. }
  55. STDAPI CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)
  56. {
  57. COM_TRY_BEGIN
  58. *outObject = 0;
  59. bool isCoder = (*iid == IID_ICompressCoder) != 0;
  60. bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;
  61. bool isFilter = (*iid == IID_ICompressFilter) != 0;
  62. const CCodecInfo &codec = *g_Codecs[index];
  63. if (!isFilter && codec.IsFilter || isFilter && !codec.IsFilter ||
  64. codec.NumInStreams != 1 && !isCoder2 || codec.NumInStreams == 1 && isCoder2)
  65. return E_NOINTERFACE;
  66. if (encode)
  67. {
  68. if (!codec.CreateEncoder)
  69. return CLASS_E_CLASSNOTAVAILABLE;
  70. *outObject = codec.CreateEncoder();
  71. }
  72. else
  73. {
  74. if (!codec.CreateDecoder)
  75. return CLASS_E_CLASSNOTAVAILABLE;
  76. *outObject = codec.CreateDecoder();
  77. }
  78. if (isCoder)
  79. ((ICompressCoder *)*outObject)->AddRef();
  80. else if (isCoder2)
  81. ((ICompressCoder2 *)*outObject)->AddRef();
  82. else
  83. ((ICompressFilter *)*outObject)->AddRef();
  84. return S_OK;
  85. COM_TRY_END
  86. }
  87. STDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)
  88. {
  89. *outObject = 0;
  90. bool isCoder = (*iid == IID_ICompressCoder) != 0;
  91. bool isCoder2 = (*iid == IID_ICompressCoder2) != 0;
  92. bool isFilter = (*iid == IID_ICompressFilter) != 0;
  93. if (!isCoder && !isCoder2 && !isFilter)
  94. return E_NOINTERFACE;
  95. bool encode;
  96. int codecIndex;
  97. HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);
  98. if (res != S_OK)
  99. return res;
  100. if (codecIndex < 0)
  101. return CLASS_E_CLASSNOTAVAILABLE;
  102. return CreateCoder2(encode, codecIndex, iid, outObject);
  103. }
  104. STDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)
  105. {
  106. ::VariantClear((VARIANTARG *)value);
  107. const CCodecInfo &codec = *g_Codecs[codecIndex];
  108. switch(propID)
  109. {
  110. case NMethodPropID::kID:
  111. {
  112. value->uhVal.QuadPart = (UInt64)codec.Id;
  113. value->vt = VT_UI8;
  114. break;
  115. }
  116. case NMethodPropID::kName:
  117. if ((value->bstrVal = ::SysAllocString(codec.Name)) != 0)
  118. value->vt = VT_BSTR;
  119. break;
  120. case NMethodPropID::kDecoder:
  121. if (codec.CreateDecoder)
  122. return SetClassID(codec.Id, false, value);
  123. break;
  124. case NMethodPropID::kEncoder:
  125. if (codec.CreateEncoder)
  126. return SetClassID(codec.Id, true, value);
  127. break;
  128. case NMethodPropID::kInStreams:
  129. {
  130. if (codec.NumInStreams != 1)
  131. {
  132. value->vt = VT_UI4;
  133. value->ulVal = codec.NumInStreams;
  134. }
  135. break;
  136. }
  137. }
  138. return S_OK;
  139. }
  140. STDAPI GetNumberOfMethods(UINT32 *numCodecs)
  141. {
  142. *numCodecs = g_NumCodecs;
  143. return S_OK;
  144. }