screenshot: improve jpeg very high quality to 91 (enables yuv444 instead of yuv420)

This commit is contained in:
dec05eba
2025-11-16 18:58:57 +01:00
parent 739fd9cd72
commit 80f0e483a4
4 changed files with 2 additions and 30 deletions

2
TODO
View File

@@ -81,8 +81,6 @@ When vulkan encode is added, mention minimum nvidia driver required. (550.54.14?
Investigate if there is a way to do gpu->gpu copy directly without touching system ram to enable video encoding on a different gpu. On nvidia this is possible with cudaMemcpyPeer, but how about from an intel/amd gpu to an nvidia gpu or the other way around or any combination of iGPU and dedicated GPU? Investigate if there is a way to do gpu->gpu copy directly without touching system ram to enable video encoding on a different gpu. On nvidia this is possible with cudaMemcpyPeer, but how about from an intel/amd gpu to an nvidia gpu or the other way around or any combination of iGPU and dedicated GPU?
Maybe something with clEnqueueMigrateMemObjects? on AMD something with DirectGMA maybe? Maybe something with clEnqueueMigrateMemObjects? on AMD something with DirectGMA maybe?
Go back to using pure vaapi without opengl for video encoding? rotation (transpose) can be done if its done after (rgb to yuv) color conversion.
Use lanczos resampling for better scaling quality. Lanczos resampling can also be used for YUV chroma for better color quality on small text. Use lanczos resampling for better scaling quality. Lanczos resampling can also be used for YUV chroma for better color quality on small text.
Flac is disabled because the frame sizes are too large which causes big audio/video desync. Flac is disabled because the frame sizes are too large which causes big audio/video desync.

View File

@@ -10,23 +10,14 @@ typedef enum {
GSR_IMAGE_FORMAT_PNG GSR_IMAGE_FORMAT_PNG
} gsr_image_format; } gsr_image_format;
typedef enum {
GSR_IMAGE_WRITER_SOURCE_OPENGL,
GSR_IMAGE_WRITER_SOURCE_MEMORY
} gsr_image_writer_source;
typedef struct { typedef struct {
gsr_image_writer_source source;
gsr_egl *egl; gsr_egl *egl;
int width; int width;
int height; int height;
unsigned int texture; unsigned int texture;
const void *memory; /* Reference */
} gsr_image_writer; } gsr_image_writer;
bool gsr_image_writer_init_opengl(gsr_image_writer *self, gsr_egl *egl, int width, int height); bool gsr_image_writer_init_opengl(gsr_image_writer *self, gsr_egl *egl, int width, int height);
/* |memory| is taken as a reference. The data is expected to be in rgba8 format (8 bit rgba) */
bool gsr_image_writer_init_memory(gsr_image_writer *self, const void *memory, int width, int height);
void gsr_image_writer_deinit(gsr_image_writer *self); void gsr_image_writer_deinit(gsr_image_writer *self);
/* Quality is between 1 and 100 where 100 is the max quality. Quality doesn't apply to lossless formats */ /* Quality is between 1 and 100 where 100 is the max quality. Quality doesn't apply to lossless formats */

View File

@@ -13,7 +13,6 @@
/* TODO: Support hdr/10-bit */ /* TODO: Support hdr/10-bit */
bool gsr_image_writer_init_opengl(gsr_image_writer *self, gsr_egl *egl, int width, int height) { bool gsr_image_writer_init_opengl(gsr_image_writer *self, gsr_egl *egl, int width, int height) {
memset(self, 0, sizeof(*self)); memset(self, 0, sizeof(*self));
self->source = GSR_IMAGE_WRITER_SOURCE_OPENGL;
self->egl = egl; self->egl = egl;
self->width = width; self->width = width;
self->height = height; self->height = height;
@@ -25,15 +24,6 @@ bool gsr_image_writer_init_opengl(gsr_image_writer *self, gsr_egl *egl, int widt
return true; return true;
} }
bool gsr_image_writer_init_memory(gsr_image_writer *self, const void *memory, int width, int height) {
memset(self, 0, sizeof(*self));
self->source = GSR_IMAGE_WRITER_SOURCE_OPENGL;
self->width = width;
self->height = height;
self->memory = memory;
return true;
}
void gsr_image_writer_deinit(gsr_image_writer *self) { void gsr_image_writer_deinit(gsr_image_writer *self) {
if(self->texture) { if(self->texture) {
self->egl->glDeleteTextures(1, &self->texture); self->egl->glDeleteTextures(1, &self->texture);
@@ -64,7 +54,6 @@ static bool gsr_image_writer_write_memory_to_file(gsr_image_writer *self, const
} }
static bool gsr_image_writer_write_opengl_texture_to_file(gsr_image_writer *self, const char *filepath, gsr_image_format image_format, int quality) { static bool gsr_image_writer_write_opengl_texture_to_file(gsr_image_writer *self, const char *filepath, gsr_image_format image_format, int quality) {
assert(self->source == GSR_IMAGE_WRITER_SOURCE_OPENGL);
uint8_t *frame_data = malloc(self->width * self->height * 4); uint8_t *frame_data = malloc(self->width * self->height * 4);
if(!frame_data) { if(!frame_data) {
fprintf(stderr, "gsr error: gsr_image_writer_write_to_file: failed to allocate memory for image frame\n"); fprintf(stderr, "gsr error: gsr_image_writer_write_to_file: failed to allocate memory for image frame\n");
@@ -90,11 +79,5 @@ static bool gsr_image_writer_write_opengl_texture_to_file(gsr_image_writer *self
} }
bool gsr_image_writer_write_to_file(gsr_image_writer *self, const char *filepath, gsr_image_format image_format, int quality) { bool gsr_image_writer_write_to_file(gsr_image_writer *self, const char *filepath, gsr_image_format image_format, int quality) {
switch(self->source) { return gsr_image_writer_write_opengl_texture_to_file(self, filepath, image_format, quality);
case GSR_IMAGE_WRITER_SOURCE_OPENGL:
return gsr_image_writer_write_opengl_texture_to_file(self, filepath, image_format, quality);
case GSR_IMAGE_WRITER_SOURCE_MEMORY:
return gsr_image_writer_write_memory_to_file(self, filepath, image_format, quality, self->memory);
}
return false;
} }

View File

@@ -2310,7 +2310,7 @@ static int video_quality_to_image_quality_value(gsr_video_quality video_quality)
case GSR_VIDEO_QUALITY_HIGH: case GSR_VIDEO_QUALITY_HIGH:
return 85; return 85;
case GSR_VIDEO_QUALITY_VERY_HIGH: case GSR_VIDEO_QUALITY_VERY_HIGH:
return 90; return 91;
case GSR_VIDEO_QUALITY_ULTRA: case GSR_VIDEO_QUALITY_ULTRA:
return 97; return 97;
} }