Macで映像転送と言えばSyphonですが、PythonでSyphonできないぽかったのでメモリマップトファイルを利用して実装しました。メモリマップトファイルはメモリを映像のような大量のデータだとソケット通信とかでは速度が間に合わないので、これ一択ぽいです。メモリマップトファイルにバイト列として画像を置いて通信する仕組みです。
注意点としては、映像のフォーマットを送受信出来ないので、決めうちにする必要があります。今回は1200x1200のRGB画像を送る前提のサンプルコードを載せておきます。なおコードは元のプロジェクトから抜き出して書いているもので、テストしておりません。ライセンスはパブリックドメインです。
Unityは、Monoではなく.NET Coreでないとメモリマップトファイルが利用出来なかった気がします。Unity側ではRawImageにメモリマップトファイルから取り出したTextureを貼ってます。Textureは明示的にDestoryしないとメモリーリークするので気をつけて。
Pythonサンプルコード
import os import mmap DATA_LENGTH = 4320000 fd = os.open('/tmp/mmappython', os.O_CREAT | os.O_TRUNC | os.O_RDWR) assert os.write(fd, b'\x00' * DATA_LENGTH) == DATA_LENGTH buf = mmap.mmap(fd, DATA_LENGTH, mmap.MAP_SHARED, mmap.PROT_WRITE) buf.seek(0) byte_data = b'\x00' * DATA_LENGTH buf.write(byte_data) buf.close()
Unityサンプルコード
using System.Collections; using System.Collections.Generic; using System.IO; using System.IO.MemoryMappedFiles; using UnityEngine; using UnityEngine.UI; public class MmfManager : MonoBehaviour { private string filePath = "/tmp/mmappython"; private const int dataLength = 4320000; private RawImage rawImage; private MemoryMappedFile mmf; private MemoryMappedViewStream stream; public void InitMemoryMappedFile() { if (File.Exists(filePath) == false) { byte[] bs = new byte[dataLength]; using(FileStream fs = File.Open(filePath, FileMode.Create)) { fs.Write(bs, 0, bs.Length); } } mmf = MemoryMappedFile.CreateFromFile(filePath, FileMode.Open); Debug.Log(filePath); stream = mmf.CreateViewStream(); Debug.Log(stream.Capacity); Debug.Log(stream.Length); } void Start () { rawImage = GetComponent<RawImage>(); } void Update () { stream.Seek(0, SeekOrigin.Begin); byte[] buffer = new byte[dataLength]; int retVal = stream.Read(buffer, 0, dataLength); if (retVal == dataLength) { Texture oldTex = rawImage.texture; Texture2D tex = new Texture2D(1200, 1200, TextureFormat.RGB24, false); tex.LoadRawTextureData(buffer); tex.Apply(); rawImage.texture = tex; Destroy(oldTex); } } void OnDestroy() { stream.Close(); stream.Dispose(); mmf.Dispose(); stream = null; mmf = null; } }