/****************************************************************************
* Copyright 2019 Nreal Techonology Limited. All rights reserved.
*
* This file is part of NRSDK.
*
* https://www.nreal.ai/
*
*****************************************************************************/
namespace NRKernal.Record
{
using UnityEngine;
using System;
using AOT;
using System.Runtime.InteropServices;
/// A video encoder.
public class VideoEncoder : IEncoder
{
#if !UNITY_EDITOR
private const int STARTENCODEEVENT = 0x1001;
private const int STOPENCODEEVENT = 0x1002;
private NativeEncoder mNativeEncoder;
private delegate void RenderEventDelegate(int eventID);
private static RenderEventDelegate RenderThreadHandle = new RenderEventDelegate(RunOnRenderThread);
private static IntPtr RenderThreadHandlePtr = Marshal.GetFunctionPointerForDelegate(RenderThreadHandle);
#endif
private AudioRecordTool m_AudioEncodeTool;
public NativeEncodeConfig EncodeConfig;
private IntPtr androidMediaProjection { get; set; }
private IntPtr m_TexPtr = IntPtr.Zero;
private byte[] m_AudioRawData;
private bool m_IsStarted = false;
/// Default constructor.
public VideoEncoder()
{
#if !UNITY_EDITOR
mNativeEncoder = NativeEncoder.GetInstance();
mNativeEncoder.Register(this);
#endif
}
#if !UNITY_EDITOR
[MonoPInvokeCallback(typeof(RenderEventDelegate))]
private static void RunOnRenderThread(int eventID)
{
if (eventID == STARTENCODEEVENT)
{
NativeEncoder.GetInstance().Start();
}
//if (eventID == STOPENCODEEVENT)
//{
// NativeEncoder.Stop();
//}
}
#endif
/// Configurations the given parameter.
/// The parameter.
public void Config(CameraParameters param)
{
EncodeConfig = new NativeEncodeConfig(param);
androidMediaProjection = (param.mediaProjection != null) ? param.mediaProjection.GetRawObject() : IntPtr.Zero;
}
/// Adjust the volume of encoder.
/// Recorder index.
/// The factor of volume.
public void AdjustVolume(RecorderIndex recordIdx, float factor)
{
#if !UNITY_EDITOR
mNativeEncoder.AdjustVolume(recordIdx, factor);
#endif
}
/// Starts this object.
public void Start()
{
if (m_IsStarted)
{
return;
}
NRDebugger.Info("[VideoEncoder] Start");
// if (EncodeConfig.audioUseExternalData)
// {
// InitAudioEncodeTool();
// m_AudioEncodeTool?.StartRecord();
// }
NRDebugger.Info("[VideoEncoder] Config {0}", EncodeConfig.ToString());
#if !UNITY_EDITOR
mNativeEncoder.SetConfigration(EncodeConfig, androidMediaProjection);
//mNativeEncoder.Start();
GL.IssuePluginEvent(RenderThreadHandlePtr, STARTENCODEEVENT);
#endif
m_IsStarted = true;
}
private void InitAudioEncodeTool()
{
AudioListener audioListener = null;
if (NRSessionManager.Instance.NRHMDPoseTracker != null)
{
audioListener = NRSessionManager.Instance.NRHMDPoseTracker.centerCamera.gameObject.GetComponent();
}
else if (GameObject.FindObjectOfType() != null)
{
audioListener = GameObject.FindObjectOfType();
}
if (audioListener != null)
{
m_AudioEncodeTool = audioListener.gameObject.GetComponent();
if (m_AudioEncodeTool == null)
{
m_AudioEncodeTool = audioListener.gameObject.AddComponent();
}
}
else
{
throw (new MissingComponentException("Can not find a 'AudioListener' in current scene."));
}
}
/// Commits.
/// The renderTexture.
/// The timestamp.
public void Commit(RenderTexture rt, UInt64 timestamp)
{
if (!m_IsStarted)
{
return;
}
if (m_TexPtr == IntPtr.Zero)
{
m_TexPtr = rt.GetNativeTexturePtr();
}
#if !UNITY_EDITOR
mNativeEncoder.UpdateSurface(m_TexPtr, timestamp);
if (m_AudioEncodeTool != null)
{
bool result = m_AudioEncodeTool.Flush(ref m_AudioRawData);
if (result)
{
mNativeEncoder.UpdateAudioData(m_AudioRawData, m_AudioEncodeTool.SampleRate,2,1);
}
}
#endif
}
/// Stops this object.
public void Stop()
{
if (!m_IsStarted)
{
return;
}
NRDebugger.Info("[VideoEncoder] Stop");
m_AudioEncodeTool?.StopRecord();
#if !UNITY_EDITOR
//GL.IssuePluginEvent(RenderThreadHandlePtr, STOPENCODEEVENT);
mNativeEncoder.Stop();
#endif
m_IsStarted = false;
}
/// Releases this object.
public void Release()
{
NRDebugger.Info("[VideoEncoder] Release...");
#if !UNITY_EDITOR
mNativeEncoder.UnRegister(this);
mNativeEncoder.Destroy();
#endif
if (m_AudioEncodeTool != null)
{
GameObject.Destroy(m_AudioEncodeTool);
m_AudioEncodeTool = null;
}
}
}
}