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