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