Fix jpeg quality setting
The encoding identifiers are supposed to be interpreted as a range. I interpreted the upper and lower limits as two discrete quality settings instead, which is wrong.pull/67/head
parent
43684ec482
commit
528eac51a3
|
@ -90,6 +90,7 @@ struct nvnc_client {
|
||||||
bool is_qemu_key_ext_notified;
|
bool is_qemu_key_ext_notified;
|
||||||
struct encoder* encoder;
|
struct encoder* encoder;
|
||||||
uint32_t cursor_seq;
|
uint32_t cursor_seq;
|
||||||
|
int quality;
|
||||||
};
|
};
|
||||||
|
|
||||||
LIST_HEAD(nvnc_client_list, nvnc_client);
|
LIST_HEAD(nvnc_client_list, nvnc_client);
|
||||||
|
|
|
@ -43,7 +43,7 @@ struct encoder_impl {
|
||||||
|
|
||||||
void (*set_output_format)(struct encoder*,
|
void (*set_output_format)(struct encoder*,
|
||||||
const struct rfb_pixel_format*);
|
const struct rfb_pixel_format*);
|
||||||
void (*set_tight_quality)(struct encoder*, int quality);
|
void (*set_quality)(struct encoder*, int quality);
|
||||||
|
|
||||||
int (*resize)(struct encoder*, uint16_t width, uint16_t height);
|
int (*resize)(struct encoder*, uint16_t width, uint16_t height);
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ enum encoder_kind encoder_get_kind(const struct encoder* self);
|
||||||
|
|
||||||
void encoder_set_output_format(struct encoder* self,
|
void encoder_set_output_format(struct encoder* self,
|
||||||
const struct rfb_pixel_format*);
|
const struct rfb_pixel_format*);
|
||||||
void encoder_set_tight_quality(struct encoder* self, int value);
|
void encoder_set_quality(struct encoder* self, int value);
|
||||||
|
|
||||||
int encoder_resize(struct encoder* self, uint16_t width, uint16_t height);
|
int encoder_resize(struct encoder* self, uint16_t width, uint16_t height);
|
||||||
|
|
||||||
|
|
|
@ -63,12 +63,13 @@ enum rfb_encodings {
|
||||||
RFB_ENCODING_OPEN_H264 = 50,
|
RFB_ENCODING_OPEN_H264 = 50,
|
||||||
RFB_ENCODING_CURSOR = -239,
|
RFB_ENCODING_CURSOR = -239,
|
||||||
RFB_ENCODING_DESKTOPSIZE = -223,
|
RFB_ENCODING_DESKTOPSIZE = -223,
|
||||||
RFB_ENCODING_JPEG_HIGHQ = -23,
|
|
||||||
RFB_ENCODING_JPEG_LOWQ = -32,
|
|
||||||
RFB_ENCODING_QEMU_EXT_KEY_EVENT = -258,
|
RFB_ENCODING_QEMU_EXT_KEY_EVENT = -258,
|
||||||
RFB_ENCODING_PTS = -1000,
|
RFB_ENCODING_PTS = -1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define RFB_ENCODING_JPEG_HIGHQ -23
|
||||||
|
#define RFB_ENCODING_JPEG_LOWQ -32
|
||||||
|
|
||||||
enum rfb_server_to_client_msg_type {
|
enum rfb_server_to_client_msg_type {
|
||||||
RFB_SERVER_TO_CLIENT_FRAMEBUFFER_UPDATE = 0,
|
RFB_SERVER_TO_CLIENT_FRAMEBUFFER_UPDATE = 0,
|
||||||
RFB_SERVER_TO_CLIENT_SET_COLOUR_MAP_ENTRIES = 1,
|
RFB_SERVER_TO_CLIENT_SET_COLOUR_MAP_ENTRIES = 1,
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 - 2021 Andri Yngvason
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
||||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
||||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
||||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
||||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
||||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
* PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
enum tight_quality {
|
|
||||||
TIGHT_QUALITY_UNSPEC = 0,
|
|
||||||
TIGHT_QUALITY_LOSSLESS,
|
|
||||||
TIGHT_QUALITY_LOW,
|
|
||||||
TIGHT_QUALITY_HIGH,
|
|
||||||
};
|
|
||||||
|
|
|
@ -93,10 +93,10 @@ void encoder_set_output_format(struct encoder* self,
|
||||||
self->impl->set_output_format(self, pixfmt);
|
self->impl->set_output_format(self, pixfmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void encoder_set_tight_quality(struct encoder* self, int value)
|
void encoder_set_quality(struct encoder* self, int value)
|
||||||
{
|
{
|
||||||
if (self->impl->set_tight_quality)
|
if (self->impl->set_quality)
|
||||||
self->impl->set_tight_quality(self, value);
|
self->impl->set_quality(self, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
int encoder_resize(struct encoder* self, uint16_t width, uint16_t height)
|
int encoder_resize(struct encoder* self, uint16_t width, uint16_t height)
|
||||||
|
|
30
src/server.c
30
src/server.c
|
@ -26,7 +26,6 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "usdt.h"
|
#include "usdt.h"
|
||||||
#include "encoder.h"
|
#include "encoder.h"
|
||||||
#include "tight.h"
|
|
||||||
#include "enc-util.h"
|
#include "enc-util.h"
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
@ -74,7 +73,6 @@ static int send_desktop_resize(struct nvnc_client* client, struct nvnc_fb* fb);
|
||||||
static int send_qemu_key_ext_frame(struct nvnc_client* client);
|
static int send_qemu_key_ext_frame(struct nvnc_client* client);
|
||||||
static enum rfb_encodings choose_frame_encoding(struct nvnc_client* client,
|
static enum rfb_encodings choose_frame_encoding(struct nvnc_client* client,
|
||||||
struct nvnc_fb*);
|
struct nvnc_fb*);
|
||||||
static enum tight_quality client_get_tight_quality(struct nvnc_client* client);
|
|
||||||
static void on_encode_frame_done(struct encoder*, struct rcbuf*, uint64_t pts);
|
static void on_encode_frame_done(struct encoder*, struct rcbuf*, uint64_t pts);
|
||||||
static bool client_has_encoding(const struct nvnc_client* client,
|
static bool client_has_encoding(const struct nvnc_client* client,
|
||||||
enum rfb_encodings encoding);
|
enum rfb_encodings encoding);
|
||||||
|
@ -500,6 +498,8 @@ static int on_client_set_encodings(struct nvnc_client* client)
|
||||||
sizeof(*msg) + n_encodings * 4)
|
sizeof(*msg) + n_encodings * 4)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
client->quality = 10;
|
||||||
|
|
||||||
for (size_t i = 0; i < n_encodings; ++i) {
|
for (size_t i = 0; i < n_encodings; ++i) {
|
||||||
enum rfb_encodings encoding = htonl(msg->encodings[i]);
|
enum rfb_encodings encoding = htonl(msg->encodings[i]);
|
||||||
|
|
||||||
|
@ -514,12 +514,14 @@ static int on_client_set_encodings(struct nvnc_client* client)
|
||||||
case RFB_ENCODING_OPEN_H264:
|
case RFB_ENCODING_OPEN_H264:
|
||||||
case RFB_ENCODING_CURSOR:
|
case RFB_ENCODING_CURSOR:
|
||||||
case RFB_ENCODING_DESKTOPSIZE:
|
case RFB_ENCODING_DESKTOPSIZE:
|
||||||
case RFB_ENCODING_JPEG_HIGHQ:
|
|
||||||
case RFB_ENCODING_JPEG_LOWQ:
|
|
||||||
case RFB_ENCODING_QEMU_EXT_KEY_EVENT:
|
case RFB_ENCODING_QEMU_EXT_KEY_EVENT:
|
||||||
case RFB_ENCODING_PTS:
|
case RFB_ENCODING_PTS:
|
||||||
client->encodings[n++] = encoding;
|
client->encodings[n++] = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RFB_ENCODING_JPEG_LOWQ <= encoding &&
|
||||||
|
encoding <= RFB_ENCODING_JPEG_HIGHQ)
|
||||||
|
client->quality = encoding - RFB_ENCODING_JPEG_LOWQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->n_encodings = n;
|
client->n_encodings = n;
|
||||||
|
@ -717,8 +719,7 @@ static void process_fb_update_requests(struct nvnc_client* client)
|
||||||
|
|
||||||
client_ref(client);
|
client_ref(client);
|
||||||
|
|
||||||
int q = client_get_tight_quality(client);
|
encoder_set_quality(client->encoder, client->quality);
|
||||||
encoder_set_tight_quality(client->encoder, q);
|
|
||||||
encoder_set_output_format(client->encoder, &client->pixfmt);
|
encoder_set_output_format(client->encoder, &client->pixfmt);
|
||||||
|
|
||||||
client->encoder->on_done = on_encode_frame_done;
|
client->encoder->on_done = on_encode_frame_done;
|
||||||
|
@ -1109,6 +1110,7 @@ static void on_connection(void* obj)
|
||||||
|
|
||||||
client->ref = 1;
|
client->ref = 1;
|
||||||
client->server = server;
|
client->server = server;
|
||||||
|
client->quality = 10; /* default to lossless */
|
||||||
|
|
||||||
int fd = accept(server->fd, NULL, 0);
|
int fd = accept(server->fd, NULL, 0);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -1367,22 +1369,6 @@ static enum rfb_encodings choose_frame_encoding(struct nvnc_client* client,
|
||||||
return RFB_ENCODING_RAW;
|
return RFB_ENCODING_RAW;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum tight_quality client_get_tight_quality(struct nvnc_client* client)
|
|
||||||
{
|
|
||||||
if (client->pixfmt.bits_per_pixel != 16 &&
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool client_has_encoding(const struct nvnc_client* client,
|
static bool client_has_encoding(const struct nvnc_client* client,
|
||||||
enum rfb_encodings encoding)
|
enum rfb_encodings encoding)
|
||||||
{
|
{
|
||||||
|
|
24
src/tight.c
24
src/tight.c
|
@ -19,7 +19,6 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "pixels.h"
|
#include "pixels.h"
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
#include "tight.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "enc-util.h"
|
#include "enc-util.h"
|
||||||
#include "fb.h"
|
#include "fb.h"
|
||||||
|
@ -66,7 +65,7 @@ struct tight_encoder {
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
uint32_t grid_width;
|
uint32_t grid_width;
|
||||||
uint32_t grid_height;
|
uint32_t grid_height;
|
||||||
enum tight_quality quality;
|
int quality;
|
||||||
|
|
||||||
struct tight_tile* grid;
|
struct tight_tile* grid;
|
||||||
|
|
||||||
|
@ -350,13 +349,7 @@ static int tight_encode_tile_jpeg(struct tight_encoder* self,
|
||||||
unsigned char* buffer = NULL;
|
unsigned char* buffer = NULL;
|
||||||
unsigned long size = 0;
|
unsigned long size = 0;
|
||||||
|
|
||||||
int quality; /* 1 - 100 */
|
int quality = 11 * self->quality + 1;
|
||||||
|
|
||||||
switch (self->quality) {
|
|
||||||
case TIGHT_QUALITY_HIGH: quality = 66; break;
|
|
||||||
case TIGHT_QUALITY_LOW: quality = 33; break;
|
|
||||||
default: abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t fourcc = nvnc_fb_get_fourcc_format(self->fb);
|
uint32_t fourcc = nvnc_fb_get_fourcc_format(self->fb);
|
||||||
enum TJPF tjfmt = tight_get_jpeg_pixfmt(fourcc);
|
enum TJPF tjfmt = tight_get_jpeg_pixfmt(fourcc);
|
||||||
|
@ -411,17 +404,10 @@ static void tight_encode_tile(struct tight_encoder* self,
|
||||||
tile->size = 0;
|
tile->size = 0;
|
||||||
|
|
||||||
#ifdef HAVE_JPEG
|
#ifdef HAVE_JPEG
|
||||||
switch (self->quality) {
|
if (self->quality >= 10) {
|
||||||
case TIGHT_QUALITY_LOSSLESS:
|
|
||||||
tight_encode_tile_basic(self, tile, x, y, width, height, gx % 4);
|
tight_encode_tile_basic(self, tile, x, y, width, height, gx % 4);
|
||||||
break;
|
} else {
|
||||||
case TIGHT_QUALITY_HIGH:
|
|
||||||
case TIGHT_QUALITY_LOW:
|
|
||||||
// TODO: Use more workers for jpeg
|
|
||||||
tight_encode_tile_jpeg(self, tile, x, y, width, height);
|
tight_encode_tile_jpeg(self, tile, x, y, width, height);
|
||||||
break;
|
|
||||||
case TIGHT_QUALITY_UNSPEC:
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
tight_encode_tile_basic(self, tile, x, y, width, height, gx % 4);
|
tight_encode_tile_basic(self, tile, x, y, width, height, gx % 4);
|
||||||
|
@ -620,7 +606,7 @@ static int tight_encoder_encode(struct encoder* encoder, struct nvnc_fb* fb,
|
||||||
struct encoder_impl encoder_impl_tight = {
|
struct encoder_impl encoder_impl_tight = {
|
||||||
.destroy = tight_encoder_destroy_wrapper,
|
.destroy = tight_encoder_destroy_wrapper,
|
||||||
.set_output_format = tight_encoder_set_output_format,
|
.set_output_format = tight_encoder_set_output_format,
|
||||||
.set_tight_quality = tight_encoder_set_quality,
|
.set_quality = tight_encoder_set_quality,
|
||||||
.resize = tight_encoder_resize_wrapper,
|
.resize = tight_encoder_resize_wrapper,
|
||||||
.encode = tight_encoder_encode,
|
.encode = tight_encoder_encode,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue