WiP: Add Tight PNG encoding

tight-png
Andri Yngvason 2019-12-30 21:44:05 +00:00
parent ee3f2fefff
commit 7fbdfb02ee
4 changed files with 100 additions and 15 deletions

View File

@ -1,4 +1,4 @@
DEPENDENCIES := pixman-1 libuv libturbojpeg DEPENDENCIES := pixman-1 libuv libturbojpeg libpng
SOURCES := \ SOURCES := \
src/server.c \ src/server.c \
@ -19,7 +19,7 @@ DSO_NAME=libneatvnc
DSO_MAJOR=0 DSO_MAJOR=0
DSO_MINOR=0 DSO_MINOR=0
CFLAGS += -fvisibility=hidden -Icontrib/miniz CFLAGS += -fvisibility=hidden -Icontrib/miniz -DENABLE_TIGHT
OBJECTS += $(BUILD_DIR)/miniz.o OBJECTS += $(BUILD_DIR)/miniz.o
DSO_PATH := $(BUILD_DIR)/$(DSO_NAME) DSO_PATH := $(BUILD_DIR)/$(DSO_NAME)

View File

@ -51,6 +51,7 @@ enum rfb_encodings {
RFB_ENCODING_RRE = 2, RFB_ENCODING_RRE = 2,
RFB_ENCODING_HEXTILE = 5, RFB_ENCODING_HEXTILE = 5,
RFB_ENCODING_TIGHT = 7, RFB_ENCODING_TIGHT = 7,
RFB_ENCODING_TIGHT_PNG = -260,
RFB_ENCODING_TRLE = 15, RFB_ENCODING_TRLE = 15,
RFB_ENCODING_ZRLE = 16, RFB_ENCODING_ZRLE = 16,
RFB_ENCODING_CURSOR = -239, RFB_ENCODING_CURSOR = -239,

View File

@ -11,6 +11,7 @@ project(
add_project_arguments([ add_project_arguments([
'-D_GNU_SOURCE', '-D_GNU_SOURCE',
'-fvisibility=hidden', '-fvisibility=hidden',
'-DENABLE_TIGHT',
], language: 'c') ], language: 'c')
cpu = host_machine.cpu_family() cpu = host_machine.cpu_family()
@ -36,6 +37,7 @@ libm = cc.find_library('m', required: false)
pixman = dependency('pixman-1') pixman = dependency('pixman-1')
libuv = dependency('libuv') libuv = dependency('libuv')
libturbojpeg = dependency('libturbojpeg') libturbojpeg = dependency('libturbojpeg')
libpng = dependency('libpng')
inc = include_directories('include', 'contrib/miniz') inc = include_directories('include', 'contrib/miniz')
@ -57,6 +59,7 @@ dependencies = [
pixman, pixman,
libuv, libuv,
libturbojpeg, libturbojpeg,
libpng,
] ]
neatvnc = shared_library( neatvnc = shared_library(

View File

@ -4,9 +4,12 @@
#include "fb.h" #include "fb.h"
#include "tight.h" #include "tight.h"
#include "common.h" #include "common.h"
#include "pixels.h"
#include "rfb-proto.h"
#include <pixman.h> #include <pixman.h>
#include <turbojpeg.h> #include <turbojpeg.h>
#include <png.h>
#include <stdlib.h> #include <stdlib.h>
#include <libdrm/drm_fourcc.h> #include <libdrm/drm_fourcc.h>
@ -44,9 +47,9 @@ static void tight_encode_size(struct vec* dst, size_t size)
vec_fast_append_8(dst, (size >> 14) & 0x7f); vec_fast_append_8(dst, (size >> 14) & 0x7f);
} }
int tight_encode_box(struct vec* dst, struct nvnc_client* client, int tight_encode_box_jpeg(struct vec* dst, struct nvnc_client* client,
const struct nvnc_fb* fb, uint32_t x, uint32_t y, const struct nvnc_fb* fb, uint32_t x, uint32_t y,
uint32_t stride, uint32_t width, uint32_t height) uint32_t stride, uint32_t width, uint32_t height)
{ {
unsigned char* buffer = NULL; unsigned char* buffer = NULL;
@ -59,16 +62,6 @@ int tight_encode_box(struct vec* dst, struct nvnc_client* client,
vec_reserve(dst, 4096); vec_reserve(dst, 4096);
struct rfb_server_fb_rect rect = {
.encoding = htonl(RFB_ENCODING_TIGHT),
.x = htons(x),
.y = htons(y),
.width = htons(width),
.height = htons(height),
};
vec_append(dst, &rect, sizeof(rect));
tjhandle handle = tjInitCompress(); tjhandle handle = tjInitCompress();
void* img = (uint32_t*)fb->addr + x + y * stride; void* img = (uint32_t*)fb->addr + x + y * stride;
@ -88,6 +81,94 @@ int tight_encode_box(struct vec* dst, struct nvnc_client* client,
return 0; return 0;
} }
static void tight_png_write(png_structp png_ptr, png_bytep data, png_size_t size)
{
struct vec* out = png_get_io_ptr(png_ptr);
assert(out);
vec_append(out, data, size);
}
static void tight_png_flush(png_structp png_ptr)
{
}
int tight_encode_box_png(struct vec* dst, struct nvnc_client* client,
const struct nvnc_fb* fb, uint32_t x, uint32_t y,
uint32_t stride, uint32_t width, uint32_t height)
{
png_structp png_ptr =
png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info_ptr = png_create_info_struct(png_ptr);
if (setjmp(png_jmpbuf(png_ptr)))
return -1;
int colour_type = PNG_COLOR_TYPE_RGB;
struct vec pngout;
vec_init(&pngout, 4096);
png_set_write_fn(png_ptr, &pngout, tight_png_write, tight_png_flush);
png_set_IHDR(png_ptr, info_ptr, width, height, 8, colour_type,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_COMPRESSION_TYPE_DEFAULT);
png_write_info(png_ptr, info_ptr);
png_byte* buffer = malloc(3 * width * sizeof(*buffer));
struct rfb_pixel_format dst_fmt = { 0 };
rfb_pixfmt_from_fourcc(&dst_fmt, DRM_FORMAT_RGB888 | DRM_FORMAT_BIG_ENDIAN);
struct rfb_pixel_format src_fmt = { 0 };
rfb_pixfmt_from_fourcc(&dst_fmt, fb->fourcc_format);
for (uint32_t r = 0; r < height; ++r) {
uint32_t* row = (uint32_t*)fb->addr + x + (y + r) * stride;
pixel32_to_cpixel(buffer, &dst_fmt, row, &src_fmt, 3, width);
png_write_row(png_ptr, buffer);
}
png_write_end(png_ptr, info_ptr);
png_write_flush(png_ptr);
free(buffer);
png_destroy_write_struct(&png_ptr, &info_ptr);
vec_reserve(dst, 4096);
vec_fast_append_8(dst, TIGHT_PNG);
tight_encode_size(dst, pngout.len);
vec_append(dst, pngout.data, pngout.len);
vec_destroy(&pngout);
return 0;
}
int tight_encode_box(struct vec* dst, struct nvnc_client* client,
const struct nvnc_fb* fb, uint32_t x, uint32_t y,
uint32_t stride, uint32_t width, uint32_t height)
{
struct rfb_server_fb_rect rect = {
.encoding = htonl(RFB_ENCODING_TIGHT_PNG),
.x = htons(x),
.y = htons(y),
.width = htons(width),
.height = htons(height),
};
vec_append(dst, &rect, sizeof(rect));
return tight_encode_box_png(dst, client, fb, x, y, stride, width,
height);
}
int tight_encode_frame(struct vec* dst, struct nvnc_client* client, int tight_encode_frame(struct vec* dst, struct nvnc_client* client,
const struct nvnc_fb* fb, struct pixman_region16* region) const struct nvnc_fb* fb, struct pixman_region16* region)
{ {