Skip to content

Commit

Permalink
#3706 decode h264 via gst + avcodec
Browse files Browse the repository at this point in the history
  • Loading branch information
totaam committed Dec 15, 2022
1 parent 7cc1667 commit d3e4cc7
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 13 deletions.
1 change: 1 addition & 0 deletions xpra/codecs/codec_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def testdecoding(decoder_module, encoding, full):
assert image is not None, "failed to decode test data for encoding '%s' with colorspace '%s'" % (encoding, cs)
assert image.get_width()==W, "expected image of width %s but got %s" % (W, image.get_width())
assert image.get_height()==H, "expected image of height %s but got %s" % (H, image.get_height())
log(f" test passed for {W}x{H} {encoding} - {cs}")
if full:
log("%s: testing %s / %s with junk data", decoder_module.get_type(), encoding, cs)
#test failures:
Expand Down
32 changes: 19 additions & 13 deletions xpra/codecs/gstreamer/decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
assert get_version and get_type and init_module and cleanup_module


CODECS = ("vp8", "h264")
def get_encodings():
return ("vp8", )
return CODECS

def get_input_colorspaces(encoding):
assert encoding in get_encodings()
Expand All @@ -44,19 +45,21 @@ def create_pipeline(self, options):
raise ValueError(f"invalid encoding {self.encoding!r}")
self.dst_formats = options.strtupleget("dst-formats")
gst_rgb_format = "I420"
#STREAM_CAPS = f"caps=video/x-vp8,width={self.width},height={self.height}"
STREAM_CAPS = f"video/x-vp8,width={self.width},height={self.height}"
IMAGE_CAPS = f"video/x-raw,width={self.width},height={self.height},format=(string){gst_rgb_format}"
if self.encoding=="vp8":
stream_caps = f"video/x-vp8,width={self.width},height={self.height}"
decode = ["vp8dec"]
elif self.encoding=="h264":
stream_caps = f"video/x-h264,profile=main,stream-format=avc,alignment=au,width={self.width},height={self.height}"
decode = ["vaapih264dec"]
decode = ["openh264dec"]
decode = ["avdec_h264"]
else:
raise RuntimeError(f"invalid encoding {self.encoding}")
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}",
"vp8dec",
#avdec_vp8
#"h264parse",
#"avdec_h264",
#video/x-h264,stream-format=avc,alignment=au
#"videoconvert",
#mp4mux
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}",
]
if not self.setup_pipeline_and_bus(elements):
Expand All @@ -77,9 +80,12 @@ def on_new_sample(self, _bus):
Ysize = Ystride*roundup(self.height, 2)
UVstride = roundup(roundup(self.width, 2)//2, 4)
UVsize = UVstride*roundup(self.height, 2)//2
total = Ysize+2*UVsize
if size<total:
raise RuntimeError(f"I420 sample buffer is too small: expected {total} but got {size}")
Y = mem[:Ysize]
U = mem[Ysize:Ysize+UVsize]
V = mem[Ysize+UVsize:Ysize+2*UVsize]
V = mem[Ysize+UVsize:total]
strides = (Ystride, UVstride, UVstride)
image = ImageWrapper(0, 0, self.width, self.height, (Y, U, V), "YUV420P", 24, strides, 3, ImageWrapper.PLANAR_3)
self.frame_queue.put(image)
Expand Down Expand Up @@ -108,4 +114,4 @@ def selftest(full=False):
log("gstreamer decoder selftest: %s", get_info())
from xpra.codecs.codec_checks import testdecoder
from xpra.codecs.gstreamer import decoder
assert testdecoder(decoder, full)
decoder.CODECS = testdecoder(decoder, full)

0 comments on commit d3e4cc7

Please sign in to comment.