diff --git a/include/h264-encoder.h b/include/h264-encoder.h index 1c33878..6466a46 100644 --- a/include/h264-encoder.h +++ b/include/h264-encoder.h @@ -25,7 +25,7 @@ typedef void (*h264_encoder_packet_handler_fn)(const void* payload, size_t size, uint64_t pts, void* userdata); 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*); diff --git a/src/h264-encoder.c b/src/h264-encoder.c index 1954334..8806a5e 100644 --- a/src/h264-encoder.c +++ b/src/h264-encoder.c @@ -298,7 +298,7 @@ failure: } 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); 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->gop_size = INT32_MAX; /* We'll select key frames manually */ 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 * 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, - uint32_t format) + uint32_t format, int quality) { 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) 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; self->codec_ctx->hw_frames_ctx = diff --git a/src/open-h264.c b/src/open-h264.c index f986933..296c4ef 100644 --- a/src/open-h264.c +++ b/src/open-h264.c @@ -24,6 +24,7 @@ #include "usdt.h" #include +#include typedef void (*open_h264_ready_fn)(void*); @@ -45,6 +46,9 @@ struct open_h264 { uint32_t format; bool needs_reset; + + int quality; + bool quality_changed; }; enum open_h264_flags { @@ -112,6 +116,7 @@ struct encoder* open_h264_new(void) } self->pts = NVNC_NO_PTS; + self->quality = 6; 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) { + int quality = 51 - round((50.0 / 9.0) * (float)self->quality); + struct h264_encoder* encoder = h264_encoder_create(fb->width, - fb->height, fb->fourcc_format); + fb->height, fb->fourcc_format, quality); if (!encoder) return -1; @@ -146,6 +153,7 @@ static int open_h264_resize(struct open_h264* self, struct nvnc_fb* fb) self->height = fb->height; self->format = fb->fourcc_format; self->needs_reset = true; + self->quality_changed = false; return 0; } @@ -159,7 +167,8 @@ static int open_h264_encode(struct encoder* enc, struct nvnc_fb* fb, (void)damage; 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) return -1; } @@ -214,9 +223,19 @@ static void open_h264_request_keyframe(struct encoder* enc) 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 = { .flags = ENCODER_IMPL_FLAG_IGNORES_DAMAGE, .destroy = open_h264_destroy, .encode = open_h264_encode, .request_key_frame = open_h264_request_keyframe, + .set_quality = open_h264_set_quality, };