summaryrefslogtreecommitdiffstats
path: root/server/dcc-encoders.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/dcc-encoders.c')
-rw-r--r--server/dcc-encoders.c131
1 files changed, 128 insertions, 3 deletions
diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c
index 24064a89..1eaa6044 100644
--- a/server/dcc-encoders.c
+++ b/server/dcc-encoders.c
@@ -584,8 +584,133 @@ void dcc_free_glz_drawables(DisplayChannelClient *dcc)
void dcc_freeze_glz(DisplayChannelClient *dcc)
{
pthread_rwlock_wrlock(&dcc->glz_dict->encode_lock);
- if (!dcc->glz_dict->migrate_freeze) {
- dcc->glz_dict->migrate_freeze = TRUE;
- }
+ dcc->glz_dict->migrate_freeze = TRUE;
pthread_rwlock_unlock(&dcc->glz_dict->encode_lock);
}
+
+static GlzSharedDictionary *glz_shared_dictionary_new(RedClient *client, uint8_t id,
+ GlzEncDictContext *dict)
+{
+ spice_return_val_if_fail(dict != NULL, NULL);
+
+ GlzSharedDictionary *shared_dict = spice_new0(GlzSharedDictionary, 1);
+
+ shared_dict->dict = dict;
+ shared_dict->id = id;
+ shared_dict->refs = 1;
+ shared_dict->migrate_freeze = FALSE;
+ shared_dict->client = client;
+ ring_item_init(&shared_dict->base);
+ pthread_rwlock_init(&shared_dict->encode_lock, NULL);
+
+ return shared_dict;
+}
+
+static pthread_mutex_t glz_dictionary_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static Ring glz_dictionary_list = {&glz_dictionary_list, &glz_dictionary_list};
+
+static GlzSharedDictionary *find_glz_dictionary(RedClient *client, uint8_t dict_id)
+{
+ RingItem *now;
+ GlzSharedDictionary *ret = NULL;
+
+ now = &glz_dictionary_list;
+ while ((now = ring_next(&glz_dictionary_list, now))) {
+ GlzSharedDictionary *dict = (GlzSharedDictionary *)now;
+ if ((dict->client == client) && (dict->id == dict_id)) {
+ ret = dict;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+#define MAX_LZ_ENCODERS MAX_CACHE_CLIENTS
+
+static GlzSharedDictionary *create_glz_dictionary(DisplayChannelClient *dcc,
+ uint8_t id, int window_size)
+{
+ spice_info("Lz Window %d Size=%d", id, window_size);
+
+ GlzEncDictContext *glz_dict =
+ glz_enc_dictionary_create(window_size, MAX_LZ_ENCODERS, &dcc->glz_data.usr);
+
+ return glz_shared_dictionary_new(RED_CHANNEL_CLIENT(dcc)->client, id, glz_dict);
+}
+
+GlzSharedDictionary *dcc_get_glz_dictionary(DisplayChannelClient *dcc,
+ uint8_t id, int window_size)
+{
+ GlzSharedDictionary *shared_dict;
+
+ pthread_mutex_lock(&glz_dictionary_list_lock);
+
+ shared_dict = find_glz_dictionary(RED_CHANNEL_CLIENT(dcc)->client, id);
+ if (shared_dict) {
+ shared_dict->refs++;
+ } else {
+ shared_dict = create_glz_dictionary(dcc, id, window_size);
+ ring_add(&glz_dictionary_list, &shared_dict->base);
+ }
+
+ pthread_mutex_unlock(&glz_dictionary_list_lock);
+ return shared_dict;
+}
+
+static GlzSharedDictionary *restore_glz_dictionary(DisplayChannelClient *dcc,
+ uint8_t id,
+ GlzEncDictRestoreData *restore_data)
+{
+ GlzEncDictContext *glz_dict =
+ glz_enc_dictionary_restore(restore_data, &dcc->glz_data.usr);
+
+ return glz_shared_dictionary_new(RED_CHANNEL_CLIENT(dcc)->client, id, glz_dict);
+}
+
+GlzSharedDictionary *dcc_restore_glz_dictionary(DisplayChannelClient *dcc,
+ uint8_t id,
+ GlzEncDictRestoreData *restore_data)
+{
+ GlzSharedDictionary *shared_dict = NULL;
+
+ pthread_mutex_lock(&glz_dictionary_list_lock);
+
+ shared_dict = find_glz_dictionary(RED_CHANNEL_CLIENT(dcc)->client, id);
+
+ if (shared_dict) {
+ shared_dict->refs++;
+ } else {
+ shared_dict = restore_glz_dictionary(dcc, id, restore_data);
+ ring_add(&glz_dictionary_list, &shared_dict->base);
+ }
+
+ pthread_mutex_unlock(&glz_dictionary_list_lock);
+ return shared_dict;
+}
+
+/* destroy encoder, and dictionary if no one uses it*/
+void dcc_release_glz(DisplayChannelClient *dcc)
+{
+ GlzSharedDictionary *shared_dict;
+
+ dcc_free_glz_drawables(dcc);
+
+ glz_encoder_destroy(dcc->glz);
+ dcc->glz = NULL;
+
+ if (!(shared_dict = dcc->glz_dict)) {
+ return;
+ }
+
+ dcc->glz_dict = NULL;
+ pthread_mutex_lock(&glz_dictionary_list_lock);
+ if (--shared_dict->refs != 0) {
+ pthread_mutex_unlock(&glz_dictionary_list_lock);
+ return;
+ }
+ ring_remove(&shared_dict->base);
+ pthread_mutex_unlock(&glz_dictionary_list_lock);
+ glz_enc_dictionary_destroy(shared_dict->dict, &dcc->glz_data.usr);
+ free(shared_dict);
+}