/****************************************************************************
* 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;
}
}
}