guacamole-spice-protocol/src/guacenc/image-stream.h

236 lines
7.3 KiB
C

/*
* 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 <cairo/cairo.h>
/**
* The initial number of bytes to allocate for the image data buffer. If this
* buffer is not sufficiently larged, 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 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);
/**
* 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