From 3708bf9cf0315c2ab7299b5b93cc6d50fd8f1dae Mon Sep 17 00:00:00 2001 From: Francois Gouget Date: Wed, 14 Oct 2015 17:31:01 +0200 Subject: server: Move the MJPEG encoder functions to mjpeg_encoder.c Note that this requires some adjustments to the encode_frame() parameters to avoid red_worker-specific types. Signed-off-by: Francois Gouget --- server/mjpeg_encoder.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++--- server/mjpeg_encoder.h | 6 ++-- server/red_worker.c | 73 ++++--------------------------------------------- 3 files changed, 78 insertions(+), 75 deletions(-) (limited to 'server') diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c index 3f8252ae..3cb2144d 100644 --- a/server/mjpeg_encoder.c +++ b/server/mjpeg_encoder.c @@ -192,7 +192,7 @@ void mjpeg_encoder_destroy(MJpegEncoder *encoder) free(encoder); } -uint8_t mjpeg_encoder_get_bytes_per_pixel(MJpegEncoder *encoder) +static uint8_t mjpeg_encoder_get_bytes_per_pixel(MJpegEncoder *encoder) { return encoder->bytes_per_pixel; } @@ -693,7 +693,8 @@ static void mjpeg_encoder_adjust_fps(MJpegEncoder *encoder, uint64_t now) } } -int mjpeg_encoder_start_frame(MJpegEncoder *encoder, SpiceBitmapFmt format, +int mjpeg_encoder_start_frame(MJpegEncoder *encoder, + SpiceBitmapFmt format, int width, int height, uint8_t **dest, size_t *dest_len, uint32_t frame_mm_time) @@ -794,8 +795,9 @@ int mjpeg_encoder_start_frame(MJpegEncoder *encoder, SpiceBitmapFmt format, return MJPEG_ENCODER_FRAME_ENCODE_START; } -int mjpeg_encoder_encode_scanline(MJpegEncoder *encoder, uint8_t *src_pixels, - size_t image_width) +static int mjpeg_encoder_encode_scanline(MJpegEncoder *encoder, + uint8_t *src_pixels, + size_t image_width) { unsigned int scanlines_written; uint8_t *row; @@ -851,6 +853,69 @@ size_t mjpeg_encoder_end_frame(MJpegEncoder *encoder) return encoder->rate_control.last_enc_size; } +static inline uint8_t *get_image_line(SpiceChunks *chunks, size_t *offset, + int *chunk_nr, int stride) +{ + uint8_t *ret; + SpiceChunk *chunk; + + chunk = &chunks->chunk[*chunk_nr]; + + if (*offset == chunk->len) { + if (*chunk_nr == chunks->num_chunks - 1) { + return NULL; /* Last chunk */ + } + *offset = 0; + (*chunk_nr)++; + chunk = &chunks->chunk[*chunk_nr]; + } + + if (chunk->len - *offset < stride) { + spice_warning("bad chunk alignment"); + return NULL; + } + ret = chunk->data + *offset; + *offset += stride; + return ret; +} + +int mjpeg_encoder_encode_frame(MJpegEncoder *encoder, const SpiceRect *src, + const SpiceBitmap *image, int top_down) +{ + SpiceChunks *chunks; + uint32_t image_stride; + size_t offset; + int i, chunk; + + chunks = image->data; + offset = 0; + chunk = 0; + image_stride = image->stride; + + const int skip_lines = top_down ? src->top : image->y - (src->bottom - 0); + for (i = 0; i < skip_lines; i++) { + get_image_line(chunks, &offset, &chunk, image_stride); + } + + const unsigned int stream_height = src->bottom - src->top; + const unsigned int stream_width = src->right - src->left; + + for (i = 0; i < stream_height; i++) { + uint8_t *src_line = get_image_line(chunks, &offset, &chunk, image_stride); + + if (!src_line) { + return FALSE; + } + + src_line += src->left * mjpeg_encoder_get_bytes_per_pixel(encoder); + if (mjpeg_encoder_encode_scanline(encoder, src_line, stream_width) == 0) { + return FALSE; + } + } + + return TRUE; +} + static void mjpeg_encoder_quality_eval_stop(MJpegEncoder *encoder) { MJpegEncoderRateControl *rate_control = &encoder->rate_control; @@ -1021,6 +1086,7 @@ static void mjpeg_encoder_increase_bit_rate(MJpegEncoder *encoder) rate_control->quality_id, rate_control->fps); } + static void mjpeg_encoder_handle_positive_client_stream_report(MJpegEncoder *encoder, uint32_t report_start_frame_mm_time) { diff --git a/server/mjpeg_encoder.h b/server/mjpeg_encoder.h index d584b92a..8e2af100 100644 --- a/server/mjpeg_encoder.h +++ b/server/mjpeg_encoder.h @@ -53,8 +53,6 @@ MJpegEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate, MJpegEncoderRateControlCbs *cbs, void *opaque); void mjpeg_encoder_destroy(MJpegEncoder *encoder); -uint8_t mjpeg_encoder_get_bytes_per_pixel(MJpegEncoder *encoder); - /* * dest must be either NULL or allocated by malloc, since it might be freed * during the encoding, if its size is too small. @@ -70,8 +68,8 @@ int mjpeg_encoder_start_frame(MJpegEncoder *encoder, SpiceBitmapFmt format, int width, int height, uint8_t **dest, size_t *dest_len, uint32_t frame_mm_time); -int mjpeg_encoder_encode_scanline(MJpegEncoder *encoder, uint8_t *src_pixels, - size_t image_width); +int mjpeg_encoder_encode_frame(MJpegEncoder *encoder, const SpiceRect *src, + const SpiceBitmap *image, int top_down); size_t mjpeg_encoder_end_frame(MJpegEncoder *encoder); /* diff --git a/server/red_worker.c b/server/red_worker.c index 1fe316ea..88035579 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -7699,69 +7699,6 @@ static inline void display_begin_send_message(RedChannelClient *rcc) red_channel_client_begin_send_message(rcc); } -static inline uint8_t *red_get_image_line(SpiceChunks *chunks, size_t *offset, - int *chunk_nr, int stride) -{ - uint8_t *ret; - SpiceChunk *chunk; - - chunk = &chunks->chunk[*chunk_nr]; - - if (*offset == chunk->len) { - if (*chunk_nr == chunks->num_chunks - 1) { - return NULL; /* Last chunk */ - } - *offset = 0; - (*chunk_nr)++; - chunk = &chunks->chunk[*chunk_nr]; - } - - if (chunk->len - *offset < stride) { - spice_warning("bad chunk alignment"); - return NULL; - } - ret = chunk->data + *offset; - *offset += stride; - return ret; -} - -static int encode_frame(DisplayChannelClient *dcc, const SpiceRect *src, - const SpiceBitmap *image, Stream *stream) -{ - SpiceChunks *chunks; - uint32_t image_stride; - size_t offset; - int i, chunk; - StreamAgent *agent = &dcc->stream_agents[stream - dcc->common.worker->streams_buf]; - - chunks = image->data; - offset = 0; - chunk = 0; - image_stride = image->stride; - - const int skip_lines = stream->top_down ? src->top : image->y - (src->bottom - 0); - for (i = 0; i < skip_lines; i++) { - red_get_image_line(chunks, &offset, &chunk, image_stride); - } - - const unsigned int stream_height = src->bottom - src->top; - const unsigned int stream_width = src->right - src->left; - - for (i = 0; i < stream_height; i++) { - uint8_t *src_line = red_get_image_line(chunks, &offset, &chunk, image_stride); - - if (!src_line) { - return FALSE; - } - - src_line += src->left * mjpeg_encoder_get_bytes_per_pixel(agent->mjpeg_encoder); - if (mjpeg_encoder_encode_scanline(agent->mjpeg_encoder, src_line, stream_width) == 0) - return FALSE; - } - - return TRUE; -} - static inline int red_marshall_stream_data(RedChannelClient *rcc, SpiceMarshaller *base_marshaller, Drawable *drawable) { @@ -7820,6 +7757,7 @@ static inline int red_marshall_stream_data(RedChannelClient *rcc, frame_mm_time = drawable->red_drawable->mm_time ? drawable->red_drawable->mm_time : reds_get_mm_time(); + outbuf_size = dcc->send_data.stream_outbuf_size; ret = mjpeg_encoder_start_frame(agent->mjpeg_encoder, image->u.bitmap.format, width, height, @@ -7842,10 +7780,11 @@ static inline int red_marshall_stream_data(RedChannelClient *rcc, return FALSE; } - if (!encode_frame(dcc, &drawable->red_drawable->u.copy.src_area, - &image->u.bitmap, stream)) { - return FALSE; - } + if (!mjpeg_encoder_encode_frame(agent->mjpeg_encoder, + &drawable->red_drawable->u.copy.src_area, + &image->u.bitmap, stream->top_down)) { + return FALSE; + } n = mjpeg_encoder_end_frame(agent->mjpeg_encoder); dcc->send_data.stream_outbuf_size = outbuf_size; -- cgit