Skip to content

Commit

Permalink
#796:
Browse files Browse the repository at this point in the history
* refactor all encoders so we pass in both the quality and speed to use (very much like the other encoding functions) so that we can deal with both at once
* re-init code for nvenc4 so we can switch to/from yuv444 mode

git-svn-id: https://xpra.org/svn/Xpra/trunk@8606 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Feb 3, 2015
1 parent 615393d commit 0c3b4c7
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 159 deletions.
14 changes: 5 additions & 9 deletions src/xpra/codecs/enc_proxy/encoder.py
Expand Up @@ -117,10 +117,12 @@ def clean(self): #@DuplicatedSignature
self.time = 0
self.first_frame_timestamp = 0

def compress_image(self, image, options={}):
def compress_image(self, image, quality=-1, speed=-1, options={}):
log("compress_image(%s, %s)", image, options)
#pass the pixels as they are
assert image.get_planes()==ImageWrapper.PACKED, "invalid number of planes: %s" % image.get_planes()
self.quality = quality
self.speed = speed
pixels = str(image.get_pixels())
#info used by proxy encoder:
client_options = {
Expand All @@ -132,8 +134,8 @@ def compress_image(self, image, options={}):
#redundant metadata:
#"width" : image.get_width(),
#"height" : image.get_height(),
"quality" : options.get("quality", self.quality),
"speed" : options.get("speed", self.speed),
"quality" : quality,
"speed" : speed,
"timestamp" : image.get_timestamp(),
"rowstride" : image.get_rowstride(),
"depth" : image.get_depth(),
Expand All @@ -150,9 +152,3 @@ def compress_image(self, image, options={}):
self.last_frame_times.append(time.time())
self.frames += 1
return pixels, client_options

def set_encoding_speed(self, pct):
self.speed = int(min(100, max(0, pct)))

def set_encoding_quality(self, pct):
self.quality = int(min(100, max(0, pct)))
68 changes: 26 additions & 42 deletions src/xpra/codecs/enc_x264/encoder.pyx
Expand Up @@ -424,7 +424,7 @@ cdef class Encoder:
return profile


def compress_image(self, image, options={}):
def compress_image(self, image, quality=-1, speed=-1, options={}):
cdef x264_nal_t *nals = NULL
cdef int i_nals = 0
cdef x264_picture_t pic_out
Expand All @@ -435,26 +435,16 @@ cdef class Encoder:
cdef Py_ssize_t pic_buf_len = 0
cdef char *out

cdef int quality_override = options.get("quality", -1)
cdef int speed_override = options.get("speed", -1)
cdef int saved_quality = self.quality
cdef int saved_speed = self.speed
cdef int i #@DuplicatedSignature
start = time.time()

if self.frames==0:
self.first_frame_timestamp = image.get_timestamp()

#deal with overriden speed or quality settings:
#(temporarily change the settings for this encode only):
speed = self.speed
if speed_override>=0 and saved_speed!=speed_override:
self.set_encoding_speed(speed_override)
speed = speed_override
quality = self.quality
if quality_override>=0 and saved_quality!=quality_override:
self.set_encoding_quality(quality_override)
quality = quality_override
if speed>=0 and abs(self.speed-speed)>5:
self.set_encoding_speed(speed)
if quality>=0 and abs(self.quality-quality)>5:
self.set_encoding_quality(quality)
assert self.context!=NULL
pixels = image.get_pixels()
istrides = image.get_rowstride()
Expand Down Expand Up @@ -482,32 +472,26 @@ cdef class Encoder:
pic_in.img.i_plane = 3
pic_in.i_pts = image.get_timestamp()-self.first_frame_timestamp

try:
with nogil:
frame_size = x264_encoder_encode(self.context, &nals, &i_nals, &pic_in, &pic_out)
if frame_size < 0:
log.error("x264 encoding error: frame_size is invalid!")
return None
out = <char *>nals[0].p_payload
cdata = out[:frame_size]
self.bytes_out += frame_size
#info for client:
client_options = {
"frame" : self.frames,
"pts" : pic_out.i_pts,
"quality" : min(99, quality),
"speed" : speed}
#accounting:
end = time.time()
self.time += end-start
self.frames += 1
self.last_frame_times.append((start, end))
return cdata, client_options
finally:
if speed_override>=0 and saved_speed!=speed_override:
self.set_encoding_speed(saved_speed)
if quality_override>=0 and saved_quality!=quality_override:
self.set_encoding_quality(saved_quality)
with nogil:
frame_size = x264_encoder_encode(self.context, &nals, &i_nals, &pic_in, &pic_out)
if frame_size < 0:
log.error("x264 encoding error: frame_size is invalid!")
return None
out = <char *>nals[0].p_payload
cdata = out[:frame_size]
self.bytes_out += frame_size
#info for client:
client_options = {
"frame" : self.frames,
"pts" : pic_out.i_pts,
"quality" : min(99, quality),
"speed" : speed}
#accounting:
end = time.time()
self.time += end-start
self.frames += 1
self.last_frame_times.append((start, end))
return cdata, client_options


def set_encoding_speed(self, int pct):
Expand Down Expand Up @@ -560,7 +544,7 @@ def selftest():
e.init_context(w, h, "YUV420P", ["YUV420P"], encoding, w, h, (1,1), {})
from xpra.codecs.image_wrapper import ImageWrapper
image = ImageWrapper(0, 0, w, h, [y, u ,v], "YUV420P", 32, [w, w/2, w/2], planes=ImageWrapper.PACKED, thread_safe=True)
c = e.compress_image(image, {})
c = e.compress_image(image)
#import binascii
#print("compressed data(%s)=%s" % (encoding, binascii.hexlify(str(c))))
finally:
Expand Down
9 changes: 1 addition & 8 deletions src/xpra/codecs/enc_x265/encoder.pyx
Expand Up @@ -406,7 +406,7 @@ cdef class Encoder:
return self.src_format


def compress_image(self, image, options={}):
def compress_image(self, image, quality=-1, speed=-1, options={}):
cdef x265_nal *nal
cdef uint32_t nnal = 0
cdef int r = 0
Expand Down Expand Up @@ -486,10 +486,3 @@ cdef class Encoder:
self.frames += 1
log("x265 compressed data size: %s, client options=%s", frame_size, client_options)
return "".join(data), client_options


def set_encoding_speed(self, int pct):
pass

def set_encoding_quality(self, int pct):
pass
9 changes: 1 addition & 8 deletions src/xpra/codecs/nvenc3/encoder.pyx
Expand Up @@ -1701,13 +1701,6 @@ cdef class Encoder:
def get_src_format(self):
return self.src_format

def set_encoding_speed(self, speed):
self.speed = max(0, min(100, speed))
self.update_bitrate()

def set_encoding_quality(self, quality):
self.quality = max(0, min(100, quality))

def update_bitrate(self):
#use an exponential scale so for a 1Kx1K image (after scaling), roughly:
#speed=0 -> 1Mbit/s
Expand Down Expand Up @@ -1736,7 +1729,7 @@ cdef class Encoder:
r = self.functionList.nvEncEncodePicture(self.context, &picParams)
raiseNVENC(r, "flushing encoder buffer")

def compress_image(self, image, options={}, retry=0):
def compress_image(self, image, quality=-1, speed=-1, options={}, retry=0):
self.cuda_context.push()
try:
try:
Expand Down
1 change: 1 addition & 0 deletions src/xpra/codecs/nvenc4/constants.txt
Expand Up @@ -61,3 +61,4 @@ NV_ENC_ERR_RESOURCE_NOT_MAPPED
NV_ENC_CAPS_MB_PER_SEC_MAX
NV_ENC_CAPS_SUPPORT_YUV444_ENCODE
NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE
NV_ENC_RECONFIGURE_PARAMS_VER

0 comments on commit 0c3b4c7

Please sign in to comment.