Last active
January 14, 2021 04:10
-
-
Save makihiro/c880535fa6f9e3055f6371e5c3142add to your computer and use it in GitHub Desktop.
ARTest-Reproducer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.Rendering; | |
using UnityEngine.XR.ARFoundation; | |
using WebSocketSharp; | |
using WebSocketSharp.Server; | |
using System.IO; | |
// Replay AR data and camera images | |
namespace ARKitStream | |
{ | |
public sealed class Reproducer : MonoBehaviour | |
{ | |
public class ARKitService : WebSocketBehavior | |
{ | |
public ARKitService() | |
{ | |
} | |
protected override void OnMessage(MessageEventArgs e) | |
{ | |
Debug.Log(e); | |
} | |
public void ExternalSend(byte[] data) | |
{ | |
Send(data); | |
} | |
public void ExternalSendAsync(byte[] data) | |
{ | |
SendAsync(data, null); | |
} | |
} | |
[SerializeField] ARCameraManager cameraManager = null; | |
[SerializeField] uint port = 8888; | |
[SerializeField] int targetFrameRate = 30; | |
RenderTexture renderTexture; | |
WebSocketServer server; | |
ARKitService service; | |
public string SavePath; | |
[SerializeField] string dirPath; | |
Texture2D tex; | |
IEnumerator<byte[]> coroutine; | |
Camera _camera; | |
float m_LastLocalizeTime = 0; | |
float m_LocalizationInterval = 4; | |
bool isLocalizing = false; | |
void Awake() | |
{ | |
Application.targetFrameRate = targetFrameRate; | |
} | |
void Start() | |
{ | |
if (!Application.isEditor) | |
{ | |
Destroy(gameObject); | |
return; | |
} | |
SavePath = Application.persistentDataPath + "/saved-ardata.bytes"; | |
dirPath = Application.persistentDataPath + "/imgs/"; | |
tex = new Texture2D(1440, 1920); | |
// Prepare coroutine for loading AR data | |
coroutine = LoadARFileCoroutine(); | |
cameraManager.frameReceived += OnCameraFrameReceived; | |
// Prepare camera texture | |
var commandBuffer = new CommandBuffer(); | |
commandBuffer.name = "CameraView"; | |
commandBuffer.Blit(tex, BuiltinRenderTextureType.CameraTarget); | |
_camera = GameObject.Find("AR Camera").GetComponent<Camera>(); | |
_camera.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, commandBuffer); | |
server = new WebSocketServer((int)port); | |
server.AddWebSocketService<ARKitService>("/arkit", (behaviour) => | |
{ | |
this.service = behaviour; | |
}); | |
server.Start(); | |
if (renderTexture == null) | |
{ | |
renderTexture = new RenderTexture(1920, 1440, 0, RenderTextureFormat.ARGB32); | |
} | |
} | |
void OnDestroy() | |
{ | |
if (cameraManager != null) | |
{ | |
cameraManager.frameReceived -= OnCameraFrameReceived; | |
} | |
server?.Stop(); | |
} | |
void OnValidate() | |
{ | |
if (cameraManager == null) | |
{ | |
cameraManager = FindObjectOfType<ARCameraManager>(); | |
} | |
} | |
void Update() | |
{ | |
if (service != null) | |
{ | |
// Load LoadARFileCoroutine() by each frame update | |
coroutine.MoveNext(); | |
if (coroutine.Current.Length > 0) | |
{ | |
// Send AR data to ARKitStream Receiver | |
service.ExternalSendAsync(coroutine.Current); | |
} | |
} | |
else | |
{ | |
Debug.Log("Preparing data to play"); | |
} | |
} | |
// Coroutine for loading saved AR data | |
public IEnumerator<byte[]> LoadARFileCoroutine() | |
{ | |
const byte RecordSeparator = 0x1e; | |
using (var stream = File.OpenRead(SavePath)) | |
{ | |
for ( ; ; ) | |
{ | |
var data = stream.ReadByte(); | |
if (data < 0) | |
{ | |
yield break; | |
} | |
using (var mem = new MemoryStream()) | |
{ | |
// Load each record data | |
for ( ; ; ) | |
{ | |
if (data == RecordSeparator) | |
{ | |
var tmp = new int[4]; | |
for (int i = 0; i < 4; i++) tmp[i] = stream.ReadByte(); | |
// use five sequential 0x1e as a record separator | |
if (tmp[0] == 0x1e && tmp[1] == 0x1e && tmp[2] == 0x1e && tmp[3] == 0x1e) | |
{ | |
break; | |
} | |
else | |
{ | |
mem.WriteByte((byte)data); | |
for (int i = 0; i < 4; i++) mem.WriteByte((byte)tmp[i]); | |
} | |
} | |
else | |
{ | |
mem.WriteByte((byte)data); | |
} | |
data = stream.ReadByte(); | |
} | |
var record = mem.ToArray(); | |
yield return record; | |
} | |
} | |
} | |
} | |
// Set texture by captured camera image | |
void OnCameraFrameReceived(ARCameraFrameEventArgs args) | |
{ | |
var cameraImagePath = dirPath + args.timestampNs.Value + ".jpg"; | |
if (File.Exists(cameraImagePath)) | |
{ | |
FileStream stream = File.OpenRead(cameraImagePath); | |
var data = new byte[stream.Length]; | |
stream.Read(data, 0, (int)stream.Length); | |
tex.LoadImage(data); | |
float curTime = Time.unscaledTime; | |
stream.Close(); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment