diff --git a/include/rfb-proto.h b/include/rfb-proto.h index 23cfcda..82a1891 100644 --- a/include/rfb-proto.h +++ b/include/rfb-proto.h @@ -57,6 +57,8 @@ enum rfb_encodings { RFB_ENCODING_ZRLE = 16, RFB_ENCODING_CURSOR = -239, RFB_ENCODING_DESKTOPSIZE = -223, + RFB_ENCODING_JPEG_HIGHQ = -23, + RFB_ENCODING_JPEG_LOWQ = -32, }; enum rfb_server_to_client_msg_type { diff --git a/include/tight.h b/include/tight.h index 9aa909f..36c28fe 100644 --- a/include/tight.h +++ b/include/tight.h @@ -24,8 +24,16 @@ struct nvnc_fb; struct pixman_region16; struct rfb_pixel_format; +enum tight_quality { + TIGHT_QUALITY_UNSPEC = 0, + TIGHT_QUALITY_LOSSLESS, + TIGHT_QUALITY_LOW, + TIGHT_QUALITY_HIGH, +}; + struct tight_encoder { z_stream zs[4]; + enum tight_quality quality; }; int tight_encoder_init(struct tight_encoder*); diff --git a/src/server.c b/src/server.c index 823f0e8..9c88fcc 100644 --- a/src/server.c +++ b/src/server.c @@ -449,6 +449,8 @@ static int on_client_set_encodings(struct nvnc_client* client) case RFB_ENCODING_ZRLE: case RFB_ENCODING_CURSOR: case RFB_ENCODING_DESKTOPSIZE: + case RFB_ENCODING_JPEG_HIGHQ: + case RFB_ENCODING_JPEG_LOWQ: client->encodings[n++] = encoding; } } diff --git a/src/tight.c b/src/tight.c index fd4fc73..627f168 100644 --- a/src/tight.c +++ b/src/tight.c @@ -38,6 +38,27 @@ #define TIGHT_MAX_WIDTH 2048 +enum tight_quality tight_get_quality(struct tight_encoder* self) +{ + struct nvnc_client* client = + container_of(self, struct nvnc_client, tight_encoder); + + /* Note: The standard specifies that 16 is OK too, but we can only + * handle 32 + */ + if (client->pixfmt.bits_per_pixel != 32) + return TIGHT_QUALITY_LOSSLESS; + + for (size_t i = 0; i < client->n_encodings; ++i) + switch (client->encodings[i]) { + case RFB_ENCODING_JPEG_HIGHQ: return TIGHT_QUALITY_HIGH; + case RFB_ENCODING_JPEG_LOWQ: return TIGHT_QUALITY_LOW; + default:; + } + + return TIGHT_QUALITY_LOSSLESS; +} + int tight_init_zstream(z_stream* zx) { int rc = deflateInit2(zx, @@ -103,7 +124,14 @@ int tight_encode_box_jpeg(struct tight_encoder* self, struct vec* dst, unsigned char* buffer = NULL; size_t size = 0; - int quality = 50; /* 1 - 100 */ + int quality; /* 1 - 100 */ + + switch (self->quality) { + case TIGHT_QUALITY_HIGH: quality = 66; break; + case TIGHT_QUALITY_LOW: quality = 33; break; + default: abort(); + } + enum TJPF tjfmt = get_jpeg_pixfmt(fb->fourcc_format); if (tjfmt == TJPF_UNKNOWN) return -1; @@ -179,7 +207,6 @@ int tight_encode_box_basic(struct tight_encoder* self, struct vec* dst, uint32_t x, uint32_t y_start, uint32_t stride, uint32_t width, uint32_t height) { - printf("Encode %u %u %u %u\n", x, y_start, width, height); struct nvnc_client* client = container_of(self, struct nvnc_client, tight_encoder); @@ -248,8 +275,22 @@ int tight_encode_box(struct tight_encoder* self, struct vec* dst, uint32_t x, uint32_t y, uint32_t stride, uint32_t width, uint32_t height) { -// return tight_encode_box_basic(self, dst, fb, src_fmt, x, y, stride, width, height); - return tight_encode_box_jpeg(self, dst, fb, x, y, stride, width, height); + if (self->quality == TIGHT_QUALITY_UNSPEC) + self->quality = tight_get_quality(self); + + switch (self->quality) { + case TIGHT_QUALITY_LOSSLESS: + return tight_encode_box_basic(self, dst, fb, src_fmt, x, y, + stride, width, height); + case TIGHT_QUALITY_HIGH: + case TIGHT_QUALITY_LOW: + return tight_encode_box_jpeg(self, dst, fb, x, y, stride, + width, height); + case TIGHT_QUALITY_UNSPEC:; + } + + abort(); + return -1; } int tight_encode_frame(struct tight_encoder* self, struct vec* dst,