h264: Set quality according to client's wishes

pull/67/head
Andri Yngvason 2022-07-10 13:53:32 +00:00
parent 528eac51a3
commit b9a5b9a3f1
3 changed files with 26 additions and 7 deletions

View File

@ -25,7 +25,7 @@ typedef void (*h264_encoder_packet_handler_fn)(const void* payload, size_t size,
uint64_t pts, void* userdata); uint64_t pts, void* userdata);
struct h264_encoder* h264_encoder_create(uint32_t width, uint32_t height, struct h264_encoder* h264_encoder_create(uint32_t width, uint32_t height,
uint32_t format); uint32_t format, int quality);
void h264_encoder_destroy(struct h264_encoder*); void h264_encoder_destroy(struct h264_encoder*);

View File

@ -298,7 +298,7 @@ failure:
} }
static int h264_encoder__init_codec_context(struct h264_encoder* self, static int h264_encoder__init_codec_context(struct h264_encoder* self,
const AVCodec* codec) const AVCodec* codec, int quality)
{ {
self->codec_ctx = avcodec_alloc_context3(codec); self->codec_ctx = avcodec_alloc_context3(codec);
if (!self->codec_ctx) if (!self->codec_ctx)
@ -312,7 +312,7 @@ static int h264_encoder__init_codec_context(struct h264_encoder* self,
c->pix_fmt = AV_PIX_FMT_VAAPI; c->pix_fmt = AV_PIX_FMT_VAAPI;
c->gop_size = INT32_MAX; /* We'll select key frames manually */ c->gop_size = INT32_MAX; /* We'll select key frames manually */
c->max_b_frames = 0; /* B-frames are bad for latency */ c->max_b_frames = 0; /* B-frames are bad for latency */
c->global_quality = 20; c->global_quality = quality;
/* open-h264 requires baseline profile, so we use constrained /* open-h264 requires baseline profile, so we use constrained
* baseline. * baseline.
@ -489,7 +489,7 @@ static int find_render_node(char *node, size_t maxlen) {
} }
struct h264_encoder* h264_encoder_create(uint32_t width, uint32_t height, struct h264_encoder* h264_encoder_create(uint32_t width, uint32_t height,
uint32_t format) uint32_t format, int quality)
{ {
int rc; int rc;
@ -536,7 +536,7 @@ struct h264_encoder* h264_encoder_create(uint32_t width, uint32_t height,
if (h264_encoder__init_filters(self) < 0) if (h264_encoder__init_filters(self) < 0)
goto filter_failure; goto filter_failure;
if (h264_encoder__init_codec_context(self, codec) < 0) if (h264_encoder__init_codec_context(self, codec, quality) < 0)
goto codec_context_failure; goto codec_context_failure;
self->codec_ctx->hw_frames_ctx = self->codec_ctx->hw_frames_ctx =

View File

@ -24,6 +24,7 @@
#include "usdt.h" #include "usdt.h"
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
typedef void (*open_h264_ready_fn)(void*); typedef void (*open_h264_ready_fn)(void*);
@ -45,6 +46,9 @@ struct open_h264 {
uint32_t format; uint32_t format;
bool needs_reset; bool needs_reset;
int quality;
bool quality_changed;
}; };
enum open_h264_flags { enum open_h264_flags {
@ -112,6 +116,7 @@ struct encoder* open_h264_new(void)
} }
self->pts = NVNC_NO_PTS; self->pts = NVNC_NO_PTS;
self->quality = 6;
return (struct encoder*)self; return (struct encoder*)self;
} }
@ -129,8 +134,10 @@ static void open_h264_destroy(struct encoder* enc)
static int open_h264_resize(struct open_h264* self, struct nvnc_fb* fb) static int open_h264_resize(struct open_h264* self, struct nvnc_fb* fb)
{ {
int quality = 51 - round((50.0 / 9.0) * (float)self->quality);
struct h264_encoder* encoder = h264_encoder_create(fb->width, struct h264_encoder* encoder = h264_encoder_create(fb->width,
fb->height, fb->fourcc_format); fb->height, fb->fourcc_format, quality);
if (!encoder) if (!encoder)
return -1; return -1;
@ -146,6 +153,7 @@ static int open_h264_resize(struct open_h264* self, struct nvnc_fb* fb)
self->height = fb->height; self->height = fb->height;
self->format = fb->fourcc_format; self->format = fb->fourcc_format;
self->needs_reset = true; self->needs_reset = true;
self->quality_changed = false;
return 0; return 0;
} }
@ -159,7 +167,8 @@ static int open_h264_encode(struct encoder* enc, struct nvnc_fb* fb,
(void)damage; (void)damage;
if (fb->width != self->width || fb->height != self->height || if (fb->width != self->width || fb->height != self->height ||
fb->fourcc_format != self->format) { fb->fourcc_format != self->format ||
self->quality_changed) {
if (open_h264_resize(self, fb) < 0) if (open_h264_resize(self, fb) < 0)
return -1; return -1;
} }
@ -214,9 +223,19 @@ static void open_h264_request_keyframe(struct encoder* enc)
h264_encoder_request_keyframe(self->encoder); h264_encoder_request_keyframe(self->encoder);
} }
static void open_h264_set_quality(struct encoder* enc, int value)
{
struct open_h264* self = open_h264(enc);
if (value == 10)
value = 6;
self->quality_changed |= self->quality != value;
self->quality = value;
}
struct encoder_impl encoder_impl_open_h264 = { struct encoder_impl encoder_impl_open_h264 = {
.flags = ENCODER_IMPL_FLAG_IGNORES_DAMAGE, .flags = ENCODER_IMPL_FLAG_IGNORES_DAMAGE,
.destroy = open_h264_destroy, .destroy = open_h264_destroy,
.encode = open_h264_encode, .encode = open_h264_encode,
.request_key_frame = open_h264_request_keyframe, .request_key_frame = open_h264_request_keyframe,
.set_quality = open_h264_set_quality,
}; };