From 578bedcd070df85abdaf50faab946e9ec684bc7a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 27 Feb 2016 19:09:33 -0800 Subject: [PATCH] GUAC-236: Add image stream allocation and management functions. --- src/guacenc/display.c | 55 ++++++++++++++++++++- src/guacenc/display.h | 98 ++++++++++++++++++++++++++++++++++++-- src/guacenc/image-stream.c | 37 ++++++++++++++ src/guacenc/image-stream.h | 46 ++++++++++++++++++ 4 files changed, 231 insertions(+), 5 deletions(-) diff --git a/src/guacenc/display.c b/src/guacenc/display.c index 560da430..6bd4c411 100644 --- a/src/guacenc/display.c +++ b/src/guacenc/display.c @@ -170,6 +170,59 @@ guacenc_buffer* guacenc_display_get_related_buffer(guacenc_display* display, } +int guacenc_display_create_image_stream(guacenc_display* display, int index, + int mask, int layer_index, const char* mimetype, int x, int y) { + + /* Do not lookup / allocate if index is invalid */ + if (index < 0 || index > GUACENC_DISPLAY_MAX_STREAMS) { + guacenc_log(GUAC_LOG_WARNING, "Stream index out of bounds: %i", index); + return 1; + } + + /* Free existing stream (if any) */ + guacenc_image_stream_free(display->image_streams[index]); + + /* Associate new stream */ + guacenc_image_stream* stream = display->image_streams[index] = + guacenc_image_stream_alloc(mask, layer_index, mimetype, x, y); + + /* Return zero only if stream is not NULL */ + return stream == NULL; + +} + +guacenc_image_stream* guacenc_display_get_image_stream( + guacenc_display* display, int index) { + + /* Do not lookup / allocate if index is invalid */ + if (index < 0 || index > GUACENC_DISPLAY_MAX_STREAMS) { + guacenc_log(GUAC_LOG_WARNING, "Stream index out of bounds: %i", index); + return NULL; + } + + /* Return existing stream (if any) */ + return display->image_streams[index]; + +} + +int guacenc_display_free_image_stream(guacenc_display* display, int index) { + + /* Do not lookup / allocate if index is invalid */ + if (index < 0 || index > GUACENC_DISPLAY_MAX_STREAMS) { + guacenc_log(GUAC_LOG_WARNING, "Stream index out of bounds: %i", index); + return 1; + } + + /* Free stream (if allocated) */ + guacenc_image_stream_free(display->image_streams[index]); + + /* Mark stream as freed */ + display->image_streams[index] = NULL; + + return 0; + +} + cairo_operator_t guacenc_display_cairo_operator(guac_composite_mode mask) { /* Translate Guacamole channel mask into Cairo operator */ @@ -249,7 +302,7 @@ int guacenc_display_free(guacenc_display* display) { /* Free all streams */ for (i = 0; i < GUACENC_DISPLAY_MAX_STREAMS; i++) - free(display->image_streams[i]); + guacenc_image_stream_free(display->image_streams[i]); free(display); return 0; diff --git a/src/guacenc/display.h b/src/guacenc/display.h index f3e296ac..68d6012e 100644 --- a/src/guacenc/display.h +++ b/src/guacenc/display.h @@ -131,6 +131,9 @@ int guacenc_display_free(guacenc_display* display); * necessary. If the layer having the given index already exists, it will be * returned. * + * @param display + * The Guacamole video encoder display to retrieve the layer from. + * * @param index * The index of the layer to retrieve. All valid layer indices are * non-negative. @@ -146,6 +149,10 @@ guacenc_layer* guacenc_display_get_layer(guacenc_display* display, * Frees all resources associated with the layer having the given index. If * the layer has not been allocated, this function has no effect. * + * @param display + * The Guacamole video encoder display associated with the layer being + * freed. + * * @param index * The index of the layer to free. All valid layer indices are * non-negative. @@ -154,14 +161,16 @@ guacenc_layer* guacenc_display_get_layer(guacenc_display* display, * Zero if the layer was successfully freed or was not allocated, non-zero * if the layer could not be freed as the index was invalid. */ -int guacenc_display_free_layer(guacenc_display* display, - int index); +int guacenc_display_free_layer(guacenc_display* display, int index); /** * Returns the buffer having the given index. A new buffer will be allocated if * necessary. If the buffer having the given index already exists, it will be * returned. * + * @param display + * The Guacamole video encoder display to retrieve the buffer from. + * * @param index * The index of the buffer to retrieve. All valid buffer indices are * negative. @@ -177,6 +186,10 @@ guacenc_buffer* guacenc_display_get_buffer(guacenc_display* display, * Frees all resources associated with the buffer having the given index. If * the buffer has not been allocated, this function has no effect. * + * @param display + * The Guacamole video encoder display associated with the buffer being + * freed. + * * @param index * The index of the buffer to free. All valid buffer indices are negative. * @@ -184,8 +197,7 @@ guacenc_buffer* guacenc_display_get_buffer(guacenc_display* display, * Zero if the buffer was successfully freed or was not allocated, non-zero * if the buffer could not be freed as the index was invalid. */ -int guacenc_display_free_buffer(guacenc_display* display, - int index); +int guacenc_display_free_buffer(guacenc_display* display, int index); /** * Returns the buffer associated with the layer or buffer having the given @@ -194,6 +206,9 @@ int guacenc_display_free_buffer(guacenc_display* display, * will be returned. If the given index refers to a buffer (is negative), that * buffer will be returned directly. * + * @param display + * The Guacamole video encoder display to retrieve the buffer from. + * * @param index * The index of the buffer or layer whose associated buffer should be * retrieved. @@ -205,6 +220,81 @@ int guacenc_display_free_buffer(guacenc_display* display, guacenc_buffer* guacenc_display_get_related_buffer(guacenc_display* display, int index); +/** + * Creates a new image stream having the given index. If the stream having the + * given index already exists, it will be freed and replaced. If the mimetype + * specified is not supported, the image stream will still be allocated but + * will have no associated decoder (blobs send to that stream will have no + * effect). + * + * @param display + * The Guacamole video encoder display to associate with the + * newly-created image stream. + * + * @param index + * The index of the stream to create. All valid stream indices are + * non-negative. + * + * @param mask + * The Guacamole protocol compositing operation (channel mask) to apply + * when drawing the image. + * + * @param layer_index + * The index of the layer or bugger that the image should be drawn to. + * + * @param mimetype + * The mimetype of the image data that will be received along this stream. + * + * @param x + * The X coordinate of the upper-left corner of the rectangle within the + * destination layer or buffer that the image should be drawn to. + * + * @param y + * The Y coordinate of the upper-left corner of the rectangle within the + * destination layer or buffer that the image should be drawn to. + * + * @return + * Zero if the image stream was successfully created, non-zero otherwise. + */ +int guacenc_display_create_image_stream(guacenc_display* display, int index, + int mask, int layer_index, const char* mimetype, int x, int y); + +/** + * Returns the stream having the given index. If no such stream exists, NULL + * will be returned. + * + * @param display + * The Guacamole video encoder display to retrieve the image stream from. + * + * @param index + * The index of the stream to retrieve. All valid stream indices are + * non-negative. + * + * @return + * The stream having the given index, or NULL if the index is invalid or + * a no such stream exists. + */ +guacenc_image_stream* guacenc_display_get_image_stream( + guacenc_display* display, int index); + +/** + * Frees all resources associated with the stream having the given index. If + * the stream has not been allocated, this function has no effect. + * + * @param display + * The Guacamole video encoder display associated with the image stream + * being freed. + * + * @param index + * The index of the stream to free. All valid stream indices are + * non-negative. + * + * @return + * Zero if the stream was successfully freed or was not allocated, non-zero + * if the stream could not be freed as the index was invalid. + */ +int guacenc_display_free_image_stream(guacenc_display* display, int index); + /** * Translates the given Guacamole protocol compositing mode (channel mask) to * the corresponding Cairo composition operator. If no such operator exists, diff --git a/src/guacenc/image-stream.c b/src/guacenc/image-stream.c index 5830722f..0872effc 100644 --- a/src/guacenc/image-stream.c +++ b/src/guacenc/image-stream.c @@ -63,3 +63,40 @@ guacenc_decoder* guacenc_get_decoder(const char* mimetype) { } +guacenc_image_stream* guacenc_image_stream_alloc(int mask, int index, + const char* mimetype, int x, int y) { + + /* Allocate stream */ + guacenc_image_stream* stream = malloc(sizeof(guacenc_image_stream)); + if (stream == NULL) + return NULL; + + /* Init properties */ + stream->index = index; + stream->mask = mask; + stream->x = x; + stream->y = y; + + /* Associate with corresponding decoder */ + stream->decoder = guacenc_get_decoder(mimetype); + + return stream; + +} + +int guacenc_image_stream_free(guacenc_image_stream* stream) { + + /* Ignore NULL streams */ + if (stream == NULL) + return 0; + + /* Invoke free handler for decoder (if associated) */ + if (stream->decoder != NULL) + stream->decoder->free_handler(stream); + + /* Free actual stream */ + free(stream); + return 0; + +} + diff --git a/src/guacenc/image-stream.h b/src/guacenc/image-stream.h index 5cd8f4cd..6275cade 100644 --- a/src/guacenc/image-stream.h +++ b/src/guacenc/image-stream.h @@ -206,5 +206,51 @@ extern guacenc_decoder_mapping guacenc_decoder_map[]; */ guacenc_decoder* guacenc_get_decoder(const char* mimetype); +/** + * Allocates and initializes a new image stream. This allocation is independent + * of the Guacamole video encoder display; the allocated guacenc_image_stream + * will not automatically be associated with the active display, nor will the + * provided layer/buffer index be validated. + * + * @param mask + * The Guacamole protocol compositing operation (channel mask) to apply + * when drawing the image. + * + * @param index + * The index of the layer or bugger that the image should be drawn to. + * + * @param mimetype + * The mimetype of the image data that will be received along this stream. + * + * @param x + * The X coordinate of the upper-left corner of the rectangle within the + * destination layer or buffer that the image should be drawn to. + * + * @param y + * The Y coordinate of the upper-left corner of the rectangle within the + * destination layer or buffer that the image should be drawn to. + * + * @return + * A newly-allocated and initialized guacenc_image_stream, or NULL if + * allocation fails. + */ +guacenc_image_stream* guacenc_image_stream_alloc(int mask, int index, + const char* mimetype, int x, int y); + +/** + * Frees the given image stream and all associated data. If the image stream + * has not yet ended (reached end-of-stream), no image will be drawn to the + * associated buffer or layer. + * + * @param stream + * The stream to free. + * + * @return + * Zero if freeing the stream succeeded, or non-zero if freeing the stream + * failed (for example, due to an error in the free handler of the + * decoder). + */ +int guacenc_image_stream_free(guacenc_image_stream* stream); + #endif