Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion examples/01_vtk/vtk_cone_simple_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
class ConeApp(TrameApp):
def __init__(self, server=None):
super().__init__(server)

self.server.cli.add_argument("--encoder", default="auto")
args, _ = self.server.cli.parse_known_args()

self.encoder = args.encoder
self.render_window = self.setup_vtk()

self._build_ui()
Expand Down Expand Up @@ -76,7 +81,9 @@ def _build_ui(self):

with layout.content:
view = rca.RemoteControlledArea(display="video-decoder")
self.view_handler = view.create_view_handler(self.render_window)
self.view_handler = view.create_view_handler(
self.render_window, encoder=self.encoder
)


# -----------------------------------------------------------------------------
Expand Down
6 changes: 4 additions & 2 deletions src/trame_rca/encoders/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
from .image_encoder import RcaImageEncoder

try:
from .video_encoder import RcaVideoEncoder
from .video_encoder import RcaVideoEncoder, VideoEncoderType
except ModuleNotFoundError:
RcaVideoEncoder = object
VideoEncoderType = object
logger = logging.getLogger(__name__)
logger.warning(
"VTKStreaming Video encoding is NOT AVAILABLE (missing Python package)"
)


__all__ = ["RcaVideoEncoder", "RcaImageEncoder"]
__all__ = ["RcaVideoEncoder", "RcaImageEncoder", "VideoEncoderType"]
17 changes: 16 additions & 1 deletion src/trame_rca/encoders/video_encoder.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
from enum import Enum, auto
from time import time_ns
from typing import Callable

Expand Down Expand Up @@ -50,19 +51,33 @@ def encode(
return (bytes(frame_data), meta, now_ms)


class VideoEncoderType(Enum):
AUTO = auto()
NVENC = auto()
VP9 = auto()


Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could add a method to convert a string to an enum instance.

@classmethod
def from(cls, name):
   if isinstance(name, cls):
      return name
   if isinstance(name, str):
      return cls[rca_encoder.upper()]
   msg = f"Invalid type: {name}"
   raise ValueError(msg)

class RcaVideoEncoder:
def __init__(
self,
render_window: vtkRenderWindow,
push_callback: Callable[[bytes, dict, int], None],
rca_encoder: VideoEncoderType | str | None = None,
) -> None:
self._render_window = render_window
self.encoder = None
self.frame = None
self._push_callback = push_callback
self._window_size = None

if vtkNvEncoderGL.CheckAvailability():
rca_encoder = rca_encoder or VideoEncoderType.AUTO
if isinstance(rca_encoder, str):
rca_encoder = VideoEncoderType[rca_encoder.upper()]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use enum method


if vtkNvEncoderGL.CheckAvailability() and rca_encoder in [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be another enum method/@Property.

rca_encoder.create_encoder()

VideoEncoderType.AUTO,
VideoEncoderType.NVENC,
]:
logger.info("Using H264 through NVENC")
self._create_encoder = create_nvenc_encoder
else:
Expand Down
5 changes: 3 additions & 2 deletions src/trame_rca/schedulers/video_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from trame_rca.rca import VtkRemoteControlledArea

from trame_rca.encoders import RcaVideoEncoder
from trame_rca.encoders import RcaVideoEncoder, VideoEncoderType
from trame_rca.rca import window_wrapper


Expand All @@ -33,10 +33,11 @@ def __init__(
*,
push_callback: Callable[[bytes, dict]] | None = None,
target_fps: float = 30.0,
rca_encoder: VideoEncoderType | None = None,
):
self._rca: VtkRemoteControlledArea = window_wrapper(window)
self._rca_encoder = RcaVideoEncoder(
self._rca.render_window, push_callback=self._push
self._rca.render_window, push_callback=self._push, rca_encoder=rca_encoder
)
self._is_closing = False
self._render_requested = False
Expand Down
8 changes: 5 additions & 3 deletions src/trame_rca/widgets/rca.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
if TYPE_CHECKING:
from vtkmodules.vtkRenderingCore import vtkRenderWindow

from trame_rca.encoders import RcaImageEncoder
from trame_rca.encoders import RcaImageEncoder, VideoEncoderType
from trame_rca.rca import RemoteControlledAreaProtocol, window_wrapper
from trame_rca.schedulers import RcaImageRenderScheduler
from trame_rca.utils import RcaViewAdapter
Expand Down Expand Up @@ -101,7 +101,7 @@ def add_view_handler(self, view_handler):
def create_view_handler(
self,
window: RemoteControlledAreaProtocol | vtkRenderWindow,
encoder: RcaImageEncoder | str | None = None,
encoder: RcaImageEncoder | VideoEncoderType | str | None = None,
target_fps: float = 30.0,
interactive_quality: int = 60,
still_quality: int = 90,
Expand All @@ -114,7 +114,9 @@ def create_view_handler(

if not isinstance(window, VtkRemoteControlledArea):
raise TypeError("Only VTK backends are supported by video decoder")
scheduler = RcaVideoRenderScheduler(window, target_fps=target_fps)
scheduler = RcaVideoRenderScheduler(
window, target_fps=target_fps, rca_encoder=encoder
)

elif encoder:
scheduler = RcaImageRenderScheduler(
Expand Down
Loading