Skip to content

Commit

Permalink
#2828 GBRP10 (aka AV_PIX_FMT_GBRP10LE) just needs byteswapping - do t…
Browse files Browse the repository at this point in the history
…hat using a bytearray for now

git-svn-id: https://xpra.org/svn/Xpra/trunk@26945 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Jul 10, 2020
1 parent 02592ed commit dff488c
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 14 deletions.
21 changes: 14 additions & 7 deletions src/xpra/client/gl/gl_window_backing_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
POSIX,
DummyContextManager,
)
from xpra.util import envint, envbool, repr_ellipsized
from xpra.util import envint, envbool, repr_ellipsized, first_time
from xpra.client.paint_colors import get_paint_box_color
from xpra.codecs.codec_constants import get_subsampling_divs
from xpra.client.window_backing_base import (
Expand Down Expand Up @@ -122,6 +122,8 @@
"YUV420P" : GL_UNSIGNED_BYTE,
"YUV422P" : GL_UNSIGNED_BYTE,
"YUV444P" : GL_UNSIGNED_BYTE,
"GBRP" : GL_UNSIGNED_BYTE,
"GBRP10" : GL_UNSIGNED_SHORT,
}
CONSTANT_TO_PIXEL_FORMAT = {
GL_BGR : "BGR",
Expand All @@ -142,6 +144,7 @@
GL_UNSIGNED_INT_2_10_10_10_REV : "UNSIGNED_INT_2_10_10_10_REV",
GL_UNSIGNED_INT_10_10_10_2 : "UNSIGNED_INT_10_10_10_2",
GL_UNSIGNED_BYTE : "UNSIGNED_BYTE",
GL_UNSIGNED_SHORT : "UNSIGNED_SHORT",
GL_UNSIGNED_SHORT_5_6_5 : "UNSIGNED_SHORT_5_6_5",
}

Expand Down Expand Up @@ -299,10 +302,12 @@ def init_formats(self):
if self.bit_depth>32:
self.internal_format = GL_RGBA16
self.RGB_MODES.append("r210")
self.RGB_MODES.append("GBRP10")
elif self.bit_depth==30:
self.internal_format = GL_RGB10_A2
self.RGB_MODES.append("r210")
elif self.bit_depth==16:
self.RGB_MODES.append("GBRP10")
elif 0<self.bit_depth<=16:
if self._alpha_enabled:
if envbool("XPRA_GL_RGBA4", True):
self.internal_format = GL_RGBA4
Expand All @@ -315,6 +320,8 @@ def init_formats(self):
self.RGB_MODES.append("BGR565")
self.RGB_MODES.append("RGB565")
else:
if self.bit_depth not in (0, 24, 32) and first_time("bit-depth-%i" % self.bit_depth):
log.warn("Warning: invalid bit depth %i, using 24", self.bit_depth)
#assume 24:
if self._alpha_enabled:
self.internal_format = GL_RGBA8
Expand Down Expand Up @@ -976,7 +983,7 @@ def pixels_for_upload(self, img_data):
return "copy:bytes(%s)" % type(img_data), strtobytes(img_data)

def set_alignment(self, width : int, rowstride : int, pixel_format):
bytes_per_pixel = len(pixel_format) #ie: BGRX -> 4
bytes_per_pixel = len(pixel_format) #ie: BGRX -> 4, Y -> 1, YY -> 2
# Compute alignment and row length
row_length = 0
alignment = 1
Expand Down Expand Up @@ -1104,7 +1111,7 @@ def do_video_paint(self, img, x : int, y : int, enc_width : int, enc_height : in
#copy so the data will be usable (usually a str)
img.clone_pixel_data()
pixel_format = img.get_pixel_format()
if pixel_format=="GBRP":
if pixel_format.startswith("GBRP"):
shader = RGBP2RGB_SHADER
else:
shader = YUV2RGB_SHADER
Expand All @@ -1119,7 +1126,7 @@ def gl_paint_planar(self, shader, flush, encoding, img,
x, y = self.gravity_adjust(x, y, options)
try:
pixel_format = img.get_pixel_format()
assert pixel_format in ("YUV420P", "YUV422P", "YUV444P", "GBRP", ), \
assert pixel_format in ("YUV420P", "YUV422P", "YUV444P", "GBRP", "GBRP10"), \
"sorry the GL backing does not handle pixel format '%s' yet!" % (pixel_format)

context = self.gl_context()
Expand Down Expand Up @@ -1184,7 +1191,7 @@ def update_planar_textures(self, width : int, height : int, img, pixel_format, s
self.gl_marker("updating planar textures: %sx%s %s", width, height, pixel_format)
rowstrides = img.get_rowstride()
img_data = img.get_pixels()
BPP = 1
BPP = 2 if pixel_format.endswith("P10") else 1
assert len(rowstrides)==3 and len(img_data)==3
for texture, index, tex_name in (
(GL_TEXTURE0, TEX_Y, "Y"*BPP),
Expand Down Expand Up @@ -1218,7 +1225,7 @@ def update_planar_textures(self, width : int, height : int, img, pixel_format, s
def render_planar_update(self, rx : int, ry : int, rw : int, rh : int, x_scale=1, y_scale=1, shader=YUV2RGB_SHADER):
log("%s.render_planar_update%s pixel_format=%s",
self, (rx, ry, rw, rh, x_scale, y_scale, shader), self.pixel_format)
if self.pixel_format not in ("YUV420P", "YUV422P", "YUV444P", "GBRP"):
if self.pixel_format not in ("YUV420P", "YUV422P", "YUV444P", "GBRP", "GBRP10"):
#not ready to render yet
return
self.gl_marker("painting planar update, format %s", self.pixel_format)
Expand Down
42 changes: 35 additions & 7 deletions src/xpra/codecs/dec_avcodec2/decoder.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,9 @@ FORMAT_TO_STR = {
#AV_PIX_FMT_NB : "NB",
}

#given one of our format names,
#describing the pixel data fed to the encoder,
#what ffmpeg AV_PIX_FMT we expect to find in the output:
FORMAT_TO_ENUM = {
"YUV420P" : AV_PIX_FMT_YUV420P,
"YUV422P" : AV_PIX_FMT_YUV422P,
Expand All @@ -513,6 +516,7 @@ FORMAT_TO_ENUM = {
"ARGB" : AV_PIX_FMT_ARGB,
"BGRA" : AV_PIX_FMT_BGRA,
"GBRP" : AV_PIX_FMT_GBRP,
"BGR48" : AV_PIX_FMT_GBRP10LE,
}
#for planar formats, this is the number of bytes per channel
BYTES_PER_PIXEL = {
Expand All @@ -525,12 +529,18 @@ BYTES_PER_PIXEL = {
AV_PIX_FMT_ARGB : 4,
AV_PIX_FMT_BGRA : 4,
AV_PIX_FMT_GBRP : 1,
AV_PIX_FMT_GBRP10LE : 6,
}

#given an ffmpeg pixel format,
#what is our format name for it:
COLORSPACES = tuple(FORMAT_TO_ENUM.keys())
ENUM_TO_FORMAT = {}
for pix_fmt, av_enum in FORMAT_TO_ENUM.items():
ENUM_TO_FORMAT[av_enum] = pix_fmt
#ENUM_TO_FORMAT[AV_PIX_FMT_YUV422P10LE] = "YUV422P10"
ENUM_TO_FORMAT[AV_PIX_FMT_GBRP10LE] = "GBRP10"


def get_version():
return (LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO)
Expand Down Expand Up @@ -596,9 +606,12 @@ def get_input_colorspaces(encoding):
def get_output_colorspace(encoding, csc):
if encoding not in CODECS:
return ""
if encoding=="h264" and csc in ("RGB", "XRGB", "BGRX", "ARGB", "BGRA"):
#h264 from plain RGB data is returned as "GBRP"!
return "GBRP"
if encoding=="h264":
if csc in ("RGB", "XRGB", "BGRX", "ARGB", "BGRA"):
#h264 from plain RGB data is returned as "GBRP"!
return "GBRP"
if csc=="BGR48":
return "GBRP10"
elif encoding in ("vp8", "mpeg4", "mpeg1", "mpeg2"):
return "YUV420P"
#everything else as normal:
Expand Down Expand Up @@ -951,7 +964,8 @@ cdef class Decoder:
log("avcodec actual output pixel format is %s (%s), expected %s (%s)", self.actual_pix_fmt, self.get_actual_colorspace(), self.pix_fmt, self.colorspace)

cs = self.get_actual_colorspace()
if cs.endswith("P"):
log("actual_colorspace(%s)=%s", self.actual_pix_fmt, cs)
if cs.find("P")>0: #ie: GBRP, YUV420P, YUV422P10LE etc
divs = get_subsampling_divs(cs)
nplanes = 3
for i in range(3):
Expand All @@ -968,16 +982,30 @@ cdef class Decoder:
size = height * stride
outsize += size

out.append(memory_as_pybuffer(<void *>av_frame.data[i], size, True))
if cs=="GBRP10":
b = bytearray(size)
for z in range(size//2):
b[z*2] = av_frame.data[i][z*2+1]
b[z*2+1] = av_frame.data[i][z*2]
obuf = bytes(b)
else:
obuf = memory_as_pybuffer(<void *>av_frame.data[i], size, True)
out.append(obuf)
#if cs=="GBRP10":
# from xpra.os_util import memoryview_to_bytes
# for y in range(12):
# line = height*y//12
# line_data = memoryview_to_bytes(out[-1])[line*stride:(line+1)*stride]
# log("plane %s line %3i %s..%s", cs[i:i+1], line, hexstr(line_data[:10]), hexstr(line_data[-10:]))
strides.append(stride)
log("decompress_image() read back yuv plane %s: %s bytes", i, size)
log("decompress_image() read back '%s' plane: %s bytes", cs[i:i+1], size)
else:
#RGB mode: "out" is a single buffer
strides = av_frame.linesize[0]+av_frame.linesize[1]+av_frame.linesize[2]
outsize = self.codec_ctx.height * strides
out = memory_as_pybuffer(<void *>av_frame.data[0], outsize, True)
nplanes = 0
log("decompress_image() read back rgb buffer: %s bytes", outsize)
log("decompress_image() read back '%s' buffer: %s bytes", cs, outsize)

if outsize==0:
av_frame_unref(av_frame)
Expand Down

0 comments on commit dff488c

Please sign in to comment.