Skip to content

Commit

Permalink
#3706 refactoring + disable b-frames for now
Browse files Browse the repository at this point in the history
  • Loading branch information
totaam committed Apr 10, 2023
1 parent 16befd0 commit bfd8948
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 39 deletions.
37 changes: 24 additions & 13 deletions xpra/codecs/gstreamer/decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from xpra.gst_common import (
GST_FLOW_OK, STREAM_TYPE, GST_FORMAT_BYTES,
make_buffer, has_plugins,
get_caps_str, get_element_str,
)
from xpra.codecs.gstreamer.codec_common import (
VideoPipeline,
Expand Down Expand Up @@ -77,27 +78,37 @@ def create_pipeline(self, options):
if self.encoding not in get_encodings():
raise ValueError(f"invalid encoding {self.encoding!r}")
self.dst_formats = options.strtupleget("dst-formats")
gst_rgb_format = "I420"
IMAGE_CAPS = f"video/x-raw,width={self.width},height={self.height},format=(string){gst_rgb_format}"
stream_caps = f"video/x-{self.encoding},width={self.width},height={self.height}"
decode = [f"{self.encoding}dec"]
if self.encoding in ("vp8", "vp9"):
pass
elif self.encoding=="av1":
stream_attrs = {
"width" : self.width,
"height" : self.height,
}
decoder_element = f"{self.encoding}dec"
if self.encoding in ("vp8", "vp9", "av1"):
pass
elif self.encoding=="h264" and not WIN32:
profile = options.strget("profile", "main")
stream_caps += f",profile={profile},stream-format=avc,alignment=au"
for k,v in {
"profile" : "main",
"stream-format" : "byte-stream",
"alignment" : "au",
}.items():
stream_attrs[k] = options.strget(k, v)
#decode = ["vaapih264dec"]
#decode = ["openh264dec"]
decode = [f"avdec_{self.encoding}"]
decoder_element = f"avdec_{self.encoding}"
else:
raise RuntimeError(f"invalid encoding {self.encoding}")
stream_caps = get_caps_str(f"video/x-{self.encoding}", stream_attrs)
gst_rgb_format = "I420"
output_caps = get_caps_str("video/x-raw", {
"width" : self.width,
"height" : self.height,
"format" : gst_rgb_format,
})
elements = [
#"do-timestamp=1",
f"appsrc name=src emit-signals=1 block=0 is-live=1 do-timestamp=1 stream-type={STREAM_TYPE} format={GST_FORMAT_BYTES} caps={stream_caps}"
] + decode + [
f"appsink name=sink emit-signals=true max-buffers=10 drop=true sync=false async=false qos=false caps={IMAGE_CAPS}",
f"appsrc name=src emit-signals=1 block=0 is-live=1 do-timestamp=1 stream-type={STREAM_TYPE} format={GST_FORMAT_BYTES} caps={stream_caps}",
decoder_element,
f"appsink name=sink emit-signals=true max-buffers=10 drop=true sync=false async=false qos=false caps={output_caps}",
]
if not self.setup_pipeline_and_bus(elements):
raise RuntimeError("failed to setup gstreamer pipeline")
Expand Down
36 changes: 10 additions & 26 deletions xpra/codecs/gstreamer/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from xpra.codecs.codec_constants import video_spec, get_profile, get_x264_quality, get_x264_preset
from xpra.gst_common import (
import_gst, normv, get_all_plugin_names,
get_caps_str, get_element_str,
STREAM_TYPE, BUFFER_FORMAT, GST_FLOW_OK,
)
from xpra.codecs.gstreamer.codec_common import (
Expand Down Expand Up @@ -214,26 +215,6 @@ def get_gst_rgb_format(rgb_format : str) -> str:
#"RGB8P"
}[rgb_format]

def get_caps_str(ctype:str="video/x-raw", caps=None) -> str:
if not caps:
return ctype
def s(v):
if isinstance(v, str):
return f"(string){v}"
if isinstance(v, tuple):
return "/".join(str(x) for x in v) #ie: "60/1"
return str(v)
els = [ctype]
for k,v in caps.items():
els.append(f"{k}={s(v)}")
return ",".join(els)

def get_element_str(element:str, eopts=None):
s = element
if eopts:
s += " "+" ".join(f"{k}={v}" for k,v in eopts.items())
return s


class Encoder(VideoPipeline):
__gsignals__ = VideoPipeline.__generic_signals__.copy()
Expand All @@ -250,6 +231,7 @@ def __repr__(self):
def create_pipeline(self, options : typedict):
if self.encoding not in get_encodings():
raise ValueError(f"invalid encoding {self.encoding!r}")
self.extra_client_info = {}
self.dst_formats = options.strtupleget("dst-formats")
gst_rgb_format = get_gst_rgb_format(self.colorspace)
vcaps = {
Expand Down Expand Up @@ -283,15 +265,16 @@ def get_encoder_options(self, options:typedict):
s = options.intget("speed", 50)
eopts.update({
"pass" : "qual",
"bframes" : int(options.boolget("b-frames", False)),
"bframes" : 0, #int(options.boolget("b-frames", False)),
"quantizer" : q,
"speed-preset" : get_x264_preset(s),
})
vopts.update({
self.extra_client_info = {
"profile" : profile,
"alignment" : "au",
"stream-format" : "byte-stream",
})
}
vopts.update(self.extra_client_info)
return eopts, vopts

def get_src_format(self):
Expand All @@ -312,9 +295,9 @@ def on_new_sample(self, _bus) -> int:
if size:
data = buf.extract_dup(0, size)
#log(" output=%s", hexstr(data))
client_info = {
"frame" : self.frames,
}
client_info = self.extra_client_info
self.extra_client_info = {}
client_info["frame"] = self.frames
self.frames += 1
pts = normv(buf.pts)
if pts>=0:
Expand All @@ -326,6 +309,7 @@ def on_new_sample(self, _bus) -> int:
if qs>0:
client_info["delayed"] = qs
self.frame_queue.put((data, client_info))
log(f"added data to frame queue, client_info={client_info}")
return GST_FLOW_OK


Expand Down
22 changes: 22 additions & 0 deletions xpra/gst_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,28 @@ def has_plugins(*names) -> bool:
log("missing %s from %s", missing, names)
return len(missing)==0


def get_caps_str(ctype:str="video/x-raw", caps=None) -> str:
if not caps:
return ctype
def s(v):
if isinstance(v, str):
return f"(string){v}"
if isinstance(v, tuple):
return "/".join(str(x) for x in v) #ie: "60/1"
return str(v)
els = [ctype]
for k,v in caps.items():
els.append(f"{k}={s(v)}")
return ",".join(els)

def get_element_str(element:str, eopts=None):
s = element
if eopts:
s += " "+" ".join(f"{k}={v}" for k,v in eopts.items())
return s


def format_element_options(options):
return csv(f"{k}={v}" for k,v in options.items())

Expand Down

0 comments on commit bfd8948

Please sign in to comment.