Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Let us know a bit about your interests, and if you'd like to become more directly involved. Take our survey!
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    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

    bilal_unity428

    Joined:
    Feb 27, 2018
    Posts:
    2
    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.     }
    7.  
    8.     int width = image.Width;
    9.     int height = image.Height;
    10.     IntPtr yPixelBuffer = image.Y;
    11.  
    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

    chaosemer

    Official Google Employee

    Joined:
    Jul 5, 2017
    Posts:
    12
    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

    bilal_unity428

    Joined:
    Feb 27, 2018
    Posts:
    2
    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.