2017-11-20 28 views
3

Unity 5.2에서 Hololens 탐지 가능한 카메라를 사용하는 컴퓨터 비전 플러그인이 있습니다. 저는 카메라 모드 인 NV12 컬러 포맷으로 2048x1156 인 가장 높은 해상도로 사진 모드를 활성화 한 상태에서 UnityEngine.XR.WSA.WebCam.PhotoCaptureFrame 클래스를 사용합니다.PhotoCaptureFrame의 IMFMediaBuffer

PhotoCaptureFrame 클래스 :

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) 

그러나, 복사 원시 버퍼마다 : 순간 https://docs.unity3d.com/2017.2/Documentation/ScriptReference/XR.WSA.WebCam.PhotoCaptureFrame.html

, 나는 어떤 하나의 사진을 처리하기 위해 내 플러그인에 대해이 작업을 수행합니다. 내 플러그인에서 직접 원시 버퍼를 사용하고 싶습니다.

IntPtr rawBufferPtr = photo.GetUnsafePointerToBuffer(); // COM pointer to IMFMediaBuffer is incremented 
// send rawBufferPtr to plugin (native function described below) 
Marshal.Release(rawBufferPtr); 

IMFMediaBuffer 인터페이스 : 그래서 나는이 시도 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 객체를 전달하는 것과 관련이 있습니까?

대단히 감사합니다!

+0

것은 당신이 Marshal.Release 전화 마십시오 photoCaptureFrame.GetUnsafePointerToBuffer()에서 반환 된 포인터는 여전히 내 질문에 같이 관리되는 환경에서 출시한다 process_photo 메소드를 호출하기 전에? 그건 나쁠거야. –

+0

그것은 실제로 나쁘지만 아니오. Marshal.Release가 호출되기 전에 플러그인에 대한 호출이 완료됩니다. 대신 플러그인이 충돌하기 때문에 '완료'라고 말합니다. – RCYR

+1

아마도 캐스팅 대신 photo_buffer_wrapper의 IID_IMFMediaBuffer에서 QueryInterface를 시도해야합니다. 포인터가 실제로 IMFMediaBuffer에 대한 참조가 아니고 IUnknown 등에서 참조되는 경우입니다. –

답변

1

나는 내 자신의 질문에 대답 할 것이다.

에 대한 포인터가 아닌 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 
     } 
    } 
} 

NB : 여기에 의도 한대로 작동 수정 된 기본 기능입니다

// MANAGED ENVIRONMENT 
IntPtr mediaBufferUnknownPtr = photoCaptureFrame.GetUnsafePointerToBuffer(); 
// send mediaBufferUnknownPtr to native function through extern DLL call 
Marshal.Release(mediaBufferUnknownPtr)