diff --git a/src/raw-encoding.c b/src/raw-encoding.c index be57d05..fef07c7 100644 --- a/src/raw-encoding.c +++ b/src/raw-encoding.c @@ -31,17 +31,20 @@ struct encoder* raw_encoder_new(void); struct raw_encoder { struct encoder encoder; - struct rfb_pixel_format output_format; - - struct nvnc_fb* current_fb; - struct pixman_region16 current_damage; - - struct rcbuf *current_result; - struct aml_work* work; }; +struct raw_encoder_work { + struct raw_encoder* parent; + struct rfb_pixel_format output_format; + struct nvnc_fb* fb; + struct pixman_region16 damage; + int n_rects; + uint16_t x_pos, y_pos; + struct rcbuf *result; +}; + struct encoder_impl encoder_impl_raw; static inline struct raw_encoder* raw_encoder(struct encoder* encoder) @@ -50,14 +53,14 @@ static inline struct raw_encoder* raw_encoder(struct encoder* encoder) return (struct raw_encoder*)encoder; } -static int raw_encode_box(struct raw_encoder* self, struct vec* dst, +static int raw_encode_box(struct raw_encoder_work* ctx, struct vec* dst, const struct rfb_pixel_format* dst_fmt, const struct nvnc_fb* fb, const struct rfb_pixel_format* src_fmt, int x_start, int y_start, int stride, int width, int height) { - uint16_t x_pos = self->encoder.x_pos; - uint16_t y_pos = self->encoder.y_pos; + uint16_t x_pos = ctx->x_pos; + uint16_t y_pos = ctx->y_pos; int rc = -1; @@ -86,15 +89,13 @@ static int raw_encode_box(struct raw_encoder* self, struct vec* dst, return 0; } -static int raw_encode_frame(struct raw_encoder* self, struct vec* dst, +static int raw_encode_frame(struct raw_encoder_work* ctx, struct vec* dst, const struct rfb_pixel_format* dst_fmt, struct nvnc_fb* src, const struct rfb_pixel_format* src_fmt, struct pixman_region16* region) { int rc = -1; - self->encoder.n_rects = 0; - int n_rects = 0; struct pixman_box16* box = pixman_region_rectangles(region, &n_rects); if (n_rects > UINT16_MAX) { @@ -116,22 +117,22 @@ static int raw_encode_frame(struct raw_encoder* self, struct vec* dst, int box_width = box[i].x2 - x; int box_height = box[i].y2 - y; - rc = raw_encode_box(self, dst, dst_fmt, src, src_fmt, x, y, + rc = raw_encode_box(ctx, dst, dst_fmt, src, src_fmt, x, y, src->stride, box_width, box_height); if (rc < 0) return -1; } - self->encoder.n_rects = n_rects; + ctx->n_rects = n_rects; return 0; } static void raw_encoder_do_work(void* obj) { - struct raw_encoder* self = aml_get_userdata(obj); + struct raw_encoder_work* ctx = aml_get_userdata(obj); int rc; - struct nvnc_fb* fb = self->current_fb; + struct nvnc_fb* fb = ctx->fb; assert(fb); // TODO: Calculate the ideal buffer size based on the size of the @@ -147,36 +148,28 @@ static void raw_encoder_do_work(void* obj) rc = rfb_pixfmt_from_fourcc(&src_fmt, nvnc_fb_get_fourcc_format(fb)); assert(rc == 0); - rc = raw_encode_frame(self, &dst, &self->output_format, fb, &src_fmt, - &self->current_damage); + rc = raw_encode_frame(ctx, &dst, &ctx->output_format, fb, &src_fmt, + &ctx->damage); assert(rc == 0); - self->current_result = rcbuf_new(dst.data, dst.len); - assert(self->current_result); + ctx->result = rcbuf_new(dst.data, dst.len); + assert(ctx->result); } static void raw_encoder_on_done(void* obj) { - struct raw_encoder* self = aml_get_userdata(obj); + struct raw_encoder_work* ctx = aml_get_userdata(obj); + struct raw_encoder* self = ctx->parent; - assert(self->current_result); + assert(ctx->result); - uint64_t pts = nvnc_fb_get_pts(self->current_fb); - nvnc_fb_unref(self->current_fb); - self->current_fb = NULL; - - pixman_region_clear(&self->current_damage); - - struct rcbuf* result = self->current_result; - self->current_result = NULL; + self->encoder.n_rects = ctx->n_rects; aml_unref(self->work); self->work = NULL; - encoder_finish_frame(&self->encoder, result, pts); - - rcbuf_unref(result); - encoder_unref(&self->encoder); + uint64_t pts = nvnc_fb_get_pts(ctx->fb); + encoder_finish_frame(&self->encoder, ctx->result, pts); } struct encoder* raw_encoder_new(void) @@ -187,19 +180,16 @@ struct encoder* raw_encoder_new(void) encoder_init(&self->encoder, &encoder_impl_raw); - pixman_region_init(&self->current_damage); - return (struct encoder*)self; } static void raw_encoder_destroy(struct encoder* encoder) { struct raw_encoder* self = raw_encoder(encoder); - pixman_region_fini(&self->current_damage); - if (self->work) + if (self->work) { + aml_stop(aml_get_default(), self->work); aml_unref(self->work); - if (self->current_result) - rcbuf_unref(self->current_result); + } free(self); } @@ -210,32 +200,45 @@ static void raw_encoder_set_output_format(struct encoder* encoder, memcpy(&self->output_format, pixfmt, sizeof(self->output_format)); } +static void raw_encoder_work_destroy(void* obj) +{ + struct raw_encoder_work* ctx = obj; + nvnc_fb_unref(ctx->fb); + pixman_region_fini(&ctx->damage); + if (ctx->result) + rcbuf_unref(ctx->result); + free(ctx); +} + static int raw_encoder_encode(struct encoder* encoder, struct nvnc_fb* fb, struct pixman_region16* damage) { struct raw_encoder* self = raw_encoder(encoder); - assert(!self->current_fb); - - self->work = aml_work_new(raw_encoder_do_work, raw_encoder_on_done, - self, NULL); - if (!self->work) + struct raw_encoder_work* ctx = calloc(1, sizeof(*ctx)); + if (!ctx) return -1; - self->current_fb = fb; - nvnc_fb_ref(self->current_fb); - pixman_region_copy(&self->current_damage, damage); + self->work = aml_work_new(raw_encoder_do_work, raw_encoder_on_done, + ctx, raw_encoder_work_destroy); + if (!self->work) { + free(ctx); + return -1; + } - encoder_ref(&self->encoder); + ctx->parent = self; + ctx->fb = fb; + memcpy(&ctx->output_format, &self->output_format, + sizeof(ctx->output_format)); + ctx->x_pos = self->encoder.x_pos; + ctx->y_pos = self->encoder.y_pos; + nvnc_fb_ref(ctx->fb); + pixman_region_copy(&ctx->damage, damage); int rc = aml_start(aml_get_default(), self->work); if (rc < 0) { - encoder_unref(&self->encoder); aml_unref(self->work); self->work = NULL; - pixman_region_clear(&self->current_damage); - nvnc_fb_unref(self->current_fb); - self->current_fb = NULL; } return rc;