/**************************************************************************** * Copyright 2019 Nreal Techonology Limited. All rights reserved. * * This file is part of NRSDK. * * https://www.nreal.ai/ * *****************************************************************************/ namespace NRKernal.Experimental.StreammingCast { using NRKernal.Record; using System; using System.Collections.Generic; using UnityEngine; /// An observer view frame capture context. public class ObserverViewFrameCaptureContext { /// The blender. private ObserverViewBlender m_Blender; /// The frame provider. private AbstractFrameProvider m_FrameProvider; /// The capture behaviour. private NRObserverViewBehaviour m_CaptureBehaviour; /// The net worker. private ObserverViewNetWorker m_NetWorker; /// The encoder. private IEncoder m_Encoder; /// Options for controlling the camera. private CameraParameters m_CameraParameters; /// True if is initialize, false if not. private bool m_IsInitialized = false; private List m_FrameConsumerList; /// Gets the preview texture. /// The preview texture. public Texture PreviewTexture { get { return m_Blender?.BlendTexture; } } /// Gets the behaviour. /// The behaviour. public NRObserverViewBehaviour GetBehaviour() { return m_CaptureBehaviour; } /// Gets frame provider. /// The frame provider. public AbstractFrameProvider GetFrameProvider() { return m_FrameProvider; } /// Request camera parameter. /// The CameraParameters. public CameraParameters RequestCameraParam() { return m_CameraParameters; } /// Gets the encoder. /// The encoder. public IEncoder GetEncoder() { return m_Encoder; } /// Default constructor. public ObserverViewFrameCaptureContext() { } /// Starts capture mode. /// The parameter. public void StartCaptureMode(CameraParameters param) { this.m_CameraParameters = param; if (m_CaptureBehaviour == null) { this.m_CaptureBehaviour = this.GetObserverViewCaptureBehaviour(); } this.m_Encoder = new VideoEncoder(); this.m_Encoder.Config(param); this.m_Blender = new ObserverViewBlender(); this.m_Blender.Config(m_CaptureBehaviour.CaptureCamera, m_Encoder, param); this.m_NetWorker = new ObserverViewNetWorker(this); this.m_NetWorker.Listen(); this.m_FrameProvider = new ObserverViewFrameProvider(m_CaptureBehaviour.CaptureCamera, this.m_CameraParameters.frameRate); this.m_FrameProvider.OnUpdate += UpdateFrame; this.m_FrameConsumerList = new List(); this.Sequence(m_Blender); this.m_IsInitialized = true; } /// Auto adaption for BlendMode based on supported feature on current device. /// source blendMode. /// Fallback blendMode. public BlendMode AutoAdaptBlendMode(BlendMode blendMode) { if (!NRDevice.Subsystem.IsFeatureSupported(NRSupportedFeature.NR_FEATURE_RGB_CAMERA)) return BlendMode.VirtualOnly; return blendMode; } private ObserverViewFrameCaptureContext Sequence(IFrameConsumer consummer) { this.m_FrameConsumerList.Add(consummer); return this; } private void UpdateFrame(UniversalTextureFrame frame) { for (int i = 0; i < m_FrameConsumerList.Count; i++) { m_FrameConsumerList[i].OnFrame(frame); } } /// Gets observer view capture behaviour. /// The observer view capture behaviour. private NRObserverViewBehaviour GetObserverViewCaptureBehaviour() { NRObserverViewBehaviour capture = GameObject.FindObjectOfType(); Transform headParent = null; if (NRSessionManager.Instance.NRSessionBehaviour != null) { headParent = NRSessionManager.Instance.NRSessionBehaviour.transform.parent; } if (capture == null) { capture = GameObject.Instantiate(Resources.Load("Record/Prefabs/NRObserverViewBehaviour"), headParent); } GameObject.DontDestroyOnLoad(capture.gameObject); return capture; } /// Stops capture mode. public void StopCaptureMode() { this.Release(); } /// Starts a capture. /// The IP. /// The callback. public void StartCapture(string ip, Action callback) { if (!m_IsInitialized) { callback?.Invoke(false); return; } NRDebugger.Info("[CaptureContext] Start... {0}", ip); ((VideoEncoder)m_Encoder).EncodeConfig.SetOutPutPath(string.Format("rtp://{0}:5555", ip)); m_NetWorker.CheckServerAvailable(ip, (result) => { NRDebugger.Info("[ObserverView] CheckServerAvailable : " + result); if (result) { m_Encoder?.Start(); m_FrameProvider?.Play(); } else { this.Release(); } callback?.Invoke(result); }); } /// Stops a capture. public void StopCapture() { if (!m_IsInitialized) { return; } NRDebugger.Info("[CaptureContext] Stop..."); // Need stop encoder firstly. m_Encoder?.Stop(); m_FrameProvider?.Stop(); } /// Releases this object. public void Release() { if (!m_IsInitialized) { return; } NRDebugger.Info("[CaptureContext] Release..."); if (m_FrameProvider != null) { this.m_FrameProvider.OnUpdate -= UpdateFrame; m_FrameProvider?.Release(); } m_Blender?.Dispose(); m_Encoder?.Release(); m_NetWorker?.Close(); m_Blender = null; m_Encoder = null; m_NetWorker = null; if (m_CaptureBehaviour != null) { GameObject.DestroyImmediate(m_CaptureBehaviour.gameObject); m_CaptureBehaviour = null; } m_IsInitialized = false; } } }