#ifndef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include static void rfb_buffer_free_mem (RfbBuffer * buffer, void *); static void rfb_buffer_free_subbuffer (RfbBuffer * buffer, void *priv); #define oil_copy_u8(a,b,c) memcpy(a,b,c) RfbBuffer * rfb_buffer_new (void) { RfbBuffer *buffer; buffer = g_new0 (RfbBuffer, 1); buffer->ref_count = 1; return buffer; } RfbBuffer * rfb_buffer_new_and_alloc (int size) { RfbBuffer *buffer = rfb_buffer_new (); buffer->data = g_malloc (size); buffer->length = size; buffer->free = rfb_buffer_free_mem; return buffer; } RfbBuffer * rfb_buffer_new_with_data (void *data, int size) { RfbBuffer *buffer = rfb_buffer_new (); buffer->data = data; buffer->length = size; buffer->free = rfb_buffer_free_mem; return buffer; } RfbBuffer * rfb_buffer_new_subbuffer (RfbBuffer * buffer, int offset, int length) { RfbBuffer *subbuffer = rfb_buffer_new (); if (buffer->parent) { rfb_buffer_ref (buffer->parent); subbuffer->parent = buffer->parent; } else { rfb_buffer_ref (buffer); subbuffer->parent = buffer; } subbuffer->data = buffer->data + offset; subbuffer->length = length; subbuffer->free = rfb_buffer_free_subbuffer; return subbuffer; } void rfb_buffer_ref (RfbBuffer * buffer) { buffer->ref_count++; } void rfb_buffer_unref (RfbBuffer * buffer) { buffer->ref_count--; if (buffer->ref_count == 0) { if (buffer->free) buffer->free (buffer, buffer->priv); g_free (buffer); } } static void rfb_buffer_free_mem (RfbBuffer * buffer, void *priv) { g_free (buffer->data); } static void rfb_buffer_free_subbuffer (RfbBuffer * buffer, void *priv) { rfb_buffer_unref (buffer->parent); } RfbBufferQueue * rfb_buffer_queue_new (void) { return g_new0 (RfbBufferQueue, 1); } int rfb_buffer_queue_get_depth (RfbBufferQueue * queue) { return queue->depth; } int rfb_buffer_queue_get_offset (RfbBufferQueue * queue) { return queue->offset; } void rfb_buffer_queue_free (RfbBufferQueue * queue) { GList *g; for (g = g_list_first (queue->buffers); g; g = g_list_next (g)) { rfb_buffer_unref ((RfbBuffer *) g->data); } g_list_free (queue->buffers); g_free (queue); } void rfb_buffer_queue_push (RfbBufferQueue * queue, RfbBuffer * buffer) { queue->buffers = g_list_append (queue->buffers, buffer); queue->depth += buffer->length; } RfbBuffer * rfb_buffer_queue_pull (RfbBufferQueue * queue, int length) { GList *g; RfbBuffer *newbuffer; RfbBuffer *buffer; RfbBuffer *subbuffer; g_return_val_if_fail (length > 0, NULL); if (queue->depth < length) { return NULL; } GST_LOG ("pulling %d, %d available", length, queue->depth); g = g_list_first (queue->buffers); buffer = g->data; if (buffer->length > length) { newbuffer = rfb_buffer_new_subbuffer (buffer, 0, length); subbuffer = rfb_buffer_new_subbuffer (buffer, length, buffer->length - length); g->data = subbuffer; rfb_buffer_unref (buffer); } else { int offset = 0; newbuffer = rfb_buffer_new_and_alloc (length); while (offset < length) { g = g_list_first (queue->buffers); buffer = g->data; if (buffer->length > length - offset) { int n = length - offset; oil_copy_u8 (newbuffer->data + offset, buffer->data, n); subbuffer = rfb_buffer_new_subbuffer (buffer, n, buffer->length - n); g->data = subbuffer; rfb_buffer_unref (buffer); offset += n; } else { oil_copy_u8 (newbuffer->data + offset, buffer->data, buffer->length); queue->buffers = g_list_delete_link (queue->buffers, g); offset += buffer->length; } } } queue->depth -= length; queue->offset += length; return newbuffer; } RfbBuffer * rfb_buffer_queue_peek (RfbBufferQueue * queue, int length) { GList *g; RfbBuffer *newbuffer; RfbBuffer *buffer; int offset = 0; g_return_val_if_fail (length > 0, NULL); if (queue->depth < length) { return NULL; } GST_LOG ("peeking %d, %d available", length, queue->depth); g = g_list_first (queue->buffers); buffer = g->data; if (buffer->length > length) { newbuffer = rfb_buffer_new_subbuffer (buffer, 0, length); } else { newbuffer = rfb_buffer_new_and_alloc (length); while (offset < length) { buffer = g->data; if (buffer->length > length - offset) { int n = length - offset; oil_copy_u8 (newbuffer->data + offset, buffer->data, n); offset += n; } else { oil_copy_u8 (newbuffer->data + offset, buffer->data, buffer->length); offset += buffer->length; } g = g_list_next (g); } } return newbuffer; }