Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on Dec 8, 2022, between 7 am & 7 pm EST, in the DOTS Dev Blitz Day 2022 - Q&A forum, Discord, and Unity3D Subreddit to learn more about DOTS directly from the Unity Developers.
    Dismiss Notice
  3. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

Get WebcamTexture pixel data without using GetPixels32()

Discussion in 'Scripting' started by Red_Dragon69, Jul 29, 2022.

  1. Red_Dragon69

    Red_Dragon69

    Joined:
    Sep 7, 2015
    Posts:
    78
    Hi,
    I'm currently trying to get WebcamTexture data without using GetPixels32(). I ended up using the following code, which should work, as long as Multithreaded Rendering is turned off in PlayerSettings. But Unity crashes every time and I don't know why :( Has anybody already achieved smth with a similar approach? WebcamTexture itself works, the RawImage is just for checking the obtained pixels. It seems that I made a mistake at Marshal.Copy, but I can't figure it out...

    Code (CSharp):
    1. IntPtr imgBufferPtr = webcamTexture.GetNativeTexturePtr();
    2. Texture2D texture = new Texture2D(webcamTexture.width, webcamTexture.height, TextureFormat.RGB24, false);
    3.  
    4. int bufferSize = webcamTexture.width * webcamTexture.height * 3;
    5. byte[] rawData = new byte[bufferSize];
    6. Marshal.Copy(imgBufferPtr, rawData, 0, bufferSize);
    7. texture.LoadRawTextureData(rawData);
    8. texture.Apply();
    9.  
    10. // display temporary achieved image
    11. rawImage.material.mainTexture = texture;
    Bug Logs:
    Obtained 27 stack frames

    0x00007ffe36c19f49 (mono-2.0-bdwgc) [icall-def.h:824] ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged_raw

    0x000001da2719edff (Mono JIT Code) (wrapper managed-to-native) System.Runtime.InteropServices.Marshal:copy_from_unmanaged_fixed (intptr,int,System.Array,int,void*)

    0x000001da273cc893 (Mono JIT Code) System.Runtime.InteropServices.Marshal:Copy (intptr,byte[],int,int)
    ....


    Best regards :)
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    29,857
    Using Marshal.Copy is essentially "unprotected" coding. This means you are responsible for 100% of having the right source, destination, count, etc. Otherwise... BOOM.

    When it blows up, usually you copied too much, or you copied data into something that isn't able to be changed.

    Since Marshal.Copy is a highly-overloaded method, I suggest you use named arguments to make sure you are supplying source / destination correctly, etc.
     
    Red_Dragon69 likes this.
  3. Red_Dragon69

    Red_Dragon69

    Joined:
    Sep 7, 2015
    Posts:
    78
    Hi, thank you for your reply.

    I played around a lot and came to the conclusion, that this doesn't work as I intended it. Seems, that the webcamTexture.GetNativeTexturePtr(); returns a pointer indeed, but the data can't be used directly in Unity for further usage. As far as I know now, this approach doesn't bring the data from GPU to CPU within Unity, explaining why the copy process doesn't work, or the returned image is pure noise or byte array is always empty. For this, using GetPixels32() is needed.

    When creating platform specific texture objects outside of Unity and using these textures in Unity Scenes Texture2D.CreateExternalTexture may be the way to go.

    Best regards :)