/* * Copyright (C) 2016 Glyptodon, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef GUACENC_IMAGE_STREAM_H #define GUACENC_IMAGE_STREAM_H #include "config.h" #include "buffer.h" #include /** * The initial number of bytes to allocate for the image data buffer. If this * buffer is not sufficiently large, it will be dynamically reallocated as it * grows. */ #define GUACENC_IMAGE_STREAM_INITIAL_LENGTH 4096 /** * Callback function which is provided raw, encoded image data of the given * length. The function is expected to return a new Cairo surface which will * later (by guacenc) be freed via cairo_surface_destroy(). * * @param data * The raw encoded image data that this function must decode. * * @param length * The length of the image data, in bytes. * * @return * A newly-allocated Cairo surface containing the decoded image, or NULL * or decoding fails. */ typedef cairo_surface_t* guacenc_decoder(unsigned char* data, int length); /** * The current state of an allocated Guacamole image stream. */ typedef struct guacenc_image_stream { /** * The index of the destination layer or buffer. */ int index; /** * The Guacamole protocol compositing operation (channel mask) to apply * when drawing the image. */ int mask; /** * The X coordinate of the upper-left corner of the rectangle within the * destination layer or buffer that the decoded image should be drawn to. */ int x; /** * The Y coordinate of the upper-left corner of the rectangle within the * destination layer or buffer that the decoded image should be drawn to. */ int y; /** * Buffer of image data which will be built up over time as chunks are * received via "blob" instructions. This will ultimately be passed in its * entirety to the decoder function. */ unsigned char* buffer; /** * The number of bytes currently stored in the buffer. */ int length; /** * The maximum number of bytes that can be stored in the current buffer * before it must be reallocated. */ int max_length; /** * The decoder to use when decoding the raw data received along this * stream, or NULL if no such decoder exists. */ guacenc_decoder* decoder; } guacenc_image_stream; /** * Mapping of image mimetype to corresponding decoder function. */ typedef struct guacenc_decoder_mapping { /** * The mimetype of the image that the associated decoder can read. */ const char* mimetype; /** * The decoder function to use when an image stream of the associated * mimetype is received. */ guacenc_decoder* decoder; } guacenc_decoder_mapping; /** * Array of all mimetype/decoder mappings for all supported image types, * terminated by an entry with a NULL mimetype. */ extern guacenc_decoder_mapping guacenc_decoder_map[]; /** * Returns the decoder associated with the given mimetype. If no such decoder * exists, NULL is returned. * * @param mimetype * The image mimetype to return the associated decoder of. * * @return * The decoder associated with the given mimetype, or NULL if no such * decoder exists. */ 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 buffer 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); /** * Appends newly-received data to the internal buffer of the given image * stream, such that the entire received image can be fed to the decoder as one * buffer once the stream ends. * * @param stream * The image stream that received the data. * * @param data * The chunk of data received along the image stream. * * @param length * The length of the chunk of data received, in bytes. * * @return * Zero if the given data was successfully appended to the in-progress * image, non-zero if an error occurs. */ int guacenc_image_stream_receive(guacenc_image_stream* stream, unsigned char* data, int length); /** * Marks the end of the given image stream (no more data will be received) and * invokes the associated decoder. The decoded image will be written to the * given buffer as-is. If no decoder is associated with the given image stream, * this function has no effect. Meta-information describing the image draw * operation itself is pulled from the guacenc_image_stream, having been stored * there when the image stream was created. * * @param stream * The image stream that has ended. * * @param buffer * The buffer that the decoded image should be written to. * * @return * Zero if the image is written successfully, or non-zero if an error * occurs. */ int guacenc_image_stream_end(guacenc_image_stream* stream, guacenc_buffer* buffer); /** * 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