/**************************************************************************** * Copyright 2019 Nreal Techonology Limited. All rights reserved. * * This file is part of NRSDK. * * https://www.nreal.ai/ * *****************************************************************************/ namespace NRKernal { using System; using UnityEngine; /// Create a YUV camera texture. public class NRRGBCamTextureYUV : CameraModelView { /// The on update. public Action OnUpdate; /// A yuv texture frame. public struct YUVTextureFrame { /// The time stamp. public UInt64 timeStamp; /// The gain public UInt32 gain; /// The exposureTime public UInt32 exposureTime; /// The texture y coordinate. public Texture2D textureY; /// The texture u. public Texture2D textureU; /// The texture v. public Texture2D textureV; /// The buffer. public byte[] YBuf; /// The buffer. public byte[] UBuf; /// The buffer. public byte[] VBuf; } /// Information describing the frame. private YUVTextureFrame m_FrameData; /// Creates the tex. private void CreateTex() { if (m_FrameData.textureY == null) { m_FrameData = new YUVTextureFrame(); m_FrameData.textureY = new Texture2D(Width, Height, TextureFormat.Alpha8, false); m_FrameData.textureU = new Texture2D(Width / 2, Height / 2, TextureFormat.Alpha8, false); m_FrameData.textureV = new Texture2D(Width / 2, Height / 2, TextureFormat.Alpha8, false); } } /// Gets the texture. /// The texture. public YUVTextureFrame GetTexture() { if (m_FrameData.textureY == null) { CreateTex(); } return m_FrameData; } /// Default constructor. public NRRGBCamTextureYUV() : base(CameraImageFormat.YUV_420_888) { CreateTex(); } /// Load raw texture data. /// . protected override void OnRawDataUpdate(FrameRawData frame) { LoadYUVTexture(frame); OnUpdate?.Invoke(m_FrameData); } /// Loads yuv texture. /// The frame. private void LoadYUVTexture(FrameRawData frame) { if (frame.data == null || frame.data.Length == 0) { NRDebugger.Error("[NRRGBCamTextureYUV] LoadYUVTexture error: frame is null"); return; } int size = frame.data.Length; if (m_FrameData.YBuf == null) { m_FrameData.YBuf = new byte[size * 2 / 3]; m_FrameData.UBuf = new byte[size / 6]; m_FrameData.VBuf = new byte[size / 6]; } if (m_FrameData.textureY == null) { CreateTex(); } m_FrameData.timeStamp = frame.timeStamp; m_FrameData.gain = frame.gain; m_FrameData.exposureTime = frame.exposureTime; Array.Copy(frame.data, 0, m_FrameData.YBuf, 0, m_FrameData.YBuf.Length); Array.Copy(frame.data, m_FrameData.YBuf.Length, m_FrameData.UBuf, 0, m_FrameData.UBuf.Length); Array.Copy(frame.data, m_FrameData.YBuf.Length + m_FrameData.UBuf.Length, m_FrameData.VBuf, 0, m_FrameData.VBuf.Length); m_FrameData.textureY.LoadRawTextureData(m_FrameData.YBuf); m_FrameData.textureU.LoadRawTextureData(m_FrameData.UBuf); m_FrameData.textureV.LoadRawTextureData(m_FrameData.VBuf); m_FrameData.textureY.Apply(); m_FrameData.textureU.Apply(); m_FrameData.textureV.Apply(); } /// On texture stopped. protected override void OnStopped() { base.OnStopped(); GameObject.Destroy(m_FrameData.textureY); GameObject.Destroy(m_FrameData.textureU); GameObject.Destroy(m_FrameData.textureV); m_FrameData.textureY = null; m_FrameData.textureU = null; m_FrameData.textureV = null; m_FrameData.YBuf = null; m_FrameData.UBuf = null; m_FrameData.VBuf = null; } } }