从CLSID创建COM接口需要从GUID获得类型Type,然后通过Activator.CreateInstance创建接口对象。代码如下:
Guid guid = new Guid("{3D2F839E-1186-4FCE-B772-B61FAE1ACED7}");
try
{
filter = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(guid));
}
catch(Exception E)
{
print(E.Message);
}
实际运行时,Type.GetTypeFromCLSID会抛出异常:
The requested feature is not implemented.
说明该函数在mono平台没有实现。
为了解决这个问题,我们现在用的办法是通过C++包装COM接口,然后通过DLL暴露COM接口,供Unity3D C#使用。
// VCamDll.cpp : Defines the entry point for the DLL application.
//
# include <dshow.h>
# include <comdef.h>
# pragma comment(lib,"strmiids.lib")
// VCam filter interface
#pragma warning(disable : 4192)
#import "VCamRenderer.tlb" no_namespace, raw_interfaces_only exclude("UINT_PTR")
#include "VCamRenderer_i.c"
_COM_SMARTPTR_TYPEDEF(IBaseFilter, IID_IBaseFilter);
IBaseFilterPtr g_pRenderer;
IVCamRenderer* g_pVCamRenderer;
template < typename T >
void SAFE_RELEASE(T *&p)
{
if (0 != p) {
p->Release();
p = NULL;
}
}
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
extern "C" __declspec(dllexport)
bool InitVCamSDK()
{
HRESULT hr = CoCreateInstance(CLSID_VCamRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, reinterpret_cast<void**>(&g_pRenderer));
if (FAILED(hr)) {
return FALSE;
}
hr = g_pRenderer->QueryInterface(IID_IVCamRenderer, reinterpret_cast<void**>(&g_pVCamRenderer));
if (FAILED(hr)) {
return FALSE;
}
g_pVCamRenderer->SetLicenseCode(::SysAllocString(L"E9CT4-HE3C6-M7F5B-K97EP-DA5B3"));
g_pVCamRenderer->SetOutputFormat(640, 480, 60, 0, 0);
return true;
}
extern "C" __declspec(dllexport)
void UninitVCamSDK()
{
SAFE_RELEASE(g_pVCamRenderer);
}
extern "C" __declspec(dllexport)
HRESULT SetCurrentDevice(BSTR friendly_name)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SetCurrentDevice(friendly_name);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SetOutputFormat(long width, long height, long fps, long format, long one_size_only)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SetOutputFormat(width, height, fps, format, one_size_only);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT GetOutputFormat(long * width, long * height, long * fps, long * format, long * one_size_only)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->GetOutputFormat(width, height, fps, format, one_size_only);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SetFillMode(long fill_mode)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SetFillMode(fill_mode);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT GetFillMode(long * fill_mode)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->GetFillMode(fill_mode);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SetMirror(long mirror)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SetMirror(mirror);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SetFlip(long flip)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SetFlip(flip);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SetRotateRight(long rotate)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SetRotateRight(rotate);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SendFrame(unsigned char * i_rgb24_pixels, long i_width, long i_height, long i_stride)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SendFrame(i_rgb24_pixels, i_width, i_height, i_stride);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SendFrame32(unsigned char * i_rgb32_pixels, long i_width, long i_height, long i_stride)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SendFrame32(i_rgb32_pixels, i_width, i_height, i_stride);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SendFrameYUY2(unsigned char * i_yuy2, long i_width, long i_height, long i_stride)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SendFrameYUY2(i_yuy2, i_width, i_height, i_stride);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SendFrameNV12(unsigned char * i_nv12, long i_width, long i_height, long i_stride)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SendFrameNV12(i_nv12, i_width, i_height, i_stride);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SendFrameEx(VARIANT i_rgb24_array, long i_width, long i_height)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SendFrameEx(i_rgb24_array, i_width, i_height);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT CaptureScreen(long i_x, long i_y, long i_width, long i_height)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->CaptureScreen(i_x, i_y, i_width, i_height);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SetConnectionNotificationEvent(__int64 i_handle)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SetConnectionNotificationEvent(i_handle);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT GetConnectedCount(long * o_count)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->GetConnectedCount(o_count);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT IsOpened()
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->IsOpened();
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT Snapshot(BSTR filename)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->Snapshot(filename);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SetIdleFileName(BSTR file_name)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SetIdleFileName(file_name);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SetFriendlyName(BSTR friendly_name)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SetFriendlyName(friendly_name);
}
else {
return S_FALSE;
}
}
extern "C" __declspec(dllexport)
HRESULT SetLicenseCode(BSTR license_code)
{
if (NULL != g_pVCamRenderer) {
return g_pVCamRenderer->SetLicenseCode(license_code);
}
else {
return S_FALSE;
}
}