Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

Converting IntPtr (CPU buffer representing Y channel) to AndroidJavaObject without copy

Discussion in 'ARCore' started by bilal_unity428, Aug 23, 2018.

  1. bilal_unity428


    Feb 27, 2018
    When calling `AcquireCameraImageBytes` to retrieve an `CameraImageBytes` instance and the underlying `Y` IntPtr buffer, I need to pass that IntPtr to my own AAR library which takes a `ByteBuffer` as argument. I could not find a way of converting the `IntPtr` to an `AndroidJavaObject` reference which would allow me to pass it to my method.

    Code (CSharp):
    1. using (GoogleARCore.CameraImageBytes image = GoogleARCore.Frame.CameraImage.AcquireCameraImageBytes())
    2. {
    3.     if (!image.IsAvailable)
    4.     {
    5.         return;
    6.     }
    8.     int width = image.Width;
    9.     int height = image.Height;
    10.     IntPtr yPixelBuffer = image.Y;
    12.     using (AndroidJavaClass utilsClass = new AndroidJavaClass("com.mypackage.MyClassUtils"))
    13.     {
    14.         utilsClass.CallStatic("setCurrentBuffer", yPixelBuffer, width, height); // <-- Need to pass a AndroidJavaObject here but no way to just pass the ByteBuffer
    15.     }
    16. }
    the Java method implementation:
    Code (CSharp):
    1. public class MyClassUtils {
    2.     public static final void setCurrentBuffer(
    3.                                               ByteBuffer buffer,
    4.                                               int width,
    5.                                               int height) {
    6. }
    Is there any way to convert the `IntPtr` to its underlying `ByteBuffer` reference ?
  2. chaosemer


    Official Google Employee

    Jul 5, 2017
    The IntPtr is actually backed by a C unsigned char*, i.e. a raw pointer to the Y channel. The most efficient way to do this would be to jump through JNI (in C) and create a ByteBuffer using the JNI NewDirectByteBuffer.

    Alternatively, you can always use Marshal.Copy to convert an IntPtr into a C# byte[], and then do normal Unity things to convert that to Java objects. That involves a bunch of copies of the image which may impact performance, though.
  3. bilal_unity428


    Feb 27, 2018
    The IntPtr is actually backed by a C unsigned char* @chaosemer thanks a lot for this, I really thought it was pointing to the address of a ByteBuffer object, my bad. I don't want to create a new ByteBuffer with NewDirectByteBuffer but to directly pass the IntPtr to my .so C++ library and use the pointer to unsigned char* there. I reckon I will have to do that. Thanks again.