Skip to content

Commit

Permalink
#3930 convert to use dataclass
Browse files Browse the repository at this point in the history
  • Loading branch information
totaam committed Jul 30, 2023
1 parent 6d1f46d commit 0ac1b84
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 69 deletions.
87 changes: 33 additions & 54 deletions xpra/codecs/codec_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import os
from weakref import WeakSet
from dataclasses import dataclass, field
from typing import Any

from xpra.util import envint, typedict
Expand Down Expand Up @@ -130,46 +131,29 @@ class CodecStateException(Exception):
pass


@dataclass(kw_only=True)
class _codec_spec:

def __init__(self, codec_class, codec_type : str="",
quality:int=50, speed:int=50,
size_efficiency:int=50,
setup_cost:int=50, cpu_cost:int=100, gpu_cost:int=0,
min_w:int=1, min_h:int=1, max_w:int=4*1024, max_h:int=4*1024,
can_scale:bool=False,
score_boost:int=0,
width_mask:int=0xFFFF, height_mask:int=0xFFFF):
self.codec_class = codec_class #ie: xpra.codecs.x264.encoder.Encoder
self.codec_type : str = codec_type #ie: "nvenc"
self.quality : int = quality
self.speed : int = speed
self.size_efficiency : int = size_efficiency
self.setup_cost : int = setup_cost
self.cpu_cost : int = cpu_cost
self.gpu_cost : int = gpu_cost
self.score_boost : int = score_boost
self.min_w : int = min_w
self.min_h : int = min_h
self.max_w : int = max_w
self.max_h : int = max_h
self.width_mask : int = width_mask
self.height_mask : int = height_mask
self.can_scale : bool = can_scale
self.max_instances : int = 0
self._exported_fields = [
"codec_class", "codec_type",
"quality", "speed",
"setup_cost", "cpu_cost", "gpu_cost", "score_boost",
"min_w", "min_h", "max_w", "max_h",
"width_mask", "height_mask",
"can_scale",
"max_instances",
]
#not exported:
self.instances : WeakSet[Any] = WeakSet()
self._all_fields = list(self._exported_fields)+["instances"]

codec_class : callable
codec_type : str
quality : int = 50
speed : int = 50
size_efficiency : int = 50
setup_cost : int = 50
cpu_cost : int = 100
gpu_cost : int = 0
min_w : int = 1
min_h : int = 1
max_w : int = 4 * 1024
max_h : int = 4 * 1024
can_scale : bool = False
score_boost : int = 0
width_mask : int = 0xFFFF
height_mask : int = 0xFFFF
max_instances : int = 0
skipped_fields : tuple[str] = ("instances", "skipped_fields", )
# not exported:
instances : WeakSet[Any] = field(default_factory=WeakSet)

def make_instance(self) -> object:
# pylint: disable=import-outside-toplevel
Expand Down Expand Up @@ -200,9 +184,9 @@ def get_instance_count(self) -> int:
return len(self.instances)

def to_dict(self) -> dict[str,Any]:
d = {}
for k in self._exported_fields:
d[k] = getattr(self, k)
v = self.asdict()
for k in self.skipped_fields:
v.pop(k, None)
return d

def get_runtime_factor(self) -> float:
Expand All @@ -220,28 +204,23 @@ def get_runtime_factor(self) -> float:
return 1.0


@dataclass(kw_only=True)
class video_spec(_codec_spec):

def __init__(self, encoding : str, input_colorspace : str, output_colorspaces : tuple, has_lossless_mode : bool,
codec_class, codec_type : str, min_w:int=2, min_h:int=2, **kwargs):
self.encoding : str = encoding #ie: "h264"
self.input_colorspace : str = input_colorspace
self.output_colorspaces = output_colorspaces #ie: ["YUV420P" : "YUV420P", ...]
self.has_lossless_mode : bool = has_lossless_mode
super().__init__(codec_class, codec_type, min_w=min_w, min_h=min_h, **kwargs)
self._exported_fields += ["encoding", "input_colorspace", "output_colorspaces", "has_lossless_mode"]
encoding : str
input_colorspace : str
output_colorspaces : tuple[str,...] # ie: ["YUV420P" : "YUV420P", ...]
has_lossless_mode : bool = False

def __repr__(self):
return f"{self.codec_type}({self.input_colorspace} to {self.encoding}"


@dataclass(kw_only=True)
class csc_spec(_codec_spec):

def __init__(self, input_colorspace:str, output_colorspace:str, codec_class, codec_type:str, **kwargs):
self.input_colorspace : str = input_colorspace
self.output_colorspace : str = output_colorspace
super().__init__(codec_class, codec_type, **kwargs)
self._exported_fields += ["input_colorspace", "output_colorspace"]
input_colorspace: str
output_colorspace: str

def __repr__(self):
return f"{self.codec_type}({self.input_colorspace} to {self.output_colorspace})"
Expand Down
4 changes: 2 additions & 2 deletions xpra/codecs/csc_cython/colorspace_converter.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ def get_spec(in_colorspace:str, out_colorspace:str):
#safer not to try to handle odd dimensions as input:
width_mask = height_mask = 0xFFFE
#low score as this should be used as fallback only:
return csc_spec(in_colorspace, out_colorspace,
ColorspaceConverter, codec_type=get_type(),
return csc_spec(input_colorspace=in_colorspace, output_colorspace=out_colorspace,
codec_class=ColorspaceConverter, codec_type=get_type(),
quality=50, speed=0, setup_cost=0, min_w=2, min_h=2,
max_w=16*1024, max_h=16*1024,
can_scale=can_scale,
Expand Down
3 changes: 2 additions & 1 deletion xpra/codecs/jpeg/encoder.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ def get_specs(encoding, colorspace):
height_mask=0xFFFE
return (
video_spec(
encoding, input_colorspace=colorspace, output_colorspaces=(colorspace, ), has_lossless_mode=False,
encoding=encoding, input_colorspace=colorspace, output_colorspaces=(colorspace, ),
has_lossless_mode=False,
codec_class=Encoder, codec_type="jpeg",
setup_cost=0, cpu_cost=100, gpu_cost=0,
min_w=16, min_h=16, max_w=16*1024, max_h=16*1024,
Expand Down
4 changes: 2 additions & 2 deletions xpra/codecs/libyuv/colorspace_converter.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ def get_output_colorspaces(input_colorspace):
def get_spec(in_colorspace, out_colorspace):
assert in_colorspace in COLORSPACES, "invalid input colorspace: %s (must be one of %s)" % (in_colorspace, COLORSPACES)
assert out_colorspace in COLORSPACES[in_colorspace], "invalid output colorspace: %s (must be one of %s)" % (out_colorspace, COLORSPACES[in_colorspace])
return csc_spec(in_colorspace, out_colorspace,
ColorspaceConverter, codec_type=get_type(),
return csc_spec(input_colorspace=in_colorspace, output_colorspace=out_colorspace,
codec_class=ColorspaceConverter, codec_type=get_type(),
quality=100, speed=100,
setup_cost=0, min_w=8, min_h=2, can_scale=in_colorspace!="NV12",
max_w=MAX_WIDTH, max_h=MAX_HEIGHT)
Expand Down
2 changes: 1 addition & 1 deletion xpra/codecs/nvidia/nvjpeg/encoder.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def get_specs(encoding, colorspace):
from xpra.codecs.codec_constants import video_spec
return (
video_spec(
"jpeg", input_colorspace=colorspace, output_colorspaces=(colorspace, ),
encoding="jpeg", input_colorspace=colorspace, output_colorspaces=(colorspace, ),
has_lossless_mode=False,
codec_class=Encoder, codec_type="nvjpeg",
setup_cost=20, cpu_cost=0, gpu_cost=100,
Expand Down
2 changes: 1 addition & 1 deletion xpra/codecs/webp/encoder.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ def get_specs(encoding, colorspace):
from xpra.codecs.codec_constants import video_spec
return (
video_spec(
encoding, input_colorspace=colorspace, output_colorspaces=(colorspace, ), has_lossless_mode=False,
encoding=encoding, input_colorspace=colorspace, output_colorspaces=(colorspace, ), has_lossless_mode=False,
codec_class=Encoder, codec_type="webp",
setup_cost=0, cpu_cost=100, gpu_cost=0,
min_w=16, min_h=16, max_w=4*1024, max_h=4*1024,
Expand Down
17 changes: 9 additions & 8 deletions xpra/server/window/window_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import threading
from math import sqrt, ceil
from collections import deque
from dataclasses import dataclass
from time import monotonic
from contextlib import nullcontext
from typing import Callable, Iterable, ContextManager, Any
Expand Down Expand Up @@ -121,13 +122,13 @@ def get_env_encodings(etype:str, valid_options:Iterable[str]=()) -> tuple[str,..
ui_context = xlog


@dataclass
class DelayedRegions:
def __init__(self, damage_time:float, regions:list[rectangle], encoding:str, options:dict|None):
self.expired : bool = False
self.damage_time : float = damage_time
self.regions = regions
self.encoding : str = encoding
self.options : dict = options or {}
damage_time : float
encoding : str
options : dict
regions : list[rectangle]
expired : bool = False

def __repr__(self):
return "DelayedRegion(time=%i, expired=%s, encoding=%s, regions=%s, options=%s)" % (
Expand Down Expand Up @@ -1604,7 +1605,7 @@ def do_damage(self, ww : int, wh : int, x : int, y : int, w : int, h : int, opti
target_delay = delay
delay = max(0, delay-elapsed)
actual_encoding = options.get("encoding", self.encoding)
self._damage_delayed = DelayedRegions(now, regions, actual_encoding, options)
self._damage_delayed = DelayedRegions(damage_time=now, regions=regions, encoding=actual_encoding, options=options)
lad = (now, delay)
self.batch_config.last_delays.append(lad)
self.batch_config.last_delay = lad
Expand Down Expand Up @@ -2400,7 +2401,7 @@ def full_quality_refresh(self, damage_options) -> None:
#just refresh the whole window:
regions = [rectangle(0, 0, w, h)]
now = monotonic()
damage = DelayedRegions(now, regions, encoding, new_options)
damage = DelayedRegions(damage_time=now, regions=regions, encoding=encoding, options=new_options)
self.send_delayed_regions(damage)

def get_refresh_options(self) -> dict[str,Any]:
Expand Down

0 comments on commit 0ac1b84

Please sign in to comment.