/****************************************************************************
* 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.Linq;
using UnityEngine;
using System;
using NRKernal.Experimental.NetWork;
using System.IO;
using System.Collections;
/// A first person streamming cast.
public class FirstPersonStreammingCast : MonoBehaviour
{
public delegate void OnResponse(bool result);
/// The FPS configuration view.
[SerializeField]
private FPSConfigView m_FPSConfigView;
public BlendMode m_BlendMode = BlendMode.Blend;
public ResolutionLevel m_ResolutionLevel = ResolutionLevel.Middle;
public LayerMask m_CullingMask = -1;
public NRVideoCapture.AudioState m_AudioState = NRVideoCapture.AudioState.None;
public bool useGreenBackGround = false;
/// The net worker.
private NetWorkBehaviour m_NetWorker;
/// The video capture.
private NRVideoCapture m_VideoCapture = null;
public NRVideoCapture VideoCapture
{
get
{
return m_VideoCapture;
}
}
private string m_ServerIP;
/// Gets the full pathname of the rtp file.
/// The full pathname of the rtp file.
public string RTPPath
{
get
{
return string.Format(@"rtp://{0}:5555", m_ServerIP);
}
}
public string VideoSavePath
{
get
{
string timeStamp = Time.time.ToString().Replace(".", "").Replace(":", "");
string filename = string.Format("Nreal_Record_{0}.mp4", timeStamp);
string filepath = Path.Combine(Application.persistentDataPath, filename);
return filepath;
}
}
private bool m_IsInitialized = false;
private bool m_IsStreamLock = false;
private bool m_IsStreamStarted = false;
private bool m_IsRecordStarted = false;
public enum ResolutionLevel
{
High,
Middle,
Low,
}
/// Starts this object.
void Start()
{
this.Init();
}
/// Initializes this object.
private void Init()
{
if (m_IsInitialized)
{
return;
}
m_FPSConfigView.OnStreamBtnClicked += OnStream;
m_FPSConfigView.OnRecordBtnClicked += OnRecord;
m_IsInitialized = true;
}
private void OnRecord(OnResponse response)
{
if (!m_IsRecordStarted)
{
CreateAndStart();
}
else
{
StopVideoCapture();
}
response?.Invoke(true);
m_IsRecordStarted = !m_IsRecordStarted;
}
private void OnStream(OnResponse response)
{
if (m_IsStreamLock)
{
return;
}
m_IsStreamLock = true;
if (m_NetWorker == null)
{
m_NetWorker = new NetWorkBehaviour();
m_NetWorker.Listen();
}
if (!m_IsStreamStarted)
{
LocalServerSearcher.Instance.Search((result) =>
{
NRDebugger.Info("[FPStreammingCast] Get the server result:{0} ip:{1}", result.isSuccess, result.endPoint?.Address);
if (result.isSuccess)
{
string ip = result.endPoint.Address.ToString();
m_NetWorker.CheckServerAvailable(ip, (isavailable) =>
{
NRDebugger.Info("[FPStreammingCast] Is the server {0} ok? {1}", ip, result);
if (isavailable)
{
m_ServerIP = ip;
m_IsStreamStarted = true;
CreateAndStart();
}
response?.Invoke(isavailable);
m_IsStreamLock = false;
});
}
else
{
m_IsStreamLock = false;
response?.Invoke(false);
NRDebugger.Error("[FPStreammingCast] Can not find the server...");
}
});
}
else
{
StopVideoCapture();
m_IsStreamStarted = false;
m_IsStreamLock = false;
response?.Invoke(true);
}
}
/// Converts this object to a server.
private void CreateAndStart()
{
CreateVideoCapture(delegate ()
{
NRDebugger.Info("[FPStreammingCast] Start video capture.");
StartCoroutine(StartVideoCapture());
});
}
private Resolution GetResolutionByLevel(ResolutionLevel level)
{
var resolutions = NRVideoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height);
Resolution resolution = new Resolution();
switch (level)
{
case ResolutionLevel.High:
resolution = resolutions.ElementAt(0);
break;
case ResolutionLevel.Middle:
resolution = resolutions.ElementAt(1);
break;
case ResolutionLevel.Low:
resolution = resolutions.ElementAt(2);
break;
default:
break;
}
return resolution;
}
#region video capture
/// Creates video capture.
/// The callback.
private void CreateVideoCapture(Action callback)
{
NRDebugger.Info("[FPStreammingCast] Created VideoCapture Instance!");
if (m_VideoCapture != null)
{
callback?.Invoke();
return;
}
NRVideoCapture.CreateAsync(false, delegate (NRVideoCapture videoCapture)
{
if (videoCapture != null)
{
m_VideoCapture = videoCapture;
callback?.Invoke();
}
else
{
NRDebugger.Error("[FPStreammingCast] Failed to create VideoCapture Instance!");
}
});
}
/// Starts video capture.
public IEnumerator StartVideoCapture()
{
Resolution cameraResolution = GetResolutionByLevel(m_ResolutionLevel);
NRDebugger.Info("[FPStreammingCast] cameraResolution:" + cameraResolution);
if (m_VideoCapture != null)
{
CameraParameters cameraParameters = new CameraParameters();
cameraParameters.hologramOpacity = 1f;
cameraParameters.frameRate = cameraResolution.refreshRate;
cameraParameters.cameraResolutionWidth = cameraResolution.width;
cameraParameters.cameraResolutionHeight = cameraResolution.height;
cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;
cameraParameters.blendMode = m_BlendMode;
cameraParameters.audioState = m_AudioState;
// Send the audioState to server.
if (m_NetWorker != null)
{
LitJson.JsonData json = new LitJson.JsonData();
json["useAudio"] = (cameraParameters.audioState != NRVideoCapture.AudioState.None);
m_NetWorker.SendMsg(json, (response) =>
{
bool result;
if (bool.TryParse(response["success"].ToString(), out result) && result)
{
m_VideoCapture.StartVideoModeAsync(cameraParameters, OnStartedVideoCaptureMode, true);
}
else
{
NRDebugger.Error("[FPStreammingCast] Can not received response from server.");
}
});
}
else
{
m_VideoCapture.StartVideoModeAsync(cameraParameters, OnStartedVideoCaptureMode, true);
}
}
else
{
NRDebugger.Info("[FPStreammingCast] VideoCapture object is null...");
}
yield return new WaitForEndOfFrame();
}
/// Stops video capture.
public void StopVideoCapture()
{
NRDebugger.Info("[FPStreammingCast] Stop Video Capture!");
m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}
/// Executes the 'started video capture mode' action.
/// The result.
void OnStartedVideoCaptureMode(NRVideoCapture.VideoCaptureResult result)
{
if (!result.success)
{
NRDebugger.Info("[FPStreammingCast] Started Video Capture Mode Faild!");
return;
}
NRDebugger.Info("[FPStreammingCast] Started Video Capture Mode!");
m_VideoCapture.StartRecordingAsync(m_IsStreamStarted ? RTPPath : VideoSavePath, OnStartedRecordingVideo);
m_VideoCapture.GetContext().GetBehaviour().CaptureCamera.cullingMask = m_CullingMask.value;
m_VideoCapture.GetContext().GetBehaviour().CaptureCamera.backgroundColor = useGreenBackGround ? Color.green : Color.black;
}
/// Executes the 'stopped video capture mode' action.
/// The result.
void OnStoppedVideoCaptureMode(NRVideoCapture.VideoCaptureResult result)
{
NRDebugger.Info("[FPStreammingCast] Stopped Video Capture Mode!");
m_VideoCapture = null;
}
/// Executes the 'started recording video' action.
/// The result.
void OnStartedRecordingVideo(NRVideoCapture.VideoCaptureResult result)
{
NRDebugger.Info("[FPStreammingCast] Started Recording Video!");
}
/// Executes the 'stopped recording video' action.
/// The result.
void OnStoppedRecordingVideo(NRVideoCapture.VideoCaptureResult result)
{
NRDebugger.Info("[FPStreammingCast] Stopped Recording Video!");
m_VideoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
if (m_NetWorker != null)
{
m_NetWorker?.Close();
m_NetWorker = null;
}
}
#endregion
}
}