我有一个在Unity 5.2上使用Hololens可定位摄像头的计算机视觉插件。我使用UnityEngine.XR.WSA.WebCam.PhotoCaptureFrame类,并在NV12颜色格式(相机本机格式)中以最高分辨率(2048x1156)启用了照片模式。

PhotoCaptureFrame类:https://docs.unity3d.com/2017.2/Documentation/ScriptReference/XR.WSA.WebCam.PhotoCaptureFrame.html

目前,我为插件执行此操作以处理任何单张照片:

PhotoCaptureFrame photo; // created correctly through Unity API

List<byte> photoBuffer = new List<byte>();
photo.CopyRawImageDataIntoBuffer(photoBuffer);

// marshal photoBuffer to plugin (and it works fine for the computer vision part)

但是,它每次都复制原始缓冲区。我想直接从插件中使用原始缓冲区。所以我尝试了这个:
IntPtr rawBufferPtr = photo.GetUnsafePointerToBuffer(); // COM pointer to IMFMediaBuffer is incremented
// send rawBufferPtr to plugin (native function described below)
Marshal.Release(rawBufferPtr);

IMFMediaBuffer接口(interface):https://msdn.microsoft.com/en-us/library/windows/desktop/ms696261(v=vs.85).aspx

在我的C++插件中:
#include <Mfidl.h> // for IMFMediaBuffer support

void process_photo(void *photo_buffer_wrapper, int photo_width, int photo_height)
{
    // photo_buffer_wrapper = rawBufferPtr in managed environment

    IMFMediaBuffer *media_buffer = reinterpret_cast<IMFMediaBuffer *>(photo_buffer_wrapper);
    BYTE *photo_buffer = NULL;
    HRESULT result = media_buffer->Lock(&photo_buffer, NULL, NULL);
    if (SUCCEEDED(result))
    {
        // do image processing stuff here (with OpenCV) using photo_buffer
        media_buffer->Unlock;
    }
}

对我来说似乎很好。它也可以编译。但是在运行时,我遇到访问冲突,并且应用程序在Hololens上崩溃了。

异常代码:0xC0000005

异常信息:线程试图读取或写入对其没有适当访问权限的虚拟地址。

有人看到问题了吗?与我将IMFMediaBuffer对象从托管环境传递到非托管环境有关吗?

非常感谢你!

最佳答案

我会回答我自己的问题。
photo_buffer_wrapper不是我所想到的IMFMediaBuffer的指针,而是IUnknown的指针。这是修改后的本机功能,可按预期工作:

// UNMANAGED ENVIRONMENT
#include <Mfidl.h> // for IMFMediaBuffer support + other COM stuff

void process_photo(void *photo_buffer_unknown, int photo_width, int photo_height)
{
    // photo_buffer_unknown = photoCaptureFrame.GetUnsafePointerToBuffer() in managed environment which is an IntPtr

    IMFMediaBuffer *media_buffer;
    if (SUCCEEDED(reinterpret_cast<IUnknown *>(photo_buffer_unknown)->QueryInterface<IMFMediaBuffer>(&media_buffer)))
    {
        BYTE* photo_buffer = NULL;
        if (SUCCEEDED(media_buffer->Lock(&photo_buffer, NULL, NULL)))
        {
            // process photo_buffer with OpenCV (wrapped in a cv::Mat)

            media_buffer->Unlock();
            media_buffer->Release(); // QueryInterface on IUnknown has incremented reference count by one
        }
    }
}

注意:从photoCaptureFrame.GetUnsafePointerToBuffer()返回的指针仍然必须在托管环境中释放,例如我的问题:
// MANAGED ENVIRONMENT
IntPtr mediaBufferUnknownPtr = photoCaptureFrame.GetUnsafePointerToBuffer();
// send mediaBufferUnknownPtr to native function through extern DLL call
Marshal.Release(mediaBufferUnknownPtr)

关于c# - PhotoCaptureFrame中的IMFMediaBuffer,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47383795/

10-11 18:33