Skip to content

Commit

Permalink
added syphon support - sadly with a bad performance
Browse files Browse the repository at this point in the history
  • Loading branch information
ICST-AHMI committed Dec 18, 2022
1 parent d72d37b commit 43a3a96
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 17 deletions.
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def register():
ui.register()
except ModuleNotFoundError:
print(
"Spout addon isn't available, install required module via Properties > Addons > Spout"
"Addon isn't available, install required module via Properties > Addons > Spout"
)


Expand Down
36 changes: 36 additions & 0 deletions fbs/FrameBufferSharingServer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from abc import ABC, abstractmethod
from sys import platform
from typing import Optional, Any

import numpy as np

class FrameBufferSharingServer(ABC):
def __init__(self, name: str):
self.name = name

@abstractmethod
def send_texture(self, texture_id: int, width: int, height: int, is_flipped: bool = False):
pass

@abstractmethod
def can_memory_buffer(self):
pass

@abstractmethod
def create_memory_buffer(self, texture_name: str, size: int):
pass

@abstractmethod
def write_memory_buffer(self, texture_name: str, buffer):
pass

@staticmethod
def create(name: str):
if platform.startswith("darwin"):
from spyphon.fbs.syphon.SyphonServer import SyphonServer
return SyphonServer(name)
elif platform.startswith("win"):
from spyphon.fbs.spout.SpoutServer import SpoutServer
return SpoutServer(name)
else:
raise Exception(f"Platform {platform} is not supported!")
Empty file added fbs/__init__.py
Empty file.
52 changes: 52 additions & 0 deletions fbs/spout/SpoutServer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import logging
from argparse import ArgumentParser, Namespace
from typing import Optional

import SpoutGL
import numpy as np
import bgl

from spyphon.fbs.FrameBufferSharingServer import FrameBufferSharingServer


class SpoutServer(FrameBufferSharingServer):
def __init__(self, name: str = "SpoutServer"):
super().__init__(name)
self.ctx: Optional[SpoutGL.SpoutSender] = None

def setup(self):
# setup spout
self.ctx = SpoutGL.SpoutSender()
self.ctx.setSenderName(self.name)

def send_texture(self, texture_id: int, width: int, height: int, is_flipped: bool = False):
success = self.ctx.sendTexture(
texture_id, bgl.GL_TEXTURE_2D, width, height, is_flipped, 0)

if not success:
logging.warning("Could not send spout texture.")
return

self.ctx.setFrameSync(self.name)

def can_memory_buffer(self):
return True

def create_memory_buffer(self, texture_name: str, size: int):
success = self.ctx.createMemoryBuffer(texture_name, size)

if not success:
logging.warning("Could not create memory buffer.")

return

def write_memory_buffer(self, texture_name: str, buffer):
success = self.ctx.writeMemoryBuffer(texture_name, buffer, len(buffer))

if not success:
logging.warning("Could not write memory buffer.")

return

def release(self):
self.ctx.releaseSender()
Empty file added fbs/spout/__init__.py
Empty file.
33 changes: 33 additions & 0 deletions fbs/syphon/SyphonServer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from argparse import Namespace, ArgumentParser
from typing import Optional, Any

import numpy as np
import syphonpy

import logging

from spyphon.fbs.FrameBufferSharingServer import FrameBufferSharingServer


class SyphonServer(FrameBufferSharingServer):
def __init__(self, name: str = "SyphonServer"):
super().__init__(name)

self.ctx: Optional[syphonpy.SyphonServer] = None

def setup(self):
# setup spout
self.ctx = syphonpy.SyphonServer(self.name)
if self.ctx.error_state():
logging.error("error in Syphonserver")

def send_texture(self, texture_id: int, width: int, height: int, is_flipped: bool = False):
self.ctx.publish_frame_texture(texture_id,
syphonpy.MakeRect(0, 0, width, height),
syphonpy.MakeSize(width, height), is_flipped)

def can_memory_buffer(self):
return False

def release(self):
self.ctx.stop()
Empty file added fbs/syphon/__init__.py
Empty file.
35 changes: 20 additions & 15 deletions operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import json
from dataclasses import dataclass


try:
import SpoutGL

from spout.fbs.FrameBufferSharingServer import FrameBufferSharingServer
except ModuleNotFoundError as ex:
print(f"Could not load SpoutGL: {ex}")
print(f"Could not load FrameSharingModule: {ex}")

import uuid

Expand Down Expand Up @@ -48,7 +50,7 @@ def handler(scene, depsgraph):


# function for the draw handler to capture the texture from the perspective of the camera
def texshare_capture(self, context, camera, object, space, region, scene, layer, offscreen, spoutSender, showPreview, frame_metadata_buffer):
def texshare_capture(self, context, camera, object, space, region, scene, layer, offscreen, spyphonSender, showPreview, frame_metadata_buffer):
dWIDTH = camera.texshare.capture_width
dHEIGHT = camera.texshare.capture_height
applyCM = camera.texshare.applyColorManagmentSettings
Expand All @@ -75,12 +77,12 @@ def texshare_capture(self, context, camera, object, space, region, scene, layer,

buffer = frame_metadata_buffer.content

spoutSender.writeMemoryBuffer(camera.name, buffer, len(buffer))
#if spyphonSender.can_memory_buffer() == True:
# spyphonSender.write_memory_buffer(camera.name, buffer, len(buffer))

spoutSender.sendTexture(offscreen.color_texture, bgl.GL_TEXTURE_2D, dWIDTH, dHEIGHT, True, 0)
spoutSender.setFrameSync(camera.name)


spyphonSender.send_texture(offscreen.color_texture, dWIDTH, dHEIGHT, True)


# main function called when the settings 'enable' property is changed
def texshare_main(self, context):
global db_drawHandle
Expand All @@ -95,15 +97,18 @@ def texshare_main(self, context):
if context.camera.texshare.enable == 1 and dbID not in db_drawHandle:
# first we create a unique identifier for the reference db dicts
dbID = str(uuid.uuid1())
updateDraw = False

dWIDTH = guivars.capture_width
dHEIGHT = guivars.capture_height

# create a new spout sender instance
spoutSender = SpoutGL.SpoutSender()
spoutSender.setSenderName(context.camera.name)

spoutSender.createMemoryBuffer(context.camera.name, 1024)
spyphonSender = FrameBufferSharingServer.create(context.camera.name)
spyphonSender.setup()

#if spyphonSender.can_memory_buffer() == True:
## spyphonSender.create_memory_buffer(context.camera.name, 1024)

# create a off screen renderer
offscreen = gpu.types.GPUOffScreen(dWIDTH, dHEIGHT)

Expand Down Expand Up @@ -133,7 +138,7 @@ def texshare_main(self, context):
frame_metadata_buffer = FrameMetDataBuffer("test")

# collect all the arguments to pass to the draw handler
args = (self, context, context.camera, context.object, mySpace, myRegion, myScene, myLayer, offscreen, spoutSender, guivars.preview, frame_metadata_buffer)
args = (self, context, context.camera, context.object, mySpace, myRegion, myScene, myLayer, offscreen, spyphonSender, guivars.preview, frame_metadata_buffer)

frameHandler = frame_metadata(context.camera.name, frame_metadata_buffer)
bpy.app.handlers.depsgraph_update_post.append(frameHandler)
Expand All @@ -145,13 +150,13 @@ def texshare_main(self, context):
# store the references inside the db-dicts
db_frameHandle[dbID] = frameHandler
db_drawHandle[dbID] = drawhandle
db_spoutInstances[dbID] = spoutSender
db_spoutInstances[dbID] = spyphonSender

# if streaming has been disabled and my ID is still stored in the db
if context.camera.texshare.enable == 0 and dbID in db_drawHandle:
bpy.app.handlers.depsgraph_update_post.remove(db_frameHandle[dbID])
bpy.types.SpaceView3D.draw_handler_remove(db_drawHandle[dbID], 'WINDOW')
db_spoutInstances[dbID].releaseSender()
db_spoutInstances[dbID].release()
#removing my ID
db_drawHandle.pop(dbID, None)
dbID == "off"
Expand Down
3 changes: 2 additions & 1 deletion pip_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ def draw(self, context):
if package._registered:
row.label(text="Registered", icon="CHECKMARK")
module = sys.modules[package.module]
row.label(text="Path: " + module.__path__[0])
if hasattr(module, '__path__'):
row.label(text="Path: " + module.__path__[0])
row.operator(
Pip_Refresh_package.bl_idname,
text="refresh",
Expand Down

0 comments on commit 43a3a96

Please sign in to comment.