WiP: Add Tight PNG encoding
parent
ee3f2fefff
commit
7fbdfb02ee
4
Makefile
4
Makefile
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(
|
||||||
|
|
107
src/tight.c
107
src/tight.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue