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